factory-factory 0.3.17 → 0.3.19

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 (276) hide show
  1. package/README.md +3 -1
  2. package/dist/client/assets/{arc-CAOrfHBL.js → arc-DQhOC8k-.js} +1 -1
  3. package/dist/client/assets/{architectureDiagram-3BPJPVTR-CzxGCKeM.js → architectureDiagram-3BPJPVTR-BnnC0MnW.js} +1 -1
  4. package/dist/client/assets/{blockDiagram-GPEHLZMM-B4k0dvv-.js → blockDiagram-GPEHLZMM-CNaYKejS.js} +1 -1
  5. package/dist/client/assets/{c4Diagram-AAUBKEIU-ByaECY1u.js → c4Diagram-AAUBKEIU-B6TiwlCJ.js} +1 -1
  6. package/dist/client/assets/channel-aiW5SBbk.js +1 -0
  7. package/dist/client/assets/{chunk-2J33WTMH-Crxo1uMY.js → chunk-2J33WTMH-XXkb30dE.js} +1 -1
  8. package/dist/client/assets/{chunk-4BX2VUAB-CggFLwAA.js → chunk-4BX2VUAB-78mYakPy.js} +1 -1
  9. package/dist/client/assets/{chunk-55IACEB6-BSoTWFAF.js → chunk-55IACEB6-D_0y5jOy.js} +1 -1
  10. package/dist/client/assets/{chunk-727SXJPM-DcQoeGkQ.js → chunk-727SXJPM-BWqoGJOj.js} +1 -1
  11. package/dist/client/assets/{chunk-AQP2D5EJ-Ci5tNJvg.js → chunk-AQP2D5EJ-l9AUcgrx.js} +1 -1
  12. package/dist/client/assets/{chunk-FMBD7UC4-CjYtwTh4.js → chunk-FMBD7UC4-B63Nwghi.js} +1 -1
  13. package/dist/client/assets/{chunk-ND2GUHAM-Dla8Gmku.js → chunk-ND2GUHAM-DYoFXWFH.js} +1 -1
  14. package/dist/client/assets/{chunk-QZHKN3VN-CiblfzNN.js → chunk-QZHKN3VN-faBOxK9Y.js} +1 -1
  15. package/dist/client/assets/classDiagram-4FO5ZUOK-DdRRgcVJ.js +1 -0
  16. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DdRRgcVJ.js +1 -0
  17. package/dist/client/assets/{cose-bilkent-S5V4N54A-DWuzgvAN.js → cose-bilkent-S5V4N54A-s9MyXm2i.js} +1 -1
  18. package/dist/client/assets/{dagre-BM42HDAG-hvdcGfHc.js → dagre-BM42HDAG-DFzoOzIg.js} +1 -1
  19. package/dist/client/assets/{diagram-2AECGRRQ-DVZDsgVY.js → diagram-2AECGRRQ-BkiOxNc9.js} +1 -1
  20. package/dist/client/assets/{diagram-5GNKFQAL-BLXKSUUu.js → diagram-5GNKFQAL-CqXCPCvK.js} +1 -1
  21. package/dist/client/assets/{diagram-KO2AKTUF-1nNBdWqs.js → diagram-KO2AKTUF-BIDL-rtL.js} +1 -1
  22. package/dist/client/assets/{diagram-LMA3HP47-CTw-M4zU.js → diagram-LMA3HP47-C5Q4rNwM.js} +1 -1
  23. package/dist/client/assets/{diagram-OG6HWLK6-D9J0vyno.js → diagram-OG6HWLK6-NUBLwB2y.js} +1 -1
  24. package/dist/client/assets/{erDiagram-TEJ5UH35-DYXcLeDs.js → erDiagram-TEJ5UH35-DE7FkKUT.js} +1 -1
  25. package/dist/client/assets/{flowDiagram-I6XJVG4X-CXFyFXcd.js → flowDiagram-I6XJVG4X-Kn-tG-yL.js} +1 -1
  26. package/dist/client/assets/{ganttDiagram-6RSMTGT7-CPGMIRhg.js → ganttDiagram-6RSMTGT7-By6WP-ZX.js} +1 -1
  27. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BCIDHp-Q.js → gitGraphDiagram-PVQCEYII-nZ9iXa1J.js} +1 -1
  28. package/dist/client/assets/{index-gIy0Sz_B.js → index-Bcwk_kNL.js} +144 -144
  29. package/dist/client/assets/index-p_tQjQfx.css +1 -0
  30. package/dist/client/assets/{infoDiagram-5YYISTIA-ThNaUmLI.js → infoDiagram-5YYISTIA-W-ABsfEh.js} +1 -1
  31. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-nD7e1KKT.js → ishikawaDiagram-YF4QCWOH-JxGcwHMc.js} +1 -1
  32. package/dist/client/assets/{journeyDiagram-JHISSGLW-DKfK1tIp.js → journeyDiagram-JHISSGLW-D_KdYlXr.js} +1 -1
  33. package/dist/client/assets/{kanban-definition-UN3LZRKU-C61PkF-T.js → kanban-definition-UN3LZRKU-D-UVbQXc.js} +1 -1
  34. package/dist/client/assets/{linear-yYp6Wht8.js → linear-Cj1wlnWl.js} +1 -1
  35. package/dist/client/assets/{mindmap-definition-RKZ34NQL-DI6Bl654.js → mindmap-definition-RKZ34NQL-DwGZS8do.js} +1 -1
  36. package/dist/client/assets/{mobile-baseline-DRrQYbFX.js → mobile-baseline-BGE4NQIr.js} +1 -1
  37. package/dist/client/assets/{pieDiagram-4H26LBE5-CNV-VY3H.js → pieDiagram-4H26LBE5-CY9En855.js} +1 -1
  38. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CDBpCVHO.js → quadrantDiagram-W4KKPZXB-DOyyttJG.js} +1 -1
  39. package/dist/client/assets/{requirementDiagram-4Y6WPE33-D_rxDIc5.js → requirementDiagram-4Y6WPE33-B4JqooNB.js} +1 -1
  40. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DeyadfL0.js → sankeyDiagram-5OEKKPKP-BB77NiWq.js} +1 -1
  41. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-36_kZ6la.js → sequenceDiagram-3UESZ5HK-BeL59Hty.js} +1 -1
  42. package/dist/client/assets/{stateDiagram-AJRCARHV-4ayM-mAT.js → stateDiagram-AJRCARHV-r1MOX3Bu.js} +1 -1
  43. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Dd555Ct_.js +1 -0
  44. package/dist/client/assets/{terminal-instance-CMp5bO62.js → terminal-instance-BjuTwvmO.js} +1 -1
  45. package/dist/client/assets/{timeline-definition-PNZ67QCA-D0pQgePo.js → timeline-definition-PNZ67QCA-D01xTiJg.js} +1 -1
  46. package/dist/client/assets/{vennDiagram-CIIHVFJN-CnoMcpwq.js → vennDiagram-CIIHVFJN-Kc3pSNeO.js} +1 -1
  47. package/dist/client/assets/{wardley-L42UT6IY-DOtSWmwv.js → wardley-L42UT6IY-Bf_y6FVI.js} +1 -1
  48. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Z3hYGa2_.js → wardleyDiagram-YWT4CUSO-7PwdKD27.js} +1 -1
  49. package/dist/client/assets/{xychartDiagram-2RQKCTM6-CBvgTdkn.js → xychartDiagram-2RQKCTM6-CAKTkp2-.js} +1 -1
  50. package/dist/client/index.html +2 -2
  51. package/dist/prisma/generated/internal/class.js +4 -4
  52. package/dist/prisma/generated/internal/class.js.map +1 -1
  53. package/dist/prisma/generated/internal/prismaNamespace.d.ts +3 -0
  54. package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
  55. package/dist/prisma/generated/internal/prismaNamespace.js +3 -0
  56. package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
  57. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +3 -0
  58. package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
  59. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +3 -0
  60. package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
  61. package/dist/prisma/generated/models/PeriodicTask.d.ts +158 -1
  62. package/dist/prisma/generated/models/PeriodicTask.d.ts.map +1 -1
  63. package/dist/src/backend/interceptors/pr-detection.interceptor.d.ts.map +1 -1
  64. package/dist/src/backend/interceptors/pr-detection.interceptor.js +10 -7
  65. package/dist/src/backend/interceptors/pr-detection.interceptor.js.map +1 -1
  66. package/dist/src/backend/interceptors/pr-detection.interceptor.test.js +88 -0
  67. package/dist/src/backend/interceptors/pr-detection.interceptor.test.js.map +1 -1
  68. package/dist/src/backend/orchestration/data-backup.service.d.ts.map +1 -1
  69. package/dist/src/backend/orchestration/data-backup.service.js +3 -1
  70. package/dist/src/backend/orchestration/data-backup.service.js.map +1 -1
  71. package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
  72. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +16 -2
  73. package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
  74. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +133 -5
  75. package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
  76. package/dist/src/backend/orchestration/workspace-init-github-username-cache.d.ts +10 -0
  77. package/dist/src/backend/orchestration/workspace-init-github-username-cache.d.ts.map +1 -0
  78. package/dist/src/backend/orchestration/workspace-init-github-username-cache.js +27 -0
  79. package/dist/src/backend/orchestration/workspace-init-github-username-cache.js.map +1 -0
  80. package/dist/src/backend/orchestration/workspace-init-issue-prompts.d.ts +6 -0
  81. package/dist/src/backend/orchestration/workspace-init-issue-prompts.d.ts.map +1 -0
  82. package/dist/src/backend/orchestration/workspace-init-issue-prompts.js +262 -0
  83. package/dist/src/backend/orchestration/workspace-init-issue-prompts.js.map +1 -0
  84. package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
  85. package/dist/src/backend/orchestration/workspace-init.orchestrator.js +16 -435
  86. package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
  87. package/dist/src/backend/services/auto-iteration/service/auto-iteration-loop-state.d.ts +16 -0
  88. package/dist/src/backend/services/auto-iteration/service/auto-iteration-loop-state.d.ts.map +1 -0
  89. package/dist/src/backend/services/auto-iteration/service/auto-iteration-loop-state.js +45 -0
  90. package/dist/src/backend/services/auto-iteration/service/auto-iteration-loop-state.js.map +1 -0
  91. package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.d.ts.map +1 -1
  92. package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.js +4 -109
  93. package/dist/src/backend/services/auto-iteration/service/auto-iteration.service.js.map +1 -1
  94. package/dist/src/backend/services/auto-iteration/service/auto-iteration.types.d.ts +2 -50
  95. package/dist/src/backend/services/auto-iteration/service/auto-iteration.types.d.ts.map +1 -1
  96. package/dist/src/backend/services/auto-iteration/service/logbook.service.d.ts.map +1 -1
  97. package/dist/src/backend/services/auto-iteration/service/logbook.service.js +6 -9
  98. package/dist/src/backend/services/auto-iteration/service/logbook.service.js.map +1 -1
  99. package/dist/src/backend/services/auto-iteration/service/logbook.service.test.d.ts +2 -0
  100. package/dist/src/backend/services/auto-iteration/service/logbook.service.test.d.ts.map +1 -0
  101. package/dist/src/backend/services/auto-iteration/service/logbook.service.test.js +63 -0
  102. package/dist/src/backend/services/auto-iteration/service/logbook.service.test.js.map +1 -0
  103. package/dist/src/backend/services/auto-iteration/service/response-parsing.d.ts +4 -0
  104. package/dist/src/backend/services/auto-iteration/service/response-parsing.d.ts.map +1 -0
  105. package/dist/src/backend/services/auto-iteration/service/response-parsing.js +91 -0
  106. package/dist/src/backend/services/auto-iteration/service/response-parsing.js.map +1 -0
  107. package/dist/src/backend/services/auto-iteration/service/response-parsing.test.d.ts +2 -0
  108. package/dist/src/backend/services/auto-iteration/service/response-parsing.test.d.ts.map +1 -0
  109. package/dist/src/backend/services/auto-iteration/service/response-parsing.test.js +66 -0
  110. package/dist/src/backend/services/auto-iteration/service/response-parsing.test.js.map +1 -0
  111. package/dist/src/backend/services/check-single-writer.test.js +21 -0
  112. package/dist/src/backend/services/check-single-writer.test.js.map +1 -1
  113. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.d.ts +6 -2
  114. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.d.ts.map +1 -1
  115. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js +151 -19
  116. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js.map +1 -1
  117. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.d.ts +2 -0
  118. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.d.ts.map +1 -0
  119. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js +150 -0
  120. package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js.map +1 -0
  121. package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts +5 -1
  122. package/dist/src/backend/services/periodic-task/service/periodic-task.service.d.ts.map +1 -1
  123. package/dist/src/backend/services/periodic-task/service/periodic-task.service.js +20 -4
  124. package/dist/src/backend/services/periodic-task/service/periodic-task.service.js.map +1 -1
  125. package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.d.ts +2 -0
  126. package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.d.ts.map +1 -0
  127. package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.js +144 -0
  128. package/dist/src/backend/services/periodic-task/service/periodic-task.service.test.js.map +1 -0
  129. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.d.ts +64 -0
  130. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.d.ts.map +1 -0
  131. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.js +76 -0
  132. package/dist/src/backend/services/ratchet/service/ratchet-decision-logging.helpers.js.map +1 -0
  133. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.d.ts +9 -0
  134. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.d.ts.map +1 -0
  135. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.js +36 -0
  136. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.js.map +1 -0
  137. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.test.d.ts +2 -0
  138. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.test.d.ts.map +1 -0
  139. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.test.js +25 -0
  140. package/dist/src/backend/services/ratchet/service/ratchet-workspace-check-coordinator.test.js.map +1 -0
  141. package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts +42 -9
  142. package/dist/src/backend/services/ratchet/service/ratchet.service.d.ts.map +1 -1
  143. package/dist/src/backend/services/ratchet/service/ratchet.service.js +38 -105
  144. package/dist/src/backend/services/ratchet/service/ratchet.service.js.map +1 -1
  145. package/dist/src/backend/services/ratchet/service/ratchet.service.test.js +43 -0
  146. package/dist/src/backend/services/ratchet/service/ratchet.service.test.js.map +1 -1
  147. package/dist/src/backend/services/ratchet/service/reconciliation.service.d.ts +3 -2
  148. package/dist/src/backend/services/ratchet/service/reconciliation.service.d.ts.map +1 -1
  149. package/dist/src/backend/services/ratchet/service/reconciliation.service.js +43 -18
  150. package/dist/src/backend/services/ratchet/service/reconciliation.service.js.map +1 -1
  151. package/dist/src/backend/services/ratchet/service/reconciliation.service.test.js +50 -16
  152. package/dist/src/backend/services/ratchet/service/reconciliation.service.test.js.map +1 -1
  153. package/dist/src/backend/services/run-script/service/run-script-output-buffer.d.ts +16 -0
  154. package/dist/src/backend/services/run-script/service/run-script-output-buffer.d.ts.map +1 -0
  155. package/dist/src/backend/services/run-script/service/run-script-output-buffer.js +62 -0
  156. package/dist/src/backend/services/run-script/service/run-script-output-buffer.js.map +1 -0
  157. package/dist/src/backend/services/run-script/service/run-script-output-buffer.test.d.ts +2 -0
  158. package/dist/src/backend/services/run-script/service/run-script-output-buffer.test.d.ts.map +1 -0
  159. package/dist/src/backend/services/run-script/service/run-script-output-buffer.test.js +25 -0
  160. package/dist/src/backend/services/run-script/service/run-script-output-buffer.test.js.map +1 -0
  161. package/dist/src/backend/services/run-script/service/run-script-process-utils.d.ts +19 -0
  162. package/dist/src/backend/services/run-script/service/run-script-process-utils.d.ts.map +1 -0
  163. package/dist/src/backend/services/run-script/service/run-script-process-utils.js +105 -0
  164. package/dist/src/backend/services/run-script/service/run-script-process-utils.js.map +1 -0
  165. package/dist/src/backend/services/run-script/service/run-script.service.d.ts +3 -6
  166. package/dist/src/backend/services/run-script/service/run-script.service.d.ts.map +1 -1
  167. package/dist/src/backend/services/run-script/service/run-script.service.js +42 -202
  168. package/dist/src/backend/services/run-script/service/run-script.service.js.map +1 -1
  169. package/dist/src/backend/services/run-script/service/run-script.service.test.js +40 -28
  170. package/dist/src/backend/services/run-script/service/run-script.service.test.js.map +1 -1
  171. package/dist/src/backend/services/session/service/acp/acp-runtime-manager.d.ts.map +1 -1
  172. package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js +3 -386
  173. package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js.map +1 -1
  174. package/dist/src/backend/services/session/service/acp/acp-runtime-spawn.d.ts +16 -0
  175. package/dist/src/backend/services/session/service/acp/acp-runtime-spawn.d.ts.map +1 -0
  176. package/dist/src/backend/services/session/service/acp/acp-runtime-spawn.js +153 -0
  177. package/dist/src/backend/services/session/service/acp/acp-runtime-spawn.js.map +1 -0
  178. package/dist/src/backend/services/session/service/acp/acp-session-config-options.d.ts +9 -0
  179. package/dist/src/backend/services/session/service/acp/acp-session-config-options.d.ts.map +1 -0
  180. package/dist/src/backend/services/session/service/acp/acp-session-config-options.js +162 -0
  181. package/dist/src/backend/services/session/service/acp/acp-session-config-options.js.map +1 -0
  182. package/dist/src/backend/services/session/service/acp/acp-stream-normalizer.d.ts +3 -0
  183. package/dist/src/backend/services/session/service/acp/acp-stream-normalizer.d.ts.map +1 -0
  184. package/dist/src/backend/services/session/service/acp/acp-stream-normalizer.js +81 -0
  185. package/dist/src/backend/services/session/service/acp/acp-stream-normalizer.js.map +1 -0
  186. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-adapter-parsing.d.ts +10 -0
  187. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-adapter-parsing.d.ts.map +1 -0
  188. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-adapter-parsing.js +162 -0
  189. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-adapter-parsing.js.map +1 -0
  190. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts +0 -7
  191. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-app-server-acp-adapter.d.ts.map +1 -1
  192. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js +19 -338
  193. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/codex-app-server-acp-adapter.js.map +1 -1
  194. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/plan-approval-handler.d.ts +23 -0
  195. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/plan-approval-handler.d.ts.map +1 -0
  196. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/plan-approval-handler.js +191 -0
  197. package/dist/src/backend/services/session/service/acp/codex-app-server-adapter/plan-approval-handler.js.map +1 -0
  198. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.d.ts.map +1 -1
  199. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js +2 -12
  200. package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js.map +1 -1
  201. package/dist/src/backend/services/session/service/lifecycle/session-config-option-helpers.d.ts +19 -0
  202. package/dist/src/backend/services/session/service/lifecycle/session-config-option-helpers.d.ts.map +1 -0
  203. package/dist/src/backend/services/session/service/lifecycle/session-config-option-helpers.js +199 -0
  204. package/dist/src/backend/services/session/service/lifecycle/session-config-option-helpers.js.map +1 -0
  205. package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.d.ts +5 -0
  206. package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.d.ts.map +1 -0
  207. package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.js +37 -0
  208. package/dist/src/backend/services/session/service/lifecycle/session-pr-discovery.service.js.map +1 -0
  209. package/dist/src/backend/services/session/service/lifecycle/session-runtime-state.helpers.d.ts +3 -0
  210. package/dist/src/backend/services/session/service/lifecycle/session-runtime-state.helpers.d.ts.map +1 -0
  211. package/dist/src/backend/services/session/service/lifecycle/session-runtime-state.helpers.js +12 -0
  212. package/dist/src/backend/services/session/service/lifecycle/session-runtime-state.helpers.js.map +1 -0
  213. package/dist/src/backend/services/session/service/lifecycle/session.config.service.d.ts +1 -13
  214. package/dist/src/backend/services/session/service/lifecycle/session.config.service.d.ts.map +1 -1
  215. package/dist/src/backend/services/session/service/lifecycle/session.config.service.js +12 -210
  216. package/dist/src/backend/services/session/service/lifecycle/session.config.service.js.map +1 -1
  217. package/dist/src/backend/services/session/service/lifecycle/session.error-message.d.ts.map +1 -1
  218. package/dist/src/backend/services/session/service/lifecycle/session.error-message.js +43 -4
  219. package/dist/src/backend/services/session/service/lifecycle/session.error-message.js.map +1 -1
  220. package/dist/src/backend/services/session/service/lifecycle/session.error-message.test.js +11 -5
  221. package/dist/src/backend/services/session/service/lifecycle/session.error-message.test.js.map +1 -1
  222. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts +0 -1
  223. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts.map +1 -1
  224. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js +4 -45
  225. package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js.map +1 -1
  226. package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts +1 -0
  227. package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts.map +1 -1
  228. package/dist/src/backend/services/session/service/lifecycle/session.service.js +26 -5
  229. package/dist/src/backend/services/session/service/lifecycle/session.service.js.map +1 -1
  230. package/dist/src/backend/services/session/service/lifecycle/session.service.test.js +35 -0
  231. package/dist/src/backend/services/session/service/lifecycle/session.service.test.js.map +1 -1
  232. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts.map +1 -1
  233. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js +13 -2
  234. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js.map +1 -1
  235. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js +37 -0
  236. package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js.map +1 -1
  237. package/dist/src/backend/trpc/admin.trpc.d.ts +16 -2
  238. package/dist/src/backend/trpc/admin.trpc.d.ts.map +1 -1
  239. package/dist/src/backend/trpc/auto-iteration.trpc.d.ts +34 -6
  240. package/dist/src/backend/trpc/auto-iteration.trpc.d.ts.map +1 -1
  241. package/dist/src/backend/trpc/auto-iteration.trpc.js +32 -26
  242. package/dist/src/backend/trpc/auto-iteration.trpc.js.map +1 -1
  243. package/dist/src/backend/trpc/auto-iteration.trpc.test.d.ts +2 -0
  244. package/dist/src/backend/trpc/auto-iteration.trpc.test.d.ts.map +1 -0
  245. package/dist/src/backend/trpc/auto-iteration.trpc.test.js +118 -0
  246. package/dist/src/backend/trpc/auto-iteration.trpc.test.js.map +1 -0
  247. package/dist/src/backend/trpc/index.d.ts +70 -8
  248. package/dist/src/backend/trpc/index.d.ts.map +1 -1
  249. package/dist/src/backend/trpc/periodic-task.trpc.d.ts +19 -0
  250. package/dist/src/backend/trpc/periodic-task.trpc.d.ts.map +1 -1
  251. package/dist/src/backend/trpc/periodic-task.trpc.js +22 -0
  252. package/dist/src/backend/trpc/periodic-task.trpc.js.map +1 -1
  253. package/dist/src/backend/trpc/workspace.router.test.js +25 -0
  254. package/dist/src/backend/trpc/workspace.router.test.js.map +1 -1
  255. package/dist/src/backend/trpc/workspace.trpc.d.ts +1 -0
  256. package/dist/src/backend/trpc/workspace.trpc.d.ts.map +1 -1
  257. package/dist/src/backend/trpc/workspace.trpc.js +2 -9
  258. package/dist/src/backend/trpc/workspace.trpc.js.map +1 -1
  259. package/dist/src/shared/schemas/auto-iteration.schema.d.ts +106 -0
  260. package/dist/src/shared/schemas/auto-iteration.schema.d.ts.map +1 -0
  261. package/dist/src/shared/schemas/auto-iteration.schema.js +60 -0
  262. package/dist/src/shared/schemas/auto-iteration.schema.js.map +1 -0
  263. package/dist/src/shared/schemas/export-data.schema.d.ts +16 -2
  264. package/dist/src/shared/schemas/export-data.schema.d.ts.map +1 -1
  265. package/dist/src/shared/schemas/export-data.schema.js +2 -1
  266. package/dist/src/shared/schemas/export-data.schema.js.map +1 -1
  267. package/dist/tsconfig.backend.tsbuildinfo +1 -1
  268. package/package.json +5 -3
  269. package/prisma/migrations/20260519122959_add_periodic_task_scheduled_time/migration.sql +3 -0
  270. package/prisma/migrations/20260520120000_add_periodic_task_scheduled_day_of_month/migration.sql +10 -0
  271. package/prisma/schema.prisma +6 -3
  272. package/dist/client/assets/channel-D2ho7Eza.js +0 -1
  273. package/dist/client/assets/classDiagram-4FO5ZUOK-ZExoOExU.js +0 -1
  274. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-ZExoOExU.js +0 -1
  275. package/dist/client/assets/index-IJ_NNlgJ.css +0 -1
  276. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-ChnnLckY.js +0 -1
@@ -0,0 +1,62 @@
1
+ export class RunScriptOutputBuffer {
2
+ maxBufferSize;
3
+ buffers = new Map();
4
+ listeners = new Map();
5
+ constructor(maxBufferSize) {
6
+ this.maxBufferSize = maxBufferSize;
7
+ }
8
+ set(workspaceId, output) {
9
+ this.buffers.set(workspaceId, this.truncate(output));
10
+ }
11
+ append(workspaceId, output) {
12
+ const currentBuffer = this.buffers.get(workspaceId) ?? '';
13
+ this.buffers.set(workspaceId, this.truncate(currentBuffer + output));
14
+ const listeners = this.listeners.get(workspaceId);
15
+ if (listeners) {
16
+ for (const listener of listeners) {
17
+ listener(output);
18
+ }
19
+ }
20
+ }
21
+ get(workspaceId) {
22
+ return this.buffers.get(workspaceId) ?? '';
23
+ }
24
+ clearBuffer(workspaceId) {
25
+ this.buffers.delete(workspaceId);
26
+ }
27
+ clearListeners(workspaceId) {
28
+ this.listeners.delete(workspaceId);
29
+ }
30
+ subscribe(workspaceId, listener) {
31
+ let listeners = this.listeners.get(workspaceId);
32
+ if (!listeners) {
33
+ listeners = new Set();
34
+ this.listeners.set(workspaceId, listeners);
35
+ }
36
+ listeners.add(listener);
37
+ return () => {
38
+ const currentListeners = this.listeners.get(workspaceId);
39
+ if (currentListeners) {
40
+ currentListeners.delete(listener);
41
+ if (currentListeners.size === 0) {
42
+ this.listeners.delete(workspaceId);
43
+ }
44
+ }
45
+ };
46
+ }
47
+ evict(workspaceId) {
48
+ this.buffers.delete(workspaceId);
49
+ this.listeners.delete(workspaceId);
50
+ }
51
+ clear() {
52
+ this.buffers.clear();
53
+ this.listeners.clear();
54
+ }
55
+ truncate(output) {
56
+ if (output.length <= this.maxBufferSize) {
57
+ return output;
58
+ }
59
+ return output.slice(-this.maxBufferSize);
60
+ }
61
+ }
62
+ //# sourceMappingURL=run-script-output-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-script-output-buffer.js","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script-output-buffer.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,qBAAqB;IAIH;IAHZ,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,SAAS,GAAG,IAAI,GAAG,EAAuC,CAAC;IAE5E,YAA6B,aAAqB;QAArB,kBAAa,GAAb,aAAa,CAAQ;IAAG,CAAC;IAEtD,GAAG,CAAC,WAAmB,EAAE,MAAc;QACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,MAAc;QACxC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC;QAErE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,SAAS,EAAE,CAAC;YACd,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC;IAED,GAAG,CAAC,WAAmB;QACrB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,WAAW,CAAC,WAAmB;QAC7B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACnC,CAAC;IAED,cAAc,CAAC,WAAmB;QAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,SAAS,CAAC,WAAmB,EAAE,QAAgC;QAC7D,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAChD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC7C,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExB,OAAO,GAAG,EAAE;YACV,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACzD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,gBAAgB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAClC,IAAI,gBAAgB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBAChC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBACrC,CAAC;YACH,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAmB;QACvB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAEO,QAAQ,CAAC,MAAc;QAC7B,IAAI,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACxC,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=run-script-output-buffer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-script-output-buffer.test.d.ts","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script-output-buffer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { RunScriptOutputBuffer } from './run-script-output-buffer.js';
3
+ describe('RunScriptOutputBuffer', () => {
4
+ it('clears a workspace buffer without dropping listeners', () => {
5
+ const buffer = new RunScriptOutputBuffer(1024);
6
+ const listener = vi.fn();
7
+ buffer.set('ws-1', 'old logs');
8
+ buffer.subscribe('ws-1', listener);
9
+ buffer.clearBuffer('ws-1');
10
+ buffer.append('ws-1', 'new logs');
11
+ expect(buffer.get('ws-1')).toBe('new logs');
12
+ expect(listener).toHaveBeenCalledWith('new logs');
13
+ });
14
+ it('evicts a workspace buffer and its listeners', () => {
15
+ const buffer = new RunScriptOutputBuffer(1024);
16
+ const listener = vi.fn();
17
+ buffer.set('ws-1', 'old logs');
18
+ buffer.subscribe('ws-1', listener);
19
+ buffer.evict('ws-1');
20
+ buffer.append('ws-1', 'new logs');
21
+ expect(buffer.get('ws-1')).toBe('new logs');
22
+ expect(listener).not.toHaveBeenCalled();
23
+ });
24
+ });
25
+ //# sourceMappingURL=run-script-output-buffer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-script-output-buffer.test.js","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script-output-buffer.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC/B,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAElC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC/B,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAElC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { ChildProcess } from 'node:child_process';
2
+ import type { createLogger } from '../../../../backend/services/logger.service.js';
3
+ import type { RunScriptStatus } from '../../../../shared/core/index.js';
4
+ type Logger = ReturnType<typeof createLogger>;
5
+ export declare function shouldRejectStopWithoutProcess(status: RunScriptStatus, childProcess: ChildProcess | undefined, pid: number | null): boolean;
6
+ export declare function runCleanupScriptProcess(workspaceId: string, workspace: {
7
+ runScriptCleanupCommand: string;
8
+ worktreePath: string;
9
+ runScriptPort: number | null;
10
+ }, logger: Logger): Promise<void>;
11
+ export declare function treeKillProcess(targetPid: number, signal: NodeJS.Signals, onError: (message: string, code?: string) => void, onComplete: () => void): Promise<void>;
12
+ export declare function waitForChildProcessExit(params: {
13
+ workspaceId: string;
14
+ childProcess: ChildProcess | undefined;
15
+ pid: number | null;
16
+ logger: Logger;
17
+ }): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=run-script-process-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-script-process-utils.d.ts","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script-process-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AAE9C,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,YAAY,GAAG,SAAS,EACtC,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAKT;AAED,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE;IACT,uBAAuB,EAAE,MAAM,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,EACD,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,OAAO,EACtB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,EACjD,UAAU,EAAE,MAAM,IAAI,GACrB,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,uBAAuB,CAAC,MAAM,EAAE;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB"}
@@ -0,0 +1,105 @@
1
+ import { spawn } from 'node:child_process';
2
+ import treeKill from 'tree-kill';
3
+ import { toError } from '../../../../backend/lib/error-utils.js';
4
+ import { FactoryConfigService } from '../../../../backend/services/factory-config.service.js';
5
+ export function shouldRejectStopWithoutProcess(status, childProcess, pid) {
6
+ if (childProcess || pid) {
7
+ return false;
8
+ }
9
+ return status !== 'STARTING';
10
+ }
11
+ export async function runCleanupScriptProcess(workspaceId, workspace, logger) {
12
+ logger.info('Running cleanup script before stopping', {
13
+ workspaceId,
14
+ cleanupCommand: workspace.runScriptCleanupCommand,
15
+ });
16
+ try {
17
+ const cleanupCommand = workspace.runScriptPort
18
+ ? FactoryConfigService.substitutePort(workspace.runScriptCleanupCommand, workspace.runScriptPort)
19
+ : workspace.runScriptCleanupCommand;
20
+ const cleanupProcess = spawn('bash', ['-c', cleanupCommand], {
21
+ cwd: workspace.worktreePath,
22
+ detached: false,
23
+ stdio: 'ignore',
24
+ });
25
+ await new Promise((resolve) => {
26
+ const timeout = setTimeout(() => {
27
+ logger.warn('Cleanup script timed out, proceeding anyway', { workspaceId });
28
+ cleanupProcess.kill('SIGTERM');
29
+ resolve();
30
+ }, 5000);
31
+ cleanupProcess.on('exit', (code) => {
32
+ clearTimeout(timeout);
33
+ logger.info('Cleanup script completed', { workspaceId, exitCode: code });
34
+ resolve();
35
+ });
36
+ cleanupProcess.on('error', (error) => {
37
+ clearTimeout(timeout);
38
+ logger.error('Cleanup script error', error, { workspaceId });
39
+ resolve();
40
+ });
41
+ });
42
+ }
43
+ catch (error) {
44
+ logger.error('Failed to run cleanup script', toError(error), { workspaceId });
45
+ }
46
+ }
47
+ export async function treeKillProcess(targetPid, signal, onError, onComplete) {
48
+ await new Promise((resolve) => {
49
+ treeKill(targetPid, signal, (err) => {
50
+ if (err) {
51
+ onError(err.message, err.code);
52
+ }
53
+ onComplete();
54
+ resolve();
55
+ });
56
+ });
57
+ }
58
+ export async function waitForChildProcessExit(params) {
59
+ const { workspaceId, childProcess, pid, logger } = params;
60
+ if (!childProcess) {
61
+ return;
62
+ }
63
+ if (childProcess.exitCode !== null) {
64
+ return;
65
+ }
66
+ if (typeof childProcess.once !== 'function' || typeof childProcess.off !== 'function') {
67
+ return;
68
+ }
69
+ const waitPid = childProcess.pid ?? pid ?? undefined;
70
+ await new Promise((resolve) => {
71
+ const timeout = setTimeout(() => {
72
+ cleanup();
73
+ logger.warn('Timed out waiting for run script process exit after stop', {
74
+ workspaceId,
75
+ pid: waitPid,
76
+ });
77
+ resolve();
78
+ }, 10_000);
79
+ const cleanup = () => {
80
+ clearTimeout(timeout);
81
+ childProcess.off('exit', onExit);
82
+ childProcess.off('error', onError);
83
+ };
84
+ const onExit = () => {
85
+ cleanup();
86
+ resolve();
87
+ };
88
+ const onError = (error) => {
89
+ cleanup();
90
+ logger.warn('Run script process emitted error while waiting for exit', {
91
+ workspaceId,
92
+ pid: waitPid,
93
+ error,
94
+ });
95
+ resolve();
96
+ };
97
+ childProcess.once('exit', onExit);
98
+ childProcess.once('error', onError);
99
+ if (childProcess.exitCode !== null) {
100
+ cleanup();
101
+ resolve();
102
+ }
103
+ });
104
+ }
105
+ //# sourceMappingURL=run-script-process-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-script-process-utils.js","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script-process-utils.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,8 @@
1
- import type { RunScriptStatus } from '../../../../shared/core/index.js';
2
1
  export declare class RunScriptService {
3
2
  private readonly runningProcesses;
4
3
  private readonly postRunProcesses;
5
- private readonly outputBuffers;
6
- private readonly outputListeners;
7
- private readonly postRunOutputBuffers;
8
- private readonly postRunOutputListeners;
4
+ private readonly runOutput;
5
+ private readonly postRunOutput;
9
6
  private isShuttingDown;
10
7
  private shutdownHandlersRegistered;
11
8
  startRunScript(workspaceId: string): Promise<{
@@ -37,7 +34,7 @@ export declare class RunScriptService {
37
34
  private killProcessTree;
38
35
  private waitForProcessExit;
39
36
  getRunScriptStatus(workspaceId: string): Promise<{
40
- status: RunScriptStatus;
37
+ status: import("../../../../shared/core/index.js").RunScriptStatus;
41
38
  pid: number | null;
42
39
  port: number | null;
43
40
  proxyUrl: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"run-script.service.d.ts","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script.service.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAsBrD,qBAAa,gBAAgB;IAE3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmC;IAGpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmC;IAGpE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAG3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkD;IAGlF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAGlE,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAkD;IAGzF,OAAO,CAAC,cAAc,CAAS;IAG/B,OAAO,CAAC,0BAA0B,CAAS;IAOrC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QACjD,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAwFF,OAAO,CAAC,0BAA0B;IAelC,OAAO,CAAC,uBAAuB;YA+CjB,iBAAiB;IAqE/B,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,mBAAmB;YAkBb,mBAAmB;YAqCnB,4BAA4B;YA0B5B,qBAAqB;YAqCrB,gBAAgB;IA6BxB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAChD,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;YAuFY,uBAAuB;YAwBvB,oBAAoB;YAwBpB,yBAAyB;YAgBzB,gBAAgB;YA0DhB,kBAAkB;YA8DlB,kBAAkB;YAiClB,eAAe;YAsCf,kBAAkB;IA8D1B,kBAAkB,CAAC,WAAW,EAAE,MAAM;;;;;;;;;;;IA+B5C,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAQ5C,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAWhD,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAuBpF,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAQnD,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAsBrF,OAAO;IAkCb,WAAW;IAyCX,wBAAwB,IAAI,IAAI;CAoCjC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE;IAAE,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,gBAAgB,CAMlB"}
1
+ {"version":3,"file":"run-script.service.d.ts","sourceRoot":"","sources":["../../../../../../src/backend/services/run-script/service/run-script.service.ts"],"names":[],"mappings":"AAwBA,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmC;IACpE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmC;IAEpE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqD;IAC/E,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqD;IAEnF,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,0BAA0B,CAAS;IAOrC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QACjD,OAAO,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IAwFF,OAAO,CAAC,0BAA0B;IAelC,OAAO,CAAC,uBAAuB;YA+CjB,iBAAiB;IAqE/B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,mBAAmB;YAIb,mBAAmB;YAqCnB,4BAA4B;YA0B5B,qBAAqB;YAqCrB,gBAAgB;IA6BxB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAChD,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;YAuFY,uBAAuB;YAwBvB,oBAAoB;YAwBpB,yBAAyB;YAgBzB,gBAAgB;YAWhB,kBAAkB;YA8DlB,kBAAkB;YA8BlB,eAAe;YAmCf,kBAAkB;IAW1B,kBAAkB,CAAC,WAAW,EAAE,MAAM;;;;;;;;;;;IA+B5C,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAQ5C,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAShD,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAOpF,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAQnD,wBAAwB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAOrF,OAAO;IAkCb,WAAW;IAuCX,wBAAwB,IAAI,IAAI;CAoCjC;AAED,wBAAgB,sBAAsB,CACpC,OAAO,GAAE;IAAE,wBAAwB,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,gBAAgB,CAMlB"}
@@ -1,5 +1,4 @@
1
1
  import { spawn } from 'node:child_process';
2
- import treeKill from 'tree-kill';
3
2
  import { toError } from '../../../../backend/lib/error-utils.js';
4
3
  import { FactoryConfigService } from '../../../../backend/services/factory-config.service.js';
5
4
  import { createLogger } from '../../../../backend/services/logger.service.js';
@@ -7,22 +6,16 @@ import { PortAllocationService } from '../../../../backend/services/port-allocat
7
6
  import { runScriptConfigPersistenceService, } from '../../../../backend/services/run-script-config-persistence.service.js';
8
7
  import { runScriptProxyService } from '../../../../backend/services/run-script-proxy.service.js';
9
8
  import { workspaceAccessor } from '../../../../backend/services/workspace/index.js';
9
+ import { RunScriptOutputBuffer } from './run-script-output-buffer.js';
10
+ import { runCleanupScriptProcess, shouldRejectStopWithoutProcess, treeKillProcess, waitForChildProcessExit, } from './run-script-process-utils.js';
10
11
  import { runScriptStateMachine } from './run-script-state-machine.service.js';
11
12
  const logger = createLogger('run-script-service');
12
13
  const MAX_OUTPUT_BUFFER_SIZE = 500 * 1024;
13
- function shouldRejectStopWithoutProcess(status, childProcess, pid) {
14
- if (childProcess || pid) {
15
- return false;
16
- }
17
- return status !== 'STARTING';
18
- }
19
14
  export class RunScriptService {
20
15
  runningProcesses = new Map();
21
16
  postRunProcesses = new Map();
22
- outputBuffers = new Map();
23
- outputListeners = new Map();
24
- postRunOutputBuffers = new Map();
25
- postRunOutputListeners = new Map();
17
+ runOutput = new RunScriptOutputBuffer(MAX_OUTPUT_BUFFER_SIZE);
18
+ postRunOutput = new RunScriptOutputBuffer(MAX_OUTPUT_BUFFER_SIZE);
26
19
  isShuttingDown = false;
27
20
  shutdownHandlersRegistered = false;
28
21
  async startRunScript(workspaceId) {
@@ -74,8 +67,8 @@ export class RunScriptService {
74
67
  }
75
68
  this.runningProcesses.set(workspaceId, childProcess);
76
69
  const startMessage = `\x1b[36m[Factory Factory]\x1b[0m Starting ${command}\n\n`;
77
- this.outputBuffers.set(workspaceId, startMessage);
78
- this.postRunOutputBuffers.delete(workspaceId);
70
+ this.runOutput.set(workspaceId, startMessage);
71
+ this.postRunOutput.clearBuffer(workspaceId);
79
72
  this.registerProcessHandlers(workspaceId, childProcess, pid);
80
73
  return await this.transitionToRunning(workspaceId, childProcess, pid, port, commands.runScriptPostRunCommand, workspace.worktreePath);
81
74
  }
@@ -137,7 +130,7 @@ export class RunScriptService {
137
130
  return;
138
131
  }
139
132
  this.runningProcesses.delete(workspaceId);
140
- this.outputListeners.delete(workspaceId);
133
+ this.runOutput.clearListeners(workspaceId);
141
134
  await this.killPostRunProcess(workspaceId);
142
135
  await runScriptProxyService.stopTunnel(workspaceId);
143
136
  try {
@@ -176,32 +169,10 @@ export class RunScriptService {
176
169
  }
177
170
  }
178
171
  appendOutput(workspaceId, output) {
179
- const currentBuffer = this.outputBuffers.get(workspaceId) ?? '';
180
- let newBuffer = currentBuffer + output;
181
- if (newBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
182
- newBuffer = newBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
183
- }
184
- this.outputBuffers.set(workspaceId, newBuffer);
185
- const listeners = this.outputListeners.get(workspaceId);
186
- if (listeners) {
187
- for (const listener of listeners) {
188
- listener(output);
189
- }
190
- }
172
+ this.runOutput.append(workspaceId, output);
191
173
  }
192
174
  appendPostRunOutput(workspaceId, output) {
193
- const currentBuffer = this.postRunOutputBuffers.get(workspaceId) ?? '';
194
- let newBuffer = currentBuffer + output;
195
- if (newBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
196
- newBuffer = newBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
197
- }
198
- this.postRunOutputBuffers.set(workspaceId, newBuffer);
199
- const listeners = this.postRunOutputListeners.get(workspaceId);
200
- if (listeners) {
201
- for (const listener of listeners) {
202
- listener(output);
203
- }
204
- }
175
+ this.postRunOutput.append(workspaceId, output);
205
176
  }
206
177
  async transitionToRunning(workspaceId, childProcess, pid, port, runScriptPostRunCommand = null, worktreePath = null) {
207
178
  try {
@@ -406,46 +377,7 @@ export class RunScriptService {
406
377
  }
407
378
  }
408
379
  async runCleanupScript(workspaceId, workspace) {
409
- logger.info('Running cleanup script before stopping', {
410
- workspaceId,
411
- cleanupCommand: workspace.runScriptCleanupCommand,
412
- });
413
- try {
414
- const cleanupCommand = workspace.runScriptPort
415
- ? FactoryConfigService.substitutePort(workspace.runScriptCleanupCommand, workspace.runScriptPort)
416
- : workspace.runScriptCleanupCommand;
417
- const cleanupProcess = spawn('bash', ['-c', cleanupCommand], {
418
- cwd: workspace.worktreePath,
419
- detached: false,
420
- stdio: ['ignore', 'pipe', 'pipe'],
421
- });
422
- cleanupProcess.stdout?.on('error', (error) => {
423
- logger.warn('Cleanup script stdout stream error', { workspaceId, error });
424
- });
425
- cleanupProcess.stderr?.on('error', (error) => {
426
- logger.warn('Cleanup script stderr stream error', { workspaceId, error });
427
- });
428
- await new Promise((resolve) => {
429
- const timeout = setTimeout(() => {
430
- logger.warn('Cleanup script timed out, proceeding anyway', { workspaceId });
431
- cleanupProcess.kill('SIGTERM');
432
- resolve();
433
- }, 5000);
434
- cleanupProcess.on('exit', (code) => {
435
- clearTimeout(timeout);
436
- logger.info('Cleanup script completed', { workspaceId, exitCode: code });
437
- resolve();
438
- });
439
- cleanupProcess.on('error', (error) => {
440
- clearTimeout(timeout);
441
- logger.error('Cleanup script error', error, { workspaceId });
442
- resolve();
443
- });
444
- });
445
- }
446
- catch (error) {
447
- logger.error('Failed to run cleanup script', toError(error), { workspaceId });
448
- }
380
+ await runCleanupScriptProcess(workspaceId, workspace, logger);
449
381
  }
450
382
  async spawnPostRunScript(workspaceId, runScriptPostRunCommand, worktreePath, port) {
451
383
  await Promise.resolve();
@@ -503,23 +435,15 @@ export class RunScriptService {
503
435
  return;
504
436
  }
505
437
  logger.info('Stopping postRun process', { workspaceId, pid: postRunPid });
506
- await new Promise((resolve) => {
507
- treeKill(postRunPid, 'SIGTERM', (err) => {
508
- if (err) {
509
- const errorCode = err.code;
510
- const message = err.message;
511
- if (errorCode !== 'ESRCH' && !message.includes('No such process')) {
512
- logger.warn('Failed to tree-kill postRun process', {
513
- workspaceId,
514
- pid: postRunPid,
515
- error: message,
516
- });
517
- }
518
- }
519
- this.postRunProcesses.delete(workspaceId);
520
- resolve();
521
- });
522
- });
438
+ await treeKillProcess(postRunPid, 'SIGTERM', (message, errorCode) => {
439
+ if (errorCode !== 'ESRCH' && !message.includes('No such process')) {
440
+ logger.warn('Failed to tree-kill postRun process', {
441
+ workspaceId,
442
+ pid: postRunPid,
443
+ error: message,
444
+ });
445
+ }
446
+ }, () => this.postRunProcesses.delete(workspaceId));
523
447
  }
524
448
  async killProcessTree(workspaceId, childProcess, pid) {
525
449
  const targetPid = childProcess?.pid ?? pid;
@@ -528,76 +452,24 @@ export class RunScriptService {
528
452
  }
529
453
  const source = childProcess?.pid ? 'stored process' : 'PID';
530
454
  logger.info(`Stopping run script via ${source}`, { workspaceId, pid: targetPid });
531
- await new Promise((resolve) => {
532
- treeKill(targetPid, 'SIGTERM', (err) => {
533
- if (err) {
534
- const errorCode = err.code;
535
- const message = err.message;
536
- if (errorCode === 'ESRCH' || message.includes('No such process')) {
537
- logger.debug('Run script process already exited before tree-kill', {
538
- workspaceId,
539
- pid: targetPid,
540
- error: message,
541
- });
542
- }
543
- else {
544
- logger.warn('Failed to tree-kill run script process', {
545
- workspaceId,
546
- pid: targetPid,
547
- error: message,
548
- });
549
- }
550
- }
551
- this.runningProcesses.delete(workspaceId);
552
- resolve();
553
- });
554
- });
555
- }
556
- async waitForProcessExit(workspaceId, childProcess, pid) {
557
- if (!childProcess) {
558
- return;
559
- }
560
- if (childProcess.exitCode !== null) {
561
- return;
562
- }
563
- if (typeof childProcess.once !== 'function' || typeof childProcess.off !== 'function') {
564
- return;
565
- }
566
- const waitPid = childProcess.pid ?? pid ?? undefined;
567
- await new Promise((resolve) => {
568
- const timeout = setTimeout(() => {
569
- cleanup();
570
- logger.warn('Timed out waiting for run script process exit after stop', {
455
+ await treeKillProcess(targetPid, 'SIGTERM', (message, errorCode) => {
456
+ if (errorCode === 'ESRCH' || message.includes('No such process')) {
457
+ logger.debug('Run script process already exited before tree-kill', {
571
458
  workspaceId,
572
- pid: waitPid,
573
- });
574
- resolve();
575
- }, 10_000);
576
- const cleanup = () => {
577
- clearTimeout(timeout);
578
- childProcess.off('exit', onExit);
579
- childProcess.off('error', onError);
580
- };
581
- const onExit = () => {
582
- cleanup();
583
- resolve();
584
- };
585
- const onError = (error) => {
586
- cleanup();
587
- logger.warn('Run script process emitted error while waiting for exit', {
588
- workspaceId,
589
- pid: waitPid,
590
- error,
459
+ pid: targetPid,
460
+ error: message,
591
461
  });
592
- resolve();
593
- };
594
- childProcess.once('exit', onExit);
595
- childProcess.once('error', onError);
596
- if (childProcess.exitCode !== null) {
597
- cleanup();
598
- resolve();
462
+ return;
599
463
  }
600
- });
464
+ logger.warn('Failed to tree-kill run script process', {
465
+ workspaceId,
466
+ pid: targetPid,
467
+ error: message,
468
+ });
469
+ }, () => this.runningProcesses.delete(workspaceId));
470
+ }
471
+ async waitForProcessExit(workspaceId, childProcess, pid) {
472
+ await waitForChildProcessExit({ workspaceId, childProcess, pid, logger });
601
473
  }
602
474
  async getRunScriptStatus(workspaceId) {
603
475
  const workspace = await workspaceAccessor.findById(workspaceId);
@@ -622,50 +494,20 @@ export class RunScriptService {
622
494
  };
623
495
  }
624
496
  getOutputBuffer(workspaceId) {
625
- return this.outputBuffers.get(workspaceId) ?? '';
497
+ return this.runOutput.get(workspaceId);
626
498
  }
627
499
  evictWorkspaceBuffers(workspaceId) {
628
- this.outputBuffers.delete(workspaceId);
629
- this.outputListeners.delete(workspaceId);
630
- this.postRunOutputBuffers.delete(workspaceId);
631
- this.postRunOutputListeners.delete(workspaceId);
500
+ this.runOutput.evict(workspaceId);
501
+ this.postRunOutput.evict(workspaceId);
632
502
  }
633
503
  subscribeToOutput(workspaceId, listener) {
634
- let listeners = this.outputListeners.get(workspaceId);
635
- if (!listeners) {
636
- listeners = new Set();
637
- this.outputListeners.set(workspaceId, listeners);
638
- }
639
- listeners.add(listener);
640
- return () => {
641
- const listeners = this.outputListeners.get(workspaceId);
642
- if (listeners) {
643
- listeners.delete(listener);
644
- if (listeners.size === 0) {
645
- this.outputListeners.delete(workspaceId);
646
- }
647
- }
648
- };
504
+ return this.runOutput.subscribe(workspaceId, listener);
649
505
  }
650
506
  getPostRunOutputBuffer(workspaceId) {
651
- return this.postRunOutputBuffers.get(workspaceId) ?? '';
507
+ return this.postRunOutput.get(workspaceId);
652
508
  }
653
509
  subscribeToPostRunOutput(workspaceId, listener) {
654
- let listeners = this.postRunOutputListeners.get(workspaceId);
655
- if (!listeners) {
656
- listeners = new Set();
657
- this.postRunOutputListeners.set(workspaceId, listeners);
658
- }
659
- listeners.add(listener);
660
- return () => {
661
- const listeners = this.postRunOutputListeners.get(workspaceId);
662
- if (listeners) {
663
- listeners.delete(listener);
664
- if (listeners.size === 0) {
665
- this.postRunOutputListeners.delete(workspaceId);
666
- }
667
- }
668
- };
510
+ return this.postRunOutput.subscribe(workspaceId, listener);
669
511
  }
670
512
  async cleanup() {
671
513
  logger.info('Cleaning up all running scripts', {
@@ -717,10 +559,8 @@ export class RunScriptService {
717
559
  }
718
560
  this.postRunProcesses.clear();
719
561
  runScriptProxyService.cleanupSync();
720
- this.outputBuffers.clear();
721
- this.outputListeners.clear();
722
- this.postRunOutputBuffers.clear();
723
- this.postRunOutputListeners.clear();
562
+ this.runOutput.clear();
563
+ this.postRunOutput.clear();
724
564
  }
725
565
  registerShutdownHandlers() {
726
566
  if (this.shutdownHandlersRegistered) {