commandmate 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +72 -0
  3. package/.next/app-path-routes-manifest.json +1 -0
  4. package/.next/build-manifest.json +32 -0
  5. package/.next/cache/.tsbuildinfo +1 -0
  6. package/.next/cache/config.json +7 -0
  7. package/.next/cache/webpack/client-production/0.pack +0 -0
  8. package/.next/cache/webpack/client-production/1.pack +0 -0
  9. package/.next/cache/webpack/client-production/2.pack +0 -0
  10. package/.next/cache/webpack/client-production/index.pack +0 -0
  11. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  12. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  13. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  14. package/.next/cache/webpack/server-production/0.pack +0 -0
  15. package/.next/cache/webpack/server-production/index.pack +0 -0
  16. package/.next/export-marker.json +1 -0
  17. package/.next/images-manifest.json +1 -0
  18. package/.next/next-minimal-server.js.nft.json +1 -0
  19. package/.next/next-server.js.nft.json +1 -0
  20. package/.next/package.json +1 -0
  21. package/.next/prerender-manifest.json +1 -0
  22. package/.next/react-loadable-manifest.json +249 -0
  23. package/.next/required-server-files.json +1 -0
  24. package/.next/routes-manifest.json +1 -0
  25. package/.next/server/app/_not-found/page.js +1 -0
  26. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  27. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  28. package/.next/server/app/_not-found.html +1 -0
  29. package/.next/server/app/_not-found.meta +6 -0
  30. package/.next/server/app/_not-found.rsc +10 -0
  31. package/.next/server/app/api/external-apps/[id]/health/route.js +45 -0
  32. package/.next/server/app/api/external-apps/[id]/health/route.js.nft.json +1 -0
  33. package/.next/server/app/api/external-apps/[id]/route.js +45 -0
  34. package/.next/server/app/api/external-apps/[id]/route.js.nft.json +1 -0
  35. package/.next/server/app/api/external-apps/route.js +45 -0
  36. package/.next/server/app/api/external-apps/route.js.nft.json +1 -0
  37. package/.next/server/app/api/hooks/claude-done/route.js +19 -0
  38. package/.next/server/app/api/hooks/claude-done/route.js.nft.json +1 -0
  39. package/.next/server/app/api/repositories/clone/[jobId]/route.js +1 -0
  40. package/.next/server/app/api/repositories/clone/[jobId]/route.js.nft.json +1 -0
  41. package/.next/server/app/api/repositories/clone/route.js +1 -0
  42. package/.next/server/app/api/repositories/clone/route.js.nft.json +1 -0
  43. package/.next/server/app/api/repositories/route.js +1 -0
  44. package/.next/server/app/api/repositories/route.js.nft.json +1 -0
  45. package/.next/server/app/api/repositories/scan/route.js +1 -0
  46. package/.next/server/app/api/repositories/scan/route.js.nft.json +1 -0
  47. package/.next/server/app/api/repositories/sync/route.js +1 -0
  48. package/.next/server/app/api/repositories/sync/route.js.nft.json +1 -0
  49. package/.next/server/app/api/slash-commands/route.js +1 -0
  50. package/.next/server/app/api/slash-commands/route.js.nft.json +1 -0
  51. package/.next/server/app/api/slash-commands.body +1 -0
  52. package/.next/server/app/api/slash-commands.meta +1 -0
  53. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js +1 -0
  54. package/.next/server/app/api/worktrees/[id]/auto-yes/route.js.nft.json +1 -0
  55. package/.next/server/app/api/worktrees/[id]/capture/route.js +2 -0
  56. package/.next/server/app/api/worktrees/[id]/capture/route.js.nft.json +1 -0
  57. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js +1 -0
  58. package/.next/server/app/api/worktrees/[id]/cli-tool/route.js.nft.json +1 -0
  59. package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -0
  60. package/.next/server/app/api/worktrees/[id]/current-output/route.js.nft.json +1 -0
  61. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js +1 -0
  62. package/.next/server/app/api/worktrees/[id]/files/[...path]/route.js.nft.json +1 -0
  63. package/.next/server/app/api/worktrees/[id]/interrupt/route.js +1 -0
  64. package/.next/server/app/api/worktrees/[id]/interrupt/route.js.nft.json +1 -0
  65. package/.next/server/app/api/worktrees/[id]/kill-session/route.js +1 -0
  66. package/.next/server/app/api/worktrees/[id]/kill-session/route.js.nft.json +1 -0
  67. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js +1 -0
  68. package/.next/server/app/api/worktrees/[id]/logs/[filename]/route.js.nft.json +1 -0
  69. package/.next/server/app/api/worktrees/[id]/logs/route.js +19 -0
  70. package/.next/server/app/api/worktrees/[id]/logs/route.js.nft.json +1 -0
  71. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js +1 -0
  72. package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route.js.nft.json +1 -0
  73. package/.next/server/app/api/worktrees/[id]/memos/route.js +1 -0
  74. package/.next/server/app/api/worktrees/[id]/memos/route.js.nft.json +1 -0
  75. package/.next/server/app/api/worktrees/[id]/messages/route.js +1 -0
  76. package/.next/server/app/api/worktrees/[id]/messages/route.js.nft.json +1 -0
  77. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js +1 -0
  78. package/.next/server/app/api/worktrees/[id]/prompt-response/route.js.nft.json +1 -0
  79. package/.next/server/app/api/worktrees/[id]/respond/route.js +1 -0
  80. package/.next/server/app/api/worktrees/[id]/respond/route.js.nft.json +1 -0
  81. package/.next/server/app/api/worktrees/[id]/route.js +1 -0
  82. package/.next/server/app/api/worktrees/[id]/route.js.nft.json +1 -0
  83. package/.next/server/app/api/worktrees/[id]/search/route.js +1 -0
  84. package/.next/server/app/api/worktrees/[id]/search/route.js.nft.json +1 -0
  85. package/.next/server/app/api/worktrees/[id]/send/route.js +1 -0
  86. package/.next/server/app/api/worktrees/[id]/send/route.js.nft.json +1 -0
  87. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js +1 -0
  88. package/.next/server/app/api/worktrees/[id]/slash-commands/route.js.nft.json +1 -0
  89. package/.next/server/app/api/worktrees/[id]/start-polling/route.js +1 -0
  90. package/.next/server/app/api/worktrees/[id]/start-polling/route.js.nft.json +1 -0
  91. package/.next/server/app/api/worktrees/[id]/terminal/route.js +1 -0
  92. package/.next/server/app/api/worktrees/[id]/terminal/route.js.nft.json +1 -0
  93. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js +1 -0
  94. package/.next/server/app/api/worktrees/[id]/tree/[...path]/route.js.nft.json +1 -0
  95. package/.next/server/app/api/worktrees/[id]/tree/route.js +1 -0
  96. package/.next/server/app/api/worktrees/[id]/tree/route.js.nft.json +1 -0
  97. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js +1 -0
  98. package/.next/server/app/api/worktrees/[id]/upload/[...path]/route.js.nft.json +1 -0
  99. package/.next/server/app/api/worktrees/[id]/viewed/route.js +1 -0
  100. package/.next/server/app/api/worktrees/[id]/viewed/route.js.nft.json +1 -0
  101. package/.next/server/app/api/worktrees/route.js +1 -0
  102. package/.next/server/app/api/worktrees/route.js.nft.json +1 -0
  103. package/.next/server/app/apple-icon.png/route.js +1 -0
  104. package/.next/server/app/apple-icon.png/route.js.nft.json +1 -0
  105. package/.next/server/app/apple-icon.png.body +0 -0
  106. package/.next/server/app/apple-icon.png.meta +1 -0
  107. package/.next/server/app/icon.png/route.js +1 -0
  108. package/.next/server/app/icon.png/route.js.nft.json +1 -0
  109. package/.next/server/app/icon.png.body +0 -0
  110. package/.next/server/app/icon.png.meta +1 -0
  111. package/.next/server/app/index.html +9 -0
  112. package/.next/server/app/index.meta +5 -0
  113. package/.next/server/app/index.rsc +8 -0
  114. package/.next/server/app/page.js +16 -0
  115. package/.next/server/app/page.js.nft.json +1 -0
  116. package/.next/server/app/page_client-reference-manifest.js +1 -0
  117. package/.next/server/app/proxy/[...path]/route.js +45 -0
  118. package/.next/server/app/proxy/[...path]/route.js.nft.json +1 -0
  119. package/.next/server/app/worktrees/[id]/files/[...path]/page.js +1 -0
  120. package/.next/server/app/worktrees/[id]/files/[...path]/page.js.nft.json +1 -0
  121. package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -0
  122. package/.next/server/app/worktrees/[id]/page.js +21 -0
  123. package/.next/server/app/worktrees/[id]/page.js.nft.json +1 -0
  124. package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -0
  125. package/.next/server/app/worktrees/[id]/simple-terminal/page.js +4 -0
  126. package/.next/server/app/worktrees/[id]/simple-terminal/page.js.nft.json +1 -0
  127. package/.next/server/app/worktrees/[id]/simple-terminal/page_client-reference-manifest.js +1 -0
  128. package/.next/server/app/worktrees/[id]/terminal/page.js +6 -0
  129. package/.next/server/app/worktrees/[id]/terminal/page.js.nft.json +1 -0
  130. package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -0
  131. package/.next/server/app-paths-manifest.json +46 -0
  132. package/.next/server/chunks/1318.js +29 -0
  133. package/.next/server/chunks/1528.js +1 -0
  134. package/.next/server/chunks/1682.js +6 -0
  135. package/.next/server/chunks/2518.js +12 -0
  136. package/.next/server/chunks/3053.js +1 -0
  137. package/.next/server/chunks/3673.js +1 -0
  138. package/.next/server/chunks/3853.js +1 -0
  139. package/.next/server/chunks/434.js +1 -0
  140. package/.next/server/chunks/4471.js +2 -0
  141. package/.next/server/chunks/4893.js +2 -0
  142. package/.next/server/chunks/5972.js +12 -0
  143. package/.next/server/chunks/6550.js +1 -0
  144. package/.next/server/chunks/6621.js +1 -0
  145. package/.next/server/chunks/7213.js +1 -0
  146. package/.next/server/chunks/7425.js +500 -0
  147. package/.next/server/chunks/8585.js +1 -0
  148. package/.next/server/chunks/8887.js +1 -0
  149. package/.next/server/chunks/8948.js +2 -0
  150. package/.next/server/chunks/9703.js +31 -0
  151. package/.next/server/chunks/9723.js +19 -0
  152. package/.next/server/chunks/font-manifest.json +1 -0
  153. package/.next/server/edge-runtime-webpack.js +2 -0
  154. package/.next/server/edge-runtime-webpack.js.map +1 -0
  155. package/.next/server/font-manifest.json +1 -0
  156. package/.next/server/functions-config-manifest.json +1 -0
  157. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  158. package/.next/server/middleware-build-manifest.js +1 -0
  159. package/.next/server/middleware-manifest.json +32 -0
  160. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  161. package/.next/server/next-font-manifest.js +1 -0
  162. package/.next/server/next-font-manifest.json +1 -0
  163. package/.next/server/pages/404.html +1 -0
  164. package/.next/server/pages/500.html +1 -0
  165. package/.next/server/pages/_app.js +1 -0
  166. package/.next/server/pages/_app.js.nft.json +1 -0
  167. package/.next/server/pages/_document.js +1 -0
  168. package/.next/server/pages/_document.js.nft.json +1 -0
  169. package/.next/server/pages/_error.js +1 -0
  170. package/.next/server/pages/_error.js.nft.json +1 -0
  171. package/.next/server/pages-manifest.json +1 -0
  172. package/.next/server/server-reference-manifest.js +1 -0
  173. package/.next/server/server-reference-manifest.json +1 -0
  174. package/.next/server/src/middleware.js +14 -0
  175. package/.next/server/src/middleware.js.map +1 -0
  176. package/.next/server/webpack-runtime.js +1 -0
  177. package/.next/static/3jNZMmFnQhc5G7met-OU4/_buildManifest.js +1 -0
  178. package/.next/static/3jNZMmFnQhc5G7met-OU4/_ssgManifest.js +1 -0
  179. package/.next/static/chunks/0dbeb660.3e800dfbd28be3bd.js +53 -0
  180. package/.next/static/chunks/1015.0eaa4da7f61149bc.js +59 -0
  181. package/.next/static/chunks/1098.49268c9fe1b028fa.js +1 -0
  182. package/.next/static/chunks/13.feeafc7cc620f8c4.js +1 -0
  183. package/.next/static/chunks/1423.7b1e8bf760d28078.js +1 -0
  184. package/.next/static/chunks/1582.9f8590f71ff798ca.js +55 -0
  185. package/.next/static/chunks/1817.a66d96cedb761daa.js +262 -0
  186. package/.next/static/chunks/2117-d845c2cd62e344a6.js +2 -0
  187. package/.next/static/chunks/2398.0b21e4eb7006a230.js +93 -0
  188. package/.next/static/chunks/2526.8ac62b527c9ab703.js +43 -0
  189. package/.next/static/chunks/2626.2125083a1ff3b80a.js +29 -0
  190. package/.next/static/chunks/2689.720a4874b02d4211.js +174 -0
  191. package/.next/static/chunks/2853-d11a80b03c9a1640.js +1 -0
  192. package/.next/static/chunks/2957-327e43ef4c12808f.js +1 -0
  193. package/.next/static/chunks/2cdb6380.35626fc6e41bbba4.js +136 -0
  194. package/.next/static/chunks/30d07d85-393352a92199f695.js +3 -0
  195. package/.next/static/chunks/3559.f073f72c4466ce0e.js +1 -0
  196. package/.next/static/chunks/3574.7a94c27e6a496a56.js +63 -0
  197. package/.next/static/chunks/383.20683891c9a5f2c4.js +4 -0
  198. package/.next/static/chunks/3843.3fdda732987f7bb8.js +1 -0
  199. package/.next/static/chunks/3852.822389f445c9b427.js +1 -0
  200. package/.next/static/chunks/3991.4bc063cb5be3a86c.js +1 -0
  201. package/.next/static/chunks/4212.52c1bb34fc97d0d0.js +131 -0
  202. package/.next/static/chunks/4327.3b84aa049900fdeb.js +60 -0
  203. package/.next/static/chunks/4362.7bd6f0282e49d79b.js +1 -0
  204. package/.next/static/chunks/4721.40615a5f4f32b5fb.js +1 -0
  205. package/.next/static/chunks/4851-45df4d388db5623f.js +1 -0
  206. package/.next/static/chunks/5112.17318d1c6b28044b.js +1 -0
  207. package/.next/static/chunks/5126.93fa4e797d609286.js +56 -0
  208. package/.next/static/chunks/5387.47590ac4ef66c864.js +5 -0
  209. package/.next/static/chunks/5813.4483664ba482beb1.js +1 -0
  210. package/.next/static/chunks/6143.1450875bd03a2366.js +36 -0
  211. package/.next/static/chunks/6406.9653f0d41ab85059.js +1 -0
  212. package/.next/static/chunks/656.d72f25ce819bd77e.js +149 -0
  213. package/.next/static/chunks/6678.492e73ca42b2a273.js +62 -0
  214. package/.next/static/chunks/6725-f7607851b7d57eb1.js +1 -0
  215. package/.next/static/chunks/6792.3c01ac4dda4b5c6d.js +1 -0
  216. package/.next/static/chunks/7004.808cbf327ef5955e.js +1 -0
  217. package/.next/static/chunks/7290.09ef84cf94f90c4d.js +1 -0
  218. package/.next/static/chunks/7415.6b481c2baf363262.js +148 -0
  219. package/.next/static/chunks/7648-325564a6e12a3257.js +1 -0
  220. package/.next/static/chunks/7665.47fccad04449a8f9.js +215 -0
  221. package/.next/static/chunks/7753.6bdce86b7fde3d10.js +166 -0
  222. package/.next/static/chunks/8125.245a9df052d274fb.js +1 -0
  223. package/.next/static/chunks/816-7e340dad784be28c.js +1 -0
  224. package/.next/static/chunks/8288.4883743fa40672e2.js +24 -0
  225. package/.next/static/chunks/8522.1607e96011c66877.js +1 -0
  226. package/.next/static/chunks/8772.863c564498d88487.js +1 -0
  227. package/.next/static/chunks/8841.dadeb1ece8e46004.js +1 -0
  228. package/.next/static/chunks/8885.f8d9912b40d74811.js +1 -0
  229. package/.next/static/chunks/90542734.c1553d0fe7fc14fc.js +1 -0
  230. package/.next/static/chunks/9365-733d8c05712d2888.js +1 -0
  231. package/.next/static/chunks/9552.b7dfb7903ead934b.js +1 -0
  232. package/.next/static/chunks/9834.295b45635ce04f5e.js +24 -0
  233. package/.next/static/chunks/app/_not-found/page-a9d04e58c81115ec.js +1 -0
  234. package/.next/static/chunks/app/layout-37e55f11dcc8b1bf.js +1 -0
  235. package/.next/static/chunks/app/page-9cd00de9cc0abc43.js +1 -0
  236. package/.next/static/chunks/app/worktrees/[id]/files/[...path]/page-9e5adf57cbbbdf05.js +1 -0
  237. package/.next/static/chunks/app/worktrees/[id]/page-8c6676303b63fdaf.js +1 -0
  238. package/.next/static/chunks/app/worktrees/[id]/simple-terminal/page-16feb3e86e42f4d1.js +1 -0
  239. package/.next/static/chunks/app/worktrees/[id]/terminal/page-be802baffc84dbd2.js +1 -0
  240. package/.next/static/chunks/d3ac728e.6c9c508274d4d2d5.js +1 -0
  241. package/.next/static/chunks/fd9d1056-bbe86e4ae099d5cd.js +1 -0
  242. package/.next/static/chunks/framework-8e0e0f4a6b83a956.js +1 -0
  243. package/.next/static/chunks/main-a960f4a5e1a2f598.js +1 -0
  244. package/.next/static/chunks/main-app-420d93e43682fee5.js +1 -0
  245. package/.next/static/chunks/pages/_app-3c9ca398d360b709.js +1 -0
  246. package/.next/static/chunks/pages/_error-cf5ca766ac8f493f.js +1 -0
  247. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  248. package/.next/static/chunks/webpack-3fc79fab9bb738d7.js +1 -0
  249. package/.next/static/css/5eacd01f773eed7f.css +11 -0
  250. package/.next/static/css/85fa6dafca566008.css +1 -0
  251. package/.next/static/css/e174aa24f94ce607.css +3 -0
  252. package/.next/trace +5 -0
  253. package/.next/types/app/api/external-apps/[id]/health/route.ts +343 -0
  254. package/.next/types/app/api/external-apps/[id]/route.ts +343 -0
  255. package/.next/types/app/api/external-apps/route.ts +343 -0
  256. package/.next/types/app/api/hooks/claude-done/route.ts +343 -0
  257. package/.next/types/app/api/repositories/clone/[jobId]/route.ts +343 -0
  258. package/.next/types/app/api/repositories/clone/route.ts +343 -0
  259. package/.next/types/app/api/repositories/route.ts +343 -0
  260. package/.next/types/app/api/repositories/scan/route.ts +343 -0
  261. package/.next/types/app/api/repositories/sync/route.ts +343 -0
  262. package/.next/types/app/api/slash-commands/route.ts +343 -0
  263. package/.next/types/app/api/worktrees/[id]/auto-yes/route.ts +343 -0
  264. package/.next/types/app/api/worktrees/[id]/capture/route.ts +343 -0
  265. package/.next/types/app/api/worktrees/[id]/cli-tool/route.ts +343 -0
  266. package/.next/types/app/api/worktrees/[id]/current-output/route.ts +343 -0
  267. package/.next/types/app/api/worktrees/[id]/files/[...path]/route.ts +343 -0
  268. package/.next/types/app/api/worktrees/[id]/interrupt/route.ts +343 -0
  269. package/.next/types/app/api/worktrees/[id]/kill-session/route.ts +343 -0
  270. package/.next/types/app/api/worktrees/[id]/logs/[filename]/route.ts +343 -0
  271. package/.next/types/app/api/worktrees/[id]/logs/route.ts +343 -0
  272. package/.next/types/app/api/worktrees/[id]/memos/[memoId]/route.ts +343 -0
  273. package/.next/types/app/api/worktrees/[id]/memos/route.ts +343 -0
  274. package/.next/types/app/api/worktrees/[id]/messages/route.ts +343 -0
  275. package/.next/types/app/api/worktrees/[id]/prompt-response/route.ts +343 -0
  276. package/.next/types/app/api/worktrees/[id]/respond/route.ts +343 -0
  277. package/.next/types/app/api/worktrees/[id]/route.ts +343 -0
  278. package/.next/types/app/api/worktrees/[id]/search/route.ts +343 -0
  279. package/.next/types/app/api/worktrees/[id]/send/route.ts +343 -0
  280. package/.next/types/app/api/worktrees/[id]/slash-commands/route.ts +343 -0
  281. package/.next/types/app/api/worktrees/[id]/start-polling/route.ts +343 -0
  282. package/.next/types/app/api/worktrees/[id]/terminal/route.ts +343 -0
  283. package/.next/types/app/api/worktrees/[id]/tree/[...path]/route.ts +343 -0
  284. package/.next/types/app/api/worktrees/[id]/tree/route.ts +343 -0
  285. package/.next/types/app/api/worktrees/[id]/upload/[...path]/route.ts +343 -0
  286. package/.next/types/app/api/worktrees/[id]/viewed/route.ts +343 -0
  287. package/.next/types/app/api/worktrees/route.ts +343 -0
  288. package/.next/types/app/page.ts +79 -0
  289. package/.next/types/app/proxy/[...path]/route.ts +343 -0
  290. package/.next/types/app/worktrees/[id]/files/[...path]/page.ts +79 -0
  291. package/.next/types/app/worktrees/[id]/page.ts +79 -0
  292. package/.next/types/app/worktrees/[id]/simple-terminal/page.ts +79 -0
  293. package/.next/types/app/worktrees/[id]/terminal/page.ts +79 -0
  294. package/.next/types/package.json +1 -0
  295. package/README.md +39 -8
  296. package/dist/cli/commands/init.d.ts +1 -0
  297. package/dist/cli/commands/init.d.ts.map +1 -1
  298. package/dist/cli/commands/init.js +143 -27
  299. package/dist/cli/types/index.d.ts +18 -0
  300. package/dist/cli/types/index.d.ts.map +1 -1
  301. package/dist/cli/utils/env-setup.d.ts +25 -0
  302. package/dist/cli/utils/env-setup.d.ts.map +1 -1
  303. package/dist/cli/utils/env-setup.js +56 -1
  304. package/dist/cli/utils/prompt.d.ts +68 -0
  305. package/dist/cli/utils/prompt.d.ts.map +1 -0
  306. package/dist/cli/utils/prompt.js +208 -0
  307. package/dist/server/server.js +123 -0
  308. package/dist/server/src/lib/claude-output.js +33 -0
  309. package/dist/server/src/lib/claude-session.js +312 -0
  310. package/dist/server/src/lib/cli-patterns.js +137 -0
  311. package/dist/server/src/lib/cli-session.js +73 -0
  312. package/dist/server/src/lib/cli-tools/base.js +51 -0
  313. package/dist/server/src/lib/cli-tools/claude.js +65 -0
  314. package/dist/server/src/lib/cli-tools/codex.js +132 -0
  315. package/dist/server/src/lib/cli-tools/gemini.js +122 -0
  316. package/dist/server/src/lib/cli-tools/index.js +22 -0
  317. package/dist/server/src/lib/cli-tools/manager.js +143 -0
  318. package/dist/server/src/lib/cli-tools/types.js +5 -0
  319. package/dist/server/src/lib/conversation-logger.js +25 -0
  320. package/dist/server/src/lib/db-instance.js +51 -0
  321. package/dist/server/src/lib/db-migrations.js +777 -0
  322. package/dist/server/src/lib/db.js +835 -0
  323. package/dist/server/src/lib/env.js +179 -0
  324. package/dist/server/src/lib/log-manager.js +234 -0
  325. package/dist/server/src/lib/logger.js +232 -0
  326. package/dist/server/src/lib/prompt-detector.js +285 -0
  327. package/dist/server/src/lib/response-poller.js +638 -0
  328. package/dist/server/src/lib/tmux.js +299 -0
  329. package/dist/server/src/lib/worktrees.js +231 -0
  330. package/dist/server/src/lib/ws-server.js +323 -0
  331. package/dist/server/src/types/clone.js +39 -0
  332. package/dist/server/src/types/conversation.js +9 -0
  333. package/dist/server/src/types/external-apps.js +6 -0
  334. package/dist/server/src/types/infinite-messages.js +65 -0
  335. package/dist/server/src/types/markdown-editor.js +94 -0
  336. package/dist/server/src/types/models.js +5 -0
  337. package/dist/server/src/types/sidebar.js +89 -0
  338. package/dist/server/src/types/slash-commands.js +47 -0
  339. package/dist/server/src/types/ui-actions.js +8 -0
  340. package/dist/server/src/types/ui-state.js +62 -0
  341. package/package.json +8 -4
@@ -0,0 +1,835 @@
1
+ "use strict";
2
+ /**
3
+ * Database operations for myCodeBranchDesk
4
+ * SQLite database client and CRUD operations
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.initDatabase = initDatabase;
8
+ exports.getWorktrees = getWorktrees;
9
+ exports.getRepositories = getRepositories;
10
+ exports.getWorktreeById = getWorktreeById;
11
+ exports.upsertWorktree = upsertWorktree;
12
+ exports.updateWorktreeDescription = updateWorktreeDescription;
13
+ exports.updateWorktreeLink = updateWorktreeLink;
14
+ exports.updateLastViewedAt = updateLastViewedAt;
15
+ exports.getLastAssistantMessageAt = getLastAssistantMessageAt;
16
+ exports.createMessage = createMessage;
17
+ exports.updateMessageContent = updateMessageContent;
18
+ exports.getMessages = getMessages;
19
+ exports.getLastUserMessage = getLastUserMessage;
20
+ exports.getLastMessage = getLastMessage;
21
+ exports.deleteAllMessages = deleteAllMessages;
22
+ exports.getSessionState = getSessionState;
23
+ exports.updateSessionState = updateSessionState;
24
+ exports.setInProgressMessageId = setInProgressMessageId;
25
+ exports.clearInProgressMessageId = clearInProgressMessageId;
26
+ exports.deleteSessionState = deleteSessionState;
27
+ exports.updateLastUserMessage = updateLastUserMessage;
28
+ exports.getMessageById = getMessageById;
29
+ exports.updatePromptData = updatePromptData;
30
+ exports.markPendingPromptsAsAnswered = markPendingPromptsAsAnswered;
31
+ exports.updateFavorite = updateFavorite;
32
+ exports.updateStatus = updateStatus;
33
+ exports.updateCliToolId = updateCliToolId;
34
+ exports.getMemosByWorktreeId = getMemosByWorktreeId;
35
+ exports.getMemoById = getMemoById;
36
+ exports.createMemo = createMemo;
37
+ exports.updateMemo = updateMemo;
38
+ exports.deleteMemo = deleteMemo;
39
+ exports.reorderMemos = reorderMemos;
40
+ exports.getWorktreeIdsByRepository = getWorktreeIdsByRepository;
41
+ exports.deleteRepositoryWorktrees = deleteRepositoryWorktrees;
42
+ const crypto_1 = require("crypto");
43
+ function mapChatMessage(row) {
44
+ return {
45
+ id: row.id,
46
+ worktreeId: row.worktree_id,
47
+ role: row.role,
48
+ content: row.content,
49
+ summary: row.summary || undefined,
50
+ timestamp: new Date(row.timestamp),
51
+ logFileName: row.log_file_name || undefined,
52
+ requestId: row.request_id || undefined,
53
+ messageType: row.message_type || 'normal',
54
+ promptData: row.prompt_data ? JSON.parse(row.prompt_data) : undefined,
55
+ cliToolId: row.cli_tool_id ?? 'claude',
56
+ };
57
+ }
58
+ /**
59
+ * Initialize database schema
60
+ */
61
+ function initDatabase(db) {
62
+ // Create worktrees table
63
+ db.exec(`
64
+ CREATE TABLE IF NOT EXISTS worktrees (
65
+ id TEXT PRIMARY KEY,
66
+ name TEXT NOT NULL,
67
+ path TEXT NOT NULL UNIQUE,
68
+ last_message_summary TEXT,
69
+ updated_at INTEGER
70
+ );
71
+ `);
72
+ // Create index for sorting by updated_at
73
+ db.exec(`
74
+ CREATE INDEX IF NOT EXISTS idx_worktrees_updated_at
75
+ ON worktrees(updated_at DESC);
76
+ `);
77
+ // Create chat_messages table
78
+ db.exec(`
79
+ CREATE TABLE IF NOT EXISTS chat_messages (
80
+ id TEXT PRIMARY KEY,
81
+ worktree_id TEXT NOT NULL,
82
+ role TEXT NOT NULL CHECK(role IN ('user', 'assistant')),
83
+ content TEXT NOT NULL,
84
+ summary TEXT,
85
+ timestamp INTEGER NOT NULL,
86
+ log_file_name TEXT,
87
+ request_id TEXT,
88
+ message_type TEXT DEFAULT 'normal',
89
+ prompt_data TEXT,
90
+ cli_tool_id TEXT DEFAULT 'claude',
91
+
92
+ FOREIGN KEY (worktree_id) REFERENCES worktrees(id) ON DELETE CASCADE
93
+ );
94
+ `);
95
+ // Create indexes for chat_messages
96
+ db.exec(`
97
+ CREATE INDEX IF NOT EXISTS idx_messages_worktree_time
98
+ ON chat_messages(worktree_id, timestamp DESC);
99
+ `);
100
+ db.exec(`
101
+ CREATE INDEX IF NOT EXISTS idx_messages_request_id
102
+ ON chat_messages(request_id);
103
+ `);
104
+ db.exec(`
105
+ CREATE INDEX IF NOT EXISTS idx_messages_type
106
+ ON chat_messages(message_type, worktree_id);
107
+ `);
108
+ db.exec(`
109
+ CREATE INDEX IF NOT EXISTS idx_messages_cli_tool
110
+ ON chat_messages(worktree_id, cli_tool_id, timestamp DESC);
111
+ `);
112
+ // Create session_states table
113
+ db.exec(`
114
+ CREATE TABLE IF NOT EXISTS session_states (
115
+ worktree_id TEXT NOT NULL,
116
+ cli_tool_id TEXT NOT NULL DEFAULT 'claude',
117
+ last_captured_line INTEGER DEFAULT 0,
118
+
119
+ PRIMARY KEY (worktree_id, cli_tool_id),
120
+ FOREIGN KEY (worktree_id) REFERENCES worktrees(id) ON DELETE CASCADE
121
+ );
122
+ `);
123
+ }
124
+ /**
125
+ * Get latest user message per CLI tool for multiple worktrees (batch query)
126
+ * Optimized to avoid N+1 query problem
127
+ */
128
+ function getLastMessagesByCliBatch(db, worktreeIds) {
129
+ if (worktreeIds.length === 0) {
130
+ return new Map();
131
+ }
132
+ // Single query to get latest user message for each worktree/cli_tool combination
133
+ // Uses window function to rank messages and filter to only the latest per group
134
+ const placeholders = worktreeIds.map(() => '?').join(',');
135
+ const stmt = db.prepare(`
136
+ WITH ranked_messages AS (
137
+ SELECT
138
+ worktree_id,
139
+ cli_tool_id,
140
+ content,
141
+ ROW_NUMBER() OVER (
142
+ PARTITION BY worktree_id, cli_tool_id
143
+ ORDER BY timestamp DESC
144
+ ) as rn
145
+ FROM chat_messages
146
+ WHERE worktree_id IN (${placeholders})
147
+ AND role = 'user'
148
+ AND cli_tool_id IN ('claude', 'codex', 'gemini')
149
+ )
150
+ SELECT worktree_id, cli_tool_id, content
151
+ FROM ranked_messages
152
+ WHERE rn = 1
153
+ `);
154
+ const rows = stmt.all(...worktreeIds);
155
+ // Build result map
156
+ const result = new Map();
157
+ // Initialize all worktree IDs with empty objects
158
+ for (const id of worktreeIds) {
159
+ result.set(id, {});
160
+ }
161
+ // Populate with query results
162
+ for (const row of rows) {
163
+ const existing = result.get(row.worktree_id) || {};
164
+ existing[row.cli_tool_id] = row.content.substring(0, 50);
165
+ result.set(row.worktree_id, existing);
166
+ }
167
+ return result;
168
+ }
169
+ /**
170
+ * Get all worktrees sorted by updated_at (desc)
171
+ * Optionally filter by repository path
172
+ * Includes lastViewedAt and lastAssistantMessageAt for unread tracking
173
+ */
174
+ function getWorktrees(db, repositoryPath) {
175
+ let query = `
176
+ SELECT
177
+ w.id, w.name, w.path, w.repository_path, w.repository_name, w.description,
178
+ w.last_user_message, w.last_user_message_at, w.last_message_summary,
179
+ w.updated_at, w.favorite, w.status, w.link, w.cli_tool_id, w.last_viewed_at,
180
+ (SELECT MAX(timestamp) FROM chat_messages
181
+ WHERE worktree_id = w.id AND role = 'assistant') as last_assistant_message_at
182
+ FROM worktrees w
183
+ `;
184
+ const params = [];
185
+ if (repositoryPath) {
186
+ query += ` WHERE w.repository_path = ?`;
187
+ params.push(repositoryPath);
188
+ }
189
+ query += ` ORDER BY w.updated_at DESC NULLS LAST`;
190
+ const stmt = db.prepare(query);
191
+ const rows = stmt.all(...params);
192
+ // Batch fetch last messages for all worktrees (N+1 optimization)
193
+ const worktreeIds = rows.map(row => row.id);
194
+ const lastMessagesByCliMap = getLastMessagesByCliBatch(db, worktreeIds);
195
+ return rows.map((row) => {
196
+ const lastMessagesByCli = lastMessagesByCliMap.get(row.id) || {};
197
+ return {
198
+ id: row.id,
199
+ name: row.name,
200
+ path: row.path,
201
+ repositoryPath: row.repository_path || '',
202
+ repositoryName: row.repository_name || '',
203
+ description: row.description || undefined,
204
+ lastUserMessage: row.last_user_message || undefined,
205
+ lastUserMessageAt: row.last_user_message_at ? new Date(row.last_user_message_at) : undefined,
206
+ lastMessageSummary: row.last_message_summary || undefined,
207
+ lastMessagesByCli,
208
+ updatedAt: row.updated_at ? new Date(row.updated_at) : undefined,
209
+ lastViewedAt: row.last_viewed_at ? new Date(row.last_viewed_at) : undefined,
210
+ lastAssistantMessageAt: row.last_assistant_message_at ? new Date(row.last_assistant_message_at) : undefined,
211
+ favorite: row.favorite === 1,
212
+ status: row.status || null,
213
+ link: row.link || undefined,
214
+ cliToolId: row.cli_tool_id ?? 'claude',
215
+ };
216
+ });
217
+ }
218
+ /**
219
+ * Get list of unique repositories from worktrees
220
+ */
221
+ function getRepositories(db) {
222
+ const stmt = db.prepare(`
223
+ SELECT
224
+ repository_path as path,
225
+ repository_name as name,
226
+ COUNT(*) as worktree_count
227
+ FROM worktrees
228
+ WHERE repository_path IS NOT NULL
229
+ GROUP BY repository_path, repository_name
230
+ ORDER BY repository_name ASC
231
+ `);
232
+ const rows = stmt.all();
233
+ return rows.map((row) => ({
234
+ path: row.path,
235
+ name: row.name,
236
+ worktreeCount: row.worktree_count,
237
+ }));
238
+ }
239
+ /**
240
+ * Get worktree by ID
241
+ * Includes lastViewedAt and lastAssistantMessageAt for unread tracking
242
+ */
243
+ function getWorktreeById(db, id) {
244
+ const stmt = db.prepare(`
245
+ SELECT
246
+ w.id, w.name, w.path, w.repository_path, w.repository_name, w.description,
247
+ w.last_user_message, w.last_user_message_at, w.last_message_summary,
248
+ w.updated_at, w.favorite, w.status, w.link, w.cli_tool_id, w.last_viewed_at,
249
+ (SELECT MAX(timestamp) FROM chat_messages
250
+ WHERE worktree_id = w.id AND role = 'assistant') as last_assistant_message_at
251
+ FROM worktrees w
252
+ WHERE w.id = ?
253
+ `);
254
+ const row = stmt.get(id);
255
+ if (!row) {
256
+ return null;
257
+ }
258
+ return {
259
+ id: row.id,
260
+ name: row.name,
261
+ path: row.path,
262
+ repositoryPath: row.repository_path || '',
263
+ repositoryName: row.repository_name || '',
264
+ description: row.description || undefined,
265
+ lastUserMessage: row.last_user_message || undefined,
266
+ lastUserMessageAt: row.last_user_message_at ? new Date(row.last_user_message_at) : undefined,
267
+ lastMessageSummary: row.last_message_summary || undefined,
268
+ updatedAt: row.updated_at ? new Date(row.updated_at) : undefined,
269
+ lastViewedAt: row.last_viewed_at ? new Date(row.last_viewed_at) : undefined,
270
+ lastAssistantMessageAt: row.last_assistant_message_at ? new Date(row.last_assistant_message_at) : undefined,
271
+ favorite: row.favorite === 1,
272
+ status: row.status || null,
273
+ link: row.link || undefined,
274
+ cliToolId: row.cli_tool_id ?? 'claude',
275
+ };
276
+ }
277
+ /**
278
+ * Insert or update worktree
279
+ */
280
+ function upsertWorktree(db, worktree) {
281
+ // First, remove any existing worktree with the same path but different ID
282
+ // This handles cases where the ID generation scheme has changed
283
+ db.prepare('DELETE FROM worktrees WHERE path = ? AND id != ?').run(worktree.path, worktree.id);
284
+ const stmt = db.prepare(`
285
+ INSERT INTO worktrees (
286
+ id, name, path, repository_path, repository_name, description,
287
+ last_user_message, last_user_message_at, last_message_summary, updated_at, cli_tool_id
288
+ )
289
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
290
+ ON CONFLICT(id) DO UPDATE SET
291
+ name = excluded.name,
292
+ path = excluded.path,
293
+ repository_path = excluded.repository_path,
294
+ repository_name = excluded.repository_name,
295
+ description = COALESCE(excluded.description, worktrees.description),
296
+ last_user_message = COALESCE(excluded.last_user_message, worktrees.last_user_message),
297
+ last_user_message_at = COALESCE(excluded.last_user_message_at, worktrees.last_user_message_at),
298
+ last_message_summary = COALESCE(excluded.last_message_summary, worktrees.last_message_summary),
299
+ updated_at = COALESCE(excluded.updated_at, worktrees.updated_at),
300
+ cli_tool_id = COALESCE(excluded.cli_tool_id, worktrees.cli_tool_id)
301
+ `);
302
+ stmt.run(worktree.id, worktree.name, worktree.path, worktree.repositoryPath || null, worktree.repositoryName || null, worktree.description || null, worktree.lastUserMessage || null, worktree.lastUserMessageAt?.getTime() || null, worktree.lastMessageSummary || null, worktree.updatedAt?.getTime() || null, worktree.cliToolId || 'claude');
303
+ }
304
+ /**
305
+ * Update worktree description
306
+ */
307
+ function updateWorktreeDescription(db, worktreeId, description) {
308
+ const stmt = db.prepare(`
309
+ UPDATE worktrees
310
+ SET description = ?
311
+ WHERE id = ?
312
+ `);
313
+ stmt.run(description || null, worktreeId);
314
+ }
315
+ /**
316
+ * Update worktree link
317
+ */
318
+ function updateWorktreeLink(db, worktreeId, link) {
319
+ const stmt = db.prepare(`
320
+ UPDATE worktrees
321
+ SET link = ?
322
+ WHERE id = ?
323
+ `);
324
+ stmt.run(link || null, worktreeId);
325
+ }
326
+ /**
327
+ * Update worktree's last_viewed_at timestamp
328
+ * Used for unread tracking (Issue #31)
329
+ */
330
+ function updateLastViewedAt(db, worktreeId, viewedAt) {
331
+ const stmt = db.prepare(`
332
+ UPDATE worktrees
333
+ SET last_viewed_at = ?
334
+ WHERE id = ?
335
+ `);
336
+ stmt.run(viewedAt.toISOString(), worktreeId);
337
+ }
338
+ /**
339
+ * Get the timestamp of the most recent assistant message for a worktree
340
+ * Used for unread tracking (Issue #31)
341
+ */
342
+ function getLastAssistantMessageAt(db, worktreeId) {
343
+ const stmt = db.prepare(`
344
+ SELECT MAX(timestamp) as last_assistant_message_at
345
+ FROM chat_messages
346
+ WHERE worktree_id = ? AND role = 'assistant'
347
+ `);
348
+ const row = stmt.get(worktreeId);
349
+ if (!row || row.last_assistant_message_at === null) {
350
+ return null;
351
+ }
352
+ return new Date(row.last_assistant_message_at);
353
+ }
354
+ /**
355
+ * Create a new chat message
356
+ */
357
+ function createMessage(db, message) {
358
+ const id = (0, crypto_1.randomUUID)();
359
+ const stmt = db.prepare(`
360
+ INSERT INTO chat_messages
361
+ (id, worktree_id, role, content, summary, timestamp, log_file_name, request_id, message_type, prompt_data, cli_tool_id)
362
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
363
+ `);
364
+ stmt.run(id, message.worktreeId, message.role, message.content, message.summary || null, message.timestamp.getTime(), message.logFileName || null, message.requestId || null, message.messageType || 'normal', message.promptData ? JSON.stringify(message.promptData) : null, message.cliToolId || 'claude');
365
+ // Update worktree's updated_at timestamp
366
+ updateWorktreeTimestamp(db, message.worktreeId, message.timestamp);
367
+ // If this is a user message, update last_user_message
368
+ if (message.role === 'user') {
369
+ updateLastUserMessage(db, message.worktreeId, message.content, message.timestamp);
370
+ }
371
+ return { id, ...message };
372
+ }
373
+ function updateMessageContent(db, messageId, content, options) {
374
+ const assignments = ['content = ?'];
375
+ const params = [content];
376
+ if (options?.summary !== undefined) {
377
+ assignments.push('summary = ?');
378
+ params.push(options.summary ?? null);
379
+ }
380
+ if (options?.logFileName !== undefined) {
381
+ assignments.push('log_file_name = ?');
382
+ params.push(options.logFileName ?? null);
383
+ }
384
+ if (options?.requestId !== undefined) {
385
+ assignments.push('request_id = ?');
386
+ params.push(options.requestId ?? null);
387
+ }
388
+ const stmt = db.prepare(`
389
+ UPDATE chat_messages
390
+ SET ${assignments.join(', ')}
391
+ WHERE id = ?
392
+ `);
393
+ stmt.run(...params, messageId);
394
+ }
395
+ /**
396
+ * Get messages for a worktree, optionally filtered by CLI tool
397
+ */
398
+ function getMessages(db, worktreeId, before, limit = 50, cliToolId) {
399
+ let query = `
400
+ SELECT id, worktree_id, role, content, summary, timestamp, log_file_name, request_id, message_type, prompt_data, cli_tool_id
401
+ FROM chat_messages
402
+ WHERE worktree_id = ? AND (? IS NULL OR timestamp < ?)
403
+ `;
404
+ const params = [worktreeId, before?.getTime() || null, before?.getTime() || null];
405
+ // Add CLI tool filter if specified
406
+ if (cliToolId) {
407
+ query += ` AND cli_tool_id = ?`;
408
+ params.push(cliToolId);
409
+ }
410
+ query += ` ORDER BY timestamp DESC LIMIT ?`;
411
+ params.push(limit);
412
+ const stmt = db.prepare(query);
413
+ const rows = stmt.all(...params);
414
+ return rows.map(mapChatMessage);
415
+ }
416
+ /**
417
+ * Fetch the most recent user-authored message for a worktree.
418
+ */
419
+ function getLastUserMessage(db, worktreeId) {
420
+ const stmt = db.prepare(`
421
+ SELECT id, worktree_id, role, content, summary, timestamp, log_file_name, request_id, message_type, prompt_data, cli_tool_id
422
+ FROM chat_messages
423
+ WHERE worktree_id = ? AND role = 'user'
424
+ ORDER BY timestamp DESC
425
+ LIMIT 1
426
+ `);
427
+ const row = stmt.get(worktreeId);
428
+ return row ? mapChatMessage(row) : null;
429
+ }
430
+ /**
431
+ * Fetch the most recent message for a worktree (any role).
432
+ * Used to determine if waiting for Claude's response.
433
+ */
434
+ function getLastMessage(db, worktreeId) {
435
+ const stmt = db.prepare(`
436
+ SELECT id, worktree_id, role, content, summary, timestamp, log_file_name, request_id, message_type, prompt_data, cli_tool_id
437
+ FROM chat_messages
438
+ WHERE worktree_id = ?
439
+ ORDER BY timestamp DESC
440
+ LIMIT 1
441
+ `);
442
+ const row = stmt.get(worktreeId);
443
+ return row ? mapChatMessage(row) : null;
444
+ }
445
+ /**
446
+ * Delete all messages for a worktree
447
+ * Used when killing a session to clear message history
448
+ * Note: Log files are preserved for historical reference
449
+ */
450
+ function deleteAllMessages(db, worktreeId) {
451
+ const stmt = db.prepare(`
452
+ DELETE FROM chat_messages
453
+ WHERE worktree_id = ?
454
+ `);
455
+ stmt.run(worktreeId);
456
+ console.log(`[deleteAllMessages] Deleted all messages for worktree: ${worktreeId}`);
457
+ }
458
+ /**
459
+ * Get session state for a worktree
460
+ */
461
+ function getSessionState(db, worktreeId, cliToolId = 'claude') {
462
+ const stmt = db.prepare(`
463
+ SELECT worktree_id, cli_tool_id, last_captured_line, in_progress_message_id
464
+ FROM session_states
465
+ WHERE worktree_id = ? AND cli_tool_id = ?
466
+ `);
467
+ const row = stmt.get(worktreeId, cliToolId);
468
+ if (!row) {
469
+ return null;
470
+ }
471
+ return {
472
+ worktreeId: row.worktree_id,
473
+ cliToolId: row.cli_tool_id,
474
+ lastCapturedLine: row.last_captured_line,
475
+ inProgressMessageId: row.in_progress_message_id || null,
476
+ };
477
+ }
478
+ /**
479
+ * Update session state for a worktree
480
+ */
481
+ function updateSessionState(db, worktreeId, cliToolId, lastCapturedLine) {
482
+ const stmt = db.prepare(`
483
+ INSERT INTO session_states (worktree_id, cli_tool_id, last_captured_line)
484
+ VALUES (?, ?, ?)
485
+ ON CONFLICT(worktree_id, cli_tool_id) DO UPDATE SET
486
+ last_captured_line = excluded.last_captured_line
487
+ `);
488
+ stmt.run(worktreeId, cliToolId, lastCapturedLine);
489
+ }
490
+ /**
491
+ * Set the in-progress message ID for a session
492
+ */
493
+ function setInProgressMessageId(db, worktreeId, cliToolId, messageId) {
494
+ const stmt = db.prepare(`
495
+ INSERT INTO session_states (worktree_id, cli_tool_id, last_captured_line, in_progress_message_id)
496
+ VALUES (?, ?, 0, ?)
497
+ ON CONFLICT(worktree_id, cli_tool_id) DO UPDATE SET
498
+ in_progress_message_id = excluded.in_progress_message_id
499
+ `);
500
+ stmt.run(worktreeId, cliToolId, messageId);
501
+ }
502
+ /**
503
+ * Clear the in-progress message ID for a session
504
+ */
505
+ function clearInProgressMessageId(db, worktreeId, cliToolId) {
506
+ setInProgressMessageId(db, worktreeId, cliToolId, null);
507
+ }
508
+ /**
509
+ * Delete session state for a worktree
510
+ * Called when a session is killed or reset
511
+ */
512
+ function deleteSessionState(db, worktreeId, cliToolId) {
513
+ if (cliToolId) {
514
+ const stmt = db.prepare(`
515
+ DELETE FROM session_states
516
+ WHERE worktree_id = ? AND cli_tool_id = ?
517
+ `);
518
+ stmt.run(worktreeId, cliToolId);
519
+ }
520
+ else {
521
+ const stmt = db.prepare(`
522
+ DELETE FROM session_states
523
+ WHERE worktree_id = ?
524
+ `);
525
+ stmt.run(worktreeId);
526
+ }
527
+ }
528
+ /**
529
+ * Update worktree's updated_at timestamp
530
+ * @private
531
+ */
532
+ function updateWorktreeTimestamp(db, worktreeId, timestamp) {
533
+ const stmt = db.prepare(`
534
+ UPDATE worktrees
535
+ SET updated_at = ?
536
+ WHERE id = ?
537
+ `);
538
+ stmt.run(timestamp.getTime(), worktreeId);
539
+ }
540
+ /**
541
+ * Update worktree's last user message
542
+ */
543
+ function updateLastUserMessage(db, worktreeId, message, timestamp) {
544
+ const stmt = db.prepare(`
545
+ UPDATE worktrees
546
+ SET last_user_message = ?,
547
+ last_user_message_at = ?
548
+ WHERE id = ?
549
+ `);
550
+ // Truncate message to 200 characters
551
+ const truncatedMessage = message.substring(0, 200);
552
+ stmt.run(truncatedMessage, timestamp.getTime(), worktreeId);
553
+ }
554
+ /**
555
+ * Get message by ID
556
+ */
557
+ function getMessageById(db, messageId) {
558
+ const stmt = db.prepare(`
559
+ SELECT id, worktree_id, role, content, summary, timestamp, log_file_name, request_id, message_type, prompt_data, cli_tool_id
560
+ FROM chat_messages
561
+ WHERE id = ?
562
+ `);
563
+ const row = stmt.get(messageId);
564
+ if (!row) {
565
+ return null;
566
+ }
567
+ return mapChatMessage(row);
568
+ }
569
+ /**
570
+ * Update prompt data for a message
571
+ */
572
+ function updatePromptData(db, messageId, promptData) {
573
+ const stmt = db.prepare(`
574
+ UPDATE chat_messages
575
+ SET prompt_data = ?
576
+ WHERE id = ?
577
+ `);
578
+ stmt.run(JSON.stringify(promptData), messageId);
579
+ }
580
+ /**
581
+ * Mark all pending prompts as answered for a worktree/CLI tool
582
+ * This is called when we detect Claude has started processing (new response detected)
583
+ * which means any pending prompts must have been answered via terminal
584
+ */
585
+ function markPendingPromptsAsAnswered(db, worktreeId, cliToolId) {
586
+ // Find all pending prompt messages for this worktree/CLI tool
587
+ const selectStmt = db.prepare(`
588
+ SELECT id, prompt_data
589
+ FROM chat_messages
590
+ WHERE worktree_id = ?
591
+ AND cli_tool_id = ?
592
+ AND message_type = 'prompt'
593
+ AND json_extract(prompt_data, '$.status') = 'pending'
594
+ ORDER BY timestamp DESC
595
+ `);
596
+ const rows = selectStmt.all(worktreeId, cliToolId);
597
+ if (rows.length === 0) {
598
+ return 0;
599
+ }
600
+ // Update each pending prompt to answered
601
+ const updateStmt = db.prepare(`
602
+ UPDATE chat_messages
603
+ SET prompt_data = ?
604
+ WHERE id = ?
605
+ `);
606
+ let updatedCount = 0;
607
+ for (const row of rows) {
608
+ try {
609
+ const promptData = JSON.parse(row.prompt_data);
610
+ promptData.status = 'answered';
611
+ promptData.answer = '(answered via terminal)';
612
+ promptData.answeredAt = new Date().toISOString();
613
+ updateStmt.run(JSON.stringify(promptData), row.id);
614
+ updatedCount++;
615
+ }
616
+ catch {
617
+ // Skip if prompt_data is invalid JSON
618
+ }
619
+ }
620
+ return updatedCount;
621
+ }
622
+ /**
623
+ * Update favorite status for a worktree
624
+ */
625
+ function updateFavorite(db, id, favorite) {
626
+ const stmt = db.prepare(`
627
+ UPDATE worktrees
628
+ SET favorite = ?
629
+ WHERE id = ?
630
+ `);
631
+ stmt.run(favorite ? 1 : 0, id);
632
+ }
633
+ /**
634
+ * Update status for a worktree
635
+ */
636
+ function updateStatus(db, id, status) {
637
+ const stmt = db.prepare(`
638
+ UPDATE worktrees
639
+ SET status = ?
640
+ WHERE id = ?
641
+ `);
642
+ stmt.run(status, id);
643
+ }
644
+ /**
645
+ * Update CLI tool ID for a worktree
646
+ */
647
+ function updateCliToolId(db, id, cliToolId) {
648
+ const stmt = db.prepare(`
649
+ UPDATE worktrees
650
+ SET cli_tool_id = ?
651
+ WHERE id = ?
652
+ `);
653
+ stmt.run(cliToolId, id);
654
+ }
655
+ /**
656
+ * Map database row to WorktreeMemo model
657
+ */
658
+ function mapMemoRow(row) {
659
+ return {
660
+ id: row.id,
661
+ worktreeId: row.worktree_id,
662
+ title: row.title,
663
+ content: row.content,
664
+ position: row.position,
665
+ createdAt: new Date(row.created_at),
666
+ updatedAt: new Date(row.updated_at),
667
+ };
668
+ }
669
+ /**
670
+ * Get all memos for a worktree, sorted by position
671
+ */
672
+ function getMemosByWorktreeId(db, worktreeId) {
673
+ const stmt = db.prepare(`
674
+ SELECT id, worktree_id, title, content, position, created_at, updated_at
675
+ FROM worktree_memos
676
+ WHERE worktree_id = ?
677
+ ORDER BY position ASC
678
+ `);
679
+ const rows = stmt.all(worktreeId);
680
+ return rows.map(mapMemoRow);
681
+ }
682
+ /**
683
+ * Get a memo by ID
684
+ *
685
+ * @param db - Database instance
686
+ * @param memoId - ID of the memo
687
+ * @returns Memo or null if not found
688
+ */
689
+ function getMemoById(db, memoId) {
690
+ const stmt = db.prepare(`
691
+ SELECT id, worktree_id, title, content, position, created_at, updated_at
692
+ FROM worktree_memos
693
+ WHERE id = ?
694
+ `);
695
+ const row = stmt.get(memoId);
696
+ return row ? mapMemoRow(row) : null;
697
+ }
698
+ /**
699
+ * Create a new memo for a worktree
700
+ *
701
+ * @param db - Database instance
702
+ * @param worktreeId - ID of the worktree
703
+ * @param options - Memo options (title, content, position)
704
+ * @returns Created memo
705
+ */
706
+ function createMemo(db, worktreeId, options) {
707
+ const id = (0, crypto_1.randomUUID)();
708
+ const now = Date.now();
709
+ const title = options.title ?? 'Memo';
710
+ const content = options.content ?? '';
711
+ const stmt = db.prepare(`
712
+ INSERT INTO worktree_memos (id, worktree_id, title, content, position, created_at, updated_at)
713
+ VALUES (?, ?, ?, ?, ?, ?, ?)
714
+ `);
715
+ stmt.run(id, worktreeId, title, content, options.position, now, now);
716
+ return {
717
+ id,
718
+ worktreeId,
719
+ title,
720
+ content,
721
+ position: options.position,
722
+ createdAt: new Date(now),
723
+ updatedAt: new Date(now),
724
+ };
725
+ }
726
+ /**
727
+ * Update an existing memo
728
+ *
729
+ * @param db - Database instance
730
+ * @param memoId - ID of the memo to update
731
+ * @param updates - Fields to update (title and/or content)
732
+ */
733
+ function updateMemo(db, memoId, updates) {
734
+ const now = Date.now();
735
+ const assignments = ['updated_at = ?'];
736
+ const params = [now];
737
+ if (updates.title !== undefined) {
738
+ assignments.push('title = ?');
739
+ params.push(updates.title);
740
+ }
741
+ if (updates.content !== undefined) {
742
+ assignments.push('content = ?');
743
+ params.push(updates.content);
744
+ }
745
+ params.push(memoId);
746
+ const stmt = db.prepare(`
747
+ UPDATE worktree_memos
748
+ SET ${assignments.join(', ')}
749
+ WHERE id = ?
750
+ `);
751
+ stmt.run(...params);
752
+ }
753
+ /**
754
+ * Delete a memo by ID
755
+ *
756
+ * @param db - Database instance
757
+ * @param memoId - ID of the memo to delete
758
+ */
759
+ function deleteMemo(db, memoId) {
760
+ const stmt = db.prepare(`
761
+ DELETE FROM worktree_memos
762
+ WHERE id = ?
763
+ `);
764
+ stmt.run(memoId);
765
+ }
766
+ /**
767
+ * Reorder memos for a worktree
768
+ *
769
+ * Uses a two-step approach to handle UNIQUE constraint on (worktree_id, position):
770
+ * 1. Set all positions to negative values (temporary)
771
+ * 2. Set new positions from the provided order
772
+ *
773
+ * @param db - Database instance
774
+ * @param worktreeId - ID of the worktree
775
+ * @param memoIds - Array of memo IDs in the desired order
776
+ */
777
+ function reorderMemos(db, worktreeId, memoIds) {
778
+ if (memoIds.length === 0) {
779
+ return;
780
+ }
781
+ const now = Date.now();
782
+ db.transaction(() => {
783
+ // Step 1: Set all positions to negative values (to avoid UNIQUE constraint violations)
784
+ const resetStmt = db.prepare(`
785
+ UPDATE worktree_memos
786
+ SET position = -1 - position
787
+ WHERE id = ?
788
+ `);
789
+ for (const memoId of memoIds) {
790
+ resetStmt.run(memoId);
791
+ }
792
+ // Step 2: Set new positions based on array order
793
+ const updateStmt = db.prepare(`
794
+ UPDATE worktree_memos
795
+ SET position = ?, updated_at = ?
796
+ WHERE id = ?
797
+ `);
798
+ memoIds.forEach((memoId, index) => {
799
+ updateStmt.run(index, now, memoId);
800
+ });
801
+ })();
802
+ }
803
+ // ============================================================
804
+ // Repository Delete Operations (Issue #69)
805
+ // ============================================================
806
+ /**
807
+ * Get all worktree IDs for a given repository path
808
+ *
809
+ * @param db - Database instance
810
+ * @param repositoryPath - Path of the repository
811
+ * @returns Array of worktree IDs
812
+ */
813
+ function getWorktreeIdsByRepository(db, repositoryPath) {
814
+ const stmt = db.prepare(`
815
+ SELECT id FROM worktrees WHERE repository_path = ?
816
+ `);
817
+ const rows = stmt.all(repositoryPath);
818
+ return rows.map(r => r.id);
819
+ }
820
+ /**
821
+ * Delete all worktrees for a given repository path
822
+ * Related data (chat_messages, session_states, worktree_memos) will be
823
+ * automatically deleted via CASCADE foreign key constraints.
824
+ *
825
+ * @param db - Database instance
826
+ * @param repositoryPath - Path of the repository to delete
827
+ * @returns Object containing the count of deleted worktrees
828
+ */
829
+ function deleteRepositoryWorktrees(db, repositoryPath) {
830
+ const stmt = db.prepare(`
831
+ DELETE FROM worktrees WHERE repository_path = ?
832
+ `);
833
+ const result = stmt.run(repositoryPath);
834
+ return { deletedCount: result.changes };
835
+ }