claude-code-workflow 6.2.2 → 6.2.3

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 +1 -1
@@ -0,0 +1,700 @@
1
+ /**
2
+ * Native Session Discovery - Discovers and tracks native CLI tool sessions
3
+ * Supports Gemini, Qwen, and Codex session formats
4
+ */
5
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
6
+ import { join, basename, resolve } from 'path';
7
+ // basename is used for extracting session ID from filename
8
+ import { createHash } from 'crypto';
9
+ import { homedir } from 'os';
10
+ /**
11
+ * Calculate project hash (same algorithm as Gemini/Qwen)
12
+ * Note: Gemini/Qwen use the absolute path AS-IS without normalization
13
+ * On Windows, this means using backslashes and original case
14
+ */
15
+ export function calculateProjectHash(projectDir) {
16
+ // resolve() returns absolute path with native separators (backslash on Windows)
17
+ const absolutePath = resolve(projectDir);
18
+ return createHash('sha256').update(absolutePath).digest('hex');
19
+ }
20
+ /**
21
+ * Get home directory path
22
+ */
23
+ function getHomePath() {
24
+ return homedir().replace(/\\/g, '/');
25
+ }
26
+ /**
27
+ * Base session discoverer interface
28
+ */
29
+ class SessionDiscoverer {
30
+ /**
31
+ * Get the latest session
32
+ */
33
+ getLatestSession(options) {
34
+ const sessions = this.getSessions({ ...options, limit: 1 });
35
+ return sessions.length > 0 ? sessions[0] : null;
36
+ }
37
+ /**
38
+ * Track new session created during execution
39
+ * @param beforeTimestamp - Filter sessions created after this time
40
+ * @param workingDir - Project working directory
41
+ * @param prompt - Optional prompt content for precise matching (fallback)
42
+ */
43
+ async trackNewSession(beforeTimestamp, workingDir, prompt) {
44
+ const sessions = this.getSessions({
45
+ workingDir,
46
+ afterTimestamp: beforeTimestamp,
47
+ limit: 10 // Get more candidates for prompt matching
48
+ });
49
+ if (sessions.length === 0)
50
+ return null;
51
+ // If only one session or no prompt provided, return the latest
52
+ if (sessions.length === 1 || !prompt) {
53
+ return sessions[0];
54
+ }
55
+ // Try to match by prompt content (fallback for parallel execution)
56
+ const matched = this.matchSessionByPrompt(sessions, prompt);
57
+ return matched || sessions[0]; // Fallback to latest if no match
58
+ }
59
+ /**
60
+ * Match session by prompt content
61
+ * Searches for the prompt in session's user messages
62
+ */
63
+ matchSessionByPrompt(sessions, prompt) {
64
+ // Normalize prompt for comparison (first 200 chars)
65
+ const promptPrefix = prompt.substring(0, 200).trim();
66
+ if (!promptPrefix)
67
+ return null;
68
+ for (const session of sessions) {
69
+ try {
70
+ const userMessage = this.extractFirstUserMessage(session.filePath);
71
+ if (userMessage && userMessage.includes(promptPrefix)) {
72
+ return session;
73
+ }
74
+ }
75
+ catch {
76
+ // Skip sessions that can't be read
77
+ }
78
+ }
79
+ return null;
80
+ }
81
+ }
82
+ /**
83
+ * Gemini Session Discoverer
84
+ * Path: ~/.gemini/tmp/<projectHash>/chats/session-*.json
85
+ */
86
+ class GeminiSessionDiscoverer extends SessionDiscoverer {
87
+ tool = 'gemini';
88
+ basePath = join(getHomePath(), '.gemini', 'tmp');
89
+ getSessions(options = {}) {
90
+ const { workingDir, limit, afterTimestamp } = options;
91
+ const sessions = [];
92
+ try {
93
+ if (!existsSync(this.basePath))
94
+ return [];
95
+ // If workingDir provided, only look in that project's folder
96
+ let projectDirs;
97
+ if (workingDir) {
98
+ const projectHash = calculateProjectHash(workingDir);
99
+ const projectPath = join(this.basePath, projectHash);
100
+ projectDirs = existsSync(projectPath) ? [projectHash] : [];
101
+ }
102
+ else {
103
+ projectDirs = readdirSync(this.basePath).filter(d => {
104
+ const fullPath = join(this.basePath, d);
105
+ return statSync(fullPath).isDirectory();
106
+ });
107
+ }
108
+ for (const projectHash of projectDirs) {
109
+ const chatsDir = join(this.basePath, projectHash, 'chats');
110
+ if (!existsSync(chatsDir))
111
+ continue;
112
+ const sessionFiles = readdirSync(chatsDir)
113
+ .filter(f => f.startsWith('session-') && f.endsWith('.json'))
114
+ .map(f => ({
115
+ name: f,
116
+ path: join(chatsDir, f),
117
+ stat: statSync(join(chatsDir, f))
118
+ }))
119
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
120
+ for (const file of sessionFiles) {
121
+ if (afterTimestamp && file.stat.mtime <= afterTimestamp)
122
+ continue;
123
+ try {
124
+ const content = JSON.parse(readFileSync(file.path, 'utf8'));
125
+ sessions.push({
126
+ sessionId: content.sessionId,
127
+ tool: this.tool,
128
+ filePath: file.path,
129
+ projectHash,
130
+ createdAt: new Date(content.startTime || file.stat.birthtime),
131
+ updatedAt: new Date(content.lastUpdated || file.stat.mtime)
132
+ });
133
+ }
134
+ catch {
135
+ // Skip invalid files
136
+ }
137
+ }
138
+ }
139
+ // Sort by updatedAt descending
140
+ sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
141
+ return limit ? sessions.slice(0, limit) : sessions;
142
+ }
143
+ catch {
144
+ return [];
145
+ }
146
+ }
147
+ findSessionById(sessionId) {
148
+ const sessions = this.getSessions();
149
+ return sessions.find(s => s.sessionId === sessionId) || null;
150
+ }
151
+ /**
152
+ * Extract first user message from Gemini session file
153
+ * Format: { "messages": [{ "type": "user", "content": "..." }] }
154
+ */
155
+ extractFirstUserMessage(filePath) {
156
+ try {
157
+ const content = JSON.parse(readFileSync(filePath, 'utf8'));
158
+ if (content.messages && Array.isArray(content.messages)) {
159
+ const userMsg = content.messages.find((m) => m.type === 'user');
160
+ return userMsg?.content || null;
161
+ }
162
+ return null;
163
+ }
164
+ catch {
165
+ return null;
166
+ }
167
+ }
168
+ }
169
+ /**
170
+ * Encode a path to Qwen's project folder name format
171
+ * D:\Claude_dms3 -> D--Claude-dms3
172
+ * Rules: : -> -, \ -> -, _ -> -
173
+ */
174
+ function encodeQwenProjectPath(projectDir) {
175
+ const absolutePath = resolve(projectDir);
176
+ // Replace : -> -, \ -> -, _ -> -
177
+ return absolutePath
178
+ .replace(/:/g, '-')
179
+ .replace(/\\/g, '-')
180
+ .replace(/_/g, '-');
181
+ }
182
+ /**
183
+ * Qwen Session Discoverer
184
+ * New path: ~/.qwen/projects/<path-encoded>/chats/<uuid>.jsonl
185
+ * Old path: ~/.qwen/tmp/<projectHash>/chats/session-*.json (deprecated, fallback)
186
+ */
187
+ class QwenSessionDiscoverer extends SessionDiscoverer {
188
+ tool = 'qwen';
189
+ basePath = join(getHomePath(), '.qwen', 'projects');
190
+ legacyBasePath = join(getHomePath(), '.qwen', 'tmp');
191
+ getSessions(options = {}) {
192
+ const { workingDir, limit, afterTimestamp } = options;
193
+ const sessions = [];
194
+ // Try new format first (projects folder)
195
+ try {
196
+ if (existsSync(this.basePath)) {
197
+ let projectDirs;
198
+ if (workingDir) {
199
+ const encodedPath = encodeQwenProjectPath(workingDir);
200
+ const projectPath = join(this.basePath, encodedPath);
201
+ projectDirs = existsSync(projectPath) ? [encodedPath] : [];
202
+ }
203
+ else {
204
+ projectDirs = readdirSync(this.basePath).filter(d => {
205
+ const fullPath = join(this.basePath, d);
206
+ return statSync(fullPath).isDirectory();
207
+ });
208
+ }
209
+ for (const projectFolder of projectDirs) {
210
+ const chatsDir = join(this.basePath, projectFolder, 'chats');
211
+ if (!existsSync(chatsDir))
212
+ continue;
213
+ // New format: <uuid>.jsonl files
214
+ const sessionFiles = readdirSync(chatsDir)
215
+ .filter(f => f.endsWith('.jsonl'))
216
+ .map(f => ({
217
+ name: f,
218
+ path: join(chatsDir, f),
219
+ stat: statSync(join(chatsDir, f))
220
+ }))
221
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
222
+ for (const file of sessionFiles) {
223
+ if (afterTimestamp && file.stat.mtime <= afterTimestamp)
224
+ continue;
225
+ try {
226
+ // Parse JSONL - read first line for session info
227
+ const content = readFileSync(file.path, 'utf8');
228
+ const firstLine = content.split('\n')[0];
229
+ const firstEntry = JSON.parse(firstLine);
230
+ // Session ID is in the filename or first entry
231
+ const sessionId = firstEntry.sessionId || basename(file.name, '.jsonl');
232
+ // Find timestamp from entries
233
+ let createdAt = file.stat.birthtime;
234
+ let updatedAt = file.stat.mtime;
235
+ if (firstEntry.timestamp) {
236
+ createdAt = new Date(firstEntry.timestamp);
237
+ }
238
+ // Get last entry for updatedAt
239
+ const lines = content.trim().split('\n').filter(l => l.trim());
240
+ if (lines.length > 0) {
241
+ try {
242
+ const lastEntry = JSON.parse(lines[lines.length - 1]);
243
+ if (lastEntry.timestamp) {
244
+ updatedAt = new Date(lastEntry.timestamp);
245
+ }
246
+ }
247
+ catch { /* ignore */ }
248
+ }
249
+ sessions.push({
250
+ sessionId,
251
+ tool: this.tool,
252
+ filePath: file.path,
253
+ projectHash: projectFolder, // Using encoded path as project identifier
254
+ createdAt,
255
+ updatedAt
256
+ });
257
+ }
258
+ catch {
259
+ // Skip invalid files
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ catch { /* ignore errors */ }
266
+ // Fallback to legacy format (tmp folder with hash)
267
+ try {
268
+ if (existsSync(this.legacyBasePath)) {
269
+ let projectDirs;
270
+ if (workingDir) {
271
+ const projectHash = calculateProjectHash(workingDir);
272
+ const projectPath = join(this.legacyBasePath, projectHash);
273
+ projectDirs = existsSync(projectPath) ? [projectHash] : [];
274
+ }
275
+ else {
276
+ projectDirs = readdirSync(this.legacyBasePath).filter(d => {
277
+ const fullPath = join(this.legacyBasePath, d);
278
+ return statSync(fullPath).isDirectory();
279
+ });
280
+ }
281
+ for (const projectHash of projectDirs) {
282
+ const chatsDir = join(this.legacyBasePath, projectHash, 'chats');
283
+ if (!existsSync(chatsDir))
284
+ continue;
285
+ const sessionFiles = readdirSync(chatsDir)
286
+ .filter(f => f.startsWith('session-') && f.endsWith('.json'))
287
+ .map(f => ({
288
+ name: f,
289
+ path: join(chatsDir, f),
290
+ stat: statSync(join(chatsDir, f))
291
+ }))
292
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
293
+ for (const file of sessionFiles) {
294
+ if (afterTimestamp && file.stat.mtime <= afterTimestamp)
295
+ continue;
296
+ try {
297
+ const content = JSON.parse(readFileSync(file.path, 'utf8'));
298
+ sessions.push({
299
+ sessionId: content.sessionId,
300
+ tool: this.tool,
301
+ filePath: file.path,
302
+ projectHash,
303
+ createdAt: new Date(content.startTime || file.stat.birthtime),
304
+ updatedAt: new Date(content.lastUpdated || file.stat.mtime)
305
+ });
306
+ }
307
+ catch {
308
+ // Skip invalid files
309
+ }
310
+ }
311
+ }
312
+ }
313
+ }
314
+ catch { /* ignore errors */ }
315
+ // Sort by updatedAt descending and dedupe by sessionId
316
+ sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
317
+ // Dedupe (new format takes precedence as it's checked first)
318
+ const seen = new Set();
319
+ const uniqueSessions = sessions.filter(s => {
320
+ if (seen.has(s.sessionId))
321
+ return false;
322
+ seen.add(s.sessionId);
323
+ return true;
324
+ });
325
+ return limit ? uniqueSessions.slice(0, limit) : uniqueSessions;
326
+ }
327
+ findSessionById(sessionId) {
328
+ const sessions = this.getSessions();
329
+ return sessions.find(s => s.sessionId === sessionId) || null;
330
+ }
331
+ /**
332
+ * Extract first user message from Qwen session file
333
+ * New format (.jsonl): { type: "user", message: { role: "user", parts: [{ text: "..." }] } }
334
+ * Legacy format (.json): { "messages": [{ "type": "user", "content": "..." }] }
335
+ */
336
+ extractFirstUserMessage(filePath) {
337
+ try {
338
+ const content = readFileSync(filePath, 'utf8');
339
+ // Check if JSONL (new format) or JSON (legacy)
340
+ if (filePath.endsWith('.jsonl')) {
341
+ // JSONL format - find first user message
342
+ const lines = content.split('\n').filter(l => l.trim());
343
+ for (const line of lines) {
344
+ try {
345
+ const entry = JSON.parse(line);
346
+ // New Qwen format: { type: "user", message: { parts: [{ text: "..." }] } }
347
+ if (entry.type === 'user' && entry.message?.parts?.[0]?.text) {
348
+ return entry.message.parts[0].text;
349
+ }
350
+ // Alternative format
351
+ if (entry.role === 'user' && entry.content) {
352
+ return entry.content;
353
+ }
354
+ }
355
+ catch { /* skip invalid lines */ }
356
+ }
357
+ }
358
+ else {
359
+ // Legacy JSON format
360
+ const data = JSON.parse(content);
361
+ if (data.messages && Array.isArray(data.messages)) {
362
+ const userMsg = data.messages.find((m) => m.type === 'user');
363
+ return userMsg?.content || null;
364
+ }
365
+ }
366
+ return null;
367
+ }
368
+ catch {
369
+ return null;
370
+ }
371
+ }
372
+ }
373
+ /**
374
+ * Codex Session Discoverer
375
+ * Path: ~/.codex/sessions/YYYY/MM/DD/rollout-*-<uuid>.jsonl
376
+ */
377
+ class CodexSessionDiscoverer extends SessionDiscoverer {
378
+ tool = 'codex';
379
+ basePath = join(getHomePath(), '.codex', 'sessions');
380
+ getSessions(options = {}) {
381
+ const { limit, afterTimestamp } = options;
382
+ const sessions = [];
383
+ try {
384
+ if (!existsSync(this.basePath))
385
+ return [];
386
+ // Get year directories (e.g., 2025)
387
+ const yearDirs = readdirSync(this.basePath)
388
+ .filter(d => /^\d{4}$/.test(d))
389
+ .sort((a, b) => b.localeCompare(a)); // Descending
390
+ for (const year of yearDirs) {
391
+ const yearPath = join(this.basePath, year);
392
+ if (!statSync(yearPath).isDirectory())
393
+ continue;
394
+ // Get month directories
395
+ const monthDirs = readdirSync(yearPath)
396
+ .filter(d => /^\d{2}$/.test(d))
397
+ .sort((a, b) => b.localeCompare(a));
398
+ for (const month of monthDirs) {
399
+ const monthPath = join(yearPath, month);
400
+ if (!statSync(monthPath).isDirectory())
401
+ continue;
402
+ // Get day directories
403
+ const dayDirs = readdirSync(monthPath)
404
+ .filter(d => /^\d{2}$/.test(d))
405
+ .sort((a, b) => b.localeCompare(a));
406
+ for (const day of dayDirs) {
407
+ const dayPath = join(monthPath, day);
408
+ if (!statSync(dayPath).isDirectory())
409
+ continue;
410
+ // Get session files
411
+ const sessionFiles = readdirSync(dayPath)
412
+ .filter(f => f.startsWith('rollout-') && f.endsWith('.jsonl'))
413
+ .map(f => ({
414
+ name: f,
415
+ path: join(dayPath, f),
416
+ stat: statSync(join(dayPath, f))
417
+ }))
418
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
419
+ for (const file of sessionFiles) {
420
+ if (afterTimestamp && file.stat.mtime <= afterTimestamp)
421
+ continue;
422
+ try {
423
+ // Parse first line for session_meta
424
+ const firstLine = readFileSync(file.path, 'utf8').split('\n')[0];
425
+ const meta = JSON.parse(firstLine);
426
+ if (meta.type === 'session_meta' && meta.payload?.id) {
427
+ sessions.push({
428
+ sessionId: meta.payload.id,
429
+ tool: this.tool,
430
+ filePath: file.path,
431
+ createdAt: new Date(meta.payload.timestamp || file.stat.birthtime),
432
+ updatedAt: file.stat.mtime
433
+ });
434
+ }
435
+ }
436
+ catch {
437
+ // Try extracting UUID from filename
438
+ const uuidMatch = file.name.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
439
+ if (uuidMatch) {
440
+ sessions.push({
441
+ sessionId: uuidMatch[1],
442
+ tool: this.tool,
443
+ filePath: file.path,
444
+ createdAt: file.stat.birthtime,
445
+ updatedAt: file.stat.mtime
446
+ });
447
+ }
448
+ }
449
+ }
450
+ }
451
+ }
452
+ }
453
+ sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
454
+ return limit ? sessions.slice(0, limit) : sessions;
455
+ }
456
+ catch {
457
+ return [];
458
+ }
459
+ }
460
+ findSessionById(sessionId) {
461
+ const sessions = this.getSessions();
462
+ return sessions.find(s => s.sessionId === sessionId) || null;
463
+ }
464
+ /**
465
+ * Extract first user message from Codex session file (.jsonl)
466
+ * Format: {"type":"event_msg","payload":{"type":"user_message","message":"..."}}
467
+ */
468
+ extractFirstUserMessage(filePath) {
469
+ try {
470
+ const content = readFileSync(filePath, 'utf8');
471
+ const lines = content.split('\n').filter(l => l.trim());
472
+ for (const line of lines) {
473
+ try {
474
+ const entry = JSON.parse(line);
475
+ // Look for user_message event
476
+ if (entry.type === 'event_msg' &&
477
+ entry.payload?.type === 'user_message' &&
478
+ entry.payload?.message) {
479
+ return entry.payload.message;
480
+ }
481
+ }
482
+ catch { /* skip invalid lines */ }
483
+ }
484
+ return null;
485
+ }
486
+ catch {
487
+ return null;
488
+ }
489
+ }
490
+ }
491
+ /**
492
+ * Claude Code Session Discoverer
493
+ * Path: ~/.claude/projects/<projectHash>/sessions/*.jsonl
494
+ * Claude Code stores sessions with UUID-based session IDs
495
+ */
496
+ class ClaudeSessionDiscoverer extends SessionDiscoverer {
497
+ tool = 'claude';
498
+ basePath = join(getHomePath(), '.claude', 'projects');
499
+ getSessions(options = {}) {
500
+ const { workingDir, limit, afterTimestamp } = options;
501
+ const sessions = [];
502
+ try {
503
+ if (!existsSync(this.basePath))
504
+ return [];
505
+ // If workingDir provided, only look in that project's folder
506
+ let projectDirs;
507
+ if (workingDir) {
508
+ const projectHash = calculateProjectHash(workingDir);
509
+ const projectPath = join(this.basePath, projectHash);
510
+ projectDirs = existsSync(projectPath) ? [projectHash] : [];
511
+ }
512
+ else {
513
+ projectDirs = readdirSync(this.basePath).filter(d => {
514
+ const fullPath = join(this.basePath, d);
515
+ return statSync(fullPath).isDirectory();
516
+ });
517
+ }
518
+ for (const projectHash of projectDirs) {
519
+ // Claude Code stores session files directly in project folder (not in 'sessions' subdirectory)
520
+ // e.g., ~/.claude/projects/D--Claude-dms3/<uuid>.jsonl
521
+ const projectDir = join(this.basePath, projectHash);
522
+ if (!existsSync(projectDir))
523
+ continue;
524
+ const sessionFiles = readdirSync(projectDir)
525
+ .filter(f => f.endsWith('.jsonl') || f.endsWith('.json'))
526
+ .map(f => ({
527
+ name: f,
528
+ path: join(projectDir, f),
529
+ stat: statSync(join(projectDir, f))
530
+ }))
531
+ .sort((a, b) => b.stat.mtimeMs - a.stat.mtimeMs);
532
+ for (const file of sessionFiles) {
533
+ if (afterTimestamp && file.stat.mtime <= afterTimestamp)
534
+ continue;
535
+ try {
536
+ // Extract session ID from filename or content
537
+ const uuidMatch = file.name.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i);
538
+ if (uuidMatch) {
539
+ sessions.push({
540
+ sessionId: uuidMatch[1],
541
+ tool: this.tool,
542
+ filePath: file.path,
543
+ projectHash,
544
+ createdAt: file.stat.birthtime,
545
+ updatedAt: file.stat.mtime
546
+ });
547
+ }
548
+ else {
549
+ // Try reading first line for session metadata
550
+ const firstLine = readFileSync(file.path, 'utf8').split('\n')[0];
551
+ const meta = JSON.parse(firstLine);
552
+ if (meta.session_id) {
553
+ sessions.push({
554
+ sessionId: meta.session_id,
555
+ tool: this.tool,
556
+ filePath: file.path,
557
+ projectHash,
558
+ createdAt: new Date(meta.timestamp || file.stat.birthtime),
559
+ updatedAt: file.stat.mtime
560
+ });
561
+ }
562
+ }
563
+ }
564
+ catch {
565
+ // Skip invalid files
566
+ }
567
+ }
568
+ }
569
+ sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
570
+ return limit ? sessions.slice(0, limit) : sessions;
571
+ }
572
+ catch {
573
+ return [];
574
+ }
575
+ }
576
+ findSessionById(sessionId) {
577
+ const sessions = this.getSessions();
578
+ return sessions.find(s => s.sessionId === sessionId) || null;
579
+ }
580
+ /**
581
+ * Extract first user message from Claude Code session file (.jsonl)
582
+ * Format: {"type":"user","message":{"role":"user","content":"..."},"isMeta":false,...}
583
+ */
584
+ extractFirstUserMessage(filePath) {
585
+ try {
586
+ const content = readFileSync(filePath, 'utf8');
587
+ const lines = content.split('\n').filter(l => l.trim());
588
+ for (const line of lines) {
589
+ try {
590
+ const entry = JSON.parse(line);
591
+ // Claude Code format: type="user", message.role="user", message.content="..."
592
+ // Skip meta messages and command messages
593
+ if (entry.type === 'user' &&
594
+ entry.message?.role === 'user' &&
595
+ entry.message?.content &&
596
+ !entry.isMeta &&
597
+ !entry.message.content.startsWith('<command-')) {
598
+ return entry.message.content;
599
+ }
600
+ }
601
+ catch { /* skip invalid lines */ }
602
+ }
603
+ return null;
604
+ }
605
+ catch {
606
+ return null;
607
+ }
608
+ }
609
+ }
610
+ // Singleton discoverers
611
+ const discoverers = {
612
+ gemini: new GeminiSessionDiscoverer(),
613
+ qwen: new QwenSessionDiscoverer(),
614
+ codex: new CodexSessionDiscoverer(),
615
+ claude: new ClaudeSessionDiscoverer()
616
+ };
617
+ /**
618
+ * Get session discoverer for a tool
619
+ */
620
+ export function getDiscoverer(tool) {
621
+ return discoverers[tool] || null;
622
+ }
623
+ /**
624
+ * Get latest native session for a tool
625
+ */
626
+ export function getLatestNativeSession(tool, workingDir) {
627
+ const discoverer = discoverers[tool];
628
+ if (!discoverer)
629
+ return null;
630
+ return discoverer.getLatestSession({ workingDir });
631
+ }
632
+ /**
633
+ * Find native session by ID
634
+ */
635
+ export function findNativeSessionById(tool, sessionId) {
636
+ const discoverer = discoverers[tool];
637
+ if (!discoverer)
638
+ return null;
639
+ return discoverer.findSessionById(sessionId);
640
+ }
641
+ /**
642
+ * Track new session created during execution
643
+ * @param tool - CLI tool name (gemini, qwen, codex, claude)
644
+ * @param beforeTimestamp - Filter sessions created after this time
645
+ * @param workingDir - Project working directory
646
+ * @param prompt - Optional prompt for precise matching in parallel execution
647
+ */
648
+ export async function trackNewSession(tool, beforeTimestamp, workingDir, prompt) {
649
+ const discoverer = discoverers[tool];
650
+ if (!discoverer)
651
+ return null;
652
+ return discoverer.trackNewSession(beforeTimestamp, workingDir, prompt);
653
+ }
654
+ /**
655
+ * Get all sessions for a tool
656
+ */
657
+ export function getNativeSessions(tool, options) {
658
+ const discoverer = discoverers[tool];
659
+ if (!discoverer)
660
+ return [];
661
+ return discoverer.getSessions(options);
662
+ }
663
+ /**
664
+ * Check if a tool supports native resume
665
+ */
666
+ export function supportsNativeResume(tool) {
667
+ return tool in discoverers;
668
+ }
669
+ /**
670
+ * Get native resume command arguments for a tool
671
+ */
672
+ export function getNativeResumeArgs(tool, sessionId) {
673
+ switch (tool) {
674
+ case 'gemini':
675
+ // gemini -r <uuid> or -r latest
676
+ return ['-r', sessionId];
677
+ case 'qwen':
678
+ // qwen --continue (latest) or --resume <uuid>
679
+ if (sessionId === 'latest') {
680
+ return ['--continue'];
681
+ }
682
+ return ['--resume', sessionId];
683
+ case 'codex':
684
+ // codex resume <uuid> or codex resume --last
685
+ if (sessionId === 'latest') {
686
+ return ['resume', '--last'];
687
+ }
688
+ return ['resume', sessionId];
689
+ default:
690
+ return [];
691
+ }
692
+ }
693
+ /**
694
+ * Get base path for a tool's sessions
695
+ */
696
+ export function getToolSessionPath(tool) {
697
+ const discoverer = discoverers[tool];
698
+ return discoverer?.basePath || null;
699
+ }
700
+ //# sourceMappingURL=native-session-discovery.js.map