@rudderhq/server 0.7.2 → 0.7.3

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 (428) hide show
  1. package/dist/agent-runtimes/registry.d.ts.map +1 -1
  2. package/dist/agent-runtimes/registry.js +0 -2
  3. package/dist/agent-runtimes/registry.js.map +1 -1
  4. package/dist/app.d.ts.map +1 -1
  5. package/dist/app.js +1 -5
  6. package/dist/app.js.map +1 -1
  7. package/dist/bootstrap/create-http-app.d.ts +1 -2
  8. package/dist/bootstrap/create-http-app.d.ts.map +1 -1
  9. package/dist/bootstrap/create-http-app.js +13 -12
  10. package/dist/bootstrap/create-http-app.js.map +1 -1
  11. package/dist/bootstrap/register-api-routes.d.ts +1 -2
  12. package/dist/bootstrap/register-api-routes.d.ts.map +1 -1
  13. package/dist/bootstrap/register-api-routes.js +20 -4
  14. package/dist/bootstrap/register-api-routes.js.map +1 -1
  15. package/dist/middleware/logger.js +2 -2
  16. package/dist/middleware/logger.js.map +1 -1
  17. package/dist/middleware/logger.test.js +26 -10
  18. package/dist/middleware/logger.test.js.map +1 -1
  19. package/dist/routes/agent-issue-creation.d.ts +25 -0
  20. package/dist/routes/agent-issue-creation.d.ts.map +1 -0
  21. package/dist/routes/agent-issue-creation.js +201 -0
  22. package/dist/routes/agent-issue-creation.js.map +1 -0
  23. package/dist/routes/app-builder.d.ts +3 -1
  24. package/dist/routes/app-builder.d.ts.map +1 -1
  25. package/dist/routes/app-builder.js +31 -11
  26. package/dist/routes/app-builder.js.map +1 -1
  27. package/dist/routes/computer.d.ts +30 -0
  28. package/dist/routes/computer.d.ts.map +1 -0
  29. package/dist/routes/computer.js +231 -0
  30. package/dist/routes/computer.js.map +1 -0
  31. package/dist/routes/health.d.ts.map +1 -1
  32. package/dist/routes/health.js +2 -0
  33. package/dist/routes/health.js.map +1 -1
  34. package/dist/routes/instance-settings.d.ts.map +1 -1
  35. package/dist/routes/instance-settings.js +3 -0
  36. package/dist/routes/instance-settings.js.map +1 -1
  37. package/dist/routes/issues.comments-attachments.d.ts.map +1 -1
  38. package/dist/routes/issues.comments-attachments.js +90 -8
  39. package/dist/routes/issues.comments-attachments.js.map +1 -1
  40. package/dist/routes/issues.d.ts.map +1 -1
  41. package/dist/routes/issues.js +12 -1
  42. package/dist/routes/issues.js.map +1 -1
  43. package/dist/routes/issues.mutations.d.ts.map +1 -1
  44. package/dist/routes/issues.mutations.js +85 -33
  45. package/dist/routes/issues.mutations.js.map +1 -1
  46. package/dist/routes/managed-mcp-runtime.d.ts.map +1 -1
  47. package/dist/routes/managed-mcp-runtime.js +109 -7
  48. package/dist/routes/managed-mcp-runtime.js.map +1 -1
  49. package/dist/routes/rudder-plugins.d.ts +4 -0
  50. package/dist/routes/rudder-plugins.d.ts.map +1 -0
  51. package/dist/routes/rudder-plugins.js +213 -0
  52. package/dist/routes/rudder-plugins.js.map +1 -0
  53. package/dist/services/activity-log.d.ts +0 -3
  54. package/dist/services/activity-log.d.ts.map +1 -1
  55. package/dist/services/activity-log.js +0 -33
  56. package/dist/services/activity-log.js.map +1 -1
  57. package/dist/services/activity.d.ts +3 -3
  58. package/dist/services/agent-issue-creation.d.ts +344 -0
  59. package/dist/services/agent-issue-creation.d.ts.map +1 -0
  60. package/dist/services/agent-issue-creation.js +675 -0
  61. package/dist/services/agent-issue-creation.js.map +1 -0
  62. package/dist/services/agent-run-context.d.ts.map +1 -1
  63. package/dist/services/agent-run-context.js +13 -2
  64. package/dist/services/agent-run-context.js.map +1 -1
  65. package/dist/services/app-builder.d.ts.map +1 -1
  66. package/dist/services/app-builder.js +24 -3
  67. package/dist/services/app-builder.js.map +1 -1
  68. package/dist/services/chat-assistant.d.ts.map +1 -1
  69. package/dist/services/chat-assistant.helpers.d.ts +1 -1
  70. package/dist/services/chat-assistant.js +11 -2
  71. package/dist/services/chat-assistant.js.map +1 -1
  72. package/dist/services/chat-generation-protocol.test.js +2 -2
  73. package/dist/services/chat-generation-protocol.test.js.map +1 -1
  74. package/dist/services/chats.d.ts +2 -2
  75. package/dist/services/computer-broker.d.ts +35 -0
  76. package/dist/services/computer-broker.d.ts.map +1 -0
  77. package/dist/services/computer-broker.js +211 -0
  78. package/dist/services/computer-broker.js.map +1 -0
  79. package/dist/services/computer-broker.test.d.ts +2 -0
  80. package/dist/services/computer-broker.test.d.ts.map +1 -0
  81. package/dist/services/computer-broker.test.js +70 -0
  82. package/dist/services/computer-broker.test.js.map +1 -0
  83. package/dist/services/computer-capability.d.ts +13 -0
  84. package/dist/services/computer-capability.d.ts.map +1 -0
  85. package/dist/services/computer-capability.js +11 -0
  86. package/dist/services/computer-capability.js.map +1 -0
  87. package/dist/services/computer-capability.test.d.ts +2 -0
  88. package/dist/services/computer-capability.test.d.ts.map +1 -0
  89. package/dist/services/computer-capability.test.js +27 -0
  90. package/dist/services/computer-capability.test.js.map +1 -0
  91. package/dist/services/finance.d.ts +1 -1
  92. package/dist/services/index.d.ts +2 -0
  93. package/dist/services/index.d.ts.map +1 -1
  94. package/dist/services/index.js +2 -0
  95. package/dist/services/index.js.map +1 -1
  96. package/dist/services/instance-settings.d.ts.map +1 -1
  97. package/dist/services/instance-settings.js +15 -2
  98. package/dist/services/instance-settings.js.map +1 -1
  99. package/dist/services/integrations/agent-integrations.d.ts +1 -1
  100. package/dist/services/issues.d.ts +86 -1
  101. package/dist/services/issues.d.ts.map +1 -1
  102. package/dist/services/issues.helpers.d.ts +4 -0
  103. package/dist/services/issues.helpers.d.ts.map +1 -1
  104. package/dist/services/issues.helpers.js +28 -6
  105. package/dist/services/issues.helpers.js.map +1 -1
  106. package/dist/services/issues.js +207 -127
  107. package/dist/services/issues.js.map +1 -1
  108. package/dist/services/knowledge-portability/organization-portability.files.d.ts +1 -1
  109. package/dist/services/knowledge-portability/organization-skills.catalog.d.ts +7 -1
  110. package/dist/services/knowledge-portability/organization-skills.catalog.d.ts.map +1 -1
  111. package/dist/services/knowledge-portability/organization-skills.catalog.js +10 -0
  112. package/dist/services/knowledge-portability/organization-skills.catalog.js.map +1 -1
  113. package/dist/services/knowledge-portability/organization-skills.d.ts +1 -0
  114. package/dist/services/knowledge-portability/organization-skills.d.ts.map +1 -1
  115. package/dist/services/knowledge-portability/organization-skills.js +36 -3
  116. package/dist/services/knowledge-portability/organization-skills.js.map +1 -1
  117. package/dist/services/mcp/managed-bindings.d.ts +3 -1
  118. package/dist/services/mcp/managed-bindings.d.ts.map +1 -1
  119. package/dist/services/mcp/managed-bindings.js +20 -3
  120. package/dist/services/mcp/managed-bindings.js.map +1 -1
  121. package/dist/services/mcp/managed-client.d.ts +15 -0
  122. package/dist/services/mcp/managed-client.d.ts.map +1 -1
  123. package/dist/services/mcp/managed-client.js +23 -1
  124. package/dist/services/mcp/managed-client.js.map +1 -1
  125. package/dist/services/mcp/managed-client.test.js +73 -9
  126. package/dist/services/mcp/managed-client.test.js.map +1 -1
  127. package/dist/services/messenger.d.ts +2 -2
  128. package/dist/services/messenger.d.ts.map +1 -1
  129. package/dist/services/messenger.js +126 -49
  130. package/dist/services/messenger.js.map +1 -1
  131. package/dist/services/product-analytics.d.ts +1 -1
  132. package/dist/services/rudder-plugins.d.ts +107 -0
  133. package/dist/services/rudder-plugins.d.ts.map +1 -0
  134. package/dist/services/rudder-plugins.js +1746 -0
  135. package/dist/services/rudder-plugins.js.map +1 -0
  136. package/dist/services/rudder-plugins.test.d.ts +2 -0
  137. package/dist/services/rudder-plugins.test.d.ts.map +1 -0
  138. package/dist/services/rudder-plugins.test.js +191 -0
  139. package/dist/services/rudder-plugins.test.js.map +1 -0
  140. package/dist/services/runtime-kernel/heartbeat.core.d.ts +1 -0
  141. package/dist/services/runtime-kernel/heartbeat.core.d.ts.map +1 -1
  142. package/dist/services/runtime-kernel/heartbeat.core.js +1 -1
  143. package/dist/services/runtime-kernel/heartbeat.core.js.map +1 -1
  144. package/dist/services/runtime-kernel/heartbeat.d.ts +53 -0
  145. package/dist/services/runtime-kernel/heartbeat.d.ts.map +1 -1
  146. package/dist/services/runtime-kernel/heartbeat.js +227 -107
  147. package/dist/services/runtime-kernel/heartbeat.js.map +1 -1
  148. package/dist/services/runtime-kernel/heartbeat.recovery.d.ts.map +1 -1
  149. package/dist/services/runtime-kernel/heartbeat.recovery.js +23 -2
  150. package/dist/services/runtime-kernel/heartbeat.recovery.js.map +1 -1
  151. package/dist/services/runtime-kernel/heartbeat.terminal.d.ts +14 -1
  152. package/dist/services/runtime-kernel/heartbeat.terminal.d.ts.map +1 -1
  153. package/dist/services/runtime-kernel/heartbeat.terminal.js +31 -0
  154. package/dist/services/runtime-kernel/heartbeat.terminal.js.map +1 -1
  155. package/dist/services/runtime-kernel/heartbeat.wakeup.d.ts.map +1 -1
  156. package/dist/services/runtime-kernel/heartbeat.wakeup.js +35 -3
  157. package/dist/services/runtime-kernel/heartbeat.wakeup.js.map +1 -1
  158. package/package.json +18 -18
  159. package/resources/bundled-skills/app-builder/SKILL.md +39 -9
  160. package/resources/bundled-skills/app-builder/assets/scaffold/app/globals.css +109 -16
  161. package/resources/bundled-skills/app-builder/assets/scaffold/components/contacts-workspace.tsx +176 -152
  162. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/alert.tsx +12 -0
  163. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/badge.tsx +27 -0
  164. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/button.tsx +9 -7
  165. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/card.tsx +15 -3
  166. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/empty.tsx +18 -0
  167. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/field.tsx +23 -0
  168. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/input.tsx +1 -1
  169. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/label.tsx +1 -1
  170. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/separator.tsx +6 -0
  171. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/skeleton.tsx +6 -0
  172. package/resources/bundled-skills/app-builder/assets/scaffold/components/ui/table.tsx +30 -0
  173. package/resources/bundled-skills/app-builder/assets/scaffold/components.json +20 -0
  174. package/resources/bundled-skills/app-builder/assets/scaffold/next-env.d.ts +1 -1
  175. package/resources/bundled-skills/app-builder/assets/scaffold/next.config.ts +19 -0
  176. package/resources/bundled-skills/app-builder/assets/scaffold/package.json +2 -1
  177. package/resources/bundled-skills/app-builder/assets/scaffold/rudder.app.json +1 -1
  178. package/resources/bundled-skills/app-builder/assets/scaffold/rudder.ui.json +13 -0
  179. package/resources/bundled-skills/app-builder/assets/scaffold/scripts/validate-rudder-ui.mjs +50 -0
  180. package/resources/bundled-skills/app-builder/assets/scaffold/tests/e2e/app.spec.ts +35 -1
  181. package/resources/bundled-skills/app-builder/evals/evals.json +2 -1
  182. package/resources/bundled-skills/app-builder/references/design-guidelines.md +19 -2
  183. package/resources/bundled-skills/app-builder/references/rudder-ui-preset.md +73 -0
  184. package/resources/bundled-skills/app-builder/references/scaffold-contract.md +12 -0
  185. package/resources/bundled-skills/app-builder/references/verification.md +6 -0
  186. package/resources/bundled-skills/app-builder/scripts/report-build-status.mjs +83 -0
  187. package/resources/bundled-skills/rudder-docs/SKILL.md +2 -2
  188. package/resources/bundled-skills/rudder-docs/evals/retrieval-authority-evals.json +40 -0
  189. package/resources/bundled-skills/rudder-docs/evals/trigger-evals.json +2 -2
  190. package/resources/bundled-skills/rudder-docs/references/api-reference.md +0 -2
  191. package/resources/bundled-skills/rudder-docs/references/plugin-authoring.md +38 -114
  192. package/resources/bundled-skills/rudder-docs/references/source-map.md +2 -0
  193. package/skills/app-builder/SKILL.md +39 -9
  194. package/skills/app-builder/assets/scaffold/app/globals.css +109 -16
  195. package/skills/app-builder/assets/scaffold/components/contacts-workspace.tsx +176 -152
  196. package/skills/app-builder/assets/scaffold/components/ui/alert.tsx +12 -0
  197. package/skills/app-builder/assets/scaffold/components/ui/badge.tsx +27 -0
  198. package/skills/app-builder/assets/scaffold/components/ui/button.tsx +9 -7
  199. package/skills/app-builder/assets/scaffold/components/ui/card.tsx +15 -3
  200. package/skills/app-builder/assets/scaffold/components/ui/empty.tsx +18 -0
  201. package/skills/app-builder/assets/scaffold/components/ui/field.tsx +23 -0
  202. package/skills/app-builder/assets/scaffold/components/ui/input.tsx +1 -1
  203. package/skills/app-builder/assets/scaffold/components/ui/label.tsx +1 -1
  204. package/skills/app-builder/assets/scaffold/components/ui/separator.tsx +6 -0
  205. package/skills/app-builder/assets/scaffold/components/ui/skeleton.tsx +6 -0
  206. package/skills/app-builder/assets/scaffold/components/ui/table.tsx +30 -0
  207. package/skills/app-builder/assets/scaffold/components.json +20 -0
  208. package/skills/app-builder/assets/scaffold/next-env.d.ts +1 -1
  209. package/skills/app-builder/assets/scaffold/next.config.ts +19 -0
  210. package/skills/app-builder/assets/scaffold/package.json +2 -1
  211. package/skills/app-builder/assets/scaffold/rudder.app.json +1 -1
  212. package/skills/app-builder/assets/scaffold/rudder.ui.json +13 -0
  213. package/skills/app-builder/assets/scaffold/scripts/validate-rudder-ui.mjs +50 -0
  214. package/skills/app-builder/assets/scaffold/tests/e2e/app.spec.ts +35 -1
  215. package/skills/app-builder/evals/evals.json +2 -1
  216. package/skills/app-builder/references/design-guidelines.md +19 -2
  217. package/skills/app-builder/references/rudder-ui-preset.md +73 -0
  218. package/skills/app-builder/references/scaffold-contract.md +12 -0
  219. package/skills/app-builder/references/verification.md +6 -0
  220. package/skills/app-builder/scripts/report-build-status.mjs +83 -0
  221. package/skills/rudder-docs/SKILL.md +2 -2
  222. package/skills/rudder-docs/evals/retrieval-authority-evals.json +40 -0
  223. package/skills/rudder-docs/evals/trigger-evals.json +2 -2
  224. package/skills/rudder-docs/references/api-reference.md +0 -2
  225. package/skills/rudder-docs/references/plugin-authoring.md +38 -114
  226. package/skills/rudder-docs/references/source-map.md +2 -0
  227. package/ui-dist/assets/{LibraryLiveSurface-cHCJmmsl.js → LibraryLiveSurface-CoGcDfo0.js} +1 -1
  228. package/ui-dist/assets/{abnfDiagram-VRR7QNED-BORJvkew.js → abnfDiagram-VRR7QNED-BnPHHNfu.js} +1 -1
  229. package/ui-dist/assets/{arc-DPUzhx87.js → arc-CAvqQQR_.js} +1 -1
  230. package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-Bz_hY8LM.js → architectureDiagram-ZJ3FMSHR-DDa31YAK.js} +1 -1
  231. package/ui-dist/assets/{blockDiagram-677ZJIJ3-Bq1X3YkP.js → blockDiagram-677ZJIJ3-DDXLU9Ej.js} +1 -1
  232. package/ui-dist/assets/{c4Diagram-LMCZKHZV-BawEM9Pc.js → c4Diagram-LMCZKHZV-zEm0rHCp.js} +1 -1
  233. package/ui-dist/assets/channel-M_3GhwHQ.js +1 -0
  234. package/ui-dist/assets/{chunk-2Q5K7J3B-D0D5ZOaA.js → chunk-2Q5K7J3B-y1Rw45sz.js} +1 -1
  235. package/ui-dist/assets/{chunk-32BRIVSS-T90P7lug.js → chunk-32BRIVSS-Cq8cQBba.js} +1 -1
  236. package/ui-dist/assets/{chunk-5VM5RSS4-jcAERTgh.js → chunk-5VM5RSS4-CjQA6jGI.js} +1 -1
  237. package/ui-dist/assets/{chunk-EX3LRPZG-t9-JXwnR.js → chunk-EX3LRPZG-VVYt7jh3.js} +1 -1
  238. package/ui-dist/assets/{chunk-JWPE2WC7-hqgD1saC.js → chunk-JWPE2WC7-BJC3ISop.js} +1 -1
  239. package/ui-dist/assets/{chunk-MOJQB5TN-BsSUoYzd.js → chunk-MOJQB5TN-ClZgTqQk.js} +1 -1
  240. package/ui-dist/assets/{chunk-RYQCIY6F-YcdDh2Zn.js → chunk-RYQCIY6F-DRei3pn2.js} +1 -1
  241. package/ui-dist/assets/{chunk-V7JOEXUC-ChFyH9Su.js → chunk-V7JOEXUC-BGWrQfpZ.js} +1 -1
  242. package/ui-dist/assets/{chunk-VR4S4FIN-BjVK8IyX.js → chunk-VR4S4FIN-BBYT57Lt.js} +1 -1
  243. package/ui-dist/assets/{chunk-XXDRQBXY-D-TvO9vT.js → chunk-XXDRQBXY-D7P4SoZB.js} +1 -1
  244. package/ui-dist/assets/classDiagram-OUVF2IWQ-G44FJFnB.js +1 -0
  245. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-G44FJFnB.js +1 -0
  246. package/ui-dist/assets/{cose-bilkent-JH36ORCC-DBwhASJG.js → cose-bilkent-JH36ORCC-mJXY7GQo.js} +1 -1
  247. package/ui-dist/assets/{cynefin-VYW2F7L2-SlCRmwl2.js → cynefin-VYW2F7L2-C-I_lPmH.js} +1 -1
  248. package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-DImV6N_p.js → cynefinDiagram-TSTJHNR4-Bm1S_w7H.js} +1 -1
  249. package/ui-dist/assets/{dagre-VKFMJZFB-FH4Wv8Zn.js → dagre-VKFMJZFB-BuPIm1AB.js} +1 -1
  250. package/ui-dist/assets/{diagram-FQU43EPY-CrZvQjId.js → diagram-FQU43EPY-DTBCuV0W.js} +1 -1
  251. package/ui-dist/assets/{diagram-G47NLZAW-B7IGl_T3.js → diagram-G47NLZAW-B4CK8uR2.js} +1 -1
  252. package/ui-dist/assets/{diagram-NH7WQ7WH-CB4i7H1a.js → diagram-NH7WQ7WH-BkbS0GkL.js} +1 -1
  253. package/ui-dist/assets/{diagram-OA4YK3LP-DNyWPYY9.js → diagram-OA4YK3LP-C_mkRe0c.js} +1 -1
  254. package/ui-dist/assets/{diagram-WEI45ONY-BAhxbhpi.js → diagram-WEI45ONY-CHUb3TIJ.js} +1 -1
  255. package/ui-dist/assets/{ebnfDiagram-CCIWWBDH-ClXtQ9qt.js → ebnfDiagram-CCIWWBDH-D_lN4ZOY.js} +1 -1
  256. package/ui-dist/assets/{erDiagram-Q63AITRT-DGXiMYfn.js → erDiagram-Q63AITRT-CRnDqcsy.js} +1 -1
  257. package/ui-dist/assets/{flowDiagram-23GEKE2U-CdZ-02zc.js → flowDiagram-23GEKE2U-ChELY-8y.js} +1 -1
  258. package/ui-dist/assets/{ganttDiagram-NO4QXBWP-TxhzNpta.js → ganttDiagram-NO4QXBWP-QIML25-M.js} +1 -1
  259. package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-D6Q_w6wR.js → gitGraphDiagram-IHSO6WYX-TB_AKH8l.js} +1 -1
  260. package/ui-dist/assets/{graph-CxNmbpl9.js → graph-HKPvyYQ1.js} +1 -1
  261. package/ui-dist/assets/{index-C12QC1Ex.js → index-Ar0zIwom.js} +1 -1
  262. package/ui-dist/assets/{index-CW21qWFm.js → index-BeNxgoKd.js} +1 -1
  263. package/ui-dist/assets/{index-BujwWE3j.js → index-CB-UdrKN.js} +1 -1
  264. package/ui-dist/assets/{index-Cx6oIZPm.js → index-CfpFS1Tl.js} +555 -581
  265. package/ui-dist/assets/{index-C_nwI4Yj.js → index-CjIeIR2m.js} +1 -1
  266. package/ui-dist/assets/{index-Rau2cGm0.js → index-DCgbySwf.js} +1 -1
  267. package/ui-dist/assets/{index-Do78GymY.js → index-DDMaBNLI.js} +1 -1
  268. package/ui-dist/assets/{index-DU2LI7f9.js → index-DSZmO4bA.js} +1 -1
  269. package/ui-dist/assets/{index-BA9tMBhO.js → index-DfzFi2fx.js} +1 -1
  270. package/ui-dist/assets/{index-BoTz5S-X.js → index-DmEf_U5I.js} +1 -1
  271. package/ui-dist/assets/{index-kbWUQ1um.js → index-OfGDMJiA.js} +1 -1
  272. package/ui-dist/assets/{index-AkhgKOxC.js → index-ZzX8P4M5.js} +1 -1
  273. package/ui-dist/assets/{index-BQ87dGIq.js → index-fDtlbG8Y.js} +1 -1
  274. package/ui-dist/assets/{index-CXnqg1Oq.js → index-gdvFtffQ.js} +1 -1
  275. package/ui-dist/assets/index-noipz8bE.css +1 -0
  276. package/ui-dist/assets/{index-Bxz75ICF.js → index-rnOTiIXd.js} +1 -1
  277. package/ui-dist/assets/{infoDiagram-FWYZ7A6U-CnJd4-Jq.js → infoDiagram-FWYZ7A6U-DUR3sDTd.js} +1 -1
  278. package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-Bq-qc3pD.js → ishikawaDiagram-FXEZZL3T-CcnYT0s0.js} +1 -1
  279. package/ui-dist/assets/{journeyDiagram-5HDEW3XC-NSmpUGUA.js → journeyDiagram-5HDEW3XC-CqfbG8T1.js} +1 -1
  280. package/ui-dist/assets/{kanban-definition-HUTT4EX6-D7pgWtfA.js → kanban-definition-HUTT4EX6-CYwQM9eR.js} +1 -1
  281. package/ui-dist/assets/{layout-BRuo6LWe.js → layout-B2IlJgLE.js} +1 -1
  282. package/ui-dist/assets/{linear-CkaWI9Nd.js → linear-CcEPcfbO.js} +1 -1
  283. package/ui-dist/assets/{map-CgA6tTpZ.js → map-Bmhfvlpu.js} +1 -1
  284. package/ui-dist/assets/{mermaid.core-DrXOt-P6.js → mermaid.core-T9Q0CuQx.js} +4 -4
  285. package/ui-dist/assets/{mindmap-definition-LN4V7U3C-D9ImeWBe.js → mindmap-definition-LN4V7U3C-CRjQlwN4.js} +1 -1
  286. package/ui-dist/assets/{pegDiagram-2B236MQR-Cq-zZ_zz.js → pegDiagram-2B236MQR-DenccdY8.js} +1 -1
  287. package/ui-dist/assets/{pieDiagram-ENE6RG2P-FgNgy726.js → pieDiagram-ENE6RG2P-CPiTrJcY.js} +1 -1
  288. package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-BxQbmGmi.js → quadrantDiagram-ABIIQ3AL-fKbvGl_-.js} +1 -1
  289. package/ui-dist/assets/{railroadDiagram-RFXS5EU6-CrpbkPH2.js → railroadDiagram-RFXS5EU6-D6uOjEmA.js} +1 -1
  290. package/ui-dist/assets/{requirementDiagram-TGXJPOKE-DQ-65ZW6.js → requirementDiagram-TGXJPOKE-CQIQ387O.js} +1 -1
  291. package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-Bom0lMZm.js → sankeyDiagram-HTMAVEWB-CKrnONJL.js} +1 -1
  292. package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-C1MSDLDj.js → sequenceDiagram-DBY2YBRQ-C3vaOiZO.js} +1 -1
  293. package/ui-dist/assets/{sizeCapture-X5ZJPWSS-Bn1vxebD.js → sizeCapture-X5ZJPWSS-F39EvxY0.js} +1 -1
  294. package/ui-dist/assets/{stateDiagram-2N3HPSRC-GRRQpmzI.js → stateDiagram-2N3HPSRC-Bq2sVFQq.js} +1 -1
  295. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-B94IPtHC.js +1 -0
  296. package/ui-dist/assets/{swimlanes-5IMT3BWC-BcOOCZ4q.js → swimlanes-5IMT3BWC-CSrygB7m.js} +2 -2
  297. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-9WQr2_E9.js +8 -0
  298. package/ui-dist/assets/{timeline-definition-FHXFAJF6-gi6amswh.js → timeline-definition-FHXFAJF6-DSMMlntv.js} +1 -1
  299. package/ui-dist/assets/{vennDiagram-L72KCM5P-B9uqeyQt.js → vennDiagram-L72KCM5P-D5XH96zV.js} +1 -1
  300. package/ui-dist/assets/{wardleyDiagram-EHGQE667-BnqWAMiE.js → wardleyDiagram-EHGQE667-BXX2RFsU.js} +1 -1
  301. package/ui-dist/assets/{xychartDiagram-FW5EYKEG-BJXKltIN.js → xychartDiagram-FW5EYKEG-awBW2lwG.js} +1 -1
  302. package/ui-dist/index.html +2 -2
  303. package/dist/bootstrap/plugin-host-runtime.d.ts +0 -116
  304. package/dist/bootstrap/plugin-host-runtime.d.ts.map +0 -1
  305. package/dist/bootstrap/plugin-host-runtime.js +0 -179
  306. package/dist/bootstrap/plugin-host-runtime.js.map +0 -1
  307. package/dist/bundled-plugins/plugin-linear/README.md +0 -22
  308. package/dist/bundled-plugins/plugin-linear/dist/manifest.js +0 -183
  309. package/dist/bundled-plugins/plugin-linear/dist/manifest.js.map +0 -7
  310. package/dist/bundled-plugins/plugin-linear/dist/ui/index.js +0 -1285
  311. package/dist/bundled-plugins/plugin-linear/dist/ui/index.js.map +0 -7
  312. package/dist/bundled-plugins/plugin-linear/dist/worker.js +0 -10699
  313. package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +0 -7
  314. package/dist/bundled-plugins/plugin-linear/package.json +0 -42
  315. package/dist/routes/plugin-ui-static.d.ts +0 -70
  316. package/dist/routes/plugin-ui-static.d.ts.map +0 -1
  317. package/dist/routes/plugin-ui-static.js +0 -375
  318. package/dist/routes/plugin-ui-static.js.map +0 -1
  319. package/dist/routes/plugins.d.ts +0 -120
  320. package/dist/routes/plugins.d.ts.map +0 -1
  321. package/dist/routes/plugins.js +0 -1125
  322. package/dist/routes/plugins.js.map +0 -1
  323. package/dist/routes/plugins.operations-routes.d.ts +0 -28
  324. package/dist/routes/plugins.operations-routes.d.ts.map +0 -1
  325. package/dist/routes/plugins.operations-routes.js +0 -720
  326. package/dist/routes/plugins.operations-routes.js.map +0 -1
  327. package/dist/services/plugin-capability-validator.d.ts +0 -108
  328. package/dist/services/plugin-capability-validator.d.ts.map +0 -1
  329. package/dist/services/plugin-capability-validator.js +0 -268
  330. package/dist/services/plugin-capability-validator.js.map +0 -1
  331. package/dist/services/plugin-config-validator.d.ts +0 -26
  332. package/dist/services/plugin-config-validator.d.ts.map +0 -1
  333. package/dist/services/plugin-config-validator.js +0 -41
  334. package/dist/services/plugin-config-validator.js.map +0 -1
  335. package/dist/services/plugin-dev-watcher.d.ts +0 -47
  336. package/dist/services/plugin-dev-watcher.d.ts.map +0 -1
  337. package/dist/services/plugin-dev-watcher.js +0 -275
  338. package/dist/services/plugin-dev-watcher.js.map +0 -1
  339. package/dist/services/plugin-event-bus.d.ts +0 -149
  340. package/dist/services/plugin-event-bus.d.ts.map +0 -1
  341. package/dist/services/plugin-event-bus.js +0 -258
  342. package/dist/services/plugin-event-bus.js.map +0 -1
  343. package/dist/services/plugin-host-service-cleanup.d.ts +0 -14
  344. package/dist/services/plugin-host-service-cleanup.d.ts.map +0 -1
  345. package/dist/services/plugin-host-service-cleanup.js +0 -37
  346. package/dist/services/plugin-host-service-cleanup.js.map +0 -1
  347. package/dist/services/plugin-host-services.d.ts +0 -13
  348. package/dist/services/plugin-host-services.d.ts.map +0 -1
  349. package/dist/services/plugin-host-services.js +0 -933
  350. package/dist/services/plugin-host-services.js.map +0 -1
  351. package/dist/services/plugin-job-coordinator.d.ts +0 -81
  352. package/dist/services/plugin-job-coordinator.d.ts.map +0 -1
  353. package/dist/services/plugin-job-coordinator.js +0 -172
  354. package/dist/services/plugin-job-coordinator.js.map +0 -1
  355. package/dist/services/plugin-job-scheduler.d.ts +0 -163
  356. package/dist/services/plugin-job-scheduler.d.ts.map +0 -1
  357. package/dist/services/plugin-job-scheduler.js +0 -452
  358. package/dist/services/plugin-job-scheduler.js.map +0 -1
  359. package/dist/services/plugin-job-store.d.ts +0 -208
  360. package/dist/services/plugin-job-store.d.ts.map +0 -1
  361. package/dist/services/plugin-job-store.js +0 -350
  362. package/dist/services/plugin-job-store.js.map +0 -1
  363. package/dist/services/plugin-lifecycle.d.ts +0 -240
  364. package/dist/services/plugin-lifecycle.d.ts.map +0 -1
  365. package/dist/services/plugin-lifecycle.js +0 -439
  366. package/dist/services/plugin-lifecycle.js.map +0 -1
  367. package/dist/services/plugin-loader.core.d.ts +0 -40
  368. package/dist/services/plugin-loader.core.d.ts.map +0 -1
  369. package/dist/services/plugin-loader.core.js +0 -879
  370. package/dist/services/plugin-loader.core.js.map +0 -1
  371. package/dist/services/plugin-loader.d.ts +0 -30
  372. package/dist/services/plugin-loader.d.ts.map +0 -1
  373. package/dist/services/plugin-loader.helpers.d.ts +0 -495
  374. package/dist/services/plugin-loader.helpers.d.ts.map +0 -1
  375. package/dist/services/plugin-loader.helpers.js +0 -238
  376. package/dist/services/plugin-loader.helpers.js.map +0 -1
  377. package/dist/services/plugin-loader.js +0 -30
  378. package/dist/services/plugin-loader.js.map +0 -1
  379. package/dist/services/plugin-loader.worker-paths.d.ts +0 -37
  380. package/dist/services/plugin-loader.worker-paths.d.ts.map +0 -1
  381. package/dist/services/plugin-loader.worker-paths.js +0 -62
  382. package/dist/services/plugin-loader.worker-paths.js.map +0 -1
  383. package/dist/services/plugin-log-retention.d.ts +0 -20
  384. package/dist/services/plugin-log-retention.d.ts.map +0 -1
  385. package/dist/services/plugin-log-retention.js +0 -63
  386. package/dist/services/plugin-log-retention.js.map +0 -1
  387. package/dist/services/plugin-manifest-validator.d.ts +0 -90
  388. package/dist/services/plugin-manifest-validator.d.ts.map +0 -1
  389. package/dist/services/plugin-manifest-validator.js +0 -72
  390. package/dist/services/plugin-manifest-validator.js.map +0 -1
  391. package/dist/services/plugin-registry.d.ts +0 -2542
  392. package/dist/services/plugin-registry.d.ts.map +0 -1
  393. package/dist/services/plugin-registry.js +0 -536
  394. package/dist/services/plugin-registry.js.map +0 -1
  395. package/dist/services/plugin-runtime-sandbox.d.ts +0 -40
  396. package/dist/services/plugin-runtime-sandbox.d.ts.map +0 -1
  397. package/dist/services/plugin-runtime-sandbox.js +0 -154
  398. package/dist/services/plugin-runtime-sandbox.js.map +0 -1
  399. package/dist/services/plugin-secrets-handler.d.ts +0 -81
  400. package/dist/services/plugin-secrets-handler.d.ts.map +0 -1
  401. package/dist/services/plugin-secrets-handler.js +0 -275
  402. package/dist/services/plugin-secrets-handler.js.map +0 -1
  403. package/dist/services/plugin-state-store.d.ts +0 -92
  404. package/dist/services/plugin-state-store.d.ts.map +0 -1
  405. package/dist/services/plugin-state-store.js +0 -190
  406. package/dist/services/plugin-state-store.js.map +0 -1
  407. package/dist/services/plugin-stream-bus.d.ts +0 -29
  408. package/dist/services/plugin-stream-bus.d.ts.map +0 -1
  409. package/dist/services/plugin-stream-bus.js +0 -48
  410. package/dist/services/plugin-stream-bus.js.map +0 -1
  411. package/dist/services/plugin-tool-dispatcher.d.ts +0 -180
  412. package/dist/services/plugin-tool-dispatcher.d.ts.map +0 -1
  413. package/dist/services/plugin-tool-dispatcher.js +0 -224
  414. package/dist/services/plugin-tool-dispatcher.js.map +0 -1
  415. package/dist/services/plugin-tool-registry.d.ts +0 -192
  416. package/dist/services/plugin-tool-registry.d.ts.map +0 -1
  417. package/dist/services/plugin-tool-registry.js +0 -224
  418. package/dist/services/plugin-tool-registry.js.map +0 -1
  419. package/dist/services/plugin-worker-manager.d.ts +0 -260
  420. package/dist/services/plugin-worker-manager.d.ts.map +0 -1
  421. package/dist/services/plugin-worker-manager.js +0 -836
  422. package/dist/services/plugin-worker-manager.js.map +0 -1
  423. package/ui-dist/assets/channel-C08AyYJr.js +0 -1
  424. package/ui-dist/assets/classDiagram-OUVF2IWQ-BIXq6fec.js +0 -1
  425. package/ui-dist/assets/classDiagram-v2-EOCWNBFH-BIXq6fec.js +0 -1
  426. package/ui-dist/assets/index-BmXb0yC1.css +0 -1
  427. package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-KvSJhiLM.js +0 -1
  428. package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Cr92NnJ4.js +0 -8
@@ -1,836 +0,0 @@
1
- /**
2
- * PluginWorkerManager — spawns and manages out-of-process plugin worker child
3
- * processes, routes JSON-RPC 2.0 calls over stdio, and handles lifecycle
4
- * management including crash recovery with exponential backoff.
5
- *
6
- * Each installed plugin gets one dedicated worker process. The host sends
7
- * JSON-RPC requests over the child's stdin and reads responses from stdout.
8
- * Worker stderr is captured and forwarded to the host logger.
9
- *
10
- * Process model. See doc/engineering/PLUGIN_RUNTIME_CONTRACT.md.
11
- * - One worker process per installed plugin
12
- * - Failure isolation: plugin crashes do not affect the host
13
- * - Graceful shutdown: 10-second drain, then SIGTERM, then SIGKILL
14
- * - Automatic restart with exponential backoff on unexpected exits
15
- *
16
- * @see doc/engineering/PLUGIN_RUNTIME_CONTRACT.md — Process Model
17
- * @see doc/engineering/PLUGIN_RUNTIME_CONTRACT.md — Graceful Shutdown Policy
18
- * @see doc/engineering/PLUGIN_RUNTIME_CONTRACT.md — Host-Worker Protocol
19
- */
20
- import { createErrorResponse, createRequest, isJsonRpcNotification, isJsonRpcRequest, isJsonRpcResponse, isJsonRpcSuccessResponse, JSONRPC_ERROR_CODES, JSONRPC_VERSION, JsonRpcCallError, JsonRpcParseError, parseMessage, PLUGIN_RPC_ERROR_CODES, serializeMessage, } from "@rudderhq/plugin-sdk";
21
- import { fork } from "node:child_process";
22
- import { EventEmitter } from "node:events";
23
- import { createInterface } from "node:readline";
24
- import { logger } from "../middleware/logger.js";
25
- // ---------------------------------------------------------------------------
26
- // Constants
27
- // ---------------------------------------------------------------------------
28
- /** Default timeout for RPC calls in milliseconds. */
29
- const DEFAULT_RPC_TIMEOUT_MS = 30_000;
30
- /** Hard upper bound for any RPC timeout (5 minutes). Prevents unbounded waits. */
31
- const MAX_RPC_TIMEOUT_MS = 5 * 60 * 1_000;
32
- /** Timeout for the initialize RPC call. */
33
- const INITIALIZE_TIMEOUT_MS = 15_000;
34
- /** Timeout for the shutdown RPC call before escalating to SIGTERM. */
35
- const SHUTDOWN_DRAIN_MS = 10_000;
36
- /** Time to wait after SIGTERM before sending SIGKILL. */
37
- const SIGTERM_GRACE_MS = 5_000;
38
- /** Minimum backoff delay for crash recovery (1 second). */
39
- const MIN_BACKOFF_MS = 1_000;
40
- /** Maximum backoff delay for crash recovery (5 minutes). */
41
- const MAX_BACKOFF_MS = 5 * 60 * 1_000;
42
- /** Backoff multiplier on each consecutive crash. */
43
- const BACKOFF_MULTIPLIER = 2;
44
- /** Maximum number of consecutive crashes before giving up on auto-restart. */
45
- const MAX_CONSECUTIVE_CRASHES = 10;
46
- /** Time window in which crashes are considered consecutive (10 minutes). */
47
- const CRASH_WINDOW_MS = 10 * 60 * 1_000;
48
- /** Maximum number of stderr characters retained for worker failure context. */
49
- const MAX_STDERR_EXCERPT_CHARS = 8_000;
50
- export function appendStderrExcerpt(current, chunk) {
51
- const next = current ? `${current}\n${chunk}` : chunk;
52
- return next.length <= MAX_STDERR_EXCERPT_CHARS
53
- ? next
54
- : next.slice(-MAX_STDERR_EXCERPT_CHARS);
55
- }
56
- export function formatWorkerFailureMessage(message, stderrExcerpt) {
57
- const excerpt = stderrExcerpt.trim();
58
- if (!excerpt)
59
- return message;
60
- if (message.includes(excerpt))
61
- return message;
62
- return `${message}\n\nWorker stderr:\n${excerpt}`;
63
- }
64
- // ---------------------------------------------------------------------------
65
- // Implementation: createPluginWorkerHandle
66
- // ---------------------------------------------------------------------------
67
- /**
68
- * Create a handle for a single plugin worker process.
69
- *
70
- * @internal Exported for testing; consumers should use `createPluginWorkerManager`.
71
- */
72
- export function createPluginWorkerHandle(pluginId, options) {
73
- const log = logger.child({ service: "plugin-worker", pluginId });
74
- const emitter = new EventEmitter();
75
- /**
76
- * Higher than default (10) to accommodate multiple subscribers to
77
- * crash/ready/exit events during integration tests and runtime monitoring.
78
- */
79
- emitter.setMaxListeners(50);
80
- // Worker process state
81
- let childProcess = null;
82
- let readline = null;
83
- let stderrReadline = null;
84
- let status = "stopped";
85
- let startedAt = null;
86
- let stderrExcerpt = "";
87
- // Pending RPC requests awaiting a response
88
- const pendingRequests = new Map();
89
- let nextRequestId = 1;
90
- // Optional methods reported by the worker during initialization
91
- let supportedMethods = [];
92
- // Crash tracking for exponential backoff
93
- let consecutiveCrashes = 0;
94
- let totalCrashes = 0;
95
- let lastCrashAt = null;
96
- let backoffTimer = null;
97
- let nextRestartAt = null;
98
- // Track open stream channels so we can emit synthetic close on crash.
99
- // Maps channel → orgId.
100
- const openStreamChannels = new Map();
101
- // Shutdown coordination
102
- let intentionalStop = false;
103
- const rpcTimeoutMs = options.rpcTimeoutMs ?? DEFAULT_RPC_TIMEOUT_MS;
104
- const autoRestart = options.autoRestart ?? true;
105
- // -----------------------------------------------------------------------
106
- // Status management
107
- // -----------------------------------------------------------------------
108
- function setStatus(newStatus) {
109
- const prev = status;
110
- if (prev === newStatus)
111
- return;
112
- status = newStatus;
113
- log.debug({ from: prev, to: newStatus }, "worker status change");
114
- emitter.emit("status", { pluginId, status: newStatus, previousStatus: prev });
115
- }
116
- // -----------------------------------------------------------------------
117
- // JSON-RPC message sending
118
- // -----------------------------------------------------------------------
119
- function sendMessage(message) {
120
- if (!childProcess?.stdin?.writable) {
121
- throw new Error(`Worker process for plugin "${pluginId}" is not writable`);
122
- }
123
- const serialized = serializeMessage(message);
124
- childProcess.stdin.write(serialized);
125
- }
126
- // -----------------------------------------------------------------------
127
- // Incoming message handling
128
- // -----------------------------------------------------------------------
129
- function handleLine(line) {
130
- if (!line.trim())
131
- return;
132
- let message;
133
- try {
134
- message = parseMessage(line);
135
- }
136
- catch (err) {
137
- if (err instanceof JsonRpcParseError) {
138
- log.warn({ rawLine: line.slice(0, 200) }, "unparseable message from worker");
139
- }
140
- else {
141
- log.warn({ err }, "error parsing worker message");
142
- }
143
- return;
144
- }
145
- if (isJsonRpcResponse(message)) {
146
- handleResponse(message);
147
- }
148
- else if (isJsonRpcRequest(message)) {
149
- handleWorkerRequest(message);
150
- }
151
- else if (isJsonRpcNotification(message)) {
152
- handleWorkerNotification(message);
153
- }
154
- else {
155
- log.warn("unknown message type from worker");
156
- }
157
- }
158
- /**
159
- * Handle a JSON-RPC response from the worker (matching a pending request).
160
- */
161
- function handleResponse(response) {
162
- const id = response.id;
163
- if (id === null || id === undefined) {
164
- log.warn("received response with null/undefined id");
165
- return;
166
- }
167
- const pending = pendingRequests.get(id);
168
- if (!pending) {
169
- log.warn({ id }, "received response for unknown request id");
170
- return;
171
- }
172
- clearTimeout(pending.timer);
173
- pendingRequests.delete(id);
174
- pending.resolve(response);
175
- }
176
- /**
177
- * Handle a JSON-RPC request from the worker (worker→host call).
178
- */
179
- async function handleWorkerRequest(request) {
180
- const method = request.method;
181
- const handler = options.hostHandlers[method];
182
- if (!handler) {
183
- log.warn({ method }, "worker called unregistered host method");
184
- try {
185
- sendMessage(createErrorResponse(request.id, JSONRPC_ERROR_CODES.METHOD_NOT_FOUND, `Host does not handle method "${method}"`));
186
- }
187
- catch {
188
- // Worker may have exited, ignore send error
189
- }
190
- return;
191
- }
192
- try {
193
- const result = await handler(request.params);
194
- sendMessage({
195
- jsonrpc: JSONRPC_VERSION,
196
- id: request.id,
197
- result: result ?? null,
198
- });
199
- }
200
- catch (err) {
201
- const errorMessage = err instanceof Error ? err.message : String(err);
202
- log.error({ method, err: errorMessage }, "host handler error");
203
- try {
204
- sendMessage(createErrorResponse(request.id, JSONRPC_ERROR_CODES.INTERNAL_ERROR, errorMessage));
205
- }
206
- catch {
207
- // Worker may have exited, ignore send error
208
- }
209
- }
210
- }
211
- /**
212
- * Handle a JSON-RPC notification from the worker (fire-and-forget).
213
- *
214
- * The `log` notification is the primary case — worker `ctx.logger` calls
215
- * arrive here. We append structured plugin context (pluginId, timestamp,
216
- * level) so every log entry is queryable by the current plugin runtime
217
- * contract.
218
- */
219
- function handleWorkerNotification(notification) {
220
- if (notification.method === "log") {
221
- const params = notification.params;
222
- const level = params?.level ?? "info";
223
- const msg = params?.message ?? "";
224
- const meta = params?.meta;
225
- // Build a structured log object that includes the plugin context fields:
226
- // pluginId, timestamp, level, message, and metadata.
227
- // The child logger already carries `pluginId` in its bindings, but we
228
- // add explicit `pluginLogLevel` and `pluginTimestamp` so downstream
229
- // consumers (log storage, UI queries) can filter without parsing.
230
- const logFields = {
231
- ...meta,
232
- pluginLogLevel: level,
233
- pluginTimestamp: new Date().toISOString(),
234
- };
235
- if (level === "error") {
236
- log.error(logFields, `[plugin] ${msg}`);
237
- }
238
- else if (level === "warn") {
239
- log.warn(logFields, `[plugin] ${msg}`);
240
- }
241
- else if (level === "debug") {
242
- log.debug(logFields, `[plugin] ${msg}`);
243
- }
244
- else {
245
- log.info(logFields, `[plugin] ${msg}`);
246
- }
247
- return;
248
- }
249
- // Stream notifications: forward to the stream bus via callback
250
- if (notification.method === "streams.open" ||
251
- notification.method === "streams.emit" ||
252
- notification.method === "streams.close") {
253
- const params = (notification.params ?? {});
254
- // Track open channels so we can emit synthetic close on crash
255
- if (notification.method === "streams.open") {
256
- const ch = String(params.channel ?? "");
257
- const co = String(params.orgId ?? "");
258
- if (ch)
259
- openStreamChannels.set(ch, co);
260
- }
261
- else if (notification.method === "streams.close") {
262
- openStreamChannels.delete(String(params.channel ?? ""));
263
- }
264
- if (options.onStreamNotification) {
265
- try {
266
- options.onStreamNotification(notification.method, params);
267
- }
268
- catch (err) {
269
- log.error({
270
- method: notification.method,
271
- err: err instanceof Error ? err.message : String(err),
272
- }, "stream notification handler failed");
273
- }
274
- }
275
- return;
276
- }
277
- log.debug({ method: notification.method }, "received notification from worker");
278
- }
279
- // -----------------------------------------------------------------------
280
- // Process lifecycle
281
- // -----------------------------------------------------------------------
282
- function spawnProcess() {
283
- // Security: Do NOT spread process.env into the worker. Plugins should only
284
- // receive a minimal, controlled environment to prevent leaking host
285
- // secrets (like DATABASE_URL, internal API keys, etc.).
286
- const workerEnv = {
287
- ...options.env,
288
- PATH: process.env.PATH ?? "",
289
- NODE_PATH: process.env.NODE_PATH ?? "",
290
- RUDDER_PLUGIN_ID: pluginId,
291
- NODE_ENV: process.env.NODE_ENV ?? "production",
292
- TZ: process.env.TZ ?? "UTC",
293
- };
294
- const child = fork(options.entrypointPath, [], {
295
- stdio: ["pipe", "pipe", "pipe", "ipc"],
296
- execArgv: options.execArgv ?? [],
297
- env: workerEnv,
298
- // Don't let the child keep the parent alive
299
- detached: false,
300
- });
301
- return child;
302
- }
303
- function attachStdioHandlers(child) {
304
- // Read NDJSON from stdout
305
- if (child.stdout) {
306
- readline = createInterface({ input: child.stdout });
307
- readline.on("line", handleLine);
308
- }
309
- // Capture stderr for logging
310
- if (child.stderr) {
311
- stderrReadline = createInterface({ input: child.stderr });
312
- stderrReadline.on("line", (line) => {
313
- stderrExcerpt = appendStderrExcerpt(stderrExcerpt, line);
314
- log.warn({ stream: "stderr" }, `[plugin stderr] ${line}`);
315
- });
316
- }
317
- // Handle process exit
318
- child.on("exit", (code, signal) => {
319
- handleProcessExit(code, signal);
320
- });
321
- // Handle process errors (e.g. spawn failure)
322
- child.on("error", (err) => {
323
- log.error({ err: err.message }, "worker process error");
324
- emitter.emit("error", { pluginId, error: err });
325
- if (status === "starting") {
326
- setStatus("crashed");
327
- rejectAllPending(new Error(formatWorkerFailureMessage(`Worker process failed to start: ${err.message}`, stderrExcerpt)));
328
- }
329
- });
330
- }
331
- function handleProcessExit(code, signal) {
332
- const wasIntentional = intentionalStop;
333
- // Clean up readline interfaces
334
- if (readline) {
335
- readline.close();
336
- readline = null;
337
- }
338
- if (stderrReadline) {
339
- stderrReadline.close();
340
- stderrReadline = null;
341
- }
342
- childProcess = null;
343
- startedAt = null;
344
- // Reject all pending requests
345
- rejectAllPending(new Error(formatWorkerFailureMessage(`Worker process exited (code=${code}, signal=${signal})`, stderrExcerpt)));
346
- // Emit synthetic close for any orphaned stream channels so SSE clients
347
- // are notified instead of hanging indefinitely.
348
- if (openStreamChannels.size > 0 && options.onStreamNotification) {
349
- for (const [channel, orgId] of openStreamChannels) {
350
- try {
351
- options.onStreamNotification("streams.close", { channel, orgId });
352
- }
353
- catch {
354
- // Best-effort cleanup — don't let it interfere with exit handling
355
- }
356
- }
357
- openStreamChannels.clear();
358
- }
359
- emitter.emit("exit", { pluginId, code, signal });
360
- if (wasIntentional) {
361
- // Graceful stop — status is already "stopping" or will be set to "stopped"
362
- setStatus("stopped");
363
- log.info({ code, signal }, "worker process stopped");
364
- return;
365
- }
366
- // Unexpected exit — crash recovery
367
- totalCrashes++;
368
- const now = Date.now();
369
- // Reset consecutive crash counter if enough time passed
370
- if (lastCrashAt !== null && now - lastCrashAt > CRASH_WINDOW_MS) {
371
- consecutiveCrashes = 0;
372
- }
373
- consecutiveCrashes++;
374
- lastCrashAt = now;
375
- log.error({ code, signal, consecutiveCrashes, totalCrashes }, "worker process crashed");
376
- const willRestart = autoRestart && consecutiveCrashes <= MAX_CONSECUTIVE_CRASHES;
377
- setStatus("crashed");
378
- emitter.emit("crash", { pluginId, code, signal, willRestart });
379
- if (willRestart) {
380
- scheduleRestart();
381
- }
382
- else {
383
- log.error({ consecutiveCrashes, maxCrashes: MAX_CONSECUTIVE_CRASHES }, "max consecutive crashes reached, not restarting");
384
- }
385
- }
386
- function rejectAllPending(error) {
387
- for (const [id, pending] of pendingRequests) {
388
- clearTimeout(pending.timer);
389
- pending.resolve(createErrorResponse(pending.id, PLUGIN_RPC_ERROR_CODES.WORKER_UNAVAILABLE, error.message));
390
- }
391
- pendingRequests.clear();
392
- }
393
- // -----------------------------------------------------------------------
394
- // Crash recovery with exponential backoff
395
- // -----------------------------------------------------------------------
396
- function computeBackoffMs() {
397
- // Exponential backoff: MIN_BACKOFF * MULTIPLIER^(consecutiveCrashes - 1)
398
- const delay = MIN_BACKOFF_MS * Math.pow(BACKOFF_MULTIPLIER, consecutiveCrashes - 1);
399
- // Add jitter: ±25%
400
- const jitter = delay * 0.25 * (Math.random() * 2 - 1);
401
- return Math.min(Math.round(delay + jitter), MAX_BACKOFF_MS);
402
- }
403
- function scheduleRestart() {
404
- const delay = computeBackoffMs();
405
- nextRestartAt = Date.now() + delay;
406
- setStatus("backoff");
407
- log.info({ delayMs: delay, consecutiveCrashes }, "scheduling restart with backoff");
408
- backoffTimer = setTimeout(async () => {
409
- backoffTimer = null;
410
- nextRestartAt = null;
411
- try {
412
- await startInternal();
413
- }
414
- catch (err) {
415
- log.error({ err: err instanceof Error ? err.message : String(err) }, "restart after backoff failed");
416
- }
417
- }, delay);
418
- }
419
- function cancelPendingRestart() {
420
- if (backoffTimer !== null) {
421
- clearTimeout(backoffTimer);
422
- backoffTimer = null;
423
- nextRestartAt = null;
424
- }
425
- }
426
- // -----------------------------------------------------------------------
427
- // Start / Stop
428
- // -----------------------------------------------------------------------
429
- async function startInternal() {
430
- if (status === "running" || status === "starting") {
431
- throw new Error(`Worker for plugin "${pluginId}" is already ${status}`);
432
- }
433
- intentionalStop = false;
434
- setStatus("starting");
435
- stderrExcerpt = "";
436
- const child = spawnProcess();
437
- childProcess = child;
438
- attachStdioHandlers(child);
439
- startedAt = Date.now();
440
- // Send the initialize RPC call
441
- const initParams = {
442
- manifest: options.manifest,
443
- config: options.config,
444
- instanceInfo: options.instanceInfo,
445
- apiVersion: options.apiVersion,
446
- };
447
- try {
448
- const result = await callInternal("initialize", initParams, INITIALIZE_TIMEOUT_MS);
449
- if (!result || !result.ok) {
450
- throw new Error("Worker initialize returned ok=false");
451
- }
452
- supportedMethods = result.supportedMethods ?? [];
453
- }
454
- catch (err) {
455
- // Initialize failed — kill the process and propagate
456
- const msg = err instanceof Error ? err.message : String(err);
457
- log.error({ err: msg }, "worker initialize failed");
458
- await killProcess();
459
- setStatus("crashed");
460
- throw new Error(`Worker initialize failed for "${pluginId}": ${msg}`);
461
- }
462
- // Reset crash counter on successful start
463
- consecutiveCrashes = 0;
464
- setStatus("running");
465
- emitter.emit("ready", { pluginId });
466
- log.info({ pid: child.pid }, "worker process started and initialized");
467
- }
468
- async function stopInternal() {
469
- cancelPendingRestart();
470
- if (status === "stopped" || status === "stopping") {
471
- return;
472
- }
473
- intentionalStop = true;
474
- setStatus("stopping");
475
- if (!childProcess) {
476
- setStatus("stopped");
477
- return;
478
- }
479
- // Step 1: Send shutdown RPC and wait for the worker to exit gracefully.
480
- // We race the shutdown call against a timeout. The worker should process
481
- // the shutdown and exit on its own within the drain period.
482
- try {
483
- await Promise.race([
484
- callInternal("shutdown", {}, SHUTDOWN_DRAIN_MS),
485
- waitForExit(SHUTDOWN_DRAIN_MS),
486
- ]);
487
- }
488
- catch {
489
- // Shutdown call failed or timed out — proceed to kill
490
- log.warn("shutdown RPC failed or timed out, escalating to SIGTERM");
491
- }
492
- // Give the process a brief moment to exit after the shutdown response
493
- if (childProcess) {
494
- await waitForExit(500);
495
- }
496
- // Check if process already exited
497
- if (!childProcess) {
498
- setStatus("stopped");
499
- return;
500
- }
501
- // Step 2: Send SIGTERM and wait
502
- log.info("worker did not exit after shutdown RPC, sending SIGTERM");
503
- await killWithSignal("SIGTERM", SIGTERM_GRACE_MS);
504
- if (!childProcess) {
505
- setStatus("stopped");
506
- return;
507
- }
508
- // Step 3: Forcefully kill with SIGKILL
509
- log.warn("worker did not exit after SIGTERM, sending SIGKILL");
510
- await killWithSignal("SIGKILL", 2_000);
511
- if (childProcess) {
512
- log.error("worker process still alive after SIGKILL — this should not happen");
513
- }
514
- setStatus("stopped");
515
- }
516
- /**
517
- * Wait for the child process to exit, up to `timeoutMs`.
518
- * Resolves immediately if the process is already gone.
519
- */
520
- function waitForExit(timeoutMs) {
521
- return new Promise((resolve) => {
522
- if (!childProcess) {
523
- resolve();
524
- return;
525
- }
526
- let settled = false;
527
- const timer = setTimeout(() => {
528
- if (settled)
529
- return;
530
- settled = true;
531
- resolve();
532
- }, timeoutMs);
533
- childProcess.once("exit", () => {
534
- if (settled)
535
- return;
536
- settled = true;
537
- clearTimeout(timer);
538
- resolve();
539
- });
540
- });
541
- }
542
- function killWithSignal(signal, waitMs) {
543
- return new Promise((resolve) => {
544
- if (!childProcess) {
545
- resolve();
546
- return;
547
- }
548
- const timer = setTimeout(() => {
549
- resolve();
550
- }, waitMs);
551
- childProcess.once("exit", () => {
552
- clearTimeout(timer);
553
- resolve();
554
- });
555
- try {
556
- childProcess.kill(signal);
557
- }
558
- catch {
559
- clearTimeout(timer);
560
- resolve();
561
- }
562
- });
563
- }
564
- async function killProcess() {
565
- if (!childProcess)
566
- return;
567
- intentionalStop = true;
568
- try {
569
- childProcess.kill("SIGKILL");
570
- }
571
- catch {
572
- // Process may already be dead
573
- }
574
- // Wait briefly for exit event
575
- await new Promise((resolve) => {
576
- if (!childProcess) {
577
- resolve();
578
- return;
579
- }
580
- const timer = setTimeout(() => {
581
- resolve();
582
- }, 1_000);
583
- childProcess.once("exit", () => {
584
- clearTimeout(timer);
585
- resolve();
586
- });
587
- });
588
- }
589
- // -----------------------------------------------------------------------
590
- // RPC call implementation
591
- // -----------------------------------------------------------------------
592
- function callInternal(method, params, timeoutMs) {
593
- return new Promise((resolve, reject) => {
594
- if (!childProcess?.stdin?.writable) {
595
- reject(new Error(`Cannot call "${method}" — worker for "${pluginId}" is not running`));
596
- return;
597
- }
598
- const id = nextRequestId++;
599
- const timeout = Math.min(timeoutMs ?? rpcTimeoutMs, MAX_RPC_TIMEOUT_MS);
600
- // Guard against double-settlement. When a process exits all pending
601
- // requests are rejected via rejectAllPending(), but the timeout timer
602
- // may still be running. Without this guard the timer's reject fires on
603
- // an already-settled promise, producing an unhandled rejection.
604
- let settled = false;
605
- const settle = (fn, value) => {
606
- if (settled)
607
- return;
608
- settled = true;
609
- clearTimeout(timer);
610
- pendingRequests.delete(id);
611
- fn(value);
612
- };
613
- const timer = setTimeout(() => {
614
- settle(reject, new JsonRpcCallError({
615
- code: PLUGIN_RPC_ERROR_CODES.TIMEOUT,
616
- message: `RPC call "${method}" timed out after ${timeout}ms`,
617
- }));
618
- }, timeout);
619
- const pending = {
620
- id,
621
- method,
622
- resolve: (response) => {
623
- if (isJsonRpcSuccessResponse(response)) {
624
- settle(resolve, response.result);
625
- }
626
- else if ("error" in response && response.error) {
627
- settle(reject, new JsonRpcCallError(response.error));
628
- }
629
- else {
630
- settle(reject, new Error(`Unexpected response format for "${method}"`));
631
- }
632
- },
633
- timer,
634
- sentAt: Date.now(),
635
- };
636
- pendingRequests.set(id, pending);
637
- try {
638
- const request = createRequest(method, params, id);
639
- sendMessage(request);
640
- }
641
- catch (err) {
642
- clearTimeout(timer);
643
- pendingRequests.delete(id);
644
- reject(new Error(`Failed to send "${method}" to worker: ${err instanceof Error ? err.message : String(err)}`));
645
- }
646
- });
647
- }
648
- // -----------------------------------------------------------------------
649
- // Public API
650
- // -----------------------------------------------------------------------
651
- const handle = {
652
- get pluginId() {
653
- return pluginId;
654
- },
655
- get status() {
656
- return status;
657
- },
658
- get supportedMethods() {
659
- return supportedMethods;
660
- },
661
- async start() {
662
- await startInternal();
663
- },
664
- async stop() {
665
- await stopInternal();
666
- },
667
- async restart() {
668
- await stopInternal();
669
- await startInternal();
670
- },
671
- call(method, params, timeoutMs) {
672
- if (status !== "running" && status !== "starting") {
673
- return Promise.reject(new Error(`Cannot call "${method}" — worker for "${pluginId}" is ${status}`));
674
- }
675
- return callInternal(method, params, timeoutMs);
676
- },
677
- notify(method, params) {
678
- if (status !== "running")
679
- return;
680
- try {
681
- sendMessage({
682
- jsonrpc: JSONRPC_VERSION,
683
- method,
684
- params,
685
- });
686
- }
687
- catch {
688
- log.warn({ method }, "failed to send notification to worker");
689
- }
690
- },
691
- on(event, listener) {
692
- emitter.on(event, listener);
693
- },
694
- off(event, listener) {
695
- emitter.off(event, listener);
696
- },
697
- diagnostics() {
698
- return {
699
- pluginId,
700
- status,
701
- pid: childProcess?.pid ?? null,
702
- uptime: startedAt !== null && status === "running"
703
- ? Date.now() - startedAt
704
- : null,
705
- consecutiveCrashes,
706
- totalCrashes,
707
- pendingRequests: pendingRequests.size,
708
- lastCrashAt,
709
- nextRestartAt,
710
- };
711
- },
712
- };
713
- return handle;
714
- }
715
- /**
716
- * Create a new PluginWorkerManager.
717
- *
718
- * The manager holds all plugin worker handles and provides a unified API for
719
- * starting, stopping, and communicating with plugin workers.
720
- *
721
- * @example
722
- * ```ts
723
- * const manager = createPluginWorkerManager();
724
- *
725
- * const handle = await manager.startWorker("acme.linear", {
726
- * entrypointPath: "/path/to/worker.cjs",
727
- * manifest,
728
- * config: resolvedConfig,
729
- * instanceInfo: { instanceId: "inst-1", hostVersion: "1.0.0" },
730
- * apiVersion: 1,
731
- * hostHandlers: { "config.get": async () => resolvedConfig, ... },
732
- * });
733
- *
734
- * // Send RPC call to the worker
735
- * const health = await manager.call("acme.linear", "health", {});
736
- *
737
- * // Shutdown all workers on server exit
738
- * await manager.stopAll();
739
- * ```
740
- */
741
- export function createPluginWorkerManager(managerOptions) {
742
- const log = logger.child({ service: "plugin-worker-manager" });
743
- const workers = new Map();
744
- /** Per-plugin startup locks to prevent concurrent spawn races. */
745
- const startupLocks = new Map();
746
- return {
747
- async startWorker(pluginId, options) {
748
- // Mutex: if a start is already in-flight for this plugin, wait for it
749
- const inFlight = startupLocks.get(pluginId);
750
- if (inFlight) {
751
- log.warn({ pluginId }, "concurrent startWorker call — waiting for in-flight start");
752
- return inFlight;
753
- }
754
- const existing = workers.get(pluginId);
755
- if (existing && existing.status !== "stopped") {
756
- throw new Error(`Worker already registered for plugin "${pluginId}" (status: ${existing.status})`);
757
- }
758
- const handle = createPluginWorkerHandle(pluginId, options);
759
- workers.set(pluginId, handle);
760
- // Subscribe to crash/ready events for live event forwarding
761
- if (managerOptions?.onWorkerEvent) {
762
- const notify = managerOptions.onWorkerEvent;
763
- handle.on("crash", (payload) => {
764
- notify({
765
- type: "plugin.worker.crashed",
766
- pluginId: payload.pluginId,
767
- code: payload.code,
768
- signal: payload.signal,
769
- willRestart: payload.willRestart,
770
- });
771
- });
772
- handle.on("ready", (payload) => {
773
- // Only emit restarted if this was a crash recovery (totalCrashes > 0)
774
- const diag = handle.diagnostics();
775
- if (diag.totalCrashes > 0) {
776
- notify({
777
- type: "plugin.worker.restarted",
778
- pluginId: payload.pluginId,
779
- });
780
- }
781
- });
782
- }
783
- log.info({ pluginId }, "starting plugin worker");
784
- // Set the lock before awaiting start() to prevent concurrent spawns
785
- const startPromise = handle.start().then(() => handle).finally(() => {
786
- startupLocks.delete(pluginId);
787
- });
788
- startupLocks.set(pluginId, startPromise);
789
- return startPromise;
790
- },
791
- async stopWorker(pluginId) {
792
- const handle = workers.get(pluginId);
793
- if (!handle) {
794
- log.warn({ pluginId }, "no worker registered for plugin, nothing to stop");
795
- return;
796
- }
797
- log.info({ pluginId }, "stopping plugin worker");
798
- await handle.stop();
799
- workers.delete(pluginId);
800
- },
801
- getWorker(pluginId) {
802
- return workers.get(pluginId);
803
- },
804
- isRunning(pluginId) {
805
- const handle = workers.get(pluginId);
806
- return handle?.status === "running";
807
- },
808
- async stopAll() {
809
- log.info({ count: workers.size }, "stopping all plugin workers");
810
- const promises = Array.from(workers.values()).map(async (handle) => {
811
- try {
812
- await handle.stop();
813
- }
814
- catch (err) {
815
- log.error({
816
- pluginId: handle.pluginId,
817
- err: err instanceof Error ? err.message : String(err),
818
- }, "error stopping worker during shutdown");
819
- }
820
- });
821
- await Promise.all(promises);
822
- workers.clear();
823
- },
824
- diagnostics() {
825
- return Array.from(workers.values()).map((h) => h.diagnostics());
826
- },
827
- call(pluginId, method, params, timeoutMs) {
828
- const handle = workers.get(pluginId);
829
- if (!handle) {
830
- return Promise.reject(new Error(`No worker registered for plugin "${pluginId}"`));
831
- }
832
- return handle.call(method, params, timeoutMs);
833
- },
834
- };
835
- }
836
- //# sourceMappingURL=plugin-worker-manager.js.map