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,179 @@
1
+ "use strict";
2
+ /**
3
+ * Environment variable configuration and validation
4
+ * Provides type-safe access to environment variables
5
+ *
6
+ * Issue #76: Environment variable fallback support
7
+ * Supports both new (CM_*) and legacy (MCBD_*) environment variable names
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ENV_MAPPING = void 0;
14
+ exports.resetWarnedKeys = resetWarnedKeys;
15
+ exports.getEnvWithFallback = getEnvWithFallback;
16
+ exports.getEnvByKey = getEnvByKey;
17
+ exports.getLogConfig = getLogConfig;
18
+ exports.getEnv = getEnv;
19
+ exports.validateEnv = validateEnv;
20
+ exports.isAuthRequired = isAuthRequired;
21
+ const path_1 = __importDefault(require("path"));
22
+ // ============================================================
23
+ // Environment Variable Mapping (for fallback support)
24
+ // Issue #76: CommandMate rename - Phase 1
25
+ // ============================================================
26
+ /**
27
+ * Environment variable mapping definition
28
+ * New name -> Old name mapping for fallback support
29
+ */
30
+ exports.ENV_MAPPING = {
31
+ CM_ROOT_DIR: 'MCBD_ROOT_DIR',
32
+ CM_PORT: 'MCBD_PORT',
33
+ CM_BIND: 'MCBD_BIND',
34
+ CM_AUTH_TOKEN: 'MCBD_AUTH_TOKEN',
35
+ CM_LOG_LEVEL: 'MCBD_LOG_LEVEL',
36
+ CM_LOG_FORMAT: 'MCBD_LOG_FORMAT',
37
+ CM_LOG_DIR: 'MCBD_LOG_DIR',
38
+ CM_DB_PATH: 'MCBD_DB_PATH',
39
+ };
40
+ /**
41
+ * Set to track warned keys and prevent duplicate warnings
42
+ * Module-scoped to persist across function calls
43
+ */
44
+ const warnedKeys = new Set();
45
+ /**
46
+ * Reset warned keys (for testing purposes)
47
+ */
48
+ function resetWarnedKeys() {
49
+ warnedKeys.clear();
50
+ }
51
+ /**
52
+ * Get environment variable with fallback support
53
+ *
54
+ * @param newKey - New environment variable name (CM_*)
55
+ * @param oldKey - Old environment variable name (MCBD_*)
56
+ * @returns Environment variable value (undefined if not set)
57
+ */
58
+ function getEnvWithFallback(newKey, oldKey) {
59
+ const newValue = process.env[newKey];
60
+ if (newValue !== undefined) {
61
+ return newValue;
62
+ }
63
+ const oldValue = process.env[oldKey];
64
+ if (oldValue !== undefined) {
65
+ if (!warnedKeys.has(oldKey)) {
66
+ console.warn(`[DEPRECATED] ${oldKey} is deprecated, use ${newKey} instead`);
67
+ warnedKeys.add(oldKey);
68
+ }
69
+ return oldValue;
70
+ }
71
+ return undefined;
72
+ }
73
+ /**
74
+ * Get environment variable using ENV_MAPPING (type-safe version)
75
+ *
76
+ * @param key - New environment variable key (from ENV_MAPPING)
77
+ * @returns Environment variable value (undefined if not set)
78
+ */
79
+ function getEnvByKey(key) {
80
+ return getEnvWithFallback(key, exports.ENV_MAPPING[key]);
81
+ }
82
+ /**
83
+ * Validate log level
84
+ */
85
+ function isValidLogLevel(level) {
86
+ return level !== undefined && ['debug', 'info', 'warn', 'error'].includes(level);
87
+ }
88
+ /**
89
+ * Get log configuration (with fallback support)
90
+ *
91
+ * @returns Log configuration with level and format
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const config = getLogConfig();
96
+ * console.log(config.level); // 'debug' in development, 'info' in production
97
+ * console.log(config.format); // 'text' or 'json'
98
+ * ```
99
+ */
100
+ function getLogConfig() {
101
+ const levelEnv = getEnvByKey('CM_LOG_LEVEL')?.toLowerCase();
102
+ const formatEnv = getEnvByKey('CM_LOG_FORMAT')?.toLowerCase();
103
+ // Default: debug in development, info in production
104
+ const defaultLevel = process.env.NODE_ENV === 'production' ? 'info' : 'debug';
105
+ return {
106
+ level: isValidLogLevel(levelEnv) ? levelEnv : defaultLevel,
107
+ format: formatEnv === 'json' ? 'json' : 'text',
108
+ };
109
+ }
110
+ /**
111
+ * Get and validate environment variables (with fallback support)
112
+ *
113
+ * @throws {Error} If required variables are missing or invalid
114
+ * @returns Validated environment configuration
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const env = getEnv();
119
+ * console.log(`Root directory: ${env.CM_ROOT_DIR}`);
120
+ * ```
121
+ */
122
+ function getEnv() {
123
+ // Get raw values with defaults (using fallback support)
124
+ const rootDir = getEnvByKey('CM_ROOT_DIR') || process.cwd();
125
+ const port = parseInt(getEnvByKey('CM_PORT') || '3000', 10);
126
+ const bind = getEnvByKey('CM_BIND') || '127.0.0.1';
127
+ const authToken = getEnvByKey('CM_AUTH_TOKEN');
128
+ const databasePath = getEnvByKey('CM_DB_PATH')
129
+ || process.env.DATABASE_PATH
130
+ || path_1.default.join(process.cwd(), 'data', 'cm.db');
131
+ // Validate values
132
+ if (!rootDir) {
133
+ throw new Error('CM_ROOT_DIR (or MCBD_ROOT_DIR) is required');
134
+ }
135
+ if (isNaN(port) || port < 1 || port > 65535) {
136
+ throw new Error(`Invalid CM_PORT: ${getEnvByKey('CM_PORT')}. Must be between 1 and 65535.`);
137
+ }
138
+ if (bind !== '127.0.0.1' && bind !== '0.0.0.0' && bind !== 'localhost') {
139
+ throw new Error(`Invalid CM_BIND: ${bind}. Must be '127.0.0.1', '0.0.0.0', or 'localhost'.`);
140
+ }
141
+ // Require auth token for public binding
142
+ if (bind === '0.0.0.0' && !authToken) {
143
+ throw new Error('CM_AUTH_TOKEN (or MCBD_AUTH_TOKEN) is required when CM_BIND=0.0.0.0');
144
+ }
145
+ return {
146
+ CM_ROOT_DIR: path_1.default.resolve(rootDir),
147
+ CM_PORT: port,
148
+ CM_BIND: bind,
149
+ CM_AUTH_TOKEN: authToken,
150
+ CM_DB_PATH: path_1.default.resolve(databasePath),
151
+ };
152
+ }
153
+ /**
154
+ * Validate environment variables without throwing
155
+ *
156
+ * @returns Validation result with errors if any
157
+ */
158
+ function validateEnv() {
159
+ const errors = [];
160
+ try {
161
+ getEnv();
162
+ return { valid: true, errors: [] };
163
+ }
164
+ catch (error) {
165
+ if (error instanceof Error) {
166
+ errors.push(error.message);
167
+ }
168
+ return { valid: false, errors };
169
+ }
170
+ }
171
+ /**
172
+ * Check if authentication is required based on bind address
173
+ *
174
+ * @returns True if authentication is required
175
+ */
176
+ function isAuthRequired() {
177
+ const env = getEnv();
178
+ return env.CM_BIND === '0.0.0.0';
179
+ }
@@ -0,0 +1,234 @@
1
+ "use strict";
2
+ /**
3
+ * Log file management for Claude output
4
+ * Generates and manages Markdown log files from Claude's responses
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.getLogFilePath = getLogFilePath;
11
+ exports.createLog = createLog;
12
+ exports.appendToLog = appendToLog;
13
+ exports.readLog = readLog;
14
+ exports.listLogs = listLogs;
15
+ exports.cleanupOldLogs = cleanupOldLogs;
16
+ const promises_1 = __importDefault(require("fs/promises"));
17
+ const path_1 = __importDefault(require("path"));
18
+ const date_fns_1 = require("date-fns");
19
+ const env_1 = require("./env");
20
+ /**
21
+ * Log directory configuration (with fallback support - Issue #76)
22
+ */
23
+ const LOG_DIR = (0, env_1.getEnvByKey)('CM_LOG_DIR') || path_1.default.join(process.cwd(), 'data', 'logs');
24
+ /**
25
+ * Get log directory for a CLI tool
26
+ *
27
+ * @param cliToolId - CLI tool ID (claude, codex, gemini)
28
+ * @returns Log directory path
29
+ */
30
+ function getCliToolLogDir(cliToolId = 'claude') {
31
+ return path_1.default.join(LOG_DIR, cliToolId);
32
+ }
33
+ /**
34
+ * Ensure log directory exists
35
+ *
36
+ * @param cliToolId - CLI tool ID (optional, defaults to 'claude')
37
+ */
38
+ async function ensureLogDirectory(cliToolId = 'claude') {
39
+ const logDir = getCliToolLogDir(cliToolId);
40
+ try {
41
+ await promises_1.default.access(logDir);
42
+ }
43
+ catch {
44
+ await promises_1.default.mkdir(logDir, { recursive: true });
45
+ }
46
+ }
47
+ /**
48
+ * Get log file path for a worktree
49
+ *
50
+ * @param worktreeId - Worktree ID
51
+ * @param cliToolId - CLI tool ID (claude, codex, gemini)
52
+ * @returns Log file path
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * getLogFilePath('feature-foo', 'claude')
57
+ * // => '/path/to/data/logs/claude/feature-foo-2025-01-20.md'
58
+ * ```
59
+ */
60
+ function getLogFilePath(worktreeId, cliToolId = 'claude') {
61
+ const date = (0, date_fns_1.format)(new Date(), 'yyyy-MM-dd');
62
+ const filename = `${worktreeId}-${date}.md`;
63
+ const logDir = getCliToolLogDir(cliToolId);
64
+ return path_1.default.join(logDir, filename);
65
+ }
66
+ /**
67
+ * Create a Markdown log file for a conversation
68
+ *
69
+ * @param worktreeId - Worktree ID
70
+ * @param userMessage - User's message
71
+ * @param claudeResponse - Claude's response
72
+ * @param cliToolId - CLI tool ID (claude, codex, gemini)
73
+ * @returns Path to the created log file
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const logPath = await createLog(
78
+ * 'feature-foo',
79
+ * 'Explain this code',
80
+ * 'This code implements...',
81
+ * 'claude'
82
+ * );
83
+ * ```
84
+ */
85
+ async function createLog(worktreeId, userMessage, claudeResponse, cliToolId = 'claude') {
86
+ await ensureLogDirectory(cliToolId);
87
+ const logPath = getLogFilePath(worktreeId, cliToolId);
88
+ const timestamp = (0, date_fns_1.format)(new Date(), 'yyyy-MM-dd HH:mm:ss');
89
+ // Check if log file already exists
90
+ let logContent = '';
91
+ try {
92
+ logContent = await promises_1.default.readFile(logPath, 'utf-8');
93
+ }
94
+ catch {
95
+ // File doesn't exist, create header
96
+ const toolName = cliToolId === 'claude' ? 'Claude Code' : cliToolId === 'codex' ? 'Codex CLI' : 'Gemini CLI';
97
+ logContent = `# ${toolName} Conversation Log: ${worktreeId}\n\n`;
98
+ logContent += `Created: ${timestamp}\n\n`;
99
+ logContent += `---\n\n`;
100
+ }
101
+ // Append new conversation
102
+ logContent += `## Conversation at ${timestamp}\n\n`;
103
+ logContent += `### User\n\n`;
104
+ logContent += `${userMessage}\n\n`;
105
+ logContent += `### ${cliToolId === 'claude' ? 'Claude' : cliToolId === 'codex' ? 'Codex' : 'Gemini'}\n\n`;
106
+ logContent += `${claudeResponse}\n\n`;
107
+ logContent += `---\n\n`;
108
+ await promises_1.default.writeFile(logPath, logContent, 'utf-8');
109
+ return logPath;
110
+ }
111
+ /**
112
+ * Append to existing log file
113
+ *
114
+ * @param worktreeId - Worktree ID
115
+ * @param content - Content to append
116
+ * @param cliToolId - CLI tool ID (claude, codex, gemini)
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * await appendToLog('feature-foo', 'Additional notes...', 'claude');
121
+ * ```
122
+ */
123
+ async function appendToLog(worktreeId, content, cliToolId = 'claude') {
124
+ await ensureLogDirectory(cliToolId);
125
+ const logPath = getLogFilePath(worktreeId, cliToolId);
126
+ const timestamp = (0, date_fns_1.format)(new Date(), 'yyyy-MM-dd HH:mm:ss');
127
+ let logContent = '';
128
+ try {
129
+ logContent = await promises_1.default.readFile(logPath, 'utf-8');
130
+ }
131
+ catch {
132
+ // File doesn't exist, create header
133
+ const toolName = cliToolId === 'claude' ? 'Claude Code' : cliToolId === 'codex' ? 'Codex CLI' : 'Gemini CLI';
134
+ logContent = `# ${toolName} Conversation Log: ${worktreeId}\n\n`;
135
+ logContent += `Created: ${timestamp}\n\n`;
136
+ logContent += `---\n\n`;
137
+ }
138
+ logContent += `${content}\n\n`;
139
+ await promises_1.default.writeFile(logPath, logContent, 'utf-8');
140
+ }
141
+ /**
142
+ * Read log file content
143
+ *
144
+ * @param worktreeId - Worktree ID
145
+ * @param cliToolId - CLI tool ID (claude, codex, gemini)
146
+ * @returns Log file content, or null if file doesn't exist
147
+ *
148
+ * @example
149
+ * ```typescript
150
+ * const log = await readLog('feature-foo', 'claude');
151
+ * if (log) {
152
+ * console.log(log);
153
+ * }
154
+ * ```
155
+ */
156
+ async function readLog(worktreeId, cliToolId = 'claude') {
157
+ const logPath = getLogFilePath(worktreeId, cliToolId);
158
+ try {
159
+ return await promises_1.default.readFile(logPath, 'utf-8');
160
+ }
161
+ catch {
162
+ return null;
163
+ }
164
+ }
165
+ /**
166
+ * List all log files for a worktree
167
+ *
168
+ * @param worktreeId - Worktree ID
169
+ * @param cliToolId - CLI tool ID (claude, codex, gemini), or 'all' for all tools
170
+ * @returns Array of log file paths
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * const logs = await listLogs('feature-foo', 'claude');
175
+ * // => ['/path/to/logs/claude/feature-foo-2025-01-20.md', '/path/to/logs/claude/feature-foo-2025-01-19.md']
176
+ * ```
177
+ */
178
+ async function listLogs(worktreeId, cliToolId = 'all') {
179
+ const toolIds = cliToolId === 'all' ? ['claude', 'codex', 'gemini'] : [cliToolId];
180
+ const allLogFiles = [];
181
+ for (const toolId of toolIds) {
182
+ await ensureLogDirectory(toolId);
183
+ const logDir = getCliToolLogDir(toolId);
184
+ try {
185
+ const files = await promises_1.default.readdir(logDir);
186
+ const logFiles = files
187
+ .filter((file) => file.startsWith(`${worktreeId}-`) && file.endsWith('.md'))
188
+ .map((file) => path_1.default.join(logDir, file));
189
+ allLogFiles.push(...logFiles);
190
+ }
191
+ catch {
192
+ // Directory doesn't exist or is not accessible, skip
193
+ }
194
+ }
195
+ return allLogFiles.sort().reverse(); // Most recent first
196
+ }
197
+ /**
198
+ * Delete old log files (older than specified days)
199
+ *
200
+ * @param days - Number of days to keep
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * // Delete logs older than 30 days
205
+ * await cleanupOldLogs(30);
206
+ * ```
207
+ */
208
+ async function cleanupOldLogs(days = 30) {
209
+ const toolIds = ['claude', 'codex', 'gemini'];
210
+ let totalDeletedCount = 0;
211
+ const now = new Date();
212
+ const cutoffDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);
213
+ for (const toolId of toolIds) {
214
+ await ensureLogDirectory(toolId);
215
+ const logDir = getCliToolLogDir(toolId);
216
+ try {
217
+ const files = await promises_1.default.readdir(logDir);
218
+ for (const file of files) {
219
+ if (!file.endsWith('.md'))
220
+ continue;
221
+ const filePath = path_1.default.join(logDir, file);
222
+ const stats = await promises_1.default.stat(filePath);
223
+ if (stats.mtime < cutoffDate) {
224
+ await promises_1.default.unlink(filePath);
225
+ totalDeletedCount++;
226
+ }
227
+ }
228
+ }
229
+ catch (error) {
230
+ console.error(`Error cleaning up old logs for ${toolId}:`, error);
231
+ }
232
+ }
233
+ return totalDeletedCount;
234
+ }
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ /**
3
+ * Structured logging utility for CommandMate
4
+ *
5
+ * Issue #41: Structured logging + log level control
6
+ *
7
+ * Features:
8
+ * - [MF-1] Sensitive data filtering (sanitize)
9
+ * - [MF-2] Server/Client log separation
10
+ * - [SF-2] Request ID generation
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const logger = createLogger('prompt-detector');
15
+ * logger.debug('detectPrompt:start', { outputLength: 1500 });
16
+ *
17
+ * const log = logger.withContext({ worktreeId: 'wt-1', requestId: generateRequestId() });
18
+ * log.info('action:complete', { result: 'success' });
19
+ * ```
20
+ */
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.generateRequestId = generateRequestId;
23
+ exports.createLogger = createLogger;
24
+ const env_1 = require("./env");
25
+ // ============================================================
26
+ // [MF-1] Sensitive Data Filtering
27
+ // ============================================================
28
+ /**
29
+ * Sensitive data patterns
30
+ */
31
+ const SENSITIVE_PATTERNS = [
32
+ // Bearer token
33
+ { pattern: /Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, replacement: 'Bearer [REDACTED]' },
34
+ // Password related
35
+ { pattern: /(password|passwd|pwd)[=:]\s*\S+/gi, replacement: '$1=[REDACTED]' },
36
+ // Token/secret related
37
+ { pattern: /(token|secret|api_key|apikey|auth)[=:]\s*\S+/gi, replacement: '$1=[REDACTED]' },
38
+ // CM_AUTH_TOKEN (new name - Issue #76)
39
+ { pattern: /CM_AUTH_TOKEN=\S+/gi, replacement: 'CM_AUTH_TOKEN=[REDACTED]' },
40
+ // MCBD_AUTH_TOKEN (legacy name)
41
+ { pattern: /MCBD_AUTH_TOKEN=\S+/gi, replacement: 'MCBD_AUTH_TOKEN=[REDACTED]' },
42
+ // Authorization header
43
+ { pattern: /Authorization:\s*\S+/gi, replacement: 'Authorization: [REDACTED]' },
44
+ // SSH key
45
+ { pattern: /-----BEGIN\s+\w+\s+PRIVATE\s+KEY-----[\s\S]*?-----END\s+\w+\s+PRIVATE\s+KEY-----/g, replacement: '[SSH_KEY_REDACTED]' },
46
+ ];
47
+ /**
48
+ * Sensitive key name patterns
49
+ */
50
+ const SENSITIVE_KEY_PATTERN = /password|secret|token|key|auth/i;
51
+ /**
52
+ * Sanitize value (mask sensitive data)
53
+ */
54
+ function sanitize(value) {
55
+ if (typeof value === 'string') {
56
+ let sanitized = value;
57
+ for (const { pattern, replacement } of SENSITIVE_PATTERNS) {
58
+ sanitized = sanitized.replace(pattern, replacement);
59
+ }
60
+ return sanitized;
61
+ }
62
+ if (typeof value === 'object' && value !== null) {
63
+ if (Array.isArray(value)) {
64
+ return value.map(sanitize);
65
+ }
66
+ const result = {};
67
+ for (const [k, v] of Object.entries(value)) {
68
+ // Mask if key name is sensitive
69
+ if (SENSITIVE_KEY_PATTERN.test(k)) {
70
+ result[k] = '[REDACTED]';
71
+ }
72
+ else {
73
+ result[k] = sanitize(v);
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ return value;
79
+ }
80
+ // ============================================================
81
+ // [MF-2] Server/Client Log Separation
82
+ // ============================================================
83
+ /**
84
+ * Check if running on server side
85
+ */
86
+ function isServer() {
87
+ return typeof window === 'undefined';
88
+ }
89
+ /**
90
+ * Check if should log on client side
91
+ * Only output in development environment
92
+ */
93
+ function shouldLogOnClient() {
94
+ return process.env.NODE_ENV === 'development';
95
+ }
96
+ // ============================================================
97
+ // Log Level Control
98
+ // ============================================================
99
+ const LOG_LEVELS = {
100
+ debug: 0,
101
+ info: 1,
102
+ warn: 2,
103
+ error: 3,
104
+ };
105
+ /**
106
+ * Get current log level
107
+ * [SF-1] Get from env.ts
108
+ */
109
+ function getCurrentLogLevel() {
110
+ const config = (0, env_1.getLogConfig)();
111
+ return config.level;
112
+ }
113
+ /**
114
+ * Get log output format
115
+ * [SF-1] Get from env.ts
116
+ */
117
+ function getLogFormat() {
118
+ const config = (0, env_1.getLogConfig)();
119
+ return config.format;
120
+ }
121
+ // ============================================================
122
+ // Log Output
123
+ // ============================================================
124
+ /**
125
+ * Format log entry
126
+ */
127
+ function formatLogEntry(entry) {
128
+ if (getLogFormat() === 'json') {
129
+ return JSON.stringify(entry);
130
+ }
131
+ // Text format
132
+ const { timestamp, level, module, action, data, worktreeId, cliToolId, requestId } = entry;
133
+ const contextParts = [worktreeId, cliToolId].filter(Boolean);
134
+ const contextStr = contextParts.length > 0 ? ` [${contextParts.join(':')}]` : '';
135
+ const requestIdStr = requestId ? ` (${requestId.slice(0, 8)})` : '';
136
+ const dataStr = data ? ` ${JSON.stringify(data)}` : '';
137
+ return `[${timestamp}] [${level.toUpperCase()}] [${module}]${contextStr}${requestIdStr} ${action}${dataStr}`;
138
+ }
139
+ /**
140
+ * Execute log output
141
+ */
142
+ function log(level, module, action, data, context) {
143
+ const currentLevel = getCurrentLogLevel();
144
+ if (LOG_LEVELS[level] < LOG_LEVELS[currentLevel]) {
145
+ return; // Do not output if below threshold
146
+ }
147
+ // [MF-2] Only output on client side in development environment
148
+ if (!isServer() && !shouldLogOnClient()) {
149
+ return;
150
+ }
151
+ // [MF-1] Sanitize data
152
+ const sanitizedData = data ? sanitize(data) : undefined;
153
+ const entry = {
154
+ level,
155
+ module,
156
+ action,
157
+ timestamp: new Date().toISOString(),
158
+ ...context,
159
+ ...(sanitizedData && { data: sanitizedData }),
160
+ };
161
+ const formatted = formatLogEntry(entry);
162
+ // Server side: structured log, Client side: console group
163
+ if (isServer()) {
164
+ switch (level) {
165
+ case 'error':
166
+ console.error(formatted);
167
+ break;
168
+ case 'warn':
169
+ console.warn(formatted);
170
+ break;
171
+ default:
172
+ console.log(formatted);
173
+ }
174
+ }
175
+ else {
176
+ // Client side (development only)
177
+ const consoleMethod = level === 'error' ? 'error' : level === 'warn' ? 'warn' : 'log';
178
+ console[consoleMethod](`[${module}] ${action}`, sanitizedData || '');
179
+ }
180
+ }
181
+ // ============================================================
182
+ // [SF-2] Request ID Generation
183
+ // ============================================================
184
+ /**
185
+ * Generate request ID
186
+ * UUID v4 format
187
+ */
188
+ function generateRequestId() {
189
+ // crypto.randomUUID() is available in Node.js 19+ and modern browsers
190
+ // Provide fallback implementation
191
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
192
+ return crypto.randomUUID();
193
+ }
194
+ // Fallback: simple random ID
195
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
196
+ const r = (Math.random() * 16) | 0;
197
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
198
+ return v.toString(16);
199
+ });
200
+ }
201
+ // ============================================================
202
+ // Logger Factory
203
+ // ============================================================
204
+ /**
205
+ * Create module-specific logger
206
+ *
207
+ * @param module - Module name (e.g., 'prompt-detector', 'cli-session')
208
+ * @returns Logger instance
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * const logger = createLogger('api-worktrees');
213
+ *
214
+ * // Basic usage
215
+ * logger.info('GET:start');
216
+ * logger.debug('statusCheck', { worktreeId: 'wt-1' });
217
+ *
218
+ * // With context
219
+ * const log = logger.withContext({ worktreeId: 'wt-1', requestId: generateRequestId() });
220
+ * log.info('action:complete');
221
+ * ```
222
+ */
223
+ function createLogger(module) {
224
+ const createLoggerWithContext = (context) => ({
225
+ debug: (action, data) => log('debug', module, action, data, context),
226
+ info: (action, data) => log('info', module, action, data, context),
227
+ warn: (action, data) => log('warn', module, action, data, context),
228
+ error: (action, data) => log('error', module, action, data, context),
229
+ withContext: (newContext) => createLoggerWithContext({ ...context, ...newContext }),
230
+ });
231
+ return createLoggerWithContext();
232
+ }