byterover-cli 0.2.1 → 0.3.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 (490) hide show
  1. package/README.md +56 -56
  2. package/bin/dev.js +1 -1
  3. package/dist/commands/cipher-agent/run.d.ts +111 -0
  4. package/dist/commands/cipher-agent/run.js +493 -0
  5. package/dist/commands/cipher-agent/set-prompt.d.ts +14 -0
  6. package/dist/commands/cipher-agent/set-prompt.js +53 -0
  7. package/dist/commands/cipher-agent/show-prompt.d.ts +11 -0
  8. package/dist/commands/cipher-agent/show-prompt.js +48 -0
  9. package/dist/commands/clear.d.ts +6 -0
  10. package/dist/commands/clear.js +36 -15
  11. package/dist/commands/curate.d.ts +74 -0
  12. package/dist/commands/curate.js +396 -0
  13. package/dist/commands/foo.d.ts +12 -0
  14. package/dist/commands/foo.js +61 -0
  15. package/dist/commands/gen-rules.d.ts +3 -0
  16. package/dist/commands/gen-rules.js +39 -20
  17. package/dist/commands/init.d.ts +48 -3
  18. package/dist/commands/init.js +242 -70
  19. package/dist/commands/login.js +9 -4
  20. package/dist/commands/pull.d.ts +33 -0
  21. package/dist/commands/pull.js +115 -0
  22. package/dist/commands/push.d.ts +13 -13
  23. package/dist/commands/push.js +81 -101
  24. package/dist/commands/query.d.ts +63 -0
  25. package/dist/commands/query.js +349 -0
  26. package/dist/commands/space/list.d.ts +5 -2
  27. package/dist/commands/space/list.js +60 -56
  28. package/dist/commands/space/switch.d.ts +16 -0
  29. package/dist/commands/space/switch.js +102 -53
  30. package/dist/commands/status.d.ts +5 -2
  31. package/dist/commands/status.js +43 -33
  32. package/dist/commands/watch.d.ts +23 -0
  33. package/dist/commands/watch.js +171 -0
  34. package/dist/config/auth.config.js +14 -2
  35. package/dist/config/context-tree-domains.d.ts +12 -0
  36. package/dist/config/context-tree-domains.js +29 -0
  37. package/dist/config/environment.d.ts +6 -0
  38. package/dist/config/environment.js +9 -2
  39. package/dist/constants.d.ts +5 -0
  40. package/dist/constants.js +6 -0
  41. package/dist/core/domain/cipher/agent/agent-state-machine.d.ts +128 -0
  42. package/dist/core/domain/cipher/agent/agent-state-machine.js +183 -0
  43. package/dist/core/domain/cipher/agent/agent-state.d.ts +77 -0
  44. package/dist/core/domain/cipher/agent/agent-state.js +59 -0
  45. package/dist/core/domain/cipher/agent/index.d.ts +7 -0
  46. package/dist/core/domain/cipher/agent/index.js +7 -0
  47. package/dist/core/domain/cipher/agent-events/index.d.ts +8 -0
  48. package/dist/core/domain/cipher/agent-events/index.js +7 -0
  49. package/dist/core/domain/cipher/agent-events/types.d.ts +419 -0
  50. package/dist/core/domain/cipher/agent-events/types.js +42 -0
  51. package/dist/core/domain/cipher/blob/types.d.ts +108 -0
  52. package/dist/core/domain/cipher/errors/blob-error.d.ts +36 -0
  53. package/dist/core/domain/cipher/errors/blob-error.js +68 -0
  54. package/dist/core/domain/cipher/errors/file-system-error.d.ts +211 -0
  55. package/dist/core/domain/cipher/errors/file-system-error.js +291 -0
  56. package/dist/core/domain/cipher/errors/llm-error.d.ts +120 -0
  57. package/dist/core/domain/cipher/errors/llm-error.js +161 -0
  58. package/dist/core/domain/cipher/errors/memory-error.d.ts +35 -0
  59. package/dist/core/domain/cipher/errors/memory-error.js +62 -0
  60. package/dist/core/domain/cipher/errors/process-error-code.d.ts +97 -0
  61. package/dist/core/domain/cipher/errors/process-error-code.js +98 -0
  62. package/dist/core/domain/cipher/errors/process-error.d.ts +135 -0
  63. package/dist/core/domain/cipher/errors/process-error.js +173 -0
  64. package/dist/core/domain/cipher/errors/session-error.d.ts +56 -0
  65. package/dist/core/domain/cipher/errors/session-error.js +74 -0
  66. package/dist/core/domain/cipher/errors/tool-error.d.ts +57 -0
  67. package/dist/core/domain/cipher/errors/tool-error.js +81 -0
  68. package/dist/core/domain/cipher/file-system/types.d.ts +203 -0
  69. package/dist/core/domain/cipher/memory/types.d.ts +102 -0
  70. package/dist/core/domain/cipher/memory/types.js +4 -0
  71. package/dist/core/domain/cipher/parsed-interaction.d.ts +47 -0
  72. package/dist/core/domain/cipher/parsed-interaction.js +25 -0
  73. package/dist/core/domain/cipher/process/types.d.ts +286 -0
  74. package/dist/core/domain/cipher/session/types.d.ts +54 -0
  75. package/dist/core/domain/cipher/storage/history-types.d.ts +38 -0
  76. package/dist/core/domain/cipher/system-prompt/types.d.ts +131 -0
  77. package/dist/core/domain/cipher/todos/index.d.ts +4 -0
  78. package/dist/core/domain/cipher/todos/index.js +4 -0
  79. package/dist/core/domain/cipher/todos/types.d.ts +57 -0
  80. package/dist/core/domain/cipher/todos/types.js +5 -0
  81. package/dist/core/domain/cipher/tools/constants.d.ts +28 -0
  82. package/dist/core/domain/cipher/tools/constants.js +24 -0
  83. package/dist/core/domain/cipher/tools/tool-error.d.ts +183 -0
  84. package/dist/core/domain/cipher/tools/tool-error.js +246 -0
  85. package/dist/core/domain/cipher/tools/types.d.ts +145 -0
  86. package/dist/core/domain/entities/brv-config.d.ts +42 -6
  87. package/dist/core/domain/entities/brv-config.js +115 -17
  88. package/dist/core/domain/entities/cogit-push-context.d.ts +38 -0
  89. package/dist/core/domain/entities/cogit-push-context.js +91 -0
  90. package/dist/core/domain/entities/cogit-push-response.d.ts +20 -0
  91. package/dist/core/domain/entities/cogit-push-response.js +31 -0
  92. package/dist/core/domain/entities/cogit-snapshot-author.d.ts +24 -0
  93. package/dist/core/domain/entities/cogit-snapshot-author.js +39 -0
  94. package/dist/core/domain/entities/cogit-snapshot-file.d.ts +34 -0
  95. package/dist/core/domain/entities/cogit-snapshot-file.js +59 -0
  96. package/dist/core/domain/entities/cogit-snapshot.d.ts +31 -0
  97. package/dist/core/domain/entities/cogit-snapshot.js +58 -0
  98. package/dist/core/domain/entities/context-tree-index.d.ts +26 -0
  99. package/dist/core/domain/entities/context-tree-index.js +27 -0
  100. package/dist/core/domain/entities/context-tree-snapshot.d.ts +56 -0
  101. package/dist/core/domain/entities/context-tree-snapshot.js +83 -0
  102. package/dist/core/domain/entities/event.d.ts +1 -1
  103. package/dist/core/domain/entities/event.js +3 -1
  104. package/dist/core/domain/entities/parser.d.ts +567 -0
  105. package/dist/core/domain/entities/parser.js +10 -0
  106. package/dist/core/domain/entities/playbook.d.ts +2 -23
  107. package/dist/core/domain/entities/playbook.js +2 -70
  108. package/dist/core/domain/errors/brv-config-version-error.d.ts +16 -0
  109. package/dist/core/domain/errors/brv-config-version-error.js +21 -0
  110. package/dist/core/domain/knowledge/directory-manager.d.ts +80 -0
  111. package/dist/core/domain/knowledge/directory-manager.js +145 -0
  112. package/dist/core/domain/knowledge/markdown-writer.d.ts +18 -0
  113. package/dist/core/domain/knowledge/markdown-writer.js +18 -0
  114. package/dist/core/domain/knowledge/relation-parser.d.ts +90 -0
  115. package/dist/core/domain/knowledge/relation-parser.js +131 -0
  116. package/dist/core/interfaces/cipher/cipher-services.d.ts +71 -0
  117. package/dist/core/interfaces/cipher/cipher-services.js +1 -0
  118. package/dist/core/interfaces/cipher/i-blob-storage.d.ts +78 -0
  119. package/dist/core/interfaces/cipher/i-blob-storage.js +1 -0
  120. package/dist/core/interfaces/cipher/i-chat-session.d.ts +62 -0
  121. package/dist/core/interfaces/cipher/i-chat-session.js +1 -0
  122. package/dist/core/interfaces/cipher/i-cipher-agent.d.ts +88 -0
  123. package/dist/core/interfaces/cipher/i-cipher-agent.js +1 -0
  124. package/dist/core/interfaces/cipher/i-coding-agent-log-parser.d.ts +20 -0
  125. package/dist/core/interfaces/cipher/i-coding-agent-log-parser.js +1 -0
  126. package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.d.ts +31 -0
  127. package/dist/core/interfaces/cipher/i-coding-agent-log-watcher.js +1 -0
  128. package/dist/core/interfaces/cipher/i-content-generator.d.ts +120 -0
  129. package/dist/core/interfaces/cipher/i-content-generator.js +12 -0
  130. package/dist/core/interfaces/cipher/i-event-emitter.d.ts +76 -0
  131. package/dist/core/interfaces/cipher/i-event-emitter.js +1 -0
  132. package/dist/core/interfaces/cipher/i-file-system.d.ts +68 -0
  133. package/dist/core/interfaces/cipher/i-file-system.js +1 -0
  134. package/dist/core/interfaces/cipher/i-history-storage.d.ts +53 -0
  135. package/dist/core/interfaces/cipher/i-history-storage.js +1 -0
  136. package/dist/core/interfaces/cipher/i-llm-provider.d.ts +14 -0
  137. package/dist/core/interfaces/cipher/i-llm-provider.js +1 -0
  138. package/dist/core/interfaces/cipher/i-llm-service.d.ts +62 -0
  139. package/dist/core/interfaces/cipher/i-llm-service.js +1 -0
  140. package/dist/core/interfaces/cipher/i-logger.d.ts +78 -0
  141. package/dist/core/interfaces/cipher/i-logger.js +28 -0
  142. package/dist/core/interfaces/cipher/i-message-formatter.d.ts +44 -0
  143. package/dist/core/interfaces/cipher/i-message-formatter.js +1 -0
  144. package/dist/core/interfaces/cipher/i-policy-engine.d.ts +102 -0
  145. package/dist/core/interfaces/cipher/i-policy-engine.js +9 -0
  146. package/dist/core/interfaces/cipher/i-process-service.d.ts +65 -0
  147. package/dist/core/interfaces/cipher/i-process-service.js +1 -0
  148. package/dist/core/interfaces/cipher/i-system-prompt-contributor.d.ts +25 -0
  149. package/dist/core/interfaces/cipher/i-system-prompt-contributor.js +1 -0
  150. package/dist/core/interfaces/cipher/i-tokenizer.d.ts +15 -0
  151. package/dist/core/interfaces/cipher/i-tokenizer.js +1 -0
  152. package/dist/core/interfaces/cipher/i-tool-provider.d.ts +64 -0
  153. package/dist/core/interfaces/cipher/i-tool-provider.js +1 -0
  154. package/dist/core/interfaces/cipher/i-tool-scheduler.d.ts +103 -0
  155. package/dist/core/interfaces/cipher/i-tool-scheduler.js +11 -0
  156. package/dist/core/interfaces/cipher/llm-types.d.ts +46 -0
  157. package/dist/core/interfaces/cipher/llm-types.js +5 -0
  158. package/dist/core/interfaces/cipher/message-types.d.ts +118 -0
  159. package/dist/core/interfaces/cipher/message-types.js +5 -0
  160. package/dist/core/interfaces/cipher/tokenizer-types.d.ts +11 -0
  161. package/dist/core/interfaces/cipher/tokenizer-types.js +14 -0
  162. package/dist/core/interfaces/i-cogit-pull-service.d.ts +24 -0
  163. package/dist/core/interfaces/i-cogit-pull-service.js +1 -0
  164. package/dist/core/interfaces/i-cogit-push-service.d.ts +27 -0
  165. package/dist/core/interfaces/i-cogit-push-service.js +1 -0
  166. package/dist/core/interfaces/i-context-file-reader.d.ts +32 -0
  167. package/dist/core/interfaces/i-context-file-reader.js +1 -0
  168. package/dist/core/interfaces/i-context-tree-service.d.ts +21 -0
  169. package/dist/core/interfaces/i-context-tree-service.js +1 -0
  170. package/dist/core/interfaces/i-context-tree-snapshot-service.d.ts +36 -0
  171. package/dist/core/interfaces/i-context-tree-snapshot-service.js +1 -0
  172. package/dist/core/interfaces/i-context-tree-writer-service.d.ts +32 -0
  173. package/dist/core/interfaces/i-context-tree-writer-service.js +1 -0
  174. package/dist/core/interfaces/i-file-watcher-service.d.ts +41 -0
  175. package/dist/core/interfaces/i-file-watcher-service.js +1 -0
  176. package/dist/core/interfaces/parser/i-clean-parser-service.d.ts +18 -0
  177. package/dist/core/interfaces/parser/i-clean-parser-service.js +1 -0
  178. package/dist/core/interfaces/parser/i-raw-parser-service.d.ts +17 -0
  179. package/dist/core/interfaces/parser/i-raw-parser-service.js +1 -0
  180. package/dist/core/interfaces/parser/i-session-normalizer.d.ts +56 -0
  181. package/dist/core/interfaces/parser/i-session-normalizer.js +1 -0
  182. package/dist/hooks/command_not_found/handle-invalid-commands.d.ts +7 -0
  183. package/dist/hooks/command_not_found/handle-invalid-commands.js +32 -0
  184. package/dist/hooks/error/clean-errors.d.ts +7 -0
  185. package/dist/hooks/error/clean-errors.js +50 -0
  186. package/dist/hooks/init/welcome.js +72 -1
  187. package/dist/hooks/prerun/validate-brv-config-version.d.ts +28 -0
  188. package/dist/hooks/prerun/validate-brv-config-version.js +43 -0
  189. package/dist/infra/cipher/agent-service-factory.d.ts +86 -0
  190. package/dist/infra/cipher/agent-service-factory.js +212 -0
  191. package/dist/infra/cipher/blob/blob-storage-factory.d.ts +13 -0
  192. package/dist/infra/cipher/blob/blob-storage-factory.js +14 -0
  193. package/dist/infra/cipher/blob/index.d.ts +10 -0
  194. package/dist/infra/cipher/blob/index.js +12 -0
  195. package/dist/infra/cipher/blob/migrations.d.ts +63 -0
  196. package/dist/infra/cipher/blob/migrations.js +148 -0
  197. package/dist/infra/cipher/blob/sqlite-blob-storage.d.ts +82 -0
  198. package/dist/infra/cipher/blob/sqlite-blob-storage.js +307 -0
  199. package/dist/infra/cipher/cipher-agent-state-manager.d.ts +63 -0
  200. package/dist/infra/cipher/cipher-agent-state-manager.js +108 -0
  201. package/dist/infra/cipher/cipher-agent.d.ts +182 -0
  202. package/dist/infra/cipher/cipher-agent.js +317 -0
  203. package/dist/infra/cipher/command-parser.d.ts +23 -0
  204. package/dist/infra/cipher/command-parser.js +85 -0
  205. package/dist/infra/cipher/display/todo-display.d.ts +23 -0
  206. package/dist/infra/cipher/display/todo-display.js +129 -0
  207. package/dist/infra/cipher/events/event-emitter.d.ts +137 -0
  208. package/dist/infra/cipher/events/event-emitter.js +158 -0
  209. package/dist/infra/cipher/exit-codes.d.ts +44 -0
  210. package/dist/infra/cipher/exit-codes.js +58 -0
  211. package/dist/infra/cipher/file-system/file-system-service.d.ts +105 -0
  212. package/dist/infra/cipher/file-system/file-system-service.js +641 -0
  213. package/dist/infra/cipher/file-system/gitignore-filter.d.ts +77 -0
  214. package/dist/infra/cipher/file-system/gitignore-filter.js +120 -0
  215. package/dist/infra/cipher/file-system/glob-utils.d.ts +60 -0
  216. package/dist/infra/cipher/file-system/glob-utils.js +120 -0
  217. package/dist/infra/cipher/file-system/path-validator.d.ts +69 -0
  218. package/dist/infra/cipher/file-system/path-validator.js +184 -0
  219. package/dist/infra/cipher/grpc/internal-llm-grpc-service.d.ts +149 -0
  220. package/dist/infra/cipher/grpc/internal-llm-grpc-service.js +364 -0
  221. package/dist/infra/cipher/grpc/internal-llm-grpc.proto +94 -0
  222. package/dist/infra/cipher/interactive-commands.d.ts +16 -0
  223. package/dist/infra/cipher/interactive-commands.js +198 -0
  224. package/dist/infra/cipher/interactive-loop.d.ts +24 -0
  225. package/dist/infra/cipher/interactive-loop.js +352 -0
  226. package/dist/infra/cipher/llm/context/async-mutex.d.ts +59 -0
  227. package/dist/infra/cipher/llm/context/async-mutex.js +92 -0
  228. package/dist/infra/cipher/llm/context/compression/index.d.ts +6 -0
  229. package/dist/infra/cipher/llm/context/compression/index.js +5 -0
  230. package/dist/infra/cipher/llm/context/compression/middle-removal.d.ts +40 -0
  231. package/dist/infra/cipher/llm/context/compression/middle-removal.js +76 -0
  232. package/dist/infra/cipher/llm/context/compression/oldest-removal.d.ts +38 -0
  233. package/dist/infra/cipher/llm/context/compression/oldest-removal.js +53 -0
  234. package/dist/infra/cipher/llm/context/compression/types.d.ts +36 -0
  235. package/dist/infra/cipher/llm/context/compression/types.js +1 -0
  236. package/dist/infra/cipher/llm/context/context-manager.d.ts +234 -0
  237. package/dist/infra/cipher/llm/context/context-manager.js +419 -0
  238. package/dist/infra/cipher/llm/context/index.d.ts +2 -0
  239. package/dist/infra/cipher/llm/context/index.js +2 -0
  240. package/dist/infra/cipher/llm/context/loop-detector.d.ts +125 -0
  241. package/dist/infra/cipher/llm/context/loop-detector.js +194 -0
  242. package/dist/infra/cipher/llm/context/utils.d.ts +17 -0
  243. package/dist/infra/cipher/llm/context/utils.js +89 -0
  244. package/dist/infra/cipher/llm/formatters/claude-formatter.d.ts +54 -0
  245. package/dist/infra/cipher/llm/formatters/claude-formatter.js +182 -0
  246. package/dist/infra/cipher/llm/formatters/gemini-formatter.d.ts +69 -0
  247. package/dist/infra/cipher/llm/formatters/gemini-formatter.js +253 -0
  248. package/dist/infra/cipher/llm/formatters/openrouter-formatter.d.ts +47 -0
  249. package/dist/infra/cipher/llm/formatters/openrouter-formatter.js +238 -0
  250. package/dist/infra/cipher/llm/generators/byterover-content-generator.d.ts +92 -0
  251. package/dist/infra/cipher/llm/generators/byterover-content-generator.js +211 -0
  252. package/dist/infra/cipher/llm/generators/index.d.ts +13 -0
  253. package/dist/infra/cipher/llm/generators/index.js +13 -0
  254. package/dist/infra/cipher/llm/generators/logging-content-generator.d.ts +104 -0
  255. package/dist/infra/cipher/llm/generators/logging-content-generator.js +182 -0
  256. package/dist/infra/cipher/llm/generators/openrouter-content-generator.d.ts +93 -0
  257. package/dist/infra/cipher/llm/generators/openrouter-content-generator.js +254 -0
  258. package/dist/infra/cipher/llm/generators/retryable-content-generator.d.ts +90 -0
  259. package/dist/infra/cipher/llm/generators/retryable-content-generator.js +157 -0
  260. package/dist/infra/cipher/llm/index.d.ts +9 -0
  261. package/dist/infra/cipher/llm/index.js +13 -0
  262. package/dist/infra/cipher/llm/internal-llm-service.d.ts +308 -0
  263. package/dist/infra/cipher/llm/internal-llm-service.js +724 -0
  264. package/dist/infra/cipher/llm/openrouter-llm-service.d.ts +183 -0
  265. package/dist/infra/cipher/llm/openrouter-llm-service.js +386 -0
  266. package/dist/infra/cipher/llm/response-validator.d.ts +89 -0
  267. package/dist/infra/cipher/llm/response-validator.js +157 -0
  268. package/dist/infra/cipher/llm/retry/index.d.ts +10 -0
  269. package/dist/infra/cipher/llm/retry/index.js +10 -0
  270. package/dist/infra/cipher/llm/retry/retry-policy.d.ts +74 -0
  271. package/dist/infra/cipher/llm/retry/retry-policy.js +146 -0
  272. package/dist/infra/cipher/llm/retry/retry-with-backoff.d.ts +113 -0
  273. package/dist/infra/cipher/llm/retry/retry-with-backoff.js +247 -0
  274. package/dist/infra/cipher/llm/thought-parser.d.ts +145 -0
  275. package/dist/infra/cipher/llm/thought-parser.js +190 -0
  276. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.d.ts +47 -0
  277. package/dist/infra/cipher/llm/tokenizers/claude-tokenizer.js +55 -0
  278. package/dist/infra/cipher/llm/tokenizers/default-tokenizer.d.ts +31 -0
  279. package/dist/infra/cipher/llm/tokenizers/default-tokenizer.js +38 -0
  280. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.d.ts +37 -0
  281. package/dist/infra/cipher/llm/tokenizers/gemini-tokenizer.js +45 -0
  282. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.d.ts +29 -0
  283. package/dist/infra/cipher/llm/tokenizers/openrouter-tokenizer.js +37 -0
  284. package/dist/infra/cipher/llm/tool-output-processor.d.ts +117 -0
  285. package/dist/infra/cipher/llm/tool-output-processor.js +153 -0
  286. package/dist/infra/cipher/logger/console-logger.d.ts +42 -0
  287. package/dist/infra/cipher/logger/console-logger.js +63 -0
  288. package/dist/infra/cipher/logger/event-based-logger.d.ts +54 -0
  289. package/dist/infra/cipher/logger/event-based-logger.js +92 -0
  290. package/dist/infra/cipher/memory/index.d.ts +6 -0
  291. package/dist/infra/cipher/memory/index.js +7 -0
  292. package/dist/infra/cipher/memory/memory-manager.d.ts +136 -0
  293. package/dist/infra/cipher/memory/memory-manager.js +523 -0
  294. package/dist/infra/cipher/parsers/coding-agent-log-parser.d.ts +24 -0
  295. package/dist/infra/cipher/parsers/coding-agent-log-parser.js +51 -0
  296. package/dist/infra/cipher/process/command-validator.d.ts +59 -0
  297. package/dist/infra/cipher/process/command-validator.js +266 -0
  298. package/dist/infra/cipher/process/index.d.ts +8 -0
  299. package/dist/infra/cipher/process/index.js +8 -0
  300. package/dist/infra/cipher/process/process-service.d.ts +95 -0
  301. package/dist/infra/cipher/process/process-service.js +439 -0
  302. package/dist/infra/cipher/session/chat-session.d.ts +80 -0
  303. package/dist/infra/cipher/session/chat-session.js +165 -0
  304. package/dist/infra/cipher/session/index.d.ts +6 -0
  305. package/dist/infra/cipher/session/index.js +5 -0
  306. package/dist/infra/cipher/session/session-event-forwarder.d.ts +37 -0
  307. package/dist/infra/cipher/session/session-event-forwarder.js +83 -0
  308. package/dist/infra/cipher/session/session-manager.d.ts +109 -0
  309. package/dist/infra/cipher/session/session-manager.js +172 -0
  310. package/dist/infra/cipher/storage/blob-history-storage.d.ts +76 -0
  311. package/dist/infra/cipher/storage/blob-history-storage.js +178 -0
  312. package/dist/infra/cipher/system-prompt/simple-prompt-factory.d.ts +105 -0
  313. package/dist/infra/cipher/system-prompt/simple-prompt-factory.js +290 -0
  314. package/dist/infra/cipher/tools/core-tool-scheduler.d.ts +99 -0
  315. package/dist/infra/cipher/tools/core-tool-scheduler.js +161 -0
  316. package/dist/infra/cipher/tools/default-policy-rules.d.ts +26 -0
  317. package/dist/infra/cipher/tools/default-policy-rules.js +125 -0
  318. package/dist/infra/cipher/tools/implementations/bash-exec-tool.d.ts +12 -0
  319. package/dist/infra/cipher/tools/implementations/bash-exec-tool.js +93 -0
  320. package/dist/infra/cipher/tools/implementations/bash-output-tool.d.ts +12 -0
  321. package/dist/infra/cipher/tools/implementations/bash-output-tool.js +47 -0
  322. package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.d.ts +11 -0
  323. package/dist/infra/cipher/tools/implementations/create-knowledge-topic-tool.js +142 -0
  324. package/dist/infra/cipher/tools/implementations/delete-memory-tool.d.ts +12 -0
  325. package/dist/infra/cipher/tools/implementations/delete-memory-tool.js +37 -0
  326. package/dist/infra/cipher/tools/implementations/detect-domains-tool.d.ts +7 -0
  327. package/dist/infra/cipher/tools/implementations/detect-domains-tool.js +73 -0
  328. package/dist/infra/cipher/tools/implementations/edit-file-tool.d.ts +13 -0
  329. package/dist/infra/cipher/tools/implementations/edit-file-tool.js +50 -0
  330. package/dist/infra/cipher/tools/implementations/edit-memory-tool.d.ts +13 -0
  331. package/dist/infra/cipher/tools/implementations/edit-memory-tool.js +53 -0
  332. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.d.ts +7 -0
  333. package/dist/infra/cipher/tools/implementations/find-knowledge-topics-tool.js +421 -0
  334. package/dist/infra/cipher/tools/implementations/glob-files-tool.d.ts +18 -0
  335. package/dist/infra/cipher/tools/implementations/glob-files-tool.js +70 -0
  336. package/dist/infra/cipher/tools/implementations/grep-content-tool.d.ts +12 -0
  337. package/dist/infra/cipher/tools/implementations/grep-content-tool.js +77 -0
  338. package/dist/infra/cipher/tools/implementations/kill-process-tool.d.ts +12 -0
  339. package/dist/infra/cipher/tools/implementations/kill-process-tool.js +55 -0
  340. package/dist/infra/cipher/tools/implementations/list-memories-tool.d.ts +12 -0
  341. package/dist/infra/cipher/tools/implementations/list-memories-tool.js +63 -0
  342. package/dist/infra/cipher/tools/implementations/read-file-tool.d.ts +12 -0
  343. package/dist/infra/cipher/tools/implementations/read-file-tool.js +54 -0
  344. package/dist/infra/cipher/tools/implementations/read-memory-tool.d.ts +12 -0
  345. package/dist/infra/cipher/tools/implementations/read-memory-tool.js +39 -0
  346. package/dist/infra/cipher/tools/implementations/search-history-tool.d.ts +10 -0
  347. package/dist/infra/cipher/tools/implementations/search-history-tool.js +36 -0
  348. package/dist/infra/cipher/tools/implementations/write-file-tool.d.ts +12 -0
  349. package/dist/infra/cipher/tools/implementations/write-file-tool.js +52 -0
  350. package/dist/infra/cipher/tools/implementations/write-memory-tool.d.ts +13 -0
  351. package/dist/infra/cipher/tools/implementations/write-memory-tool.js +52 -0
  352. package/dist/infra/cipher/tools/implementations/write-todos-tool.d.ts +10 -0
  353. package/dist/infra/cipher/tools/implementations/write-todos-tool.js +165 -0
  354. package/dist/infra/cipher/tools/index.d.ts +18 -0
  355. package/dist/infra/cipher/tools/index.js +19 -0
  356. package/dist/infra/cipher/tools/policy-engine.d.ts +80 -0
  357. package/dist/infra/cipher/tools/policy-engine.js +110 -0
  358. package/dist/infra/cipher/tools/tool-invocation-queue.d.ts +191 -0
  359. package/dist/infra/cipher/tools/tool-invocation-queue.js +254 -0
  360. package/dist/infra/cipher/tools/tool-invocation.d.ts +216 -0
  361. package/dist/infra/cipher/tools/tool-invocation.js +294 -0
  362. package/dist/infra/cipher/tools/tool-manager.d.ts +135 -0
  363. package/dist/infra/cipher/tools/tool-manager.js +209 -0
  364. package/dist/infra/cipher/tools/tool-markers.d.ts +48 -0
  365. package/dist/infra/cipher/tools/tool-markers.js +49 -0
  366. package/dist/infra/cipher/tools/tool-provider.d.ts +77 -0
  367. package/dist/infra/cipher/tools/tool-provider.js +196 -0
  368. package/dist/infra/cipher/tools/tool-registry.d.ts +52 -0
  369. package/dist/infra/cipher/tools/tool-registry.js +144 -0
  370. package/dist/infra/cipher/tools/utils/schema-converter.d.ts +10 -0
  371. package/dist/infra/cipher/tools/utils/schema-converter.js +29 -0
  372. package/dist/infra/cipher/validation/workspace-validator.d.ts +19 -0
  373. package/dist/infra/cipher/validation/workspace-validator.js +37 -0
  374. package/dist/infra/cipher/watcher/coding-agent-log-watcher.d.ts +14 -0
  375. package/dist/infra/cipher/watcher/coding-agent-log-watcher.js +55 -0
  376. package/dist/infra/cogit/context-tree-to-push-context-mapper.d.ts +21 -0
  377. package/dist/infra/cogit/context-tree-to-push-context-mapper.js +32 -0
  378. package/dist/infra/cogit/http-cogit-pull-service.d.ts +15 -0
  379. package/dist/infra/cogit/http-cogit-pull-service.js +30 -0
  380. package/dist/infra/cogit/http-cogit-push-service.d.ts +17 -0
  381. package/dist/infra/cogit/http-cogit-push-service.js +104 -0
  382. package/dist/infra/config/file-config-store.js +9 -3
  383. package/dist/infra/context-tree/file-context-file-reader.d.ts +14 -0
  384. package/dist/infra/context-tree/file-context-file-reader.js +46 -0
  385. package/dist/infra/context-tree/file-context-tree-service.d.ts +14 -0
  386. package/dist/infra/context-tree/file-context-tree-service.js +46 -0
  387. package/dist/infra/context-tree/file-context-tree-snapshot-service.d.ts +34 -0
  388. package/dist/infra/context-tree/file-context-tree-snapshot-service.js +117 -0
  389. package/dist/infra/context-tree/file-context-tree-writer-service.d.ts +22 -0
  390. package/dist/infra/context-tree/file-context-tree-writer-service.js +61 -0
  391. package/dist/infra/memory/http-memory-retrieval-service.js +2 -1
  392. package/dist/infra/memory/http-memory-storage-service.js +4 -3
  393. package/dist/infra/parsers/clean/clean-claude-service.d.ts +111 -0
  394. package/dist/infra/parsers/clean/clean-claude-service.js +271 -0
  395. package/dist/infra/parsers/clean/clean-codex-service.d.ts +231 -0
  396. package/dist/infra/parsers/clean/clean-codex-service.js +534 -0
  397. package/dist/infra/parsers/clean/clean-copilot-service.d.ts +255 -0
  398. package/dist/infra/parsers/clean/clean-copilot-service.js +729 -0
  399. package/dist/infra/parsers/clean/clean-cursor-service.d.ts +161 -0
  400. package/dist/infra/parsers/clean/clean-cursor-service.js +432 -0
  401. package/dist/infra/parsers/clean/clean-parser-service-factory.d.ts +54 -0
  402. package/dist/infra/parsers/clean/clean-parser-service-factory.js +80 -0
  403. package/dist/infra/parsers/clean/shared.d.ts +84 -0
  404. package/dist/infra/parsers/clean/shared.js +273 -0
  405. package/dist/infra/parsers/raw/raw-claude-service.d.ts +195 -0
  406. package/dist/infra/parsers/raw/raw-claude-service.js +548 -0
  407. package/dist/infra/parsers/raw/raw-codex-service.d.ts +313 -0
  408. package/dist/infra/parsers/raw/raw-codex-service.js +782 -0
  409. package/dist/infra/parsers/raw/raw-copilot-service.d.ts +196 -0
  410. package/dist/infra/parsers/raw/raw-copilot-service.js +558 -0
  411. package/dist/infra/parsers/raw/raw-cursor-service.d.ts +316 -0
  412. package/dist/infra/parsers/raw/raw-cursor-service.js +818 -0
  413. package/dist/infra/parsers/raw/raw-parser-service-factory.d.ts +54 -0
  414. package/dist/infra/parsers/raw/raw-parser-service-factory.js +81 -0
  415. package/dist/infra/space/http-space-service.js +2 -1
  416. package/dist/infra/team/http-team-service.js +2 -1
  417. package/dist/infra/user/http-user-service.js +2 -1
  418. package/dist/infra/watcher/file-watcher-service.d.ts +10 -0
  419. package/dist/infra/watcher/file-watcher-service.js +81 -0
  420. package/dist/infra/workspace/workspace-detector-service.d.ts +60 -0
  421. package/dist/infra/workspace/workspace-detector-service.js +165 -0
  422. package/dist/resources/prompts/curate-context-tree-curation.yml +48 -0
  423. package/dist/resources/prompts/modes/autonomous.yml +9 -0
  424. package/dist/resources/prompts/query-context-tree-retrieval.yml +49 -0
  425. package/dist/resources/prompts/reflection.yml +27 -0
  426. package/dist/resources/prompts/system-prompt.yml +82 -0
  427. package/dist/resources/prompts/tool-outputs.yml +30 -0
  428. package/dist/templates/README.md +6 -7
  429. package/dist/templates/sections/command-reference.md +40 -111
  430. package/dist/templates/sections/workflow.md +3 -30
  431. package/dist/utils/emoji-helpers.d.ts +38 -0
  432. package/dist/utils/emoji-helpers.js +42 -0
  433. package/dist/utils/error-handler.d.ts +51 -0
  434. package/dist/utils/error-handler.js +169 -0
  435. package/dist/utils/error-helpers.d.ts +30 -0
  436. package/dist/utils/error-helpers.js +47 -0
  437. package/dist/utils/file-helpers.d.ts +15 -0
  438. package/dist/utils/file-helpers.js +44 -0
  439. package/dist/utils/oclif-error-helpers.d.ts +40 -0
  440. package/dist/utils/oclif-error-helpers.js +46 -0
  441. package/dist/utils/tool-display-formatter.d.ts +53 -0
  442. package/dist/utils/tool-display-formatter.js +257 -0
  443. package/oclif.manifest.json +381 -141
  444. package/package.json +27 -6
  445. package/dist/commands/add.d.ts +0 -49
  446. package/dist/commands/add.js +0 -192
  447. package/dist/commands/complete.d.ts +0 -108
  448. package/dist/commands/complete.js +0 -340
  449. package/dist/commands/retrieve.d.ts +0 -26
  450. package/dist/commands/retrieve.js +0 -101
  451. package/dist/core/domain/entities/curator-output.d.ts +0 -14
  452. package/dist/core/domain/entities/curator-output.js +0 -23
  453. package/dist/core/domain/entities/delta-batch.d.ts +0 -30
  454. package/dist/core/domain/entities/delta-batch.js +0 -52
  455. package/dist/core/domain/entities/delta-operation.d.ts +0 -31
  456. package/dist/core/domain/entities/delta-operation.js +0 -50
  457. package/dist/core/domain/entities/executor-output.d.ts +0 -27
  458. package/dist/core/domain/entities/executor-output.js +0 -33
  459. package/dist/core/domain/entities/reflector-output.d.ts +0 -38
  460. package/dist/core/domain/entities/reflector-output.js +0 -44
  461. package/dist/core/interfaces/i-ace-prompt-builder.d.ts +0 -48
  462. package/dist/core/interfaces/i-bullet-content-store.d.ts +0 -36
  463. package/dist/core/interfaces/i-delta-store.d.ts +0 -15
  464. package/dist/core/interfaces/i-executor-output-store.d.ts +0 -14
  465. package/dist/core/interfaces/i-playbook-service.d.ts +0 -69
  466. package/dist/core/interfaces/i-playbook-store.d.ts +0 -38
  467. package/dist/core/interfaces/i-reflection-store.d.ts +0 -21
  468. package/dist/infra/ace/ace-file-utils.d.ts +0 -46
  469. package/dist/infra/ace/ace-file-utils.js +0 -83
  470. package/dist/infra/ace/ace-prompt-templates.d.ts +0 -13
  471. package/dist/infra/ace/ace-prompt-templates.js +0 -177
  472. package/dist/infra/ace/file-bullet-content-store.d.ts +0 -27
  473. package/dist/infra/ace/file-bullet-content-store.js +0 -89
  474. package/dist/infra/ace/file-delta-store.d.ts +0 -9
  475. package/dist/infra/ace/file-delta-store.js +0 -26
  476. package/dist/infra/ace/file-executor-output-store.d.ts +0 -9
  477. package/dist/infra/ace/file-executor-output-store.js +0 -26
  478. package/dist/infra/ace/file-playbook-store.d.ts +0 -29
  479. package/dist/infra/ace/file-playbook-store.js +0 -107
  480. package/dist/infra/ace/file-reflection-store.d.ts +0 -10
  481. package/dist/infra/ace/file-reflection-store.js +0 -55
  482. package/dist/infra/playbook/file-playbook-service.d.ts +0 -42
  483. package/dist/infra/playbook/file-playbook-service.js +0 -132
  484. /package/dist/core/{interfaces/i-ace-prompt-builder.js → domain/cipher/blob/types.js} +0 -0
  485. /package/dist/core/{interfaces/i-bullet-content-store.js → domain/cipher/file-system/types.js} +0 -0
  486. /package/dist/core/{interfaces/i-delta-store.js → domain/cipher/process/types.js} +0 -0
  487. /package/dist/core/{interfaces/i-executor-output-store.js → domain/cipher/session/types.js} +0 -0
  488. /package/dist/core/{interfaces/i-playbook-service.js → domain/cipher/storage/history-types.js} +0 -0
  489. /package/dist/core/{interfaces/i-playbook-store.js → domain/cipher/system-prompt/types.js} +0 -0
  490. /package/dist/core/{interfaces/i-reflection-store.js → domain/cipher/tools/types.js} +0 -0
@@ -0,0 +1,818 @@
1
+ /**
2
+ * Cursor IDE Raw Service
3
+ * Consolidates CursorParser + CursorRawParser + Enhanced Bubble Extraction
4
+ * Parses Cursor IDE chat sessions from local storage and workspace data
5
+ */
6
+ import Database from 'better-sqlite3';
7
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
8
+ import { basename, dirname, join } from 'node:path';
9
+ // ============================================================================
10
+ // CONSTANTS
11
+ // ============================================================================
12
+ // Database file paths
13
+ const WORKSPACE_DB_FILE = 'state.vscdb';
14
+ const GLOBAL_STORAGE_DB_PATH = '../globalStorage/state.vscdb';
15
+ // Database query patterns
16
+ const COMPOSER_DATA_KEY = 'composer.composerData';
17
+ const BUBBLE_ID_KEY_PATTERN = 'bubbleId:%';
18
+ const CODE_BLOCK_DIFF_KEY_PATTERN = 'codeBlockDiff:%';
19
+ const CHECKPOINT_ID_KEY_PATTERN = 'checkpointId:%';
20
+ const MESSAGE_REQUEST_CONTEXT_KEY_PATTERN = 'messageRequestContext:%';
21
+ const COMPOSER_DATA_KEY_PATTERN = 'composerData:%';
22
+ const FULL_CONVERSATION_HEADERS_PATTERN = '%fullConversationHeadersOnly%';
23
+ // Database queries
24
+ const SQL_QUERIES = {
25
+ BUBBLE_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${BUBBLE_ID_KEY_PATTERN}'`,
26
+ CHECKPOINT_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${CHECKPOINT_ID_KEY_PATTERN}'`,
27
+ CODE_BLOCK_DIFF_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${CODE_BLOCK_DIFF_KEY_PATTERN}'`,
28
+ COMPOSER_DATA: `SELECT value FROM ItemTable WHERE key = '${COMPOSER_DATA_KEY}'`,
29
+ COMPOSER_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${COMPOSER_DATA_KEY_PATTERN}' AND value LIKE '${FULL_CONVERSATION_HEADERS_PATTERN}'`,
30
+ MESSAGE_REQUEST_CONTEXT_ROWS: `SELECT key, value FROM cursorDiskKV WHERE key LIKE '${MESSAGE_REQUEST_CONTEXT_KEY_PATTERN}'`,
31
+ };
32
+ // Regex patterns
33
+ const PATTERNS = {
34
+ CODE_BLOCK_DIFF_KEY: /^codeBlockDiff:([^:]+):/,
35
+ };
36
+ // Magic numbers
37
+ const HEADER_TYPE_USER = 1;
38
+ const FLOAT_PRECISION = 2;
39
+ // Default values
40
+ const DEFAULT_CONTEXT_ID = 'default';
41
+ const COMPOSER_ID_PREVIEW_LENGTH = 8;
42
+ // ============================================================================
43
+ // CURSOR RAW SERVICE - Orchestration + File I/O
44
+ // ============================================================================
45
+ /**
46
+ * Cursor Raw Service
47
+ * Handles extraction of Cursor sessions from both exported files and raw storage
48
+ *
49
+ * Method Organization:
50
+ * - Constructor
51
+ * - Public Methods: parse(), parseFromDirectory()
52
+ * - Private Workspace Methods: loadWorkspaceComposers(), extractChatIdFromCodeBlockDiffKey()
53
+ * - Private Helper Methods (Bubble Extraction): createEnhancedBubble(), and extraction methods
54
+ * - Private Utility Methods: safeParseJSON()
55
+ */
56
+ export class CursorRawService {
57
+ ide;
58
+ // ============================================================================
59
+ // CONSTRUCTOR
60
+ // ============================================================================
61
+ /**
62
+ * Initialize Cursor Raw Service
63
+ *
64
+ * @param ide - The IDE type (Cursor)
65
+ */
66
+ constructor(ide) {
67
+ this.ide = ide;
68
+ }
69
+ // ============================================================================
70
+ // PUBLIC METHODS
71
+ // ============================================================================
72
+ /**
73
+ * Main entry point - Parse Cursor IDE sessions from a custom directory
74
+ *
75
+ * Parses Cursor IDE chat sessions from workspace storage and exports to JSON files.
76
+ * Handles extraction from database files and raw workspace data structures.
77
+ *
78
+ * @param customDir - Path to directory containing Cursor session data
79
+ * @param outputDir - Optional output directory (defaults to process.cwd()/.brv/logs/{ide}/raw)
80
+ * @returns Promise resolving to true if parsing succeeded, false otherwise
81
+ */
82
+ async parse(customDir, outputDir) {
83
+ try {
84
+ return this.parseFromDirectory(customDir, outputDir);
85
+ }
86
+ catch (error) {
87
+ console.error('❌ Error during parsing:', error);
88
+ throw error;
89
+ }
90
+ }
91
+ // ============================================================================
92
+ // PRIVATE WORKSPACE METHODS
93
+ // ============================================================================
94
+ /**
95
+ * Parse Cursor IDE sessions from a workspace directory
96
+ *
97
+ * Handles extraction of chat sessions from Cursor's database and storage structures.
98
+ * Processes bubbles, composer data, and other session metadata to create normalized
99
+ * session files. Exports results to workspace-specific output directory.
100
+ *
101
+ * @param customDir - Path to workspace directory containing Cursor session data
102
+ * @param outputDir - Optional output directory (defaults to process.cwd()/.brv/logs/{ide}/raw)
103
+ * @returns Promise resolving to true if parsing succeeded, false otherwise
104
+ */
105
+ async parseFromDirectory(customDir, outputDir) {
106
+ const baseOutputDir = outputDir || join(process.cwd(), `.brv/logs/${this.ide}/raw`);
107
+ console.log('🔍 Starting Cursor conversation parsing...');
108
+ console.log(`📁 Custom directory: ${customDir}`);
109
+ const workspacePath = customDir;
110
+ const workspaceHash = basename(customDir);
111
+ const workspaceDir = join(baseOutputDir, workspaceHash);
112
+ if (!existsSync(workspaceDir)) {
113
+ mkdirSync(workspaceDir, { recursive: true });
114
+ }
115
+ // Use global database to read all conversations
116
+ const dbPath = join(dirname(customDir), GLOBAL_STORAGE_DB_PATH);
117
+ if (!existsSync(dbPath)) {
118
+ console.error(`❌ Database not found at ${dbPath}`);
119
+ return false;
120
+ }
121
+ let db = null;
122
+ try {
123
+ console.log('\n🔍 Loading workspace-specific composers...');
124
+ const workspaceComposers = this.loadWorkspaceComposers(customDir);
125
+ if (workspaceComposers.size === 0) {
126
+ console.log('⚠️ No workspace-specific composers found. This workspace may not have any conversations.');
127
+ }
128
+ db = new Database(dbPath, { readonly: true });
129
+ // Load all required data from database
130
+ const { bubbleMap, bubbleWorkspaceMap } = this.loadBubbles(db);
131
+ const codeBlockDiffMap = this.loadCodeBlockDiffs(db);
132
+ const checkpointMap = this.loadCheckpoints(db);
133
+ const messageRequestContextMap = this.loadMessageContext(db);
134
+ // Process conversations and export
135
+ const allConversations = this.processConversations(db, workspacePath, workspaceComposers, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
136
+ // Export conversations to files
137
+ this.exportConversations(allConversations, workspaceDir, workspaceHash, baseOutputDir);
138
+ console.log(`\n🎉 Complete! Conversations exported to: ${baseOutputDir}`);
139
+ return true;
140
+ }
141
+ catch (error) {
142
+ const err = error;
143
+ console.error('❌ Error during parsing:', err);
144
+ throw err;
145
+ }
146
+ finally {
147
+ if (db) {
148
+ db.close();
149
+ }
150
+ }
151
+ }
152
+ /**
153
+ * Create an enhanced chat bubble with all extracted metadata and context
154
+ *
155
+ * Consolidates raw Cursor bubble data with associated tool results, console logs,
156
+ * context information, code diffs, file checkpoints, and code blocks into a single
157
+ * enhanced bubble structure. Extracts optional data from maps if available.
158
+ *
159
+ * @param type - Message type: 'ai' for assistant messages or 'user' for user messages
160
+ * @param text - Raw message text content from the bubble
161
+ * @param timestamp - Unix timestamp in milliseconds when the bubble was created
162
+ * @param bubble - Raw Cursor bubble object containing base message data
163
+ * @param bubbleId - Unique identifier for this bubble, used to look up associated data
164
+ * @param messageContextMap - Optional map of bubble IDs to RawCursorMessageRequestContext arrays
165
+ * @param codeBlockDiffMap - Optional map of bubble IDs to RawCursorCodeDiff arrays
166
+ * @param checkpointMap - Optional map of bubble IDs to RawCursorFileCheckpoint data
167
+ * @returns Enhanced bubble with all extracted metadata and context information
168
+ */
169
+ // eslint-disable-next-line max-params
170
+ createEnhancedBubble(type, text, timestamp, bubble, bubbleId, messageContextMap, codeBlockDiffMap, checkpointMap) {
171
+ const enhanced = {
172
+ text,
173
+ timestamp,
174
+ type,
175
+ };
176
+ // Extract tool results
177
+ const toolResults = this.extractToolResults(bubble);
178
+ if (toolResults) {
179
+ enhanced.toolResults = toolResults;
180
+ }
181
+ // Extract console logs
182
+ const consoleLogs = this.extractConsoleLogs(bubble);
183
+ if (consoleLogs) {
184
+ enhanced.consoleLogs = consoleLogs;
185
+ }
186
+ // Extract context information
187
+ const context = this.extractContextInfo(bubble, messageContextMap, bubbleId);
188
+ if (context) {
189
+ enhanced.context = context;
190
+ }
191
+ // Extract code diffs (if this bubble is associated with diffs)
192
+ const codeDiffs = this.extractCodeDiffs(bubbleId, codeBlockDiffMap);
193
+ if (codeDiffs) {
194
+ enhanced.codeDiffs = codeDiffs;
195
+ }
196
+ // Extract file checkpoint
197
+ const fileCheckpoint = this.extractFileCheckpoint(bubbleId, checkpointMap);
198
+ if (fileCheckpoint) {
199
+ enhanced.fileCheckpoint = fileCheckpoint;
200
+ }
201
+ // Extract code blocks
202
+ const codeBlocks = this.extractCodeBlocks(bubble);
203
+ if (codeBlocks) {
204
+ enhanced.codeBlocks = codeBlocks;
205
+ }
206
+ return enhanced;
207
+ }
208
+ /**
209
+ * Export parsed conversations to JSON files in workspace-specific output directory
210
+ *
211
+ * Writes each conversation to a separate JSON file named by composer ID, containing
212
+ * bubbles, metadata (id, timestamp, title), workspace hash, and workspace paths.
213
+ * Logs file sizes in KB and exports all conversations with structured formatting.
214
+ *
215
+ * @param allConversations - Array of conversation objects with bubbles and metadata
216
+ * @param workspaceDir - Path to workspace directory for output files
217
+ * @param workspaceHash - Unique hash identifier for the workspace
218
+ * @param _outputDir - Root output directory (used for logging reference)
219
+ */
220
+ exportConversations(allConversations, workspaceDir, workspaceHash, _outputDir) {
221
+ console.log('\n💾 Exporting conversations...');
222
+ console.log(`\n 📂 Workspace folder (${workspaceHash})`);
223
+ for (const conversation of allConversations) {
224
+ const filename = `${conversation.composerId}.json`;
225
+ const filepath = join(workspaceDir, filename);
226
+ const data = {
227
+ bubbles: conversation.bubbles,
228
+ id: conversation.composerId,
229
+ timestamp: conversation.timestamp,
230
+ title: conversation.name,
231
+ workspaceHash,
232
+ workspacePath: conversation.workspacePath,
233
+ };
234
+ writeFileSync(filepath, JSON.stringify(data, null, 2));
235
+ const fileSize = readFileSync(filepath).length;
236
+ const fileSizeKb = (fileSize / 1024).toFixed(FLOAT_PRECISION);
237
+ console.log(` ✅ ${conversation.name} (${fileSizeKb} KB)`);
238
+ }
239
+ }
240
+ /**
241
+ * Extract the composer ID from a code block diff database key
242
+ *
243
+ * Parses the database key pattern "codeBlockDiff:chatId:diffId" to extract
244
+ * the chat/composer ID using regex pattern matching. Returns null if key format
245
+ * doesn't match expected pattern.
246
+ *
247
+ * @param key - Database key string in format "codeBlockDiff:chatId:diffId"
248
+ * @returns The extracted composer/chat ID, or null if pattern doesn't match
249
+ */
250
+ extractChatIdFromCodeBlockDiffKey(key) {
251
+ const match = key.match(PATTERNS.CODE_BLOCK_DIFF_KEY);
252
+ return match ? match[1] : null;
253
+ }
254
+ /**
255
+ * Extract code blocks from a Cursor bubble's codeBlocks object
256
+ *
257
+ * Retrieves the code blocks map from a bubble if it exists and is non-empty.
258
+ * Code blocks are stored as key-value pairs where keys are block IDs and values
259
+ * are the code content strings. Returns undefined if bubble has no code blocks,
260
+ * codeBlocks property is not an object, or the object is empty.
261
+ *
262
+ * @param bubble - The raw Cursor bubble object to extract code blocks from
263
+ * @returns Object mapping code block IDs to code content strings, or undefined if none exist
264
+ */
265
+ extractCodeBlocks(bubble) {
266
+ if (bubble.codeBlocks &&
267
+ typeof bubble.codeBlocks === 'object' &&
268
+ Object.keys(bubble.codeBlocks).length > 0) {
269
+ return bubble.codeBlocks;
270
+ }
271
+ return undefined;
272
+ }
273
+ /**
274
+ * Extract code diffs associated with a specific bubble from the code block diff map
275
+ *
276
+ * Looks up code diffs for the given bubble ID in the codeBlockDiffMap. Code diffs
277
+ * represent changes made to files during the conversation, containing both the original
278
+ * and new versions relative to a base version (v0). Returns undefined if the map is
279
+ * unavailable, the bubble has no associated diffs, or the diffs array is empty.
280
+ * Normalizes diff objects to ensure all required fields (diffId, filePath,
281
+ * newModelDiffWrtV0, originalModelDiffWrtV0) are present, using empty string for missing diffId.
282
+ *
283
+ * @param bubbleId - Unique identifier of the bubble to look up diffs for
284
+ * @param codeBlockDiffMap - Optional map of bubble IDs to RawCursorCodeDiff arrays
285
+ * @returns Array of normalized RawCursorCodeDiff objects with all required fields, or undefined if none exist
286
+ */
287
+ extractCodeDiffs(bubbleId, codeBlockDiffMap) {
288
+ if (!codeBlockDiffMap) {
289
+ return undefined;
290
+ }
291
+ const diffs = codeBlockDiffMap[bubbleId];
292
+ if (!diffs || !Array.isArray(diffs) || diffs.length === 0) {
293
+ return undefined;
294
+ }
295
+ return diffs.map((diff) => ({
296
+ diffId: diff.diffId || '',
297
+ filePath: diff.filePath,
298
+ newModelDiffWrtV0: diff.newModelDiffWrtV0,
299
+ originalModelDiffWrtV0: diff.originalModelDiffWrtV0,
300
+ }));
301
+ }
302
+ /**
303
+ * Extract console logs from a Cursor bubble's consoleLogs array
304
+ *
305
+ * Retrieves the console logs array from a bubble if it exists and contains entries.
306
+ * Console logs capture terminal or debug output associated with a conversation turn.
307
+ * Returns undefined if the bubble has no console logs, consoleLogs property is not an array,
308
+ * or the array is empty. Used to preserve terminal/console output context in enhanced bubbles.
309
+ *
310
+ * @param bubble - The raw Cursor bubble object to extract console logs from
311
+ * @returns Array of console log strings, or undefined if none exist
312
+ */
313
+ extractConsoleLogs(bubble) {
314
+ if (bubble.consoleLogs &&
315
+ Array.isArray(bubble.consoleLogs) &&
316
+ bubble.consoleLogs.length > 0) {
317
+ return bubble.consoleLogs;
318
+ }
319
+ return undefined;
320
+ }
321
+ /**
322
+ * Extract and consolidate context information from bubble and message context map
323
+ *
324
+ * Consolidates context data from two sources to create a comprehensive view of the
325
+ * conversation context:
326
+ * 1. Direct bubble properties: attachedFoldersListDirResults, cursorRules
327
+ * 2. Message context map data: gitStatus, knowledgeItems, todos, deletedFiles, terminalFiles
328
+ *
329
+ * When both sources provide the same field, preference is given to the message context map
330
+ * data as it tends to be more complete. Returns undefined if no context data is found from
331
+ * either source. The consolidated context helps understand the environment and state during
332
+ * the conversation turn.
333
+ *
334
+ * @param bubble - The raw Cursor bubble object with inline context data
335
+ * @param messageContextMap - Optional map of bubble IDs to RawCursorMessageRequestContext arrays
336
+ * @param bubbleId - Optional bubble ID to look up context in messageContextMap
337
+ * @returns RawCursorContextInfo object with consolidated context data, or undefined if no data found
338
+ */
339
+ extractContextInfo(bubble, messageContextMap, bubbleId) {
340
+ const context = {};
341
+ let hasData = false;
342
+ // From bubble itself
343
+ if (bubble.attachedFoldersListDirResults) {
344
+ context.attachedFoldersListDirResults = bubble.attachedFoldersListDirResults;
345
+ hasData = true;
346
+ }
347
+ if (bubble.cursorRules && Array.isArray(bubble.cursorRules)) {
348
+ context.cursorRules = bubble.cursorRules;
349
+ hasData = true;
350
+ }
351
+ // From message request context if available
352
+ if (messageContextMap && bubbleId) {
353
+ const contexts = messageContextMap[bubbleId];
354
+ if (contexts && Array.isArray(contexts) && contexts.length > 0) {
355
+ const msgContext = contexts[0];
356
+ if (msgContext.gitStatusRaw) {
357
+ context.gitStatus = msgContext.gitStatusRaw;
358
+ hasData = true;
359
+ }
360
+ if (msgContext.attachedFoldersListDirResults) {
361
+ context.attachedFoldersListDirResults = msgContext.attachedFoldersListDirResults;
362
+ hasData = true;
363
+ }
364
+ if (msgContext.cursorRules) {
365
+ context.cursorRules = msgContext.cursorRules;
366
+ hasData = true;
367
+ }
368
+ if (msgContext.terminalFiles) {
369
+ context.terminalFiles = msgContext.terminalFiles;
370
+ hasData = true;
371
+ }
372
+ if (msgContext.knowledgeItems) {
373
+ context.knowledgeItems = msgContext.knowledgeItems;
374
+ hasData = true;
375
+ }
376
+ if (msgContext.todos) {
377
+ context.todos = msgContext.todos;
378
+ hasData = true;
379
+ }
380
+ if (msgContext.deletedFiles) {
381
+ context.deletedFiles = msgContext.deletedFiles;
382
+ hasData = true;
383
+ }
384
+ }
385
+ }
386
+ return hasData ? context : undefined;
387
+ }
388
+ /**
389
+ * Extract file checkpoint state associated with a bubble from the checkpoint map
390
+ *
391
+ * Looks up the file checkpoint for a given bubble ID in the checkpoint map. File checkpoints
392
+ * capture the state of the file system at a particular conversation turn, including which files
393
+ * existed, were newly created, or were non-existent, as well as active inline diff information.
394
+ * Returns undefined if the map is unavailable or the bubble has no associated checkpoint.
395
+ *
396
+ * Normalizes the checkpoint object to ensure all array fields (files, newlyCreatedFolders,
397
+ * nonExistentFiles, activeInlineDiffs) are present, using empty arrays as defaults if not found.
398
+ * This normalization ensures consistent structure for downstream processing. The checkpointId
399
+ * field is intentionally excluded from the returned object.
400
+ *
401
+ * @param bubbleId - Unique identifier of the bubble to look up checkpoint for
402
+ * @param checkpointMap - Optional map of bubble IDs to RawCursorFileCheckpoint objects with checkpointId
403
+ * @returns Normalized RawCursorFileCheckpoint object with all required array fields, or undefined if none exists
404
+ */
405
+ extractFileCheckpoint(bubbleId, checkpointMap) {
406
+ if (!checkpointMap || !checkpointMap[bubbleId]) {
407
+ return undefined;
408
+ }
409
+ const checkpoint = checkpointMap[bubbleId];
410
+ return {
411
+ activeInlineDiffs: checkpoint.activeInlineDiffs || [],
412
+ files: checkpoint.files || [],
413
+ inlineDiffNewlyCreatedResources: checkpoint.inlineDiffNewlyCreatedResources,
414
+ newlyCreatedFolders: checkpoint.newlyCreatedFolders || [],
415
+ nonExistentFiles: checkpoint.nonExistentFiles || [],
416
+ };
417
+ }
418
+ /**
419
+ * Extract tool execution results from a bubble's toolFormerData object
420
+ *
421
+ * Parses tool execution metadata from the bubble, including tool name, status,
422
+ * parameters, results, and additional context. Returns undefined if bubble has no
423
+ * toolFormerData or is missing required fields (name, status). Safely parses JSON
424
+ * strings for params, rawArgs, and result fields that may contain serialized data.
425
+ *
426
+ * @param bubble - The raw Cursor bubble object containing tool execution data
427
+ * @returns RawCursorToolResult object with execution details, or undefined if no valid tool data
428
+ */
429
+ extractToolResults(bubble) {
430
+ if (!bubble.toolFormerData || typeof bubble.toolFormerData !== 'object') {
431
+ return undefined;
432
+ }
433
+ const tool = bubble.toolFormerData;
434
+ // Only return if it has the required fields for a valid tool result
435
+ if (tool.name && tool.status) {
436
+ return {
437
+ additionalData: tool.additionalData,
438
+ modelCallId: tool.modelCallId || '',
439
+ name: tool.name,
440
+ params: this.safeParseJSON(tool.params) || {},
441
+ rawArgs: this.safeParseJSON(tool.rawArgs) || {},
442
+ result: this.safeParseJSON(tool.result) || {},
443
+ status: tool.status,
444
+ tool: tool.tool || 0,
445
+ toolCallId: tool.toolCallId || '',
446
+ toolIndex: tool.toolIndex || 0,
447
+ };
448
+ }
449
+ return undefined;
450
+ }
451
+ /**
452
+ * Load all bubbles from the database and build indexed maps
453
+ *
454
+ * Queries the database for all bubble entries matching the bubble ID pattern,
455
+ * parses JSON values, and builds maps for fast lookups. Creates bubble-to-workspace
456
+ * mapping and tracks unique workspace hashes. Skips invalid or unparseable entries.
457
+ *
458
+ * @param db - Better-sqlite3 database instance with cursorDiskKV table
459
+ * @returns Object containing: bubbleMap (ID -> bubble), bubbleWorkspaceMap (ID -> workspace hash), uniqueWorkspaces set
460
+ */
461
+ loadBubbles(db) {
462
+ console.log('\n📝 Loading bubbles...');
463
+ const bubbleMap = {};
464
+ const bubbleWorkspaceMap = {};
465
+ const bubblesByWorkspace = {};
466
+ const bubbleRows = db.prepare(SQL_QUERIES.BUBBLE_ROWS).all();
467
+ for (const rowUntyped of bubbleRows) {
468
+ const row = rowUntyped;
469
+ const keyParts = row.key.split(':');
470
+ const bubbleWorkspaceHash = keyParts[1];
471
+ const bubbleId = keyParts[2];
472
+ try {
473
+ const bubble = JSON.parse(row.value);
474
+ if (!bubble || typeof bubble !== 'object')
475
+ continue;
476
+ bubbleMap[bubbleId] = bubble;
477
+ bubbleWorkspaceMap[bubbleId] = bubbleWorkspaceHash;
478
+ if (!bubblesByWorkspace[bubbleWorkspaceHash]) {
479
+ bubblesByWorkspace[bubbleWorkspaceHash] = new Set();
480
+ }
481
+ bubblesByWorkspace[bubbleWorkspaceHash].add(bubbleId);
482
+ }
483
+ catch {
484
+ // Skip parse errors
485
+ }
486
+ }
487
+ const uniqueWorkspaces = new Set(Object.values(bubbleWorkspaceMap));
488
+ console.log(`✅ Loaded ${Object.keys(bubbleMap).length} total bubbles from ${uniqueWorkspaces.size} workspace(s)`);
489
+ return { bubbleMap, bubbleWorkspaceMap, uniqueWorkspaces };
490
+ }
491
+ /**
492
+ * Load all file checkpoints from the database and build indexed map
493
+ *
494
+ * Queries the database for all checkpoint entries matching the checkpoint ID pattern,
495
+ * parses JSON values, and builds a map for fast lookups. Handles multiple checkpoints
496
+ * per composer by keeping the latest based on checkpoint ID string comparison.
497
+ * Skips invalid or unparseable entries.
498
+ *
499
+ * @param db - Better-sqlite3 database instance with cursorDiskKV table
500
+ * @returns Map of composer IDs to their RawCursorFileCheckpoint objects with checkpointId field
501
+ */
502
+ loadCheckpoints(db) {
503
+ console.log('📝 Loading checkpoints...');
504
+ const checkpointMap = {};
505
+ const checkpointRows = db.prepare(SQL_QUERIES.CHECKPOINT_ROWS).all();
506
+ for (const rowUntyped of checkpointRows) {
507
+ const row = rowUntyped;
508
+ const parts = row.key.split(':');
509
+ if (parts.length < 3)
510
+ continue;
511
+ const composerId = parts[1];
512
+ const checkpointId = parts[2];
513
+ try {
514
+ const checkpoint = JSON.parse(row.value);
515
+ if (!checkpointMap[composerId] || checkpointId > (checkpointMap[composerId].checkpointId || '')) {
516
+ checkpointMap[composerId] = {
517
+ ...checkpoint,
518
+ checkpointId,
519
+ };
520
+ }
521
+ }
522
+ catch {
523
+ // Skip parse errors
524
+ }
525
+ }
526
+ console.log(`✅ Loaded checkpoints`);
527
+ return checkpointMap;
528
+ }
529
+ /**
530
+ * Load all code block diffs from the database and build indexed map
531
+ *
532
+ * Queries the database for all code block diff entries, extracts chat/composer IDs
533
+ * from keys, parses JSON values, and groups diffs by composer ID. Each diff includes
534
+ * the diffId extracted from the database key. Skips invalid or unparseable entries.
535
+ *
536
+ * @param db - Better-sqlite3 database instance with cursorDiskKV table
537
+ * @returns Map of composer IDs to arrays of RawCursorCodeDiff objects with diffId field
538
+ */
539
+ loadCodeBlockDiffs(db) {
540
+ console.log('📝 Loading code diffs...');
541
+ const codeBlockDiffMap = {};
542
+ const codeBlockDiffRows = db.prepare(SQL_QUERIES.CODE_BLOCK_DIFF_ROWS).all();
543
+ for (const rowUntyped of codeBlockDiffRows) {
544
+ const row = rowUntyped;
545
+ const chatId = this.extractChatIdFromCodeBlockDiffKey(row.key);
546
+ if (!chatId)
547
+ continue;
548
+ try {
549
+ const codeBlockDiff = JSON.parse(row.value);
550
+ if (!codeBlockDiffMap[chatId])
551
+ codeBlockDiffMap[chatId] = [];
552
+ codeBlockDiffMap[chatId].push({
553
+ ...codeBlockDiff,
554
+ diffId: row.key.split(':')[2],
555
+ });
556
+ }
557
+ catch {
558
+ // Skip parse errors
559
+ }
560
+ }
561
+ console.log(`✅ Loaded ${Object.keys(codeBlockDiffMap).length} diff groups`);
562
+ return codeBlockDiffMap;
563
+ }
564
+ /**
565
+ * Load all message request context from the database and build indexed map
566
+ *
567
+ * Queries the database for all message request context entries, parses JSON values,
568
+ * and groups contexts by composer ID. Extracts context ID from key parts or uses
569
+ * default context ID if not present. Skips invalid or unparseable entries and keys
570
+ * with insufficient format.
571
+ *
572
+ * @param db - Better-sqlite3 database instance with cursorDiskKV table
573
+ * @returns Map of composer IDs to arrays of RawCursorMessageRequestContext objects with contextId field
574
+ */
575
+ loadMessageContext(db) {
576
+ console.log('📝 Loading message context...');
577
+ const messageRequestContextMap = {};
578
+ const messageRequestContextRows = db.prepare(SQL_QUERIES.MESSAGE_REQUEST_CONTEXT_ROWS).all();
579
+ for (const rowUntyped of messageRequestContextRows) {
580
+ const row = rowUntyped;
581
+ const parts = row.key.split(':');
582
+ if (parts.length < 2)
583
+ continue;
584
+ const composerId = parts[1];
585
+ const contextId = parts.length >= 3 ? parts[2] : DEFAULT_CONTEXT_ID;
586
+ try {
587
+ const context = JSON.parse(row.value);
588
+ if (!messageRequestContextMap[composerId])
589
+ messageRequestContextMap[composerId] = [];
590
+ messageRequestContextMap[composerId].push({
591
+ ...context,
592
+ bubbleId: context.bubbleId,
593
+ contextId,
594
+ });
595
+ }
596
+ catch {
597
+ // Skip parse errors
598
+ }
599
+ }
600
+ console.log(`✅ Loaded context for ${Object.keys(messageRequestContextMap).length} composers`);
601
+ return messageRequestContextMap;
602
+ }
603
+ /**
604
+ * Load composer IDs that are specific to a workspace
605
+ *
606
+ * Reads the workspace's state.vscdb database, extracts composer data from the
607
+ * ItemTable, and builds a set of composer IDs that belong to this workspace.
608
+ * Returns empty set if database or composer data is not found. Logs warnings
609
+ * if database or data is unavailable.
610
+ *
611
+ * @param workspacePath - Path to the workspace directory containing state.vscdb
612
+ * @returns Set of composer IDs that belong to this workspace
613
+ */
614
+ loadWorkspaceComposers(workspacePath) {
615
+ const workspaceComposers = new Set();
616
+ try {
617
+ const workspaceDbPath = join(workspacePath, WORKSPACE_DB_FILE);
618
+ if (!existsSync(workspaceDbPath)) {
619
+ console.log(`⚠️ Workspace database not found at ${workspaceDbPath}`);
620
+ return workspaceComposers;
621
+ }
622
+ const wsDb = new Database(workspaceDbPath, { readonly: true });
623
+ try {
624
+ const result = wsDb
625
+ .prepare(SQL_QUERIES.COMPOSER_DATA)
626
+ .get();
627
+ if (!result || !result.value) {
628
+ console.log('⚠️ No composer data found in workspace ItemTable');
629
+ return workspaceComposers;
630
+ }
631
+ const composerData = JSON.parse(result.value.toString());
632
+ const allComposers = composerData.allComposers || [];
633
+ for (const composer of allComposers) {
634
+ const composerData = composer;
635
+ if (composerData.composerId) {
636
+ workspaceComposers.add(composerData.composerId);
637
+ }
638
+ }
639
+ console.log(`✅ Loaded ${workspaceComposers.size} workspace-specific composers from ItemTable`);
640
+ }
641
+ finally {
642
+ wsDb.close();
643
+ }
644
+ }
645
+ catch (error) {
646
+ console.log(`⚠️ Could not load workspace composers:`, error instanceof Error ? error.message : String(error));
647
+ }
648
+ return workspaceComposers;
649
+ }
650
+ /**
651
+ * Log parsing statistics for processed conversations
652
+ *
653
+ * Outputs summary information about conversation parsing results, including both successful
654
+ * parses and various skip conditions. Helps users understand why certain conversations were
655
+ * not included in the output. The function displays:
656
+ * - Total successfully parsed conversations
657
+ * - Conversations skipped because they don't belong to this workspace
658
+ * - Conversations skipped due to having no extractable bubbles (empty conversations)
659
+ * - Conversations skipped due to missing conversation headers (malformed data)
660
+ *
661
+ * Omits zero-count skip reasons from output for cleaner, more focused logging that only
662
+ * shows relevant information.
663
+ *
664
+ * @param parsed - Number of successfully parsed conversations
665
+ * @param skippedNotInWorkspace - Number of conversations skipped (not in this workspace)
666
+ * @param skippedNoBubbles - Number of conversations skipped (no extractable bubbles)
667
+ * @param skippedNoHeaders - Number of conversations skipped (no conversation headers)
668
+ */
669
+ logConversationStats(parsed, skippedNotInWorkspace, skippedNoBubbles, skippedNoHeaders) {
670
+ console.log(`\n✅ Parsed ${parsed} conversations`);
671
+ if (skippedNotInWorkspace > 0) {
672
+ console.log(`⚠️ Skipped ${skippedNotInWorkspace} conversations not in this workspace`);
673
+ }
674
+ if (skippedNoBubbles > 0) {
675
+ console.log(`⚠️ Skipped ${skippedNoBubbles} conversations with no extractable bubbles`);
676
+ }
677
+ if (skippedNoHeaders > 0) {
678
+ console.log(`⚠️ Skipped ${skippedNoHeaders} conversations with no headers`);
679
+ }
680
+ }
681
+ /**
682
+ * Process conversation headers and create enhanced bubbles from raw data
683
+ *
684
+ * This is a core transformation function that converts raw Cursor conversation headers and
685
+ * bubble data into enriched, enhanced bubble objects ready for export. The function:
686
+ * 1. Iterates through conversation headers (which contain bubble IDs and message types)
687
+ * 2. Looks up corresponding raw bubbles by ID in the bubbleMap
688
+ * 3. Determines message type (user vs assistant) based on header type field
689
+ * 4. Creates enhanced bubbles by extracting and consolidating metadata from multiple sources:
690
+ * - Tool results, console logs, code blocks from the bubble itself
691
+ * - Context information from messageRequestContextMap
692
+ * - Code diffs from codeBlockDiffMap
693
+ * - File checkpoints from checkpointMap
694
+ * 5. Filters out empty bubbles (no text, tool results, or console logs) to keep only meaningful content
695
+ * 6. Tracks unique workspace hashes that bubbles belong to for workspace association
696
+ *
697
+ * This process enriches basic bubble data with all available context and metadata, creating
698
+ * a comprehensive representation of each conversation turn.
699
+ *
700
+ * @param conversationHeaders - Array of header objects containing bubble IDs and types (1=user, other=ai)
701
+ * @param bubbleMap - Map of bubble IDs to raw RawCursorBubbleRaw objects
702
+ * @param bubbleWorkspaceMap - Map of bubble IDs to their workspace hash identifiers
703
+ * @param messageRequestContextMap - Map of bubble IDs to RawCursorMessageRequestContext arrays
704
+ * @param codeBlockDiffMap - Map of bubble IDs to RawCursorCodeDiff arrays
705
+ * @param checkpointMap - Map of bubble IDs to RawCursorFileCheckpoint objects with checkpointId
706
+ * @returns Object containing enhanced bubbles array and set of workspace hashes used by these bubbles
707
+ */
708
+ // eslint-disable-next-line max-params
709
+ processBubbleHeaders(conversationHeaders, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap) {
710
+ const bubbles = [];
711
+ const usedWorkspaces = new Set();
712
+ for (const header of conversationHeaders) {
713
+ const bubbleId = header.bubbleId;
714
+ const bubble = bubbleMap?.[bubbleId];
715
+ if (!bubble)
716
+ continue;
717
+ const bubbleWs = bubbleWorkspaceMap[bubbleId];
718
+ if (bubbleWs) {
719
+ usedWorkspaces.add(bubbleWs);
720
+ }
721
+ const isUser = header.type === HEADER_TYPE_USER;
722
+ const messageType = isUser ? 'user' : 'ai';
723
+ const text = bubble.text?.trim() || '';
724
+ const enhancedBubble = this.createEnhancedBubble(messageType, text, bubble.timestamp || Date.now(), bubble, bubbleId, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
725
+ if (enhancedBubble.text.trim() || enhancedBubble.toolResults || enhancedBubble.consoleLogs) {
726
+ bubbles.push(enhancedBubble);
727
+ }
728
+ }
729
+ return { bubbles, usedWorkspaces };
730
+ }
731
+ /**
732
+ * Load and process all conversations from the database for a specific workspace
733
+ *
734
+ * Queries the database for all composer conversation data, filters to workspace-specific
735
+ * composers, parses each conversation's headers, creates enhanced bubbles, and returns
736
+ * conversation objects with metadata. Tracks and logs statistics on parsed vs skipped
737
+ * conversations (not in workspace, no headers, no extractable bubbles).
738
+ *
739
+ * @param db - Better-sqlite3 database instance
740
+ * @param workspacePath - Path to the workspace directory
741
+ * @param workspaceComposers - Set of composer IDs belonging to this workspace
742
+ * @param bubbleMap - Map of bubble IDs to raw RawCursorBubbleRaw objects
743
+ * @param bubbleWorkspaceMap - Map of bubble IDs to their workspace hashes
744
+ * @param messageRequestContextMap - Map of bubble IDs to RawCursorMessageRequestContext arrays
745
+ * @param codeBlockDiffMap - Map of bubble IDs to RawCursorCodeDiff arrays
746
+ * @param checkpointMap - Map of bubble IDs to RawCursorFileCheckpoint objects
747
+ * @returns Array of conversation objects with bubbles and metadata
748
+ */
749
+ // eslint-disable-next-line max-params
750
+ processConversations(db, workspacePath, workspaceComposers, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap) {
751
+ console.log('📝 Loading conversations...');
752
+ const composerRows = db.prepare(SQL_QUERIES.COMPOSER_ROWS).all();
753
+ console.log(`📊 Found ${composerRows.length} conversations`);
754
+ let skippedNoHeaders = 0;
755
+ let skippedNoBubbles = 0;
756
+ let skippedNotInWorkspace = 0;
757
+ const allConversations = [];
758
+ for (const rowUntyped of composerRows) {
759
+ const row = rowUntyped;
760
+ const composerId = row.key.split(':')[1];
761
+ if (!workspaceComposers.has(composerId)) {
762
+ skippedNotInWorkspace++;
763
+ continue;
764
+ }
765
+ try {
766
+ const composerData = JSON.parse(row.value);
767
+ const conversationHeaders = composerData.fullConversationHeadersOnly || [];
768
+ if (conversationHeaders.length === 0) {
769
+ skippedNoHeaders++;
770
+ continue;
771
+ }
772
+ const { bubbles } = this.processBubbleHeaders(conversationHeaders, bubbleMap, bubbleWorkspaceMap, messageRequestContextMap, codeBlockDiffMap, checkpointMap);
773
+ if (bubbles.length > 0) {
774
+ const conversationName = composerData.name || `Conversation ${composerId.slice(0, COMPOSER_ID_PREVIEW_LENGTH)}`;
775
+ allConversations.push({
776
+ bubbles,
777
+ composerId,
778
+ name: conversationName,
779
+ timestamp: composerData.lastUpdatedAt || composerData.createdAt,
780
+ workspacePath,
781
+ });
782
+ }
783
+ else {
784
+ skippedNoBubbles++;
785
+ }
786
+ }
787
+ catch (error) {
788
+ console.error(`⚠️ Error parsing conversation ${composerId}:`, error);
789
+ }
790
+ }
791
+ this.logConversationStats(allConversations.length, skippedNotInWorkspace, skippedNoBubbles, skippedNoHeaders);
792
+ return allConversations;
793
+ }
794
+ // ============================================================================
795
+ // PRIVATE UTILITY METHODS
796
+ // ============================================================================
797
+ /**
798
+ * Safely parse JSON strings with graceful fallback to original value
799
+ *
800
+ * Attempts to parse a string as JSON. If parsing succeeds, returns the parsed object.
801
+ * If parsing fails or value is not a string, returns the original value unchanged.
802
+ * Used for fields that may contain either pre-parsed objects or JSON strings.
803
+ *
804
+ * @param value - Value to parse, may be string, object, or any other type
805
+ * @returns Parsed JSON object if string input, original value otherwise
806
+ */
807
+ safeParseJSON(value) {
808
+ if (typeof value === 'string') {
809
+ try {
810
+ return JSON.parse(value);
811
+ }
812
+ catch {
813
+ return value; // Return original string if parsing fails
814
+ }
815
+ }
816
+ return value; // Already parsed or not a string
817
+ }
818
+ }