mstro-app 0.4.3 → 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 (306) hide show
  1. package/dist/server/cli/headless/claude-invoker-process.d.ts +11 -0
  2. package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -0
  3. package/dist/server/cli/headless/claude-invoker-process.js +140 -0
  4. package/dist/server/cli/headless/claude-invoker-process.js.map +1 -0
  5. package/dist/server/cli/headless/claude-invoker-stall.d.ts +40 -0
  6. package/dist/server/cli/headless/claude-invoker-stall.d.ts.map +1 -0
  7. package/dist/server/cli/headless/claude-invoker-stall.js +98 -0
  8. package/dist/server/cli/headless/claude-invoker-stall.js.map +1 -0
  9. package/dist/server/cli/headless/claude-invoker-stream.d.ts +44 -0
  10. package/dist/server/cli/headless/claude-invoker-stream.d.ts.map +1 -0
  11. package/dist/server/cli/headless/claude-invoker-stream.js +276 -0
  12. package/dist/server/cli/headless/claude-invoker-stream.js.map +1 -0
  13. package/dist/server/cli/headless/claude-invoker-tools.d.ts +21 -0
  14. package/dist/server/cli/headless/claude-invoker-tools.d.ts.map +1 -0
  15. package/dist/server/cli/headless/claude-invoker-tools.js +137 -0
  16. package/dist/server/cli/headless/claude-invoker-tools.js.map +1 -0
  17. package/dist/server/cli/headless/claude-invoker.d.ts +6 -4
  18. package/dist/server/cli/headless/claude-invoker.d.ts.map +1 -1
  19. package/dist/server/cli/headless/claude-invoker.js +10 -807
  20. package/dist/server/cli/headless/claude-invoker.js.map +1 -1
  21. package/dist/server/cli/headless/haiku-assessments.d.ts +62 -0
  22. package/dist/server/cli/headless/haiku-assessments.d.ts.map +1 -0
  23. package/dist/server/cli/headless/haiku-assessments.js +281 -0
  24. package/dist/server/cli/headless/haiku-assessments.js.map +1 -0
  25. package/dist/server/cli/headless/headless-logger.d.ts +3 -2
  26. package/dist/server/cli/headless/headless-logger.d.ts.map +1 -1
  27. package/dist/server/cli/headless/headless-logger.js +28 -5
  28. package/dist/server/cli/headless/headless-logger.js.map +1 -1
  29. package/dist/server/cli/headless/native-timeout-detector.d.ts +44 -0
  30. package/dist/server/cli/headless/native-timeout-detector.d.ts.map +1 -0
  31. package/dist/server/cli/headless/native-timeout-detector.js +99 -0
  32. package/dist/server/cli/headless/native-timeout-detector.js.map +1 -0
  33. package/dist/server/cli/headless/stall-assessor.d.ts +2 -110
  34. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  35. package/dist/server/cli/headless/stall-assessor.js +65 -457
  36. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  37. package/dist/server/cli/improvisation-attachments.d.ts +21 -0
  38. package/dist/server/cli/improvisation-attachments.d.ts.map +1 -0
  39. package/dist/server/cli/improvisation-attachments.js +116 -0
  40. package/dist/server/cli/improvisation-attachments.js.map +1 -0
  41. package/dist/server/cli/improvisation-retry.d.ts +52 -0
  42. package/dist/server/cli/improvisation-retry.d.ts.map +1 -0
  43. package/dist/server/cli/improvisation-retry.js +434 -0
  44. package/dist/server/cli/improvisation-retry.js.map +1 -0
  45. package/dist/server/cli/improvisation-session-manager.d.ts +10 -266
  46. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  47. package/dist/server/cli/improvisation-session-manager.js +117 -1079
  48. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  49. package/dist/server/cli/improvisation-types.d.ts +86 -0
  50. package/dist/server/cli/improvisation-types.d.ts.map +1 -0
  51. package/dist/server/cli/improvisation-types.js +10 -0
  52. package/dist/server/cli/improvisation-types.js.map +1 -0
  53. package/dist/server/cli/prompt-builders.d.ts +68 -0
  54. package/dist/server/cli/prompt-builders.d.ts.map +1 -0
  55. package/dist/server/cli/prompt-builders.js +312 -0
  56. package/dist/server/cli/prompt-builders.js.map +1 -0
  57. package/dist/server/index.js +33 -212
  58. package/dist/server/index.js.map +1 -1
  59. package/dist/server/mcp/bouncer-haiku.d.ts +10 -0
  60. package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -0
  61. package/dist/server/mcp/bouncer-haiku.js +152 -0
  62. package/dist/server/mcp/bouncer-haiku.js.map +1 -0
  63. package/dist/server/mcp/bouncer-integration.d.ts +3 -4
  64. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  65. package/dist/server/mcp/bouncer-integration.js +50 -196
  66. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  67. package/dist/server/mcp/security-analysis.d.ts +38 -0
  68. package/dist/server/mcp/security-analysis.d.ts.map +1 -0
  69. package/dist/server/mcp/security-analysis.js +183 -0
  70. package/dist/server/mcp/security-analysis.js.map +1 -0
  71. package/dist/server/mcp/security-audit.d.ts +1 -1
  72. package/dist/server/mcp/security-audit.d.ts.map +1 -1
  73. package/dist/server/mcp/security-patterns.d.ts +1 -25
  74. package/dist/server/mcp/security-patterns.d.ts.map +1 -1
  75. package/dist/server/mcp/security-patterns.js +55 -260
  76. package/dist/server/mcp/security-patterns.js.map +1 -1
  77. package/dist/server/server-setup.d.ts +22 -0
  78. package/dist/server/server-setup.d.ts.map +1 -0
  79. package/dist/server/server-setup.js +101 -0
  80. package/dist/server/server-setup.js.map +1 -0
  81. package/dist/server/services/file-explorer-ops.d.ts +24 -0
  82. package/dist/server/services/file-explorer-ops.d.ts.map +1 -0
  83. package/dist/server/services/file-explorer-ops.js +211 -0
  84. package/dist/server/services/file-explorer-ops.js.map +1 -0
  85. package/dist/server/services/files.d.ts +2 -85
  86. package/dist/server/services/files.d.ts.map +1 -1
  87. package/dist/server/services/files.js +7 -427
  88. package/dist/server/services/files.js.map +1 -1
  89. package/dist/server/services/plan/composer.d.ts.map +1 -1
  90. package/dist/server/services/plan/composer.js +2 -1
  91. package/dist/server/services/plan/composer.js.map +1 -1
  92. package/dist/server/services/plan/executor.d.ts.map +1 -1
  93. package/dist/server/services/plan/executor.js +3 -1
  94. package/dist/server/services/plan/executor.js.map +1 -1
  95. package/dist/server/services/plan/parser-core.d.ts +20 -0
  96. package/dist/server/services/plan/parser-core.d.ts.map +1 -0
  97. package/dist/server/services/plan/parser-core.js +350 -0
  98. package/dist/server/services/plan/parser-core.js.map +1 -0
  99. package/dist/server/services/plan/parser-migration.d.ts +5 -0
  100. package/dist/server/services/plan/parser-migration.d.ts.map +1 -0
  101. package/dist/server/services/plan/parser-migration.js +124 -0
  102. package/dist/server/services/plan/parser-migration.js.map +1 -0
  103. package/dist/server/services/plan/parser.d.ts +0 -8
  104. package/dist/server/services/plan/parser.d.ts.map +1 -1
  105. package/dist/server/services/plan/parser.js +50 -569
  106. package/dist/server/services/plan/parser.js.map +1 -1
  107. package/dist/server/services/plan/review-gate.d.ts +2 -0
  108. package/dist/server/services/plan/review-gate.d.ts.map +1 -1
  109. package/dist/server/services/plan/review-gate.js +2 -2
  110. package/dist/server/services/plan/review-gate.js.map +1 -1
  111. package/dist/server/services/plan/types.d.ts +2 -0
  112. package/dist/server/services/plan/types.d.ts.map +1 -1
  113. package/dist/server/services/platform-credentials.d.ts +24 -0
  114. package/dist/server/services/platform-credentials.d.ts.map +1 -0
  115. package/dist/server/services/platform-credentials.js +68 -0
  116. package/dist/server/services/platform-credentials.js.map +1 -0
  117. package/dist/server/services/platform.d.ts +1 -31
  118. package/dist/server/services/platform.d.ts.map +1 -1
  119. package/dist/server/services/platform.js +10 -119
  120. package/dist/server/services/platform.js.map +1 -1
  121. package/dist/server/services/terminal/pty-manager.d.ts +7 -97
  122. package/dist/server/services/terminal/pty-manager.d.ts.map +1 -1
  123. package/dist/server/services/terminal/pty-manager.js +53 -266
  124. package/dist/server/services/terminal/pty-manager.js.map +1 -1
  125. package/dist/server/services/terminal/pty-utils.d.ts +57 -0
  126. package/dist/server/services/terminal/pty-utils.d.ts.map +1 -0
  127. package/dist/server/services/terminal/pty-utils.js +141 -0
  128. package/dist/server/services/terminal/pty-utils.js.map +1 -0
  129. package/dist/server/services/websocket/file-definition-handlers.d.ts +4 -0
  130. package/dist/server/services/websocket/file-definition-handlers.d.ts.map +1 -0
  131. package/dist/server/services/websocket/file-definition-handlers.js +153 -0
  132. package/dist/server/services/websocket/file-definition-handlers.js.map +1 -0
  133. package/dist/server/services/websocket/file-explorer-handlers.d.ts.map +1 -1
  134. package/dist/server/services/websocket/file-explorer-handlers.js +52 -391
  135. package/dist/server/services/websocket/file-explorer-handlers.js.map +1 -1
  136. package/dist/server/services/websocket/file-search-handlers.d.ts +5 -0
  137. package/dist/server/services/websocket/file-search-handlers.d.ts.map +1 -0
  138. package/dist/server/services/websocket/file-search-handlers.js +238 -0
  139. package/dist/server/services/websocket/file-search-handlers.js.map +1 -0
  140. package/dist/server/services/websocket/file-utils.js +3 -3
  141. package/dist/server/services/websocket/file-utils.js.map +1 -1
  142. package/dist/server/services/websocket/git-branch-handlers.d.ts +7 -0
  143. package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -0
  144. package/dist/server/services/websocket/git-branch-handlers.js +110 -0
  145. package/dist/server/services/websocket/git-branch-handlers.js.map +1 -0
  146. package/dist/server/services/websocket/git-diff-handlers.d.ts +6 -0
  147. package/dist/server/services/websocket/git-diff-handlers.d.ts.map +1 -0
  148. package/dist/server/services/websocket/git-diff-handlers.js +123 -0
  149. package/dist/server/services/websocket/git-diff-handlers.js.map +1 -0
  150. package/dist/server/services/websocket/git-handlers.d.ts +2 -31
  151. package/dist/server/services/websocket/git-handlers.d.ts.map +1 -1
  152. package/dist/server/services/websocket/git-handlers.js +35 -541
  153. package/dist/server/services/websocket/git-handlers.js.map +1 -1
  154. package/dist/server/services/websocket/git-log-handlers.d.ts +6 -0
  155. package/dist/server/services/websocket/git-log-handlers.d.ts.map +1 -0
  156. package/dist/server/services/websocket/git-log-handlers.js +128 -0
  157. package/dist/server/services/websocket/git-log-handlers.js.map +1 -0
  158. package/dist/server/services/websocket/git-pr-handlers.d.ts.map +1 -1
  159. package/dist/server/services/websocket/git-pr-handlers.js +13 -53
  160. package/dist/server/services/websocket/git-pr-handlers.js.map +1 -1
  161. package/dist/server/services/websocket/git-tag-handlers.d.ts +6 -0
  162. package/dist/server/services/websocket/git-tag-handlers.d.ts.map +1 -0
  163. package/dist/server/services/websocket/git-tag-handlers.js +76 -0
  164. package/dist/server/services/websocket/git-tag-handlers.js.map +1 -0
  165. package/dist/server/services/websocket/git-utils.d.ts +43 -0
  166. package/dist/server/services/websocket/git-utils.d.ts.map +1 -0
  167. package/dist/server/services/websocket/git-utils.js +201 -0
  168. package/dist/server/services/websocket/git-utils.js.map +1 -0
  169. package/dist/server/services/websocket/handler.d.ts +2 -0
  170. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  171. package/dist/server/services/websocket/handler.js +37 -126
  172. package/dist/server/services/websocket/handler.js.map +1 -1
  173. package/dist/server/services/websocket/plan-board-handlers.d.ts +11 -0
  174. package/dist/server/services/websocket/plan-board-handlers.d.ts.map +1 -0
  175. package/dist/server/services/websocket/plan-board-handlers.js +218 -0
  176. package/dist/server/services/websocket/plan-board-handlers.js.map +1 -0
  177. package/dist/server/services/websocket/plan-execution-handlers.d.ts +9 -0
  178. package/dist/server/services/websocket/plan-execution-handlers.d.ts.map +1 -0
  179. package/dist/server/services/websocket/plan-execution-handlers.js +142 -0
  180. package/dist/server/services/websocket/plan-execution-handlers.js.map +1 -0
  181. package/dist/server/services/websocket/plan-handlers.d.ts +7 -2
  182. package/dist/server/services/websocket/plan-handlers.d.ts.map +1 -1
  183. package/dist/server/services/websocket/plan-handlers.js +6 -925
  184. package/dist/server/services/websocket/plan-handlers.js.map +1 -1
  185. package/dist/server/services/websocket/plan-helpers.d.ts +19 -0
  186. package/dist/server/services/websocket/plan-helpers.d.ts.map +1 -0
  187. package/dist/server/services/websocket/plan-helpers.js +199 -0
  188. package/dist/server/services/websocket/plan-helpers.js.map +1 -0
  189. package/dist/server/services/websocket/plan-issue-handlers.d.ts +12 -0
  190. package/dist/server/services/websocket/plan-issue-handlers.d.ts.map +1 -0
  191. package/dist/server/services/websocket/plan-issue-handlers.js +162 -0
  192. package/dist/server/services/websocket/plan-issue-handlers.js.map +1 -0
  193. package/dist/server/services/websocket/plan-sprint-handlers.d.ts +7 -0
  194. package/dist/server/services/websocket/plan-sprint-handlers.d.ts.map +1 -0
  195. package/dist/server/services/websocket/plan-sprint-handlers.js +206 -0
  196. package/dist/server/services/websocket/plan-sprint-handlers.js.map +1 -0
  197. package/dist/server/services/websocket/quality-complexity.d.ts +14 -0
  198. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -0
  199. package/dist/server/services/websocket/quality-complexity.js +262 -0
  200. package/dist/server/services/websocket/quality-complexity.js.map +1 -0
  201. package/dist/server/services/websocket/quality-fix-agent.d.ts +16 -0
  202. package/dist/server/services/websocket/quality-fix-agent.d.ts.map +1 -0
  203. package/dist/server/services/websocket/quality-fix-agent.js +140 -0
  204. package/dist/server/services/websocket/quality-fix-agent.js.map +1 -0
  205. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
  206. package/dist/server/services/websocket/quality-handlers.js +34 -346
  207. package/dist/server/services/websocket/quality-handlers.js.map +1 -1
  208. package/dist/server/services/websocket/quality-linting.d.ts +9 -0
  209. package/dist/server/services/websocket/quality-linting.d.ts.map +1 -0
  210. package/dist/server/services/websocket/quality-linting.js +178 -0
  211. package/dist/server/services/websocket/quality-linting.js.map +1 -0
  212. package/dist/server/services/websocket/quality-review-agent.d.ts +19 -0
  213. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -0
  214. package/dist/server/services/websocket/quality-review-agent.js +206 -0
  215. package/dist/server/services/websocket/quality-review-agent.js.map +1 -0
  216. package/dist/server/services/websocket/quality-service.d.ts +3 -51
  217. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  218. package/dist/server/services/websocket/quality-service.js +9 -651
  219. package/dist/server/services/websocket/quality-service.js.map +1 -1
  220. package/dist/server/services/websocket/quality-tools.d.ts +23 -0
  221. package/dist/server/services/websocket/quality-tools.d.ts.map +1 -0
  222. package/dist/server/services/websocket/quality-tools.js +208 -0
  223. package/dist/server/services/websocket/quality-tools.js.map +1 -0
  224. package/dist/server/services/websocket/quality-types.d.ts +59 -0
  225. package/dist/server/services/websocket/quality-types.d.ts.map +1 -0
  226. package/dist/server/services/websocket/quality-types.js +101 -0
  227. package/dist/server/services/websocket/quality-types.js.map +1 -0
  228. package/dist/server/services/websocket/session-handlers.d.ts +3 -4
  229. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  230. package/dist/server/services/websocket/session-handlers.js +3 -378
  231. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  232. package/dist/server/services/websocket/session-history.d.ts +4 -0
  233. package/dist/server/services/websocket/session-history.d.ts.map +1 -0
  234. package/dist/server/services/websocket/session-history.js +208 -0
  235. package/dist/server/services/websocket/session-history.js.map +1 -0
  236. package/dist/server/services/websocket/session-initialization.d.ts +5 -0
  237. package/dist/server/services/websocket/session-initialization.d.ts.map +1 -0
  238. package/dist/server/services/websocket/session-initialization.js +163 -0
  239. package/dist/server/services/websocket/session-initialization.js.map +1 -0
  240. package/dist/server/services/websocket/types.d.ts +12 -2
  241. package/dist/server/services/websocket/types.d.ts.map +1 -1
  242. package/package.json +1 -1
  243. package/server/cli/headless/claude-invoker-process.ts +204 -0
  244. package/server/cli/headless/claude-invoker-stall.ts +164 -0
  245. package/server/cli/headless/claude-invoker-stream.ts +353 -0
  246. package/server/cli/headless/claude-invoker-tools.ts +187 -0
  247. package/server/cli/headless/claude-invoker.ts +15 -1096
  248. package/server/cli/headless/haiku-assessments.ts +365 -0
  249. package/server/cli/headless/headless-logger.ts +26 -5
  250. package/server/cli/headless/native-timeout-detector.ts +117 -0
  251. package/server/cli/headless/stall-assessor.ts +65 -618
  252. package/server/cli/improvisation-attachments.ts +148 -0
  253. package/server/cli/improvisation-retry.ts +602 -0
  254. package/server/cli/improvisation-session-manager.ts +140 -1349
  255. package/server/cli/improvisation-types.ts +98 -0
  256. package/server/cli/prompt-builders.ts +370 -0
  257. package/server/index.ts +35 -246
  258. package/server/mcp/bouncer-haiku.ts +182 -0
  259. package/server/mcp/bouncer-integration.ts +87 -248
  260. package/server/mcp/security-analysis.ts +217 -0
  261. package/server/mcp/security-audit.ts +1 -1
  262. package/server/mcp/security-patterns.ts +60 -283
  263. package/server/server-setup.ts +114 -0
  264. package/server/services/file-explorer-ops.ts +293 -0
  265. package/server/services/files.ts +20 -532
  266. package/server/services/plan/composer.ts +2 -1
  267. package/server/services/plan/executor.ts +3 -1
  268. package/server/services/plan/parser-core.ts +406 -0
  269. package/server/services/plan/parser-migration.ts +128 -0
  270. package/server/services/plan/parser.ts +52 -620
  271. package/server/services/plan/review-gate.ts +4 -2
  272. package/server/services/plan/types.ts +2 -0
  273. package/server/services/platform-credentials.ts +83 -0
  274. package/server/services/platform.ts +15 -141
  275. package/server/services/terminal/pty-manager.ts +66 -313
  276. package/server/services/terminal/pty-utils.ts +176 -0
  277. package/server/services/websocket/file-definition-handlers.ts +165 -0
  278. package/server/services/websocket/file-explorer-handlers.ts +37 -452
  279. package/server/services/websocket/file-search-handlers.ts +291 -0
  280. package/server/services/websocket/file-utils.ts +3 -3
  281. package/server/services/websocket/git-branch-handlers.ts +130 -0
  282. package/server/services/websocket/git-diff-handlers.ts +140 -0
  283. package/server/services/websocket/git-handlers.ts +40 -625
  284. package/server/services/websocket/git-log-handlers.ts +149 -0
  285. package/server/services/websocket/git-pr-handlers.ts +17 -62
  286. package/server/services/websocket/git-tag-handlers.ts +91 -0
  287. package/server/services/websocket/git-utils.ts +230 -0
  288. package/server/services/websocket/handler.ts +39 -126
  289. package/server/services/websocket/plan-board-handlers.ts +277 -0
  290. package/server/services/websocket/plan-execution-handlers.ts +184 -0
  291. package/server/services/websocket/plan-handlers.ts +8 -1114
  292. package/server/services/websocket/plan-helpers.ts +215 -0
  293. package/server/services/websocket/plan-issue-handlers.ts +204 -0
  294. package/server/services/websocket/plan-sprint-handlers.ts +252 -0
  295. package/server/services/websocket/quality-complexity.ts +294 -0
  296. package/server/services/websocket/quality-fix-agent.ts +181 -0
  297. package/server/services/websocket/quality-handlers.ts +36 -404
  298. package/server/services/websocket/quality-linting.ts +187 -0
  299. package/server/services/websocket/quality-review-agent.ts +246 -0
  300. package/server/services/websocket/quality-service.ts +11 -762
  301. package/server/services/websocket/quality-tools.ts +209 -0
  302. package/server/services/websocket/quality-types.ts +169 -0
  303. package/server/services/websocket/session-handlers.ts +5 -437
  304. package/server/services/websocket/session-history.ts +222 -0
  305. package/server/services/websocket/session-initialization.ts +209 -0
  306. package/server/services/websocket/types.ts +17 -0
@@ -0,0 +1,11 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { StreamHandlerContext } from './claude-invoker-stream.js';
3
+ import type { ExecutionResult, ResolvedHeadlessConfig } from './types.js';
4
+ export declare function handleSpawnError(error: NodeJS.ErrnoException, config: ResolvedHeadlessConfig, reject: (reason: Error) => void): void;
5
+ export declare function buildClaudeArgs(config: ResolvedHeadlessConfig, prompt: string, hasImageAttachments: boolean, useStreamJson: boolean, mcpConfigPath: string | null): string[];
6
+ /** Spawn the Claude CLI process and register it */
7
+ export declare function spawnAndRegister(config: ResolvedHeadlessConfig, prompt: string, hasImageAttachments: boolean, useStreamJson: boolean, runningProcesses: Map<number, ChildProcess>, perfStart: number): ChildProcess;
8
+ export declare function buildCloseResult(ctx: StreamHandlerContext, stdout: string, stderr: string, code: number | null, signal: NodeJS.Signals | null, sessionCapture: {
9
+ claudeSessionId?: string;
10
+ }): ExecutionResult;
11
+ //# sourceMappingURL=claude-invoker-process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-invoker-process.d.ts","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker-process.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAE9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAKvE,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AA0B1E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,CAAC,cAAc,EAC5B,MAAM,EAAE,sBAAsB,EAC9B,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,KAAK,IAAI,GAC9B,IAAI,CAYN;AAID,wBAAgB,eAAe,CAC7B,MAAM,EAAE,sBAAsB,EAC9B,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,OAAO,EAC5B,aAAa,EAAE,OAAO,EACtB,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,MAAM,EAAE,CAwCV;AAqBD,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,sBAAsB,EAC9B,MAAM,EAAE,MAAM,EACd,mBAAmB,EAAE,OAAO,EAC5B,aAAa,EAAE,OAAO,EACtB,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAC3C,SAAS,EAAE,MAAM,GAChB,YAAY,CAyCd;AAID,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,oBAAoB,EACzB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,EAC7B,cAAc,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3C,eAAe,CAoBjB"}
@@ -0,0 +1,140 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ import { spawn } from 'node:child_process';
4
+ import { sanitizeEnvForSandbox } from '../../services/sandbox-utils.js';
5
+ import { flushNativeTimeoutBuffers, verboseLog } from './claude-invoker-stream.js';
6
+ import { herror } from './headless-logger.js';
7
+ import { generateMcpConfig } from './mcp-config.js';
8
+ import { buildMultimodalMessage } from './prompt-utils.js';
9
+ // ========== Signal Helpers ==========
10
+ /** Map a Node.js signal name to its numeric value for exit code computation */
11
+ function signalToNumber(signal) {
12
+ const map = {
13
+ SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGABRT: 6,
14
+ SIGKILL: 9, SIGTERM: 15, SIGUSR1: 10, SIGUSR2: 12,
15
+ };
16
+ return map[signal];
17
+ }
18
+ // ========== Error Handling ==========
19
+ const SPAWN_ERROR_MAP = {
20
+ ENOENT: {
21
+ code: 'CLAUDE_NOT_INSTALLED',
22
+ message: 'Claude Code is not installed or not in PATH. Please install Claude Code: npm install -g @anthropic-ai/claude-code'
23
+ },
24
+ EACCES: {
25
+ code: 'PERMISSION_DENIED',
26
+ message: 'Permission denied when running Claude Code. Please check file permissions.'
27
+ }
28
+ };
29
+ export function handleSpawnError(error, config, reject) {
30
+ const mapped = error.code ? SPAWN_ERROR_MAP[error.code] : undefined;
31
+ if (!mapped) {
32
+ reject(error);
33
+ return;
34
+ }
35
+ const formatted = `[[MSTRO_ERROR:${mapped.code}]] ${mapped.message}`;
36
+ if (config.outputCallback) {
37
+ config.outputCallback(`\n${formatted}\n`);
38
+ }
39
+ reject(new Error(formatted));
40
+ }
41
+ // ========== Argument Building ==========
42
+ export function buildClaudeArgs(config, prompt, hasImageAttachments, useStreamJson, mcpConfigPath) {
43
+ const args = ['--print'];
44
+ if (config.model && config.model !== 'default') {
45
+ args.push('--model', config.model);
46
+ }
47
+ if (useStreamJson) {
48
+ args.push('--output-format', 'stream-json', '--include-partial-messages', '--verbose');
49
+ }
50
+ if (hasImageAttachments) {
51
+ args.push('--input-format', 'stream-json');
52
+ }
53
+ if (config.claudeSessionId) {
54
+ args.push('--resume', config.claudeSessionId);
55
+ }
56
+ else if (config.continueSession) {
57
+ args.push('--continue');
58
+ }
59
+ if (config.disallowedTools && config.disallowedTools.length > 0) {
60
+ args.push('--disallowedTools', config.disallowedTools.join(','));
61
+ }
62
+ if (mcpConfigPath) {
63
+ args.push('--mcp-config', mcpConfigPath);
64
+ args.push('--permission-prompt-tool', 'mcp__mstro-bouncer__approval_prompt');
65
+ }
66
+ else {
67
+ args.push('--permission-mode', 'acceptEdits');
68
+ }
69
+ // Reduce Edit-without-Read errors by reminding the model
70
+ args.push('--append-system-prompt', 'IMPORTANT: Always use the Read tool to read a file before using Edit or Write on it. Never edit a file you have not read in this session.');
71
+ if (!hasImageAttachments) {
72
+ args.push(prompt);
73
+ }
74
+ return args;
75
+ }
76
+ /** Write image attachments to the Claude process stdin as stream-json */
77
+ function writeImageAttachmentsToStdin(claudeProcess, prompt, config) {
78
+ claudeProcess.stdin.on('error', (err) => {
79
+ if (config.verbose) {
80
+ herror('[STDIN] Write error:', err.message);
81
+ }
82
+ config.outputCallback?.(`\n[[MSTRO_ERROR:STDIN_WRITE_FAILED]] Failed to send image data to Claude: ${err.message}\n`);
83
+ });
84
+ const multimodalMessage = buildMultimodalMessage(prompt, config.imageAttachments);
85
+ claudeProcess.stdin.write(multimodalMessage);
86
+ claudeProcess.stdin.end();
87
+ }
88
+ // ========== Process Spawning ==========
89
+ /** Spawn the Claude CLI process and register it */
90
+ export function spawnAndRegister(config, prompt, hasImageAttachments, useStreamJson, runningProcesses, perfStart) {
91
+ const mcpConfigPath = generateMcpConfig(config.workingDir, config.verbose);
92
+ if (!mcpConfigPath && config.outputCallback) {
93
+ config.outputCallback('\n[[MSTRO_ERROR:BOUNCER_UNAVAILABLE]] Security bouncer not available. Running with limited permissions — file edits allowed, but shell commands may be restricted.\n');
94
+ }
95
+ const args = buildClaudeArgs(config, prompt, hasImageAttachments, useStreamJson, mcpConfigPath);
96
+ verboseLog(config.verbose, `[PERF] About to spawn: ${Date.now() - perfStart}ms`, `[PERF] Command: ${config.claudeCommand} ${args.join(' ')}`);
97
+ const baseEnv = config.sandboxed
98
+ ? sanitizeEnvForSandbox(process.env, config.workingDir)
99
+ : { ...process.env };
100
+ const spawnEnv = config.extraEnv
101
+ ? { ...baseEnv, ...config.extraEnv }
102
+ : baseEnv;
103
+ const claudeProcess = spawn(config.claudeCommand, args, {
104
+ cwd: config.workingDir,
105
+ detached: true,
106
+ env: spawnEnv,
107
+ stdio: [hasImageAttachments ? 'pipe' : 'ignore', 'pipe', 'pipe']
108
+ });
109
+ if (hasImageAttachments && claudeProcess.stdin) {
110
+ writeImageAttachmentsToStdin(claudeProcess, prompt, config);
111
+ }
112
+ if (claudeProcess.pid) {
113
+ runningProcesses.set(claudeProcess.pid, claudeProcess);
114
+ }
115
+ verboseLog(config.verbose, `[PERF] Spawned: ${Date.now() - perfStart}ms`);
116
+ return claudeProcess;
117
+ }
118
+ // ========== Result Building ==========
119
+ export function buildCloseResult(ctx, stdout, stderr, code, signal, sessionCapture) {
120
+ const postTimeout = flushNativeTimeoutBuffers(ctx);
121
+ const resumeBuffered = ctx.resumeAssessmentActive ? (ctx.resumeAssessmentBuffer || undefined) : undefined;
122
+ const exitCode = code ?? (signal ? 128 + (signalToNumber(signal) ?? 0) : 0);
123
+ const hasTokenUsage = ctx.apiTokenUsage.inputTokens > 0 || ctx.apiTokenUsage.outputTokens > 0;
124
+ return {
125
+ output: stdout,
126
+ error: stderr || undefined,
127
+ exitCode,
128
+ signalName: signal || undefined,
129
+ assistantResponse: ctx.accumulatedAssistantResponse || undefined,
130
+ thinkingOutput: ctx.accumulatedThinking || undefined,
131
+ toolUseHistory: ctx.accumulatedToolUse.length > 0 ? ctx.accumulatedToolUse : undefined,
132
+ claudeSessionId: sessionCapture.claudeSessionId,
133
+ nativeTimeoutCount: ctx.nativeTimeoutDetector.timeoutCount || undefined,
134
+ postTimeoutOutput: postTimeout,
135
+ resumeBufferedOutput: resumeBuffered,
136
+ apiTokenUsage: hasTokenUsage ? { ...ctx.apiTokenUsage } : undefined,
137
+ stopReason: ctx.stopReason,
138
+ };
139
+ }
140
+ //# sourceMappingURL=claude-invoker-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-invoker-process.js","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { ChildProcess } from 'node:child_process';
2
+ import { type StallContext } from './stall-assessor.js';
3
+ import type { ResolvedHeadlessConfig } from './types.js';
4
+ export interface StallAssessmentParams {
5
+ stallCtx: StallContext;
6
+ config: ResolvedHeadlessConfig;
7
+ now: number;
8
+ extensionsGranted: number;
9
+ maxExtensions: number;
10
+ toolWatchdogActive?: boolean;
11
+ }
12
+ /** Mutable state for stall detection, shared between the interval callback and the outer function */
13
+ export interface StallState {
14
+ lastActivityTime: number;
15
+ stallWarningEmitted: boolean;
16
+ assessmentInProgress: boolean;
17
+ extensionsGranted: number;
18
+ currentKillDeadline: number;
19
+ nextWarningAfter: number;
20
+ }
21
+ /** Terminate a stalled process: SIGTERM then SIGKILL after 5s */
22
+ export declare function terminateStallProcess(claudeProcess: ChildProcess, interval: ReturnType<typeof setInterval>, config: ResolvedHeadlessConfig, message: string): void;
23
+ /** Run a single stall-check tick */
24
+ export declare function runStallCheckTick(state: StallState, opts: {
25
+ perfStart: number;
26
+ stallWarningMs: number;
27
+ stallHardCapMs: number;
28
+ maxExtensions: number;
29
+ stallAssessEnabled: boolean;
30
+ toolWatchdogActive: boolean;
31
+ prompt: string;
32
+ pendingTools: Map<string, string>;
33
+ lastToolInputSummary: string | undefined;
34
+ totalToolCalls: number;
35
+ claudeProcess: ChildProcess;
36
+ stallCheckInterval: ReturnType<typeof setInterval>;
37
+ config: ResolvedHeadlessConfig;
38
+ lastTokenActivityTime: number;
39
+ }): Promise<void>;
40
+ //# sourceMappingURL=claude-invoker-stall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-invoker-stall.d.ts","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker-stall.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EAAe,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEzD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,YAAY,CAAC;IACvB,MAAM,EAAE,sBAAsB,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,qGAAqG;AACrG,MAAM,WAAW,UAAU;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,iEAAiE;AACjE,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,YAAY,EAC3B,QAAQ,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,EACxC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,MAAM,GACd,IAAI,CASN;AA2CD,oCAAoC;AACpC,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE;IACJ,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,YAAY,CAAC;IAC5B,kBAAkB,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;IACnD,MAAM,EAAE,sBAAsB,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;CAC/B,GACA,OAAO,CAAC,IAAI,CAAC,CA0Df"}
@@ -0,0 +1,98 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ import { hlog } from './headless-logger.js';
4
+ import { killProcessGroup } from './runner.js';
5
+ import { assessStall } from './stall-assessor.js';
6
+ /** Terminate a stalled process: SIGTERM then SIGKILL after 5s */
7
+ export function terminateStallProcess(claudeProcess, interval, config, message) {
8
+ clearInterval(interval);
9
+ config.outputCallback?.(message);
10
+ if (claudeProcess.pid)
11
+ killProcessGroup(claudeProcess.pid, 'SIGTERM');
12
+ setTimeout(() => {
13
+ if (!claudeProcess.killed && claudeProcess.pid) {
14
+ killProcessGroup(claudeProcess.pid, 'SIGKILL');
15
+ }
16
+ }, 5000);
17
+ }
18
+ /** Run stall assessment and return updated state if extended, null otherwise */
19
+ async function runStallAssessment(params) {
20
+ const { stallCtx, config, now, extensionsGranted, maxExtensions, toolWatchdogActive } = params;
21
+ try {
22
+ const verdict = await assessStall(stallCtx, config.claudeCommand, config.verbose, toolWatchdogActive);
23
+ if (verdict.action === 'extend') {
24
+ const newExtensions = extensionsGranted + 1;
25
+ const elapsedMin = Math.round(stallCtx.elapsedTotalMs / 60_000);
26
+ const pendingNames = stallCtx.pendingToolNames ?? new Set();
27
+ const isAgentTeamsLead = verdict.reason.includes('Agent Teams lead');
28
+ if (pendingNames.has('Task') || isAgentTeamsLead) {
29
+ config.outputCallback?.(`\n[[MSTRO_STALL_EXTENDED]] ${isAgentTeamsLead ? 'Teammates still working' : 'Task subagent still running'} (${elapsedMin} min elapsed). ${verdict.reason}.\n`);
30
+ }
31
+ else {
32
+ config.outputCallback?.(`\n[[MSTRO_STALL_EXTENDED]] Process still working (${elapsedMin} min elapsed). ${verdict.reason}. Extension ${newExtensions}/${maxExtensions}.\n`);
33
+ }
34
+ if (config.verbose) {
35
+ hlog(`[STALL] Extended by ${Math.round(verdict.extensionMs / 60_000)} min: ${verdict.reason}`);
36
+ }
37
+ return { extensionsGranted: newExtensions, currentKillDeadline: now + verdict.extensionMs };
38
+ }
39
+ config.outputCallback?.(`\n[[MSTRO_STALL_CONFIRMED]] Assessment: process likely stalled. ${verdict.reason}.\n`);
40
+ if (config.verbose) {
41
+ hlog(`[STALL] Assessment says stalled: ${verdict.reason}`);
42
+ }
43
+ }
44
+ catch (err) {
45
+ if (config.verbose) {
46
+ hlog(`[STALL] Assessment error: ${err}`);
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ /** Run a single stall-check tick */
52
+ export async function runStallCheckTick(state, opts) {
53
+ const now = Date.now();
54
+ const silenceMs = now - state.lastActivityTime;
55
+ const totalElapsed = now - opts.perfStart;
56
+ const tokenSilenceMs = now - opts.lastTokenActivityTime;
57
+ if (totalElapsed >= opts.stallHardCapMs) {
58
+ terminateStallProcess(opts.claudeProcess, opts.stallCheckInterval, opts.config, `\n[[MSTRO_ERROR:EXECUTION_STALLED]] Hard time limit reached (${Math.round(opts.stallHardCapMs / 60000)} min total). Terminating process.\n`);
59
+ return;
60
+ }
61
+ // Token activity pushes the kill deadline forward
62
+ if (tokenSilenceMs < 60_000 && now < state.currentKillDeadline) {
63
+ const killMs = opts.config.stallKillMs ?? 1_800_000;
64
+ state.currentKillDeadline = Math.max(state.currentKillDeadline, now + killMs);
65
+ }
66
+ if (now >= state.currentKillDeadline) {
67
+ terminateStallProcess(opts.claudeProcess, opts.stallCheckInterval, opts.config, `\n[[MSTRO_ERROR:EXECUTION_STALLED]] No output for ${Math.round(silenceMs / 60_000)} minutes. Terminating process.\n`);
68
+ return;
69
+ }
70
+ if (silenceMs < opts.stallWarningMs || state.stallWarningEmitted || now < state.nextWarningAfter || state.assessmentInProgress)
71
+ return;
72
+ const stallCtx = {
73
+ originalPrompt: opts.prompt,
74
+ silenceMs,
75
+ lastToolName: opts.pendingTools.size > 0 ? Array.from(opts.pendingTools.values()).pop() : undefined,
76
+ lastToolInputSummary: opts.lastToolInputSummary,
77
+ pendingToolCount: opts.pendingTools.size,
78
+ pendingToolNames: new Set(opts.pendingTools.values()),
79
+ totalToolCalls: opts.totalToolCalls,
80
+ elapsedTotalMs: totalElapsed,
81
+ tokenSilenceMs,
82
+ };
83
+ if (opts.stallAssessEnabled && state.extensionsGranted < opts.maxExtensions) {
84
+ state.assessmentInProgress = true;
85
+ const result = await runStallAssessment({ stallCtx, config: opts.config, now, extensionsGranted: state.extensionsGranted, maxExtensions: opts.maxExtensions, toolWatchdogActive: opts.toolWatchdogActive });
86
+ state.assessmentInProgress = false;
87
+ if (result) {
88
+ state.extensionsGranted = result.extensionsGranted;
89
+ state.currentKillDeadline = result.currentKillDeadline;
90
+ state.nextWarningAfter = now + opts.stallWarningMs;
91
+ return;
92
+ }
93
+ }
94
+ state.stallWarningEmitted = true;
95
+ const killIn = Math.round((state.currentKillDeadline - now) / 60_000);
96
+ opts.config.outputCallback?.(`\n[[MSTRO_ERROR:EXECUTION_STALLED]] No output for ${Math.round(silenceMs / 60_000)} minutes. Will terminate in ${killIn} minutes if no activity.\n`);
97
+ }
98
+ //# sourceMappingURL=claude-invoker-stall.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-invoker-stall.js","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker-stall.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,gEAAgE;AAGhE,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAsBrE,iEAAiE;AACjE,MAAM,UAAU,qBAAqB,CACnC,aAA2B,EAC3B,QAAwC,EACxC,MAA8B,EAC9B,OAAe;IAEf,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxB,MAAM,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,aAAa,CAAC,GAAG;QAAE,gBAAgB,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACtE,UAAU,CAAC,GAAG,EAAE;QACd,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,CAAC;YAC/C,gBAAgB,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC;AAED,gFAAgF;AAChF,KAAK,UAAU,kBAAkB,CAC/B,MAA6B;IAE7B,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAAC;IAC/F,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC,CAAC;QACtG,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,aAAa,GAAG,iBAAiB,GAAG,CAAC,CAAC;YAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,GAAG,MAAM,CAAC,CAAC;YAChE,MAAM,YAAY,GAAG,QAAQ,CAAC,gBAAgB,IAAI,IAAI,GAAG,EAAU,CAAC;YAEpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC;YACrE,IAAI,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;gBACjD,MAAM,CAAC,cAAc,EAAE,CACrB,8BAA8B,gBAAgB,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,6BAA6B,KAAK,UAAU,kBAAkB,OAAO,CAAC,MAAM,KAAK,CAC/J,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,cAAc,EAAE,CACrB,qDAAqD,UAAU,kBAAkB,OAAO,CAAC,MAAM,eAAe,aAAa,IAAI,aAAa,KAAK,CAClJ,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,uBAAuB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACjG,CAAC;YACD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,mBAAmB,EAAE,GAAG,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QAC9F,CAAC;QACD,MAAM,CAAC,cAAc,EAAE,CACrB,mEAAmE,OAAO,CAAC,MAAM,KAAK,CACvF,CAAC;QACF,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,oCAAoC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAiB,EACjB,IAeC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,GAAG,GAAG,KAAK,CAAC,gBAAgB,CAAC;IAC/C,MAAM,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC;IAC1C,MAAM,cAAc,GAAG,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC;IAExD,IAAI,YAAY,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACxC,qBAAqB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,MAAM,EAC5E,gEAAgE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC,qCAAqC,CAC7I,CAAC;QACF,OAAO;IACT,CAAC;IAED,kDAAkD;IAClD,IAAI,cAAc,GAAG,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,mBAAmB,EAAE,CAAC;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,SAAS,CAAC;QACpD,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,mBAAmB,EAAE,GAAG,GAAG,MAAM,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,GAAG,IAAI,KAAK,CAAC,mBAAmB,EAAE,CAAC;QACrC,qBAAqB,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,MAAM,EAC5E,qDAAqD,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,kCAAkC,CACtH,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,SAAS,GAAG,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,mBAAmB,IAAI,GAAG,GAAG,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,oBAAoB;QAAE,OAAO;IAEvI,MAAM,QAAQ,GAAiB;QAC7B,cAAc,EAAE,IAAI,CAAC,MAAM;QAC3B,SAAS;QACT,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;QACnG,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;QAC/C,gBAAgB,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI;QACxC,gBAAgB,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QACrD,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,cAAc,EAAE,YAAY;QAC5B,cAAc;KACf,CAAC;IAEF,IAAI,IAAI,CAAC,kBAAkB,IAAI,KAAK,CAAC,iBAAiB,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAC5E,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC;QAC5M,KAAK,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAEnC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;YACnD,KAAK,CAAC,mBAAmB,GAAG,MAAM,CAAC,mBAAmB,CAAC;YACvD,KAAK,CAAC,gBAAgB,GAAG,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC;YACnD,OAAO;QACT,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,mBAAmB,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IACtE,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAC1B,qDAAqD,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,+BAA+B,MAAM,4BAA4B,CACrJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { NativeTimeoutDetector } from './native-timeout-detector.js';
2
+ import type { ResolvedHeadlessConfig, ToolUseAccumulator } from './types.js';
3
+ type StreamJson = any;
4
+ export interface StreamHandlerContext {
5
+ config: ResolvedHeadlessConfig;
6
+ accumulatedAssistantResponse: string;
7
+ accumulatedThinking: string;
8
+ accumulatedToolUse: ToolUseAccumulator[];
9
+ toolInputBuffers: Map<number, {
10
+ name: string;
11
+ id: string;
12
+ inputJson: string;
13
+ startTime: number;
14
+ }>;
15
+ nativeTimeoutDetector: NativeTimeoutDetector;
16
+ /** When true, assistant text is buffered instead of forwarded to outputCallback.
17
+ * Active during resume mode until thinking/tool activity confirms Claude has context. */
18
+ resumeAssessmentActive: boolean;
19
+ /** Buffered assistant text during resume assessment */
20
+ resumeAssessmentBuffer: string;
21
+ /** Cumulative API token usage from message_start/message_delta events */
22
+ apiTokenUsage: {
23
+ inputTokens: number;
24
+ outputTokens: number;
25
+ };
26
+ /** Tracks cumulative output_tokens within the current step (message_delta is cumulative per-step) */
27
+ currentStepOutputTokens: number;
28
+ /** Timestamp of the last token usage change (tokens still flowing = process alive) */
29
+ lastTokenActivityTime: number;
30
+ /** Claude Code result event stop_reason (e.g., 'end_turn', 'max_tokens') */
31
+ stopReason?: string;
32
+ }
33
+ /** Log messages when verbose mode is enabled */
34
+ export declare function verboseLog(verbose: boolean | undefined, ...msgs: string[]): void;
35
+ export declare function processStreamEvent(parsed: StreamJson, ctx: StreamHandlerContext): void;
36
+ export declare function processStreamLines(buffer: string, sessionCapture: {
37
+ claudeSessionId?: string;
38
+ }, ctx: StreamHandlerContext): string;
39
+ /** Flush native timeout detector buffers and return post-timeout output if any */
40
+ export declare function flushNativeTimeoutBuffers(ctx: StreamHandlerContext): string | undefined;
41
+ /** Classify unmatched stderr via Haiku when process exits with error */
42
+ export declare function classifyUnmatchedStderr(stderr: string, errorAlreadySurfaced: boolean, code: number | null, config: ResolvedHeadlessConfig): Promise<void>;
43
+ export {};
44
+ //# sourceMappingURL=claude-invoker-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-invoker-stream.d.ts","sourceRoot":"","sources":["../../../../server/cli/headless/claude-invoker-stream.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG7E,KAAK,UAAU,GAAG,GAAG,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,sBAAsB,CAAC;IAC/B,4BAA4B,EAAE,MAAM,CAAC;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAClG,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C;8FAC0F;IAC1F,sBAAsB,EAAE,OAAO,CAAC;IAChC,uDAAuD;IACvD,sBAAsB,EAAE,MAAM,CAAC;IAC/B,yEAAyE;IACzE,aAAa,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,qGAAqG;IACrG,uBAAuB,EAAE,MAAM,CAAC;IAChC,sFAAsF;IACtF,qBAAqB,EAAE,MAAM,CAAC;IAC9B,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAIhF;AA8KD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,oBAAoB,GAAG,IAAI,CA2BtF;AA+DD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,EAC5C,GAAG,EAAE,oBAAoB,GACxB,MAAM,CAcR;AAED,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAUvF;AAED,wEAAwE;AACxE,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,oBAAoB,EAAE,OAAO,EAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,EACnB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAWf"}
@@ -0,0 +1,276 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ import { hlog } from './headless-logger.js';
4
+ import { classifyError } from './stall-assessor.js';
5
+ /** Log messages when verbose mode is enabled */
6
+ export function verboseLog(verbose, ...msgs) {
7
+ if (verbose) {
8
+ for (const msg of msgs)
9
+ hlog(msg);
10
+ }
11
+ }
12
+ // ========== Stream Event Handlers ==========
13
+ function handleSessionCapture(parsed, captured) {
14
+ if (parsed.type === 'system' && parsed.subtype === 'init' && parsed.session_id) {
15
+ captured.claudeSessionId = parsed.session_id;
16
+ }
17
+ if (parsed.type === 'result' && parsed.session_id && !captured.claudeSessionId) {
18
+ captured.claudeSessionId = parsed.session_id;
19
+ }
20
+ }
21
+ function handleThinkingDelta(event, ctx) {
22
+ if (event.type !== 'content_block_delta' ||
23
+ event.delta?.type !== 'thinking_delta' ||
24
+ !event.delta?.thinking) {
25
+ return ctx.accumulatedThinking;
26
+ }
27
+ if (ctx.resumeAssessmentActive) {
28
+ ctx.resumeAssessmentActive = false;
29
+ if (ctx.resumeAssessmentBuffer) {
30
+ ctx.config.outputCallback?.(ctx.resumeAssessmentBuffer);
31
+ ctx.resumeAssessmentBuffer = '';
32
+ }
33
+ }
34
+ const thinking = event.delta.thinking;
35
+ const updated = ctx.accumulatedThinking + thinking;
36
+ if (ctx.config.thinkingCallback) {
37
+ ctx.config.thinkingCallback(thinking);
38
+ }
39
+ else if (ctx.config.outputCallback) {
40
+ ctx.config.outputCallback(thinking);
41
+ }
42
+ else {
43
+ process.stdout.write(thinking);
44
+ }
45
+ return updated;
46
+ }
47
+ function handleTextDelta(event, ctx) {
48
+ if (event.type !== 'content_block_delta' ||
49
+ event.delta?.type !== 'text_delta' ||
50
+ !event.delta?.text) {
51
+ return ctx.accumulatedAssistantResponse;
52
+ }
53
+ const text = event.delta.text;
54
+ const updated = ctx.accumulatedAssistantResponse + text;
55
+ const { passthrough, timeouts } = ctx.nativeTimeoutDetector.processChunk(text);
56
+ for (const timeout of timeouts) {
57
+ ctx.config.outputCallback?.(`\n[[MSTRO_NATIVE_TIMEOUT]] ${timeout.toolName} timed out \u2014 ${timeout.action} with ${timeout.preservedCount} results preserved\n`);
58
+ }
59
+ if (ctx.resumeAssessmentActive) {
60
+ if (passthrough) {
61
+ ctx.resumeAssessmentBuffer += passthrough;
62
+ }
63
+ return updated;
64
+ }
65
+ if (passthrough && ctx.config.outputCallback) {
66
+ ctx.config.outputCallback(passthrough);
67
+ }
68
+ return updated;
69
+ }
70
+ /** Accumulate input tokens from a message_start event */
71
+ function handleMessageStartTokens(event, ctx) {
72
+ if (event.type !== 'message_start' || !event.message?.usage)
73
+ return false;
74
+ const usage = event.message.usage;
75
+ ctx.currentStepOutputTokens = 0;
76
+ let changed = false;
77
+ if (typeof usage.input_tokens === 'number') {
78
+ ctx.apiTokenUsage.inputTokens += usage.input_tokens;
79
+ changed = true;
80
+ }
81
+ if (typeof usage.cache_creation_input_tokens === 'number') {
82
+ ctx.apiTokenUsage.inputTokens += usage.cache_creation_input_tokens;
83
+ changed = true;
84
+ }
85
+ if (typeof usage.cache_read_input_tokens === 'number') {
86
+ ctx.apiTokenUsage.inputTokens += usage.cache_read_input_tokens;
87
+ changed = true;
88
+ }
89
+ verboseLog(ctx.config.verbose, `[TOKENS] message_start: input=${usage.input_tokens ?? 0} cache_create=${usage.cache_creation_input_tokens ?? 0} cache_read=${usage.cache_read_input_tokens ?? 0} → total_input=${ctx.apiTokenUsage.inputTokens}`);
90
+ return changed;
91
+ }
92
+ /** Accumulate output tokens from a message_delta event (cumulative tracking) */
93
+ function handleMessageDeltaTokens(event, ctx) {
94
+ if (event.type !== 'message_delta' || !event.usage)
95
+ return false;
96
+ if (typeof event.usage.output_tokens !== 'number')
97
+ return false;
98
+ const increment = event.usage.output_tokens - ctx.currentStepOutputTokens;
99
+ verboseLog(ctx.config.verbose, `[TOKENS] message_delta: output=${event.usage.output_tokens} (step_prev=${ctx.currentStepOutputTokens} increment=${increment}) → total_output=${ctx.apiTokenUsage.outputTokens + Math.max(increment, 0)}`);
100
+ if (increment <= 0)
101
+ return false;
102
+ ctx.apiTokenUsage.outputTokens += increment;
103
+ ctx.currentStepOutputTokens = event.usage.output_tokens;
104
+ return true;
105
+ }
106
+ function handleTokenUsage(event, ctx) {
107
+ const changed = handleMessageStartTokens(event, ctx) || handleMessageDeltaTokens(event, ctx);
108
+ if (changed) {
109
+ ctx.lastTokenActivityTime = Date.now();
110
+ ctx.config.tokenUsageCallback?.({ ...ctx.apiTokenUsage });
111
+ }
112
+ }
113
+ /** Extract definitive token usage from the result event */
114
+ function handleResultTokenUsage(parsed, ctx) {
115
+ if (!parsed.usage)
116
+ return;
117
+ const u = parsed.usage;
118
+ const input = (typeof u.input_tokens === 'number' ? u.input_tokens : 0)
119
+ + (typeof u.cache_creation_input_tokens === 'number' ? u.cache_creation_input_tokens : 0)
120
+ + (typeof u.cache_read_input_tokens === 'number' ? u.cache_read_input_tokens : 0);
121
+ const output = typeof u.output_tokens === 'number' ? u.output_tokens : 0;
122
+ if (input > 0 || output > 0) {
123
+ verboseLog(ctx.config.verbose, `[TOKENS] Result event usage: input=${input} output=${output} ` +
124
+ `(stream accumulated: input=${ctx.apiTokenUsage.inputTokens} output=${ctx.apiTokenUsage.outputTokens})`);
125
+ ctx.apiTokenUsage = { inputTokens: input, outputTokens: output };
126
+ ctx.lastTokenActivityTime = Date.now();
127
+ ctx.config.tokenUsageCallback?.({ ...ctx.apiTokenUsage });
128
+ }
129
+ }
130
+ function handleToolResult(parsed, ctx) {
131
+ if (parsed.type !== 'user' || !parsed.message?.content) {
132
+ return;
133
+ }
134
+ for (const content of parsed.message.content) {
135
+ if (content.type !== 'tool_result') {
136
+ continue;
137
+ }
138
+ const toolId = content.tool_use_id;
139
+ const result = content.content;
140
+ const isError = content.is_error || false;
141
+ const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
142
+ const toolEntry = ctx.accumulatedToolUse.find(t => t.toolId === toolId);
143
+ if (toolEntry) {
144
+ toolEntry.result = resultStr;
145
+ toolEntry.isError = isError;
146
+ toolEntry.duration = Date.now() - toolEntry.startTime;
147
+ }
148
+ if (ctx.config.toolUseCallback) {
149
+ ctx.config.toolUseCallback({ type: 'tool_result', toolId, result: resultStr, isError });
150
+ }
151
+ }
152
+ }
153
+ // ========== Stream Processing ==========
154
+ export function processStreamEvent(parsed, ctx) {
155
+ if (parsed.type === 'error') {
156
+ const errorMessage = parsed.error?.message || parsed.message || JSON.stringify(parsed);
157
+ ctx.config.outputCallback?.(`\n[[MSTRO_ERROR:CLAUDE_ERROR]] ${errorMessage}\n`);
158
+ return;
159
+ }
160
+ if (parsed.type === 'result') {
161
+ handleResultTokenUsage(parsed, ctx);
162
+ if (parsed.stop_reason) {
163
+ ctx.stopReason = parsed.stop_reason;
164
+ }
165
+ if (parsed.is_error) {
166
+ const errorMessage = parsed.error || parsed.result || 'Unknown error in result';
167
+ ctx.config.outputCallback?.(`\n[[MSTRO_ERROR:CLAUDE_RESULT_ERROR]] ${errorMessage}\n`);
168
+ return;
169
+ }
170
+ }
171
+ if (parsed.type === 'stream_event' && parsed.event) {
172
+ const event = parsed.event;
173
+ ctx.accumulatedThinking = handleThinkingDelta(event, ctx);
174
+ ctx.accumulatedAssistantResponse = handleTextDelta(event, ctx);
175
+ handleToolStreamEvents(event, ctx);
176
+ handleTokenUsage(event, ctx);
177
+ }
178
+ handleToolResult(parsed, ctx);
179
+ }
180
+ /** Handle tool_use content_block_start */
181
+ function handleToolStart(event, ctx) {
182
+ if (event.type !== 'content_block_start' || event.content_block?.type !== 'tool_use')
183
+ return;
184
+ if (ctx.resumeAssessmentActive) {
185
+ ctx.resumeAssessmentActive = false;
186
+ if (ctx.resumeAssessmentBuffer) {
187
+ ctx.config.outputCallback?.(ctx.resumeAssessmentBuffer);
188
+ ctx.resumeAssessmentBuffer = '';
189
+ }
190
+ }
191
+ const toolName = event.content_block.name;
192
+ const toolId = event.content_block.id;
193
+ const index = event.index;
194
+ ctx.toolInputBuffers.set(index, { name: toolName, id: toolId, inputJson: '', startTime: Date.now() });
195
+ ctx.config.toolUseCallback?.({ type: 'tool_start', toolName, toolId, index });
196
+ }
197
+ /** Handle input_json_delta for tool input streaming */
198
+ function handleToolInputDelta(event, ctx) {
199
+ if (event.type !== 'content_block_delta' || event.delta?.type !== 'input_json_delta')
200
+ return;
201
+ const index = event.index;
202
+ const partialJson = event.delta.partial_json;
203
+ const toolBuffer = ctx.toolInputBuffers.get(index);
204
+ if (toolBuffer)
205
+ toolBuffer.inputJson += partialJson;
206
+ ctx.config.toolUseCallback?.({ type: 'tool_input_delta', partialJson, index });
207
+ }
208
+ /** Handle content_block_stop — finalize tool input and emit tool_complete */
209
+ function handleToolComplete(event, ctx) {
210
+ if (event.type !== 'content_block_stop')
211
+ return;
212
+ const index = event.index;
213
+ const toolBuffer = ctx.toolInputBuffers.get(index);
214
+ if (!toolBuffer)
215
+ return;
216
+ let completeInput = {};
217
+ try {
218
+ completeInput = JSON.parse(toolBuffer.inputJson);
219
+ }
220
+ catch { /* incomplete JSON */ }
221
+ ctx.accumulatedToolUse.push({
222
+ toolName: toolBuffer.name, toolId: toolBuffer.id,
223
+ toolInput: completeInput, startTime: toolBuffer.startTime
224
+ });
225
+ ctx.toolInputBuffers.delete(index);
226
+ ctx.config.toolUseCallback?.({
227
+ type: 'tool_complete', toolName: toolBuffer.name, toolId: toolBuffer.id,
228
+ index, completeInput
229
+ });
230
+ }
231
+ /** Handle tool-specific stream events (start, input delta, complete) */
232
+ function handleToolStreamEvents(event, ctx) {
233
+ handleToolStart(event, ctx);
234
+ handleToolInputDelta(event, ctx);
235
+ handleToolComplete(event, ctx);
236
+ }
237
+ export function processStreamLines(buffer, sessionCapture, ctx) {
238
+ const lines = buffer.split('\n');
239
+ const remainder = lines.pop() || '';
240
+ for (const line of lines) {
241
+ if (!line.trim())
242
+ continue;
243
+ try {
244
+ const parsed = JSON.parse(line);
245
+ handleSessionCapture(parsed, sessionCapture);
246
+ processStreamEvent(parsed, ctx);
247
+ }
248
+ catch { /* Ignore parse errors */ }
249
+ }
250
+ return remainder;
251
+ }
252
+ /** Flush native timeout detector buffers and return post-timeout output if any */
253
+ export function flushNativeTimeoutBuffers(ctx) {
254
+ const remaining = ctx.nativeTimeoutDetector.flush();
255
+ const buffered = ctx.nativeTimeoutDetector.bufferedPostTimeoutOutput;
256
+ const postTimeout = (buffered + remaining) || undefined;
257
+ if (!postTimeout && remaining) {
258
+ ctx.config.outputCallback?.(remaining);
259
+ }
260
+ return postTimeout;
261
+ }
262
+ /** Classify unmatched stderr via Haiku when process exits with error */
263
+ export async function classifyUnmatchedStderr(stderr, errorAlreadySurfaced, code, config) {
264
+ if (!stderr || errorAlreadySurfaced || code === 0)
265
+ return;
266
+ try {
267
+ const classified = await classifyError(stderr, config.claudeCommand, config.verbose);
268
+ if (classified) {
269
+ config.outputCallback?.(`\n[[MSTRO_ERROR:${classified.errorCode}]] ${classified.message}\n`);
270
+ }
271
+ }
272
+ catch {
273
+ // Haiku classification failed — proceed without it
274
+ }
275
+ }
276
+ //# sourceMappingURL=claude-invoker-stream.js.map