mstro-app 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/bin/mstro.js +119 -40
  2. package/dist/server/cli/headless/claude-invoker-process.d.ts +11 -0
  3. package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -0
  4. package/dist/server/cli/headless/claude-invoker-process.js +140 -0
  5. package/dist/server/cli/headless/claude-invoker-process.js.map +1 -0
  6. package/dist/server/cli/headless/claude-invoker-stall.d.ts +40 -0
  7. package/dist/server/cli/headless/claude-invoker-stall.d.ts.map +1 -0
  8. package/dist/server/cli/headless/claude-invoker-stall.js +98 -0
  9. package/dist/server/cli/headless/claude-invoker-stall.js.map +1 -0
  10. package/dist/server/cli/headless/claude-invoker-stream.d.ts +44 -0
  11. package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -0
  12. package/dist/server/cli/headless/claude-invoker-stream.js +276 -0
  13. package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -0
  14. package/dist/server/cli/headless/claude-invoker-tools.d.ts +21 -0
  15. package/dist/server/cli/headless/claude-invoker-tools.d.ts.map +1 -0
  16. package/dist/server/cli/headless/claude-invoker-tools.js +137 -0
  17. package/dist/server/cli/headless/claude-invoker-tools.js.map +1 -0
  18. package/dist/server/cli/headless/claude-invoker.d.ts +6 -4
  19. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
  20. package/dist/server/cli/headless/claude-invoker.js +10 -804
  21. package/dist/server/cli/headless/claude-invoker.js.map +1 -1
  22. package/dist/server/cli/headless/haiku-assessments.d.ts +62 -0
  23. package/dist/server/cli/headless/haiku-assessments.d.ts.map +1 -0
  24. package/dist/server/cli/headless/haiku-assessments.js +281 -0
  25. package/dist/server/cli/headless/haiku-assessments.js.map +1 -0
  26. package/dist/server/cli/headless/headless-logger.d.ts +3 -2
  27. package/dist/server/cli/headless/headless-logger.d.ts.map +1 -1
  28. package/dist/server/cli/headless/headless-logger.js +28 -5
  29. package/dist/server/cli/headless/headless-logger.js.map +1 -1
  30. package/dist/server/cli/headless/native-timeout-detector.d.ts +44 -0
  31. package/dist/server/cli/headless/native-timeout-detector.d.ts.map +1 -0
  32. package/dist/server/cli/headless/native-timeout-detector.js +99 -0
  33. package/dist/server/cli/headless/native-timeout-detector.js.map +1 -0
  34. package/dist/server/cli/headless/stall-assessor.d.ts +2 -110
  35. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  36. package/dist/server/cli/headless/stall-assessor.js +65 -457
  37. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  38. package/dist/server/cli/headless/types.d.ts +4 -1
  39. package/dist/server/cli/headless/types.d.ts.map +1 -1
  40. package/dist/server/cli/improvisation-attachments.d.ts +21 -0
  41. package/dist/server/cli/improvisation-attachments.d.ts.map +1 -0
  42. package/dist/server/cli/improvisation-attachments.js +116 -0
  43. package/dist/server/cli/improvisation-attachments.js.map +1 -0
  44. package/dist/server/cli/improvisation-retry.d.ts +52 -0
  45. package/dist/server/cli/improvisation-retry.d.ts.map +1 -0
  46. package/dist/server/cli/improvisation-retry.js +434 -0
  47. package/dist/server/cli/improvisation-retry.js.map +1 -0
  48. package/dist/server/cli/improvisation-session-manager.d.ts +10 -266
  49. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  50. package/dist/server/cli/improvisation-session-manager.js +117 -1079
  51. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  52. package/dist/server/cli/improvisation-types.d.ts +86 -0
  53. package/dist/server/cli/improvisation-types.d.ts.map +1 -0
  54. package/dist/server/cli/improvisation-types.js +10 -0
  55. package/dist/server/cli/improvisation-types.js.map +1 -0
  56. package/dist/server/cli/prompt-builders.d.ts +68 -0
  57. package/dist/server/cli/prompt-builders.d.ts.map +1 -0
  58. package/dist/server/cli/prompt-builders.js +312 -0
  59. package/dist/server/cli/prompt-builders.js.map +1 -0
  60. package/dist/server/index.js +33 -212
  61. package/dist/server/index.js.map +1 -1
  62. package/dist/server/mcp/bouncer-haiku.d.ts +10 -0
  63. package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -0
  64. package/dist/server/mcp/bouncer-haiku.js +152 -0
  65. package/dist/server/mcp/bouncer-haiku.js.map +1 -0
  66. package/dist/server/mcp/bouncer-integration.d.ts +3 -4
  67. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  68. package/dist/server/mcp/bouncer-integration.js +50 -196
  69. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  70. package/dist/server/mcp/security-analysis.d.ts +38 -0
  71. package/dist/server/mcp/security-analysis.d.ts.map +1 -0
  72. package/dist/server/mcp/security-analysis.js +183 -0
  73. package/dist/server/mcp/security-analysis.js.map +1 -0
  74. package/dist/server/mcp/security-audit.d.ts +1 -1
  75. package/dist/server/mcp/security-audit.d.ts.map +1 -1
  76. package/dist/server/mcp/security-patterns.d.ts +1 -25
  77. package/dist/server/mcp/security-patterns.d.ts.map +1 -1
  78. package/dist/server/mcp/security-patterns.js +55 -260
  79. package/dist/server/mcp/security-patterns.js.map +1 -1
  80. package/dist/server/server-setup.d.ts +22 -0
  81. package/dist/server/server-setup.d.ts.map +1 -0
  82. package/dist/server/server-setup.js +101 -0
  83. package/dist/server/server-setup.js.map +1 -0
  84. package/dist/server/services/file-explorer-ops.d.ts +24 -0
  85. package/dist/server/services/file-explorer-ops.d.ts.map +1 -0
  86. package/dist/server/services/file-explorer-ops.js +211 -0
  87. package/dist/server/services/file-explorer-ops.js.map +1 -0
  88. package/dist/server/services/files.d.ts +2 -85
  89. package/dist/server/services/files.d.ts.map +1 -1
  90. package/dist/server/services/files.js +7 -427
  91. package/dist/server/services/files.js.map +1 -1
  92. package/dist/server/services/plan/composer.d.ts +1 -1
  93. package/dist/server/services/plan/composer.d.ts.map +1 -1
  94. package/dist/server/services/plan/composer.js +118 -32
  95. package/dist/server/services/plan/composer.js.map +1 -1
  96. package/dist/server/services/plan/config-installer.d.ts +25 -0
  97. package/dist/server/services/plan/config-installer.d.ts.map +1 -0
  98. package/dist/server/services/plan/config-installer.js +182 -0
  99. package/dist/server/services/plan/config-installer.js.map +1 -0
  100. package/dist/server/services/plan/dependency-resolver.d.ts +1 -1
  101. package/dist/server/services/plan/dependency-resolver.d.ts.map +1 -1
  102. package/dist/server/services/plan/dependency-resolver.js +4 -1
  103. package/dist/server/services/plan/dependency-resolver.js.map +1 -1
  104. package/dist/server/services/plan/executor.d.ts +38 -74
  105. package/dist/server/services/plan/executor.d.ts.map +1 -1
  106. package/dist/server/services/plan/executor.js +274 -460
  107. package/dist/server/services/plan/executor.js.map +1 -1
  108. package/dist/server/services/plan/front-matter.d.ts +18 -0
  109. package/dist/server/services/plan/front-matter.d.ts.map +1 -0
  110. package/dist/server/services/plan/front-matter.js +44 -0
  111. package/dist/server/services/plan/front-matter.js.map +1 -0
  112. package/dist/server/services/plan/output-manager.d.ts +22 -0
  113. package/dist/server/services/plan/output-manager.d.ts.map +1 -0
  114. package/dist/server/services/plan/output-manager.js +97 -0
  115. package/dist/server/services/plan/output-manager.js.map +1 -0
  116. package/dist/server/services/plan/parser-core.d.ts +20 -0
  117. package/dist/server/services/plan/parser-core.d.ts.map +1 -0
  118. package/dist/server/services/plan/parser-core.js +350 -0
  119. package/dist/server/services/plan/parser-core.js.map +1 -0
  120. package/dist/server/services/plan/parser-migration.d.ts +5 -0
  121. package/dist/server/services/plan/parser-migration.d.ts.map +1 -0
  122. package/dist/server/services/plan/parser-migration.js +124 -0
  123. package/dist/server/services/plan/parser-migration.js.map +1 -0
  124. package/dist/server/services/plan/parser.d.ts +11 -3
  125. package/dist/server/services/plan/parser.d.ts.map +1 -1
  126. package/dist/server/services/plan/parser.js +184 -369
  127. package/dist/server/services/plan/parser.js.map +1 -1
  128. package/dist/server/services/plan/prompt-builder.d.ts +17 -0
  129. package/dist/server/services/plan/prompt-builder.d.ts.map +1 -0
  130. package/dist/server/services/plan/prompt-builder.js +137 -0
  131. package/dist/server/services/plan/prompt-builder.js.map +1 -0
  132. package/dist/server/services/plan/review-gate.d.ts +28 -0
  133. package/dist/server/services/plan/review-gate.d.ts.map +1 -0
  134. package/dist/server/services/plan/review-gate.js +191 -0
  135. package/dist/server/services/plan/review-gate.js.map +1 -0
  136. package/dist/server/services/plan/state-reconciler.d.ts +1 -1
  137. package/dist/server/services/plan/state-reconciler.d.ts.map +1 -1
  138. package/dist/server/services/plan/state-reconciler.js +59 -7
  139. package/dist/server/services/plan/state-reconciler.js.map +1 -1
  140. package/dist/server/services/plan/types.d.ts +68 -0
  141. package/dist/server/services/plan/types.d.ts.map +1 -1
  142. package/dist/server/services/platform-credentials.d.ts +24 -0
  143. package/dist/server/services/platform-credentials.d.ts.map +1 -0
  144. package/dist/server/services/platform-credentials.js +68 -0
  145. package/dist/server/services/platform-credentials.js.map +1 -0
  146. package/dist/server/services/platform.d.ts +1 -31
  147. package/dist/server/services/platform.d.ts.map +1 -1
  148. package/dist/server/services/platform.js +11 -109
  149. package/dist/server/services/platform.js.map +1 -1
  150. package/dist/server/services/terminal/pty-manager.d.ts +7 -97
  151. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
  152. package/dist/server/services/terminal/pty-manager.js +53 -266
  153. package/dist/server/services/terminal/pty-manager.js.map +1 -1
  154. package/dist/server/services/terminal/pty-utils.d.ts +57 -0
  155. package/dist/server/services/terminal/pty-utils.d.ts.map +1 -0
  156. package/dist/server/services/terminal/pty-utils.js +141 -0
  157. package/dist/server/services/terminal/pty-utils.js.map +1 -0
  158. package/dist/server/services/websocket/file-definition-handlers.d.ts +4 -0
  159. package/dist/server/services/websocket/file-definition-handlers.d.ts.map +1 -0
  160. package/dist/server/services/websocket/file-definition-handlers.js +153 -0
  161. package/dist/server/services/websocket/file-definition-handlers.js.map +1 -0
  162. package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
  163. package/dist/server/services/websocket/file-explorer-handlers.js +52 -391
  164. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  165. package/dist/server/services/websocket/file-search-handlers.d.ts +5 -0
  166. package/dist/server/services/websocket/file-search-handlers.d.ts.map +1 -0
  167. package/dist/server/services/websocket/file-search-handlers.js +238 -0
  168. package/dist/server/services/websocket/file-search-handlers.js.map +1 -0
  169. package/dist/server/services/websocket/file-utils.js +3 -3
  170. package/dist/server/services/websocket/file-utils.js.map +1 -1
  171. package/dist/server/services/websocket/git-branch-handlers.d.ts +7 -0
  172. package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -0
  173. package/dist/server/services/websocket/git-branch-handlers.js +110 -0
  174. package/dist/server/services/websocket/git-branch-handlers.js.map +1 -0
  175. package/dist/server/services/websocket/git-diff-handlers.d.ts +6 -0
  176. package/dist/server/services/websocket/git-diff-handlers.d.ts.map +1 -0
  177. package/dist/server/services/websocket/git-diff-handlers.js +123 -0
  178. package/dist/server/services/websocket/git-diff-handlers.js.map +1 -0
  179. package/dist/server/services/websocket/git-handlers.d.ts +2 -31
  180. package/dist/server/services/websocket/git-handlers.d.ts.map +1 -1
  181. package/dist/server/services/websocket/git-handlers.js +35 -541
  182. package/dist/server/services/websocket/git-handlers.js.map +1 -1
  183. package/dist/server/services/websocket/git-log-handlers.d.ts +6 -0
  184. package/dist/server/services/websocket/git-log-handlers.d.ts.map +1 -0
  185. package/dist/server/services/websocket/git-log-handlers.js +128 -0
  186. package/dist/server/services/websocket/git-log-handlers.js.map +1 -0
  187. package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
  188. package/dist/server/services/websocket/git-pr-handlers.js +13 -53
  189. package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
  190. package/dist/server/services/websocket/git-tag-handlers.d.ts +6 -0
  191. package/dist/server/services/websocket/git-tag-handlers.d.ts.map +1 -0
  192. package/dist/server/services/websocket/git-tag-handlers.js +76 -0
  193. package/dist/server/services/websocket/git-tag-handlers.js.map +1 -0
  194. package/dist/server/services/websocket/git-utils.d.ts +43 -0
  195. package/dist/server/services/websocket/git-utils.d.ts.map +1 -0
  196. package/dist/server/services/websocket/git-utils.js +201 -0
  197. package/dist/server/services/websocket/git-utils.js.map +1 -0
  198. package/dist/server/services/websocket/handler.d.ts +2 -0
  199. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  200. package/dist/server/services/websocket/handler.js +37 -112
  201. package/dist/server/services/websocket/handler.js.map +1 -1
  202. package/dist/server/services/websocket/plan-board-handlers.d.ts +11 -0
  203. package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -0
  204. package/dist/server/services/websocket/plan-board-handlers.js +218 -0
  205. package/dist/server/services/websocket/plan-board-handlers.js.map +1 -0
  206. package/dist/server/services/websocket/plan-execution-handlers.d.ts +9 -0
  207. package/dist/server/services/websocket/plan-execution-handlers.d.ts.map +1 -0
  208. package/dist/server/services/websocket/plan-execution-handlers.js +142 -0
  209. package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -0
  210. package/dist/server/services/websocket/plan-handlers.d.ts +7 -2
  211. package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -1
  212. package/dist/server/services/websocket/plan-handlers.js +21 -462
  213. package/dist/server/services/websocket/plan-handlers.js.map +1 -1
  214. package/dist/server/services/websocket/plan-helpers.d.ts +19 -0
  215. package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -0
  216. package/dist/server/services/websocket/plan-helpers.js +199 -0
  217. package/dist/server/services/websocket/plan-helpers.js.map +1 -0
  218. package/dist/server/services/websocket/plan-issue-handlers.d.ts +12 -0
  219. package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -0
  220. package/dist/server/services/websocket/plan-issue-handlers.js +162 -0
  221. package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -0
  222. package/dist/server/services/websocket/plan-sprint-handlers.d.ts +7 -0
  223. package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -0
  224. package/dist/server/services/websocket/plan-sprint-handlers.js +206 -0
  225. package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -0
  226. package/dist/server/services/websocket/quality-complexity.d.ts +14 -0
  227. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -0
  228. package/dist/server/services/websocket/quality-complexity.js +262 -0
  229. package/dist/server/services/websocket/quality-complexity.js.map +1 -0
  230. package/dist/server/services/websocket/quality-fix-agent.d.ts +16 -0
  231. package/dist/server/services/websocket/quality-fix-agent.d.ts.map +1 -0
  232. package/dist/server/services/websocket/quality-fix-agent.js +140 -0
  233. package/dist/server/services/websocket/quality-fix-agent.js.map +1 -0
  234. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
  235. package/dist/server/services/websocket/quality-handlers.js +34 -346
  236. package/dist/server/services/websocket/quality-handlers.js.map +1 -1
  237. package/dist/server/services/websocket/quality-linting.d.ts +9 -0
  238. package/dist/server/services/websocket/quality-linting.d.ts.map +1 -0
  239. package/dist/server/services/websocket/quality-linting.js +178 -0
  240. package/dist/server/services/websocket/quality-linting.js.map +1 -0
  241. package/dist/server/services/websocket/quality-review-agent.d.ts +19 -0
  242. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -0
  243. package/dist/server/services/websocket/quality-review-agent.js +206 -0
  244. package/dist/server/services/websocket/quality-review-agent.js.map +1 -0
  245. package/dist/server/services/websocket/quality-service.d.ts +3 -51
  246. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  247. package/dist/server/services/websocket/quality-service.js +9 -651
  248. package/dist/server/services/websocket/quality-service.js.map +1 -1
  249. package/dist/server/services/websocket/quality-tools.d.ts +23 -0
  250. package/dist/server/services/websocket/quality-tools.d.ts.map +1 -0
  251. package/dist/server/services/websocket/quality-tools.js +208 -0
  252. package/dist/server/services/websocket/quality-tools.js.map +1 -0
  253. package/dist/server/services/websocket/quality-types.d.ts +59 -0
  254. package/dist/server/services/websocket/quality-types.d.ts.map +1 -0
  255. package/dist/server/services/websocket/quality-types.js +101 -0
  256. package/dist/server/services/websocket/quality-types.js.map +1 -0
  257. package/dist/server/services/websocket/session-handlers.d.ts +3 -4
  258. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  259. package/dist/server/services/websocket/session-handlers.js +3 -378
  260. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  261. package/dist/server/services/websocket/session-history.d.ts +4 -0
  262. package/dist/server/services/websocket/session-history.d.ts.map +1 -0
  263. package/dist/server/services/websocket/session-history.js +208 -0
  264. package/dist/server/services/websocket/session-history.js.map +1 -0
  265. package/dist/server/services/websocket/session-initialization.d.ts +5 -0
  266. package/dist/server/services/websocket/session-initialization.d.ts.map +1 -0
  267. package/dist/server/services/websocket/session-initialization.js +163 -0
  268. package/dist/server/services/websocket/session-initialization.js.map +1 -0
  269. package/dist/server/services/websocket/types.d.ts +12 -2
  270. package/dist/server/services/websocket/types.d.ts.map +1 -1
  271. package/package.json +1 -2
  272. package/server/cli/headless/claude-invoker-process.ts +204 -0
  273. package/server/cli/headless/claude-invoker-stall.ts +164 -0
  274. package/server/cli/headless/claude-invoker-stream.ts +353 -0
  275. package/server/cli/headless/claude-invoker-tools.ts +187 -0
  276. package/server/cli/headless/claude-invoker.ts +15 -1092
  277. package/server/cli/headless/haiku-assessments.ts +365 -0
  278. package/server/cli/headless/headless-logger.ts +26 -5
  279. package/server/cli/headless/native-timeout-detector.ts +117 -0
  280. package/server/cli/headless/stall-assessor.ts +65 -618
  281. package/server/cli/headless/types.ts +4 -1
  282. package/server/cli/improvisation-attachments.ts +148 -0
  283. package/server/cli/improvisation-retry.ts +602 -0
  284. package/server/cli/improvisation-session-manager.ts +140 -1349
  285. package/server/cli/improvisation-types.ts +98 -0
  286. package/server/cli/prompt-builders.ts +370 -0
  287. package/server/index.ts +35 -246
  288. package/server/mcp/bouncer-haiku.ts +182 -0
  289. package/server/mcp/bouncer-integration.ts +87 -248
  290. package/server/mcp/security-analysis.ts +217 -0
  291. package/server/mcp/security-audit.ts +1 -1
  292. package/server/mcp/security-patterns.ts +60 -283
  293. package/server/server-setup.ts +114 -0
  294. package/server/services/file-explorer-ops.ts +293 -0
  295. package/server/services/files.ts +20 -532
  296. package/server/services/plan/composer.ts +140 -35
  297. package/server/services/plan/config-installer.ts +187 -0
  298. package/server/services/plan/dependency-resolver.ts +4 -1
  299. package/server/services/plan/executor.ts +281 -488
  300. package/server/services/plan/front-matter.ts +48 -0
  301. package/server/services/plan/output-manager.ts +113 -0
  302. package/server/services/plan/parser-core.ts +406 -0
  303. package/server/services/plan/parser-migration.ts +128 -0
  304. package/server/services/plan/parser.ts +188 -394
  305. package/server/services/plan/prompt-builder.ts +161 -0
  306. package/server/services/plan/review-gate.ts +212 -0
  307. package/server/services/plan/state-reconciler.ts +68 -7
  308. package/server/services/plan/types.ts +101 -1
  309. package/server/services/platform-credentials.ts +83 -0
  310. package/server/services/platform.ts +16 -131
  311. package/server/services/terminal/pty-manager.ts +66 -313
  312. package/server/services/terminal/pty-utils.ts +176 -0
  313. package/server/services/websocket/file-definition-handlers.ts +165 -0
  314. package/server/services/websocket/file-explorer-handlers.ts +37 -452
  315. package/server/services/websocket/file-search-handlers.ts +291 -0
  316. package/server/services/websocket/file-utils.ts +3 -3
  317. package/server/services/websocket/git-branch-handlers.ts +130 -0
  318. package/server/services/websocket/git-diff-handlers.ts +140 -0
  319. package/server/services/websocket/git-handlers.ts +40 -625
  320. package/server/services/websocket/git-log-handlers.ts +149 -0
  321. package/server/services/websocket/git-pr-handlers.ts +17 -62
  322. package/server/services/websocket/git-tag-handlers.ts +91 -0
  323. package/server/services/websocket/git-utils.ts +230 -0
  324. package/server/services/websocket/handler.ts +39 -112
  325. package/server/services/websocket/plan-board-handlers.ts +277 -0
  326. package/server/services/websocket/plan-execution-handlers.ts +184 -0
  327. package/server/services/websocket/plan-handlers.ts +23 -544
  328. package/server/services/websocket/plan-helpers.ts +215 -0
  329. package/server/services/websocket/plan-issue-handlers.ts +204 -0
  330. package/server/services/websocket/plan-sprint-handlers.ts +252 -0
  331. package/server/services/websocket/quality-complexity.ts +294 -0
  332. package/server/services/websocket/quality-fix-agent.ts +181 -0
  333. package/server/services/websocket/quality-handlers.ts +36 -404
  334. package/server/services/websocket/quality-linting.ts +187 -0
  335. package/server/services/websocket/quality-review-agent.ts +246 -0
  336. package/server/services/websocket/quality-service.ts +11 -762
  337. package/server/services/websocket/quality-tools.ts +209 -0
  338. package/server/services/websocket/quality-types.ts +169 -0
  339. package/server/services/websocket/session-handlers.ts +5 -437
  340. package/server/services/websocket/session-history.ts +222 -0
  341. package/server/services/websocket/session-initialization.ts +209 -0
  342. package/server/services/websocket/types.ts +46 -2
@@ -12,10 +12,16 @@
12
12
  * - Only truly catastrophic operations (rm -rf /, fork bombs) are auto-denied
13
13
  * - Sensitive operations (system paths, credentials) get AI review with context
14
14
  * - The question is: "Does this operation make sense given user intent?"
15
+ *
16
+ * Analysis logic (requiresAIReview, classifyRisk) lives in security-analysis.ts
17
+ * and is re-exported here for backward compatibility.
15
18
  */
16
19
 
17
20
  import { resolve } from 'node:path';
18
21
 
22
+ // Re-export analysis functions for backward compatibility
23
+ export { classifyRisk, isSensitivePath, requiresAIReview } from './security-analysis.js';
24
+
19
25
  export interface SecurityPattern {
20
26
  pattern: RegExp;
21
27
  reason?: string;
@@ -56,8 +62,6 @@ export const SENSITIVE_PATHS: SecurityPattern[] = [
56
62
  * for context review. Only truly never-legitimate commands are here.
57
63
  */
58
64
  export const CRITICAL_THREATS: SecurityPattern[] = [
59
- // Deleting root or home - no legitimate dev task requires this
60
- // If user really wants this, they can run it manually outside Claude
61
65
  {
62
66
  pattern: /rm\s+-rf\s+(\/|~)($|\s)/i,
63
67
  reason: 'Deleting root (/) or home (~) directory is never a legitimate dev task'
@@ -86,7 +90,6 @@ export const CRITICAL_THREATS: SecurityPattern[] = [
86
90
  pattern: /chmod\s+000\s+\//i,
87
91
  reason: 'Attempting to make system directories inaccessible'
88
92
  },
89
- // Reverse shells - never legitimate in a dev workflow
90
93
  {
91
94
  pattern: /\/dev\/tcp\//i,
92
95
  reason: 'Reverse shell via /dev/tcp - classic backdoor technique'
@@ -95,8 +98,6 @@ export const CRITICAL_THREATS: SecurityPattern[] = [
95
98
  pattern: /\bnc\b.*-[elp].*\b\d+\b/i,
96
99
  reason: 'Netcat listener/reverse shell - common backdoor technique'
97
100
  },
98
- // NOTE: curl|bash is NOT here - it goes to Haiku for context review
99
- // The question is "did a bad actor inject this?" not "is curl|bash dangerous?"
100
101
  ];
101
102
 
102
103
  /**
@@ -109,15 +110,13 @@ export const SAFE_OPERATIONS: SecurityPattern[] = [
109
110
  { pattern: /^Glob:/i },
110
111
  { pattern: /^Grep:/i },
111
112
 
112
- // Write/Edit to user home directory or subdirectories - user requested, allow it
113
- // Excludes system paths which go through critical threats check
114
- { pattern: /^Write:\s*\/Users\/[^/]+\//i }, // macOS home dirs - Write
115
- { pattern: /^Edit:\s*\/Users\/[^/]+\//i }, // macOS home dirs - Edit
116
- { pattern: /^Write:\s*\/home\/[^/]+\//i }, // Linux home dirs - Write
117
- { pattern: /^Edit:\s*\/home\/[^/]+\//i }, // Linux home dirs - Edit
113
+ // Write/Edit to user home directory or subdirectories
114
+ { pattern: /^Write:\s*\/Users\/[^/]+\//i },
115
+ { pattern: /^Edit:\s*\/Users\/[^/]+\//i },
116
+ { pattern: /^Write:\s*\/home\/[^/]+\//i },
117
+ { pattern: /^Edit:\s*\/home\/[^/]+\//i },
118
118
 
119
119
  // Safe bash commands - common development workflows
120
- // NOTE: curl|bash goes to Haiku for context review, not auto-allowed
121
120
  { pattern: /^Bash:\s*(npm|yarn|pnpm|bun)\s+(install|ci|run|test|build|dev|start|lint|format)($|\s)/i },
122
121
  { pattern: /^Bash:\s*git\s+(status|log|diff|show|branch|clone|pull|fetch|add|stash|checkout)($|\s)/i },
123
122
  { pattern: /^Bash:\s*docker\s+(build|run|ps|logs|compose|images)($|\s)/i },
@@ -133,22 +132,42 @@ export const SAFE_OPERATIONS: SecurityPattern[] = [
133
132
  { pattern: /^Bash:\s*rm\s+-rf\s+(\.\/)?target($|\s)/i },
134
133
  { pattern: /^Bash:\s*rm\s+-rf\s+(\.\/)?__pycache__($|\s)/i },
135
134
 
136
- // Write/Edit to temp directories - ephemeral, low risk
135
+ // Write/Edit to temp directories
137
136
  { pattern: /^(Write|Edit):\s*\/tmp\//i },
138
137
  { pattern: /^(Write|Edit):\s*\/var\/tmp\//i },
139
138
 
140
- // Side-effect-free tools - no dangerous operations possible
139
+ // Side-effect-free tools
141
140
  { pattern: /^(ExitPlanMode|EnterPlanMode|TodoWrite|AskUserQuestion):/i },
141
+
142
+ // Additional common dev commands
143
+ { pattern: /^Bash:\s*(tsc|tsx|node|bun|deno|npx|bunx)\s/i },
144
+ { pattern: /^Bash:\s*(vitest|jest|mocha|tap)\s/i },
145
+ { pattern: /^Bash:\s*(biome|eslint|prettier|tslint)\s+(check|lint|format)/i },
146
+ { pattern: /^Bash:\s*(make|cmake|ninja|meson)($|\s)/i },
147
+ { pattern: /^Bash:\s*git\s+(commit|push|tag|remote|rebase|merge|cherry-pick|reset|revert)($|\s)/i },
148
+ { pattern: /^Bash:\s*git\s+(worktree|submodule|config|clean|gc)($|\s)/i },
149
+ { pattern: /^Bash:\s*(uname|hostname|whoami|id|groups|uptime|df|du|free|top|ps|lsof|stat|file|readlink)($|\s)/i },
150
+ { pattern: /^Bash:\s*(mv|cp|touch|ln|basename|dirname|realpath|mktemp|xargs|tee|tr|cut|paste|comm|diff|patch)($|\s)/i },
151
+ { pattern: /^Bash:\s*(tar|gzip|gunzip|zip|unzip|bzip2)\s/i },
152
+ { pattern: /^Bash:\s*(ruby|python3?|php|java|javac|scala|kotlinc|swift|rustc|gcc|g\+\+|clang)\s/i },
153
+ { pattern: /^Bash:\s*(pip|pip3|gem|bundle|composer|maven|gradle|sbt|cargo|rustup)\s/i },
154
+ { pattern: /^Bash:\s*(gh|hub)\s+(pr|issue|repo|release|run|api)\s/i },
155
+ { pattern: /^Bash:\s*(flyctl|fly)\s+(status|logs|ssh|deploy|apps|machines|secrets)($|\s)/i },
156
+ { pattern: /^Bash:\s*(terraform|tofu)\s+(init|plan|apply|validate|fmt|show|output)($|\s)/i },
157
+ { pattern: /^Bash:\s*wc($|\s)/i },
158
+
159
+ // WebFetch/WebSearch are inherently read-only
160
+ { pattern: /^WebFetch:/i },
161
+ { pattern: /^WebSearch:/i },
162
+
163
+ // Agent and NotebookEdit are orchestration-only
164
+ { pattern: /^Agent:/i },
165
+ { pattern: /^NotebookEdit:/i },
142
166
  ];
143
167
 
144
168
  /**
145
169
  * Patterns that trigger AI context review
146
170
  * These operations need context analysis to determine if they align with user intent
147
- *
148
- * The AI should consider:
149
- * 1. Did the user explicitly request this operation?
150
- * 2. Does it make sense given the task at hand?
151
- * 3. Is the content/action appropriate for the target?
152
171
  */
153
172
  export const NEEDS_AI_REVIEW: SecurityPattern[] = [
154
173
  // Remote code execution patterns
@@ -158,103 +177,57 @@ export const NEEDS_AI_REVIEW: SecurityPattern[] = [
158
177
  },
159
178
 
160
179
  // Elevated privileges
161
- {
162
- pattern: /sudo/i,
163
- reason: 'Elevated privileges - verify user intended this action'
164
- },
180
+ { pattern: /sudo/i, reason: 'Elevated privileges - verify user intended this action' },
165
181
 
166
182
  // Destructive operations (except safe build artifact cleanup)
167
- {
168
- pattern: /rm\s+-rf/i,
169
- reason: 'Recursive deletion - verify target matches user intent'
170
- },
183
+ { pattern: /rm\s+-rf/i, reason: 'Recursive deletion - verify target matches user intent' },
171
184
 
172
- // Data exfiltration patterns — piping data to network tools
173
- {
174
- pattern: /\|\s*(nc|netcat|ncat)\b/i,
175
- reason: 'Pipe to netcat - potential data exfiltration'
176
- },
177
- {
178
- pattern: /\bscp\b.*@/i,
179
- reason: 'SCP to remote host - potential data exfiltration'
180
- },
181
- {
182
- pattern: /\|\s*curl\b/i,
183
- reason: 'Pipe to curl - potential data exfiltration'
184
- },
185
- {
186
- pattern: /curl\b.*-d\s*@/i,
187
- reason: 'Curl with file upload - potential data exfiltration'
188
- },
185
+ // Data exfiltration patterns
186
+ { pattern: /\|\s*(nc|netcat|ncat)\b/i, reason: 'Pipe to netcat - potential data exfiltration' },
187
+ { pattern: /\bscp\b.*@/i, reason: 'SCP to remote host - potential data exfiltration' },
188
+ { pattern: /\|\s*curl\b/i, reason: 'Pipe to curl - potential data exfiltration' },
189
+ { pattern: /curl\b.*-d\s*@/i, reason: 'Curl with file upload - potential data exfiltration' },
189
190
 
190
191
  // ALL Write/Edit operations that aren't to /tmp go through context review
191
- // This is the key change: we review based on context, not blanket allow/deny
192
192
  {
193
193
  pattern: /^(Write|Edit):\s*(?!\/tmp\/|\/var\/tmp\/)/i,
194
194
  reason: 'File modification - verify aligns with user request'
195
195
  },
196
196
 
197
- // Reverse shells and bind shells — network-connected interactive shells
198
- {
199
- pattern: /\/dev\/tcp\//i,
200
- reason: 'Potential reverse shell via /dev/tcp'
201
- },
202
- {
203
- pattern: /\b(nc|netcat|ncat)\b.*-e\s/i,
204
- reason: 'Netcat with -e flag - potential reverse shell'
205
- },
197
+ // Reverse shells and bind shells
198
+ { pattern: /\/dev\/tcp\//i, reason: 'Potential reverse shell via /dev/tcp' },
199
+ { pattern: /\b(nc|netcat|ncat)\b.*-e\s/i, reason: 'Netcat with -e flag - potential reverse shell' },
206
200
  {
207
201
  pattern: /\bsocket\b.*\bconnect\b.*\b(dup2|subprocess|exec)\b/i,
208
202
  reason: 'Programmatic reverse shell pattern (socket+connect+exec)'
209
203
  },
210
- {
211
- pattern: /\bperl\b.*\bsocket\b.*\bexec\b/i,
212
- reason: 'Perl reverse shell pattern'
213
- },
204
+ { pattern: /\bperl\b.*\bsocket\b.*\bexec\b/i, reason: 'Perl reverse shell pattern' },
214
205
 
215
206
  // Encoded/obfuscated payloads piped to shell or eval
216
207
  {
217
208
  pattern: /\b(base64|base32)\b.*-d.*\|\s*(bash|sh)\b/i,
218
209
  reason: 'Decoded payload piped to shell - obfuscated command execution'
219
210
  },
220
- {
221
- pattern: /\\x[0-9a-f]{2}.*\|\s*(bash|sh)\b/i,
222
- reason: 'Hex-encoded payload piped to shell'
223
- },
224
- {
225
- pattern: /\bexec\b.*\b(base64|b64decode)\b/i,
226
- reason: 'Exec with base64 decoding - obfuscated code execution'
227
- },
211
+ { pattern: /\\x[0-9a-f]{2}.*\|\s*(bash|sh)\b/i, reason: 'Hex-encoded payload piped to shell' },
212
+ { pattern: /\bexec\b.*\b(base64|b64decode)\b/i, reason: 'Exec with base64 decoding - obfuscated code execution' },
228
213
  {
229
214
  pattern: /\bprintf\b.*\\x[0-9a-f].*\|\s*(bash|sh)\b/i,
230
215
  reason: 'Printf hex payload piped to shell'
231
216
  },
232
217
 
233
- // Cloud metadata / SSRF — accessing cloud instance credentials
234
- {
235
- pattern: /169\.254\.169\.254/i,
236
- reason: 'AWS/Azure IMDS access - potential credential theft'
237
- },
238
- {
239
- pattern: /metadata\.google\.internal/i,
240
- reason: 'GCP metadata access - potential credential theft'
241
- },
218
+ // Cloud metadata / SSRF
219
+ { pattern: /169\.254\.169\.254/i, reason: 'AWS/Azure IMDS access - potential credential theft' },
220
+ { pattern: /metadata\.google\.internal/i, reason: 'GCP metadata access - potential credential theft' },
242
221
 
243
- // Persistence — writing to shell profiles, cron, authorized_keys via echo/append
222
+ // Persistence mechanisms
244
223
  {
245
224
  pattern: />>\s*~?\/?.*\/(authorized_keys|\.bashrc|\.bash_profile|\.zshrc|\.profile)/i,
246
225
  reason: 'Appending to sensitive file - potential persistence mechanism'
247
226
  },
248
- {
249
- pattern: /\bld\.so\.preload\b/i,
250
- reason: 'LD_PRELOAD injection - shared library hijacking'
251
- },
227
+ { pattern: /\bld\.so\.preload\b/i, reason: 'LD_PRELOAD injection - shared library hijacking' },
252
228
 
253
229
  // wget with file upload
254
- {
255
- pattern: /wget\b.*--post-file/i,
256
- reason: 'wget file upload - potential data exfiltration'
257
- },
230
+ { pattern: /wget\b.*--post-file/i, reason: 'wget file upload - potential data exfiltration' },
258
231
 
259
232
  // pip install from custom index (supply chain attack)
260
233
  {
@@ -263,12 +236,11 @@ export const NEEDS_AI_REVIEW: SecurityPattern[] = [
263
236
  },
264
237
 
265
238
  // MCP server manipulation
266
- {
267
- pattern: /\bclaude\b.*\bmcp\b.*\badd\b/i,
268
- reason: 'Adding MCP server - verify source is trusted'
269
- },
239
+ { pattern: /\bclaude\b.*\bmcp\b.*\badd\b/i, reason: 'Adding MCP server - verify source is trusted' },
270
240
  ];
271
241
 
242
+ // ── Utility functions ─────────────────────────────────────────
243
+
272
244
  /**
273
245
  * Check if operation matches any pattern in array
274
246
  */
@@ -295,198 +267,3 @@ export function normalizeOperation(operation: string): string {
295
267
  }
296
268
  return operation;
297
269
  }
298
-
299
- /** Check if a Bash command contains chain operators that could hide dangerous ops after a safe prefix. */
300
- function containsChainOperators(operation: string): boolean {
301
- const commandPart = operation.replace(/^Bash:\s*/i, '');
302
- return /;|&&|\|\||\n/.test(commandPart);
303
- }
304
-
305
- /** Check if a Bash command pipes output to known exfiltration/network tools or shells. */
306
- function containsDangerousPipe(operation: string): boolean {
307
- const commandPart = operation.replace(/^Bash:\s*/i, '');
308
- return /\|\s*(nc|netcat|ncat|curl|wget|scp|bash|sh)\b/i.test(commandPart);
309
- }
310
-
311
- /** Check if a Bash command redirects output to sensitive paths (append or overwrite). */
312
- function containsSensitiveRedirect(operation: string): boolean {
313
- const commandPart = operation.replace(/^Bash:\s*/i, '');
314
- return />>?\s*~?\/?.*\/(authorized_keys|\.bashrc|\.bash_profile|\.zshrc|\.profile|\.ssh\/|\.aws\/|\.gnupg\/|ld\.so\.preload|crontab|sudoers)/i.test(commandPart)
315
- || />>?\s*\/etc\//i.test(commandPart);
316
- }
317
-
318
- /** Check if a Bash command contains subshell or backtick expansion (not simple ${VAR}). */
319
- function containsBashExpansion(operation: string): boolean {
320
- const commandPart = operation.replace(/^Bash:\s*/i, '');
321
- return /`[^`]+`/.test(commandPart) || /\$\([^)]+\)/.test(commandPart);
322
- }
323
-
324
- /** Check if a Bash command contains any form of shell expansion: ${VAR}, $(...), or backticks. */
325
- function containsAnyExpansion(operation: string): boolean {
326
- const cmd = operation.replace(/^Bash:\s*/i, '');
327
- return /\$\{[^}]+\}/.test(cmd) || /\$\([^)]+\)/.test(cmd) || /`[^`]+`/.test(cmd);
328
- }
329
-
330
- /** Check if expansion is safely used as an argument to a known-safe command prefix.
331
- * e.g., "echo ${HOME}" or "cat ${FILE}" — the expansion can't change the command itself. */
332
- function isSafeExpansionUse(operation: string): boolean {
333
- const cmd = operation.replace(/^Bash:\s*/i, '').trim();
334
- // If the expansion IS the command (first token), it's never safe
335
- if (/^(\$\{|\$\(|`)/.test(cmd)) return false;
336
- // Safe command prefixes where expansion as an argument is harmless
337
- const safePrefix = /^(echo|printf|cat|ls|pwd|whoami|date|env|printenv|test|true|false)\s/i;
338
- return safePrefix.test(cmd);
339
- }
340
-
341
- /**
342
- * Determine if operation requires AI context review
343
- *
344
- * The philosophy here is:
345
- * - SENSITIVE_PATHS: Always require review (credentials, system configs)
346
- * - SAFE_OPERATIONS: No review needed, UNLESS the bash command contains
347
- * chain operators, dangerous pipes, or subshell/backtick expansion
348
- * - CRITICAL_THREATS: Auto-deny, no review (catastrophic operations)
349
- * - Everything else: AI reviews context to determine if it matches user intent
350
- */
351
- const SAFE_RM_PATTERNS = [
352
- /rm\s+-rf\s+(\.\/)?node_modules($|\s)/i,
353
- /rm\s+-rf\s+(\.\/)?dist($|\s)/i,
354
- /rm\s+-rf\s+(\.\/)?build($|\s)/i,
355
- /rm\s+-rf\s+(\.\/)?\.cache($|\s)/i,
356
- /rm\s+-rf\s+(\.\/)?\.next($|\s)/i,
357
- /rm\s+-rf\s+(\.\/)?target($|\s)/i,
358
- /rm\s+-rf\s+(\.\/)?__pycache__($|\s)/i,
359
- ];
360
-
361
- export function requiresAIReview(operation: string): boolean {
362
- // Normalize paths to prevent .. traversal bypass
363
- const op = normalizeOperation(operation);
364
-
365
- // Check sensitive paths BEFORE safe operations — prevents home-dir
366
- // safe pattern from masking .ssh, .aws, .bashrc, etc.
367
- if (matchesPattern(op, SENSITIVE_PATHS)) return true;
368
-
369
- // Bash commands with any shell expansion (${VAR}, $(...), backticks) are
370
- // opaque — the bouncer can't predict what they expand to at runtime.
371
- // Route to AI review BEFORE checking CRITICAL_THREATS or SAFE_OPERATIONS,
372
- // UNLESS the command is clearly safe (expansion is just an argument to a
373
- // known-safe prefix like "echo ${HOME}").
374
- if (/^Bash:/i.test(op) && containsAnyExpansion(op) && !isSafeExpansionUse(op)) {
375
- return true;
376
- }
377
-
378
- if (matchesPattern(op, SAFE_OPERATIONS)) {
379
- // Safe bash commands must not contain chain operators, dangerous pipes,
380
- // or subshell/backtick expansion that could hide dangerous operations.
381
- // A safe prefix (e.g., "git clone") with chain operators (&&, ;, ||)
382
- // means the full command isn't necessarily safe — route to AI review.
383
- if (/^Bash:/i.test(op) && (
384
- containsChainOperators(op) ||
385
- containsDangerousPipe(op) ||
386
- containsBashExpansion(op) ||
387
- containsSensitiveRedirect(op)
388
- )) {
389
- return true;
390
- }
391
- return false;
392
- }
393
-
394
- if (matchesPattern(op, CRITICAL_THREATS)) return false;
395
-
396
- if (matchesPattern(op, NEEDS_AI_REVIEW)) {
397
- return !SAFE_RM_PATTERNS.some(p => p.test(op));
398
- }
399
-
400
- // Glob patterns and script execution are concerning in Bash commands
401
- if (/^Bash:/.test(op)) {
402
- if (/\*\*?/.test(op)) return true;
403
- if (/^Bash:\s*\.\//.test(op)) return true;
404
- }
405
-
406
- return false;
407
- }
408
-
409
- /**
410
- * Check if operation targets a sensitive path
411
- * Used to provide additional context to AI reviewer
412
- */
413
- export function isSensitivePath(operation: string): SecurityPattern | null {
414
- return matchesPattern(operation, SENSITIVE_PATHS);
415
- }
416
-
417
- /**
418
- * Classify operation risk level for context-aware review
419
- *
420
- * Risk levels indicate how much scrutiny the AI should apply:
421
- * - critical: Catastrophic if wrong (rm -rf /, fork bombs) - auto-deny
422
- * - high: Needs clear user intent (sudo, sensitive paths, credentials)
423
- * - medium: Normal file operations - verify matches user request
424
- * - low: Safe operations - minimal review needed
425
- */
426
- export function classifyRisk(operation: string): {
427
- isDestructive: boolean;
428
- riskLevel: 'low' | 'medium' | 'high' | 'critical';
429
- reasons: string[];
430
- } {
431
- // Critical threats are auto-denied
432
- const criticalThreat = matchesPattern(operation, CRITICAL_THREATS);
433
- if (criticalThreat) {
434
- return {
435
- isDestructive: true,
436
- riskLevel: 'critical',
437
- reasons: [criticalThreat.reason || 'Critical threat detected']
438
- };
439
- }
440
-
441
- // Sensitive paths need high scrutiny but aren't auto-denied
442
- const sensitivePath = matchesPattern(operation, SENSITIVE_PATHS);
443
- if (sensitivePath) {
444
- return {
445
- isDestructive: false, // Not inherently destructive, just sensitive
446
- riskLevel: 'high',
447
- reasons: [sensitivePath.reason || 'Sensitive path - requires clear user intent']
448
- };
449
- }
450
-
451
- // Other patterns that need elevated review
452
- const elevatedPatterns: SecurityPattern[] = [
453
- { pattern: /sudo/i, reason: 'Elevated privileges requested' },
454
- { pattern: /DROP\s+(TABLE|DATABASE)/i, reason: 'Database deletion' },
455
- { pattern: /chmod\s+777/i, reason: 'Dangerous permissions' },
456
- { pattern: /(curl|wget).*\|.*(bash|sh)/i, reason: 'Remote code execution' },
457
- { pattern: /pkill|killall/i, reason: 'Process termination' },
458
- { pattern: /\|\s*(nc|netcat|ncat)\b/i, reason: 'Data exfiltration via netcat' },
459
- { pattern: /\bscp\b.*@/i, reason: 'Data exfiltration via SCP' },
460
- { pattern: /curl\b.*-d\s*@/i, reason: 'Data exfiltration via curl file upload' },
461
- ];
462
-
463
- for (const pattern of elevatedPatterns) {
464
- if (pattern.pattern.test(operation)) {
465
- return {
466
- isDestructive: true,
467
- riskLevel: 'high',
468
- reasons: [pattern.reason || 'Elevated risk operation']
469
- };
470
- }
471
- }
472
-
473
- // Medium risk: only recursive deletions outside safe dirs
474
- // NOTE: Write/Edit are NOT flagged as risky - they're normal dev operations
475
- if (/rm\s+-rf/i.test(operation)) {
476
- // Check if it's actually safe (build artifacts, temp)
477
- if (matchesPattern(operation, SAFE_OPERATIONS)) {
478
- return { isDestructive: false, riskLevel: 'low', reasons: [] };
479
- }
480
- return {
481
- isDestructive: true,
482
- riskLevel: 'medium',
483
- reasons: ['Recursive deletion']
484
- };
485
- }
486
-
487
- return {
488
- isDestructive: false,
489
- riskLevel: 'low',
490
- reasons: []
491
- };
492
- }
@@ -0,0 +1,114 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+
4
+ /**
5
+ * Server Setup Utilities — Helpers for the main server entry point.
6
+ *
7
+ * - ensureClaudeSettings: Ensures .claude/settings.json has recommended defaults
8
+ * - wrapWebSocket / createPlatformRelayContext: WSContext adapters
9
+ */
10
+
11
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
12
+ import { basename, join } from 'node:path'
13
+ import type { WebSocket as NodeWebSocket } from 'ws'
14
+ import type { WSContext } from './services/websocket/types.js'
15
+
16
+ /**
17
+ * Set the terminal tab title
18
+ * Format: "mstro: directory_name"
19
+ */
20
+ export function setTerminalTitle(directory: string): void {
21
+ const dirName = basename(directory) || directory
22
+ const title = `mstro: ${dirName}`
23
+ process.stdout.write(`\x1b]0;${title}\x07`)
24
+ }
25
+
26
+ /**
27
+ * Ensure .claude/settings.json exists with recommended settings
28
+ * for optimal Claude Code performance with Mstro
29
+ */
30
+ export function ensureClaudeSettings(workingDir: string): void {
31
+ const claudeDir = join(workingDir, '.claude')
32
+ const settingsPath = join(claudeDir, 'settings.json')
33
+
34
+ if (!existsSync(claudeDir)) {
35
+ mkdirSync(claudeDir, { recursive: true })
36
+ }
37
+
38
+ const recommendedSettings = {
39
+ env: {
40
+ CLAUDE_CODE_MAX_OUTPUT_TOKENS: "64000",
41
+ DISABLE_NONESSENTIAL_TRAFFIC: "1"
42
+ }
43
+ }
44
+
45
+ if (!existsSync(settingsPath)) {
46
+ writeFileSync(settingsPath, JSON.stringify(recommendedSettings, null, 2))
47
+ console.log(`📝 Created .claude/settings.json with recommended settings`)
48
+ } else {
49
+ try {
50
+ const existingSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'))
51
+ let updated = false
52
+
53
+ if (!existingSettings.env) {
54
+ existingSettings.env = {}
55
+ updated = true
56
+ }
57
+
58
+ if (!existingSettings.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS) {
59
+ existingSettings.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS = "64000"
60
+ updated = true
61
+ }
62
+ if (!existingSettings.env.DISABLE_NONESSENTIAL_TRAFFIC) {
63
+ existingSettings.env.DISABLE_NONESSENTIAL_TRAFFIC = "1"
64
+ updated = true
65
+ }
66
+
67
+ if (updated) {
68
+ writeFileSync(settingsPath, JSON.stringify(existingSettings, null, 2))
69
+ console.log(`📝 Updated .claude/settings.json with recommended env settings`)
70
+ }
71
+ } catch (_e) {
72
+ console.warn(`⚠️ Could not parse existing .claude/settings.json, skipping update`)
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Wrap a ws WebSocket to match our WSContext interface
79
+ */
80
+ export function wrapWebSocket(ws: NodeWebSocket, workingDir: string): WSContext {
81
+ return {
82
+ send: (data: string | Buffer) => ws.send(data),
83
+ close: () => ws.close(),
84
+ readyState: ws.readyState,
85
+ _workingDir: workingDir,
86
+ _ws: ws
87
+ } as WSContext
88
+ }
89
+
90
+ /**
91
+ * Create a virtual WebSocket context that sends responses through the platform relay.
92
+ * This allows messages from the web (via platform) to be handled by the same wsHandler.
93
+ */
94
+ export function createPlatformRelayContext(
95
+ platformSend: (message: unknown) => void,
96
+ workingDir: string
97
+ ): WSContext {
98
+ return {
99
+ send: (data: string | Buffer) => {
100
+ try {
101
+ const response = typeof data === 'string' ? JSON.parse(data) : JSON.parse(data.toString())
102
+ platformSend(response)
103
+ } catch (e) {
104
+ console.error('[PlatformRelay] Failed to parse response:', e)
105
+ }
106
+ },
107
+ close: () => {
108
+ // No-op for platform relay
109
+ },
110
+ readyState: 1, // WebSocket.OPEN
111
+ _workingDir: workingDir,
112
+ _isPlatformRelay: true
113
+ } as WSContext
114
+ }