@truefoundry/trueforge 0.1.4 → 0.2.0-rc.1

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 (252) hide show
  1. package/README.md +1 -1
  2. package/dist/_frontend/assets/AgentCodeSnippets-NZOFJE57-Bn94i1Ie.js +1 -0
  3. package/dist/_frontend/assets/AgentCodeSnippets-NZOFJE57-Bn94i1Ie.js.br +0 -0
  4. package/dist/_frontend/assets/AgentCodeSnippets-NZOFJE57-Bn94i1Ie.js.gz +0 -0
  5. package/dist/_frontend/assets/AgentMetricChart-JPU3MFQ2-pn-oatgo.js +1 -0
  6. package/dist/_frontend/assets/AgentMetricChart-JPU3MFQ2-pn-oatgo.js.br +0 -0
  7. package/dist/_frontend/assets/AgentMetricChart-JPU3MFQ2-pn-oatgo.js.gz +0 -0
  8. package/dist/_frontend/assets/AgentOverview-EEBHJC32-Bn4qidnv.js +1 -0
  9. package/dist/_frontend/assets/AgentOverview-EEBHJC32-Bn4qidnv.js.br +0 -0
  10. package/dist/_frontend/assets/AgentOverview-EEBHJC32-Bn4qidnv.js.gz +0 -0
  11. package/dist/_frontend/assets/AgentSessionEventTimeline-26Z6IB3B-D_yCZz1m.js +1 -0
  12. package/dist/_frontend/assets/AgentSessionEventTimeline-26Z6IB3B-D_yCZz1m.js.br +0 -0
  13. package/dist/_frontend/assets/AgentSessionEventTimeline-26Z6IB3B-D_yCZz1m.js.gz +0 -0
  14. package/dist/_frontend/assets/AgentSessionEventTimelineChart-CGCU7WBK-JGwv6e5T.js +1 -0
  15. package/dist/_frontend/assets/AgentSessionEventTimelineChart-CGCU7WBK-JGwv6e5T.js.br +0 -0
  16. package/dist/_frontend/assets/AgentSessionEventTimelineChart-CGCU7WBK-JGwv6e5T.js.gz +0 -0
  17. package/dist/_frontend/assets/AgentSessions-3MPDZASK-Dp6vYfGN.js +1 -0
  18. package/dist/_frontend/assets/AgentSessions-3MPDZASK-Dp6vYfGN.js.br +0 -0
  19. package/dist/_frontend/assets/AgentSessions-3MPDZASK-Dp6vYfGN.js.gz +0 -0
  20. package/dist/_frontend/assets/ConnectorSettings-MXFRWWR6-BEwXZbPM.js +1 -0
  21. package/dist/_frontend/assets/ConnectorSettings-MXFRWWR6-BEwXZbPM.js.br +0 -0
  22. package/dist/_frontend/assets/ConnectorSettings-MXFRWWR6-BEwXZbPM.js.gz +0 -0
  23. package/dist/_frontend/assets/{DockLayout-2RWDSUKE-eKoTN8R3.js → DockLayout-LM4AFMFY-DoBwJ3-e.js} +1 -1
  24. package/dist/_frontend/assets/DrawerLayout-JR3O6RRB-BZ9sffvm.js +2 -0
  25. package/dist/_frontend/assets/DrawerLayout-JR3O6RRB-BZ9sffvm.js.br +0 -0
  26. package/dist/_frontend/assets/DrawerLayout-JR3O6RRB-BZ9sffvm.js.gz +0 -0
  27. package/dist/_frontend/assets/ModelSettings-G7IFNC2Y-DxVYHG2m.js +1 -0
  28. package/dist/_frontend/assets/ModelSettings-G7IFNC2Y-DxVYHG2m.js.br +0 -0
  29. package/dist/_frontend/assets/ModelSettings-G7IFNC2Y-DxVYHG2m.js.gz +0 -0
  30. package/dist/_frontend/assets/SandboxSettings-NXAANMAX-DhC28qE6.js +1 -0
  31. package/dist/_frontend/assets/SandboxSettings-NXAANMAX-DhC28qE6.js.br +0 -0
  32. package/dist/_frontend/assets/SandboxSettings-NXAANMAX-DhC28qE6.js.gz +0 -0
  33. package/dist/_frontend/assets/SchedulesPage-KKLUDO6B-CWdrd7KY.js +1 -0
  34. package/dist/_frontend/assets/SchedulesPage-KKLUDO6B-CWdrd7KY.js.br +0 -0
  35. package/dist/_frontend/assets/SchedulesPage-KKLUDO6B-CWdrd7KY.js.gz +0 -0
  36. package/dist/_frontend/assets/SettingsBuilder-L34IQ56S-BQuxGH5w.js +2 -0
  37. package/dist/_frontend/assets/SettingsBuilder-L34IQ56S-BQuxGH5w.js.br +0 -0
  38. package/dist/_frontend/assets/SettingsBuilder-L34IQ56S-BQuxGH5w.js.gz +0 -0
  39. package/dist/_frontend/assets/ShellRouteSync-CEBETGEJ-C4NOyyck.js +1 -0
  40. package/dist/_frontend/assets/ShellRouteSync-CEBETGEJ-C4NOyyck.js.br +0 -0
  41. package/dist/_frontend/assets/ShellRouteSync-CEBETGEJ-C4NOyyck.js.gz +0 -0
  42. package/dist/_frontend/assets/SidebarLayout-A2HJPPHS-kusjDx4J.js +2 -0
  43. package/dist/_frontend/assets/SidebarLayout-A2HJPPHS-kusjDx4J.js.br +0 -0
  44. package/dist/_frontend/assets/SidebarLayout-A2HJPPHS-kusjDx4J.js.gz +0 -0
  45. package/dist/_frontend/assets/SkillSettings-FGGMSUNO-CjrGBX5J.js +1 -0
  46. package/dist/_frontend/assets/SkillSettings-FGGMSUNO-CjrGBX5J.js.br +0 -0
  47. package/dist/_frontend/assets/SkillSettings-FGGMSUNO-CjrGBX5J.js.gz +0 -0
  48. package/dist/_frontend/assets/TrueForgeUIWithRouter-MZVJWJMB-CZ8BOF1k.js +1 -0
  49. package/dist/_frontend/assets/WidgetLayout-6QM45OQQ-Bp0tde9v.js +1 -0
  50. package/dist/_frontend/assets/WidgetLayout-6QM45OQQ-Bp0tde9v.js.br +0 -0
  51. package/dist/_frontend/assets/WidgetLayout-6QM45OQQ-Bp0tde9v.js.gz +0 -0
  52. package/dist/_frontend/assets/chunk-62JRHF6Z-BLb_tkPU.js +12 -0
  53. package/dist/_frontend/assets/chunk-62JRHF6Z-BLb_tkPU.js.br +0 -0
  54. package/dist/_frontend/assets/chunk-62JRHF6Z-BLb_tkPU.js.gz +0 -0
  55. package/dist/_frontend/assets/chunk-DMMZSZTN-BBNhHida.js +1 -0
  56. package/dist/_frontend/assets/chunk-DMMZSZTN-BBNhHida.js.br +0 -0
  57. package/dist/_frontend/assets/chunk-DMMZSZTN-BBNhHida.js.gz +0 -0
  58. package/dist/_frontend/assets/chunk-FJW36PD7-R_XSoO50.js +2 -0
  59. package/dist/_frontend/assets/chunk-FJW36PD7-R_XSoO50.js.br +0 -0
  60. package/dist/_frontend/assets/chunk-FJW36PD7-R_XSoO50.js.gz +0 -0
  61. package/dist/_frontend/assets/chunk-WVE3F724-CL71bP7s.js +1 -0
  62. package/dist/_frontend/assets/chunk-WVE3F724-CL71bP7s.js.br +0 -0
  63. package/dist/_frontend/assets/chunk-WVE3F724-CL71bP7s.js.gz +0 -0
  64. package/dist/_frontend/assets/{cssMode-CvKwYh_L.js → cssMode-CVefs5W-.js} +1 -1
  65. package/dist/_frontend/assets/cssMode-CVefs5W-.js.br +0 -0
  66. package/dist/_frontend/assets/cssMode-CVefs5W-.js.gz +0 -0
  67. package/dist/_frontend/assets/{freemarker2-Bb2yOpT3.js → freemarker2-mt8l8QVE.js} +1 -1
  68. package/dist/_frontend/assets/freemarker2-mt8l8QVE.js.br +0 -0
  69. package/dist/_frontend/assets/freemarker2-mt8l8QVE.js.gz +0 -0
  70. package/dist/_frontend/assets/{handlebars-FL3wsxe0.js → handlebars-C97jT8Zn.js} +1 -1
  71. package/dist/_frontend/assets/handlebars-C97jT8Zn.js.br +0 -0
  72. package/dist/_frontend/assets/handlebars-C97jT8Zn.js.gz +0 -0
  73. package/dist/_frontend/assets/{html-Cb3v_ZRD.js → html-DKtvlaWU.js} +1 -1
  74. package/dist/_frontend/assets/html-DKtvlaWU.js.br +0 -0
  75. package/dist/_frontend/assets/html-DKtvlaWU.js.gz +0 -0
  76. package/dist/_frontend/assets/{htmlMode-JQDvK0Qf.js → htmlMode-BHsrcqlc.js} +1 -1
  77. package/dist/_frontend/assets/htmlMode-BHsrcqlc.js.br +0 -0
  78. package/dist/_frontend/assets/htmlMode-BHsrcqlc.js.gz +0 -0
  79. package/dist/_frontend/assets/{index-DRjgykCE.js → index-BW-oaxAt.js} +3 -3
  80. package/dist/_frontend/assets/index-BW-oaxAt.js.br +0 -0
  81. package/dist/_frontend/assets/index-BW-oaxAt.js.gz +0 -0
  82. package/dist/_frontend/assets/{index-DEKCw40W.css → index-D8eVAzN5.css} +1 -1
  83. package/dist/_frontend/assets/index-D8eVAzN5.css.br +0 -0
  84. package/dist/_frontend/assets/index-D8eVAzN5.css.gz +0 -0
  85. package/dist/_frontend/assets/index-DVCxCjDg.js +923 -0
  86. package/dist/_frontend/assets/index-DVCxCjDg.js.br +0 -0
  87. package/dist/_frontend/assets/index-DVCxCjDg.js.gz +0 -0
  88. package/dist/_frontend/assets/index-DuKoX4ct.js +18 -0
  89. package/dist/_frontend/assets/index-DuKoX4ct.js.br +0 -0
  90. package/dist/_frontend/assets/index-DuKoX4ct.js.gz +0 -0
  91. package/dist/_frontend/assets/{javascript-2WsgEpYV.js → javascript-Cs0N3w-s.js} +1 -1
  92. package/dist/_frontend/assets/{jsonMode-DnbseMlM.js → jsonMode-CqrfFSVA.js} +1 -1
  93. package/dist/_frontend/assets/jsonMode-CqrfFSVA.js.br +0 -0
  94. package/dist/_frontend/assets/jsonMode-CqrfFSVA.js.gz +0 -0
  95. package/dist/_frontend/assets/{liquid-DeE37I1e.js → liquid-C11lKF6J.js} +1 -1
  96. package/dist/_frontend/assets/liquid-C11lKF6J.js.br +0 -0
  97. package/dist/_frontend/assets/liquid-C11lKF6J.js.gz +0 -0
  98. package/dist/_frontend/assets/{lspLanguageFeatures-Bty8j9di.js → lspLanguageFeatures-DBZtnSMo.js} +1 -1
  99. package/dist/_frontend/assets/lspLanguageFeatures-DBZtnSMo.js.br +0 -0
  100. package/dist/_frontend/assets/lspLanguageFeatures-DBZtnSMo.js.gz +0 -0
  101. package/dist/_frontend/assets/{mdx-DfKPZX1Z.js → mdx-CCo4oKJJ.js} +1 -1
  102. package/dist/_frontend/assets/mdx-CCo4oKJJ.js.br +0 -0
  103. package/dist/_frontend/assets/mdx-CCo4oKJJ.js.gz +0 -0
  104. package/dist/_frontend/assets/{python-2i3Kiv75.js → python-627g_SSG.js} +1 -1
  105. package/dist/_frontend/assets/python-627g_SSG.js.br +0 -0
  106. package/dist/_frontend/assets/python-627g_SSG.js.gz +0 -0
  107. package/dist/_frontend/assets/{razor-B0N4vZnc.js → razor-BGDxoA7p.js} +1 -1
  108. package/dist/_frontend/assets/razor-BGDxoA7p.js.br +0 -0
  109. package/dist/_frontend/assets/razor-BGDxoA7p.js.gz +0 -0
  110. package/dist/_frontend/assets/{tsMode-D1Y8xh-o.js → tsMode-gPT7Bbjh.js} +1 -1
  111. package/dist/_frontend/assets/tsMode-gPT7Bbjh.js.br +0 -0
  112. package/dist/_frontend/assets/tsMode-gPT7Bbjh.js.gz +0 -0
  113. package/dist/_frontend/assets/{typescript-2nhip0PT.js → typescript-Cb0PzreF.js} +1 -1
  114. package/dist/_frontend/assets/typescript-Cb0PzreF.js.br +0 -0
  115. package/dist/_frontend/assets/typescript-Cb0PzreF.js.gz +0 -0
  116. package/dist/_frontend/assets/{workers-DSmTvA39.js → workers-BAgwFgJ0.js} +1 -1
  117. package/dist/_frontend/assets/workers-BAgwFgJ0.js.br +0 -0
  118. package/dist/_frontend/assets/workers-BAgwFgJ0.js.gz +0 -0
  119. package/dist/_frontend/assets/{xml-CA4M6Pks.js → xml-BpvCCHF9.js} +1 -1
  120. package/dist/_frontend/assets/xml-BpvCCHF9.js.br +0 -0
  121. package/dist/_frontend/assets/xml-BpvCCHF9.js.gz +0 -0
  122. package/dist/_frontend/assets/{yaml-D5KNk7Ji.js → yaml-f3XKmHoH.js} +1 -1
  123. package/dist/_frontend/assets/yaml-f3XKmHoH.js.br +0 -0
  124. package/dist/_frontend/assets/yaml-f3XKmHoH.js.gz +0 -0
  125. package/dist/_frontend/index.html +2 -31
  126. package/dist/controller-main.js +1259 -0
  127. package/dist/controller-main.js.map +1 -0
  128. package/dist/main.js +10419 -5343
  129. package/dist/main.js.map +1 -1
  130. package/dist/postgres/migrations/20260821_000001_agent_compaction.js +63 -0
  131. package/dist/postgres/migrations/20260821_000001_agent_compaction.js.map +1 -0
  132. package/dist/postgres/migrations/20260827_000001_schedule.js +40 -0
  133. package/dist/postgres/migrations/20260827_000001_schedule.js.map +1 -0
  134. package/dist/postgres/migrations/20260827_000001_session_metrics.js +25 -0
  135. package/dist/postgres/migrations/20260827_000001_session_metrics.js.map +1 -0
  136. package/dist/postgres/migrations/20260828_000001_schedule_name_uq.js +15 -0
  137. package/dist/postgres/migrations/20260828_000001_schedule_name_uq.js.map +1 -0
  138. package/dist/postgres/migrations/20260831_000001_session_external_id.js +26 -0
  139. package/dist/postgres/migrations/20260831_000001_session_external_id.js.map +1 -0
  140. package/dist/postgres/migrations/20260901_000001_agent_metadata.js +18 -0
  141. package/dist/postgres/migrations/20260901_000001_agent_metadata.js.map +1 -0
  142. package/dist/postgres/migrations/20260902_000001_session_metadata.js +15 -0
  143. package/dist/postgres/migrations/20260902_000001_session_metadata.js.map +1 -0
  144. package/dist/postgres/migrations/20260902_000002_agent_external_id.js +26 -0
  145. package/dist/postgres/migrations/20260902_000002_agent_external_id.js.map +1 -0
  146. package/dist/postgres/migrations/20260903_000001_drop_agent_metadata.js +18 -0
  147. package/dist/postgres/migrations/20260903_000001_drop_agent_metadata.js.map +1 -0
  148. package/dist/postgres/migrations/20260903_000002_created_by_subject.js +110 -0
  149. package/dist/postgres/migrations/20260903_000002_created_by_subject.js.map +1 -0
  150. package/dist/postgres/migrations/20260904_000001_schedule_agent_id.js +48 -0
  151. package/dist/postgres/migrations/20260904_000001_schedule_agent_id.js.map +1 -0
  152. package/dist/sqlite/migrations/20260821_000001_agent_compaction.js +69 -0
  153. package/dist/sqlite/migrations/20260821_000001_agent_compaction.js.map +1 -0
  154. package/dist/sqlite/migrations/20260827_000001_schedule.js +69 -0
  155. package/dist/sqlite/migrations/20260827_000001_schedule.js.map +1 -0
  156. package/dist/sqlite/migrations/20260827_000001_session_metrics.js +165 -0
  157. package/dist/sqlite/migrations/20260827_000001_session_metrics.js.map +1 -0
  158. package/dist/sqlite/migrations/20260828_000001_schedule_name_uq.js +20 -0
  159. package/dist/sqlite/migrations/20260828_000001_schedule_name_uq.js.map +1 -0
  160. package/dist/sqlite/migrations/20260831_000001_session_external_id.js +28 -0
  161. package/dist/sqlite/migrations/20260831_000001_session_external_id.js.map +1 -0
  162. package/dist/sqlite/migrations/20260901_000001_agent_metadata.js +92 -0
  163. package/dist/sqlite/migrations/20260901_000001_agent_metadata.js.map +1 -0
  164. package/dist/sqlite/migrations/20260902_000001_session_metadata.js +197 -0
  165. package/dist/sqlite/migrations/20260902_000001_session_metadata.js.map +1 -0
  166. package/dist/sqlite/migrations/20260902_000002_agent_external_id.js +28 -0
  167. package/dist/sqlite/migrations/20260902_000002_agent_external_id.js.map +1 -0
  168. package/dist/sqlite/migrations/20260903_000001_drop_agent_metadata.js +114 -0
  169. package/dist/sqlite/migrations/20260903_000001_drop_agent_metadata.js.map +1 -0
  170. package/dist/sqlite/migrations/20260903_000002_created_by_subject.js +496 -0
  171. package/dist/sqlite/migrations/20260903_000002_created_by_subject.js.map +1 -0
  172. package/dist/sqlite/migrations/20260904_000001_schedule_agent_id.js +131 -0
  173. package/dist/sqlite/migrations/20260904_000001_schedule_agent_id.js.map +1 -0
  174. package/package.json +31 -24
  175. package/dist/_frontend/assets/ConnectorSettings-ODC3LVHN-CAU9MgGN.js +0 -1
  176. package/dist/_frontend/assets/ConnectorSettings-ODC3LVHN-CAU9MgGN.js.br +0 -0
  177. package/dist/_frontend/assets/ConnectorSettings-ODC3LVHN-CAU9MgGN.js.gz +0 -0
  178. package/dist/_frontend/assets/DrawerLayout-CZLJYMIN-DWPAdLZz.js +0 -2
  179. package/dist/_frontend/assets/DrawerLayout-CZLJYMIN-DWPAdLZz.js.br +0 -0
  180. package/dist/_frontend/assets/DrawerLayout-CZLJYMIN-DWPAdLZz.js.gz +0 -0
  181. package/dist/_frontend/assets/ModelSettings-CKQ5CVAC-UBz_ch6T.js +0 -1
  182. package/dist/_frontend/assets/ModelSettings-CKQ5CVAC-UBz_ch6T.js.br +0 -0
  183. package/dist/_frontend/assets/ModelSettings-CKQ5CVAC-UBz_ch6T.js.gz +0 -0
  184. package/dist/_frontend/assets/SandboxSettings-HSCPYUOC-Csl-nC9h.js +0 -1
  185. package/dist/_frontend/assets/SandboxSettings-HSCPYUOC-Csl-nC9h.js.br +0 -0
  186. package/dist/_frontend/assets/SandboxSettings-HSCPYUOC-Csl-nC9h.js.gz +0 -0
  187. package/dist/_frontend/assets/SettingsBuilder-MYWRFXRI-Ce3OWfa1.js +0 -2
  188. package/dist/_frontend/assets/SettingsBuilder-MYWRFXRI-Ce3OWfa1.js.br +0 -0
  189. package/dist/_frontend/assets/SettingsBuilder-MYWRFXRI-Ce3OWfa1.js.gz +0 -0
  190. package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-B5lyCu4o.js +0 -1
  191. package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-B5lyCu4o.js.br +0 -0
  192. package/dist/_frontend/assets/ShellRouteSync-T4WLY57Q-B5lyCu4o.js.gz +0 -0
  193. package/dist/_frontend/assets/SidebarLayout-WVY54TGZ-CIx5jQIC.js +0 -2
  194. package/dist/_frontend/assets/SidebarLayout-WVY54TGZ-CIx5jQIC.js.br +0 -0
  195. package/dist/_frontend/assets/SidebarLayout-WVY54TGZ-CIx5jQIC.js.gz +0 -0
  196. package/dist/_frontend/assets/SkillSettings-ECH6SHZ7-CKWEzdO_.js +0 -1
  197. package/dist/_frontend/assets/SkillSettings-ECH6SHZ7-CKWEzdO_.js.br +0 -0
  198. package/dist/_frontend/assets/SkillSettings-ECH6SHZ7-CKWEzdO_.js.gz +0 -0
  199. package/dist/_frontend/assets/TrueForgeUIWithRouter-RKZ2E7PV-CoVbEgto.js +0 -1
  200. package/dist/_frontend/assets/WidgetLayout-NWWB2SXI-cUmY1p2v.js +0 -1
  201. package/dist/_frontend/assets/WidgetLayout-NWWB2SXI-cUmY1p2v.js.br +0 -0
  202. package/dist/_frontend/assets/WidgetLayout-NWWB2SXI-cUmY1p2v.js.gz +0 -0
  203. package/dist/_frontend/assets/chunk-62JRHF6Z-BftTGWZl.js +0 -12
  204. package/dist/_frontend/assets/chunk-62JRHF6Z-BftTGWZl.js.br +0 -0
  205. package/dist/_frontend/assets/chunk-62JRHF6Z-BftTGWZl.js.gz +0 -0
  206. package/dist/_frontend/assets/chunk-OZTNBS6V-CLmmFX7d.js +0 -4
  207. package/dist/_frontend/assets/chunk-OZTNBS6V-CLmmFX7d.js.br +0 -0
  208. package/dist/_frontend/assets/chunk-OZTNBS6V-CLmmFX7d.js.gz +0 -0
  209. package/dist/_frontend/assets/chunk-TCAVLWYL-DVhtkE3q.js +0 -2
  210. package/dist/_frontend/assets/chunk-TCAVLWYL-DVhtkE3q.js.br +0 -0
  211. package/dist/_frontend/assets/chunk-TCAVLWYL-DVhtkE3q.js.gz +0 -0
  212. package/dist/_frontend/assets/cssMode-CvKwYh_L.js.br +0 -0
  213. package/dist/_frontend/assets/cssMode-CvKwYh_L.js.gz +0 -0
  214. package/dist/_frontend/assets/freemarker2-Bb2yOpT3.js.br +0 -0
  215. package/dist/_frontend/assets/freemarker2-Bb2yOpT3.js.gz +0 -0
  216. package/dist/_frontend/assets/handlebars-FL3wsxe0.js.br +0 -0
  217. package/dist/_frontend/assets/handlebars-FL3wsxe0.js.gz +0 -0
  218. package/dist/_frontend/assets/html-Cb3v_ZRD.js.br +0 -0
  219. package/dist/_frontend/assets/html-Cb3v_ZRD.js.gz +0 -0
  220. package/dist/_frontend/assets/htmlMode-JQDvK0Qf.js.br +0 -0
  221. package/dist/_frontend/assets/htmlMode-JQDvK0Qf.js.gz +0 -0
  222. package/dist/_frontend/assets/index-DEKCw40W.css.br +0 -0
  223. package/dist/_frontend/assets/index-DEKCw40W.css.gz +0 -0
  224. package/dist/_frontend/assets/index-DJ1uWGdt.js +0 -859
  225. package/dist/_frontend/assets/index-DJ1uWGdt.js.br +0 -0
  226. package/dist/_frontend/assets/index-DJ1uWGdt.js.gz +0 -0
  227. package/dist/_frontend/assets/index-DRjgykCE.js.br +0 -0
  228. package/dist/_frontend/assets/index-DRjgykCE.js.gz +0 -0
  229. package/dist/_frontend/assets/jsonMode-DnbseMlM.js.br +0 -0
  230. package/dist/_frontend/assets/jsonMode-DnbseMlM.js.gz +0 -0
  231. package/dist/_frontend/assets/liquid-DeE37I1e.js.br +0 -0
  232. package/dist/_frontend/assets/liquid-DeE37I1e.js.gz +0 -0
  233. package/dist/_frontend/assets/lspLanguageFeatures-Bty8j9di.js.br +0 -0
  234. package/dist/_frontend/assets/lspLanguageFeatures-Bty8j9di.js.gz +0 -0
  235. package/dist/_frontend/assets/mdx-DfKPZX1Z.js.br +0 -0
  236. package/dist/_frontend/assets/mdx-DfKPZX1Z.js.gz +0 -0
  237. package/dist/_frontend/assets/python-2i3Kiv75.js.br +0 -0
  238. package/dist/_frontend/assets/python-2i3Kiv75.js.gz +0 -0
  239. package/dist/_frontend/assets/razor-B0N4vZnc.js.br +0 -0
  240. package/dist/_frontend/assets/razor-B0N4vZnc.js.gz +0 -0
  241. package/dist/_frontend/assets/tsMode-D1Y8xh-o.js.br +0 -0
  242. package/dist/_frontend/assets/tsMode-D1Y8xh-o.js.gz +0 -0
  243. package/dist/_frontend/assets/typescript-2nhip0PT.js.br +0 -0
  244. package/dist/_frontend/assets/typescript-2nhip0PT.js.gz +0 -0
  245. package/dist/_frontend/assets/workers-DSmTvA39.js.br +0 -0
  246. package/dist/_frontend/assets/workers-DSmTvA39.js.gz +0 -0
  247. package/dist/_frontend/assets/xml-CA4M6Pks.js.br +0 -0
  248. package/dist/_frontend/assets/xml-CA4M6Pks.js.gz +0 -0
  249. package/dist/_frontend/assets/yaml-D5KNk7Ji.js.br +0 -0
  250. package/dist/_frontend/assets/yaml-D5KNk7Ji.js.gz +0 -0
  251. package/dist/_frontend/index.html.br +0 -0
  252. package/dist/_frontend/index.html.gz +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/controller.ts","../src/controller/Controller.ts","../src/db/scheduleStore.ts","../src/schemas/schedule.ts","../src/schemas/common.ts","../src/runtime/cron.ts","../src/controller/scheduleDispatch.ts","../src/http/tls.ts","../src/db/postgres/client.ts","../src/db/postgres/schema.ts","../src/db/postgres/schedule-store/PostgresScheduleStore.ts","../src/utils/id.ts","../src/db/createdBySubject.ts","../src/db/postgres/sqlExpressions.ts","../src/logger.ts","../src/packageVersion.ts","../src/controller-main.ts"],"sourcesContent":["/**\n * Server configuration.\n *\n * Environment variables are read once at module load into a typed\n * `configuration` object exported as default. Any invalid value throws at\n * import time, so a misconfigured server fails fast at boot instead of\n * mid-run.\n *\n * `STANDALONE` is a discriminated mode selector:\n * - `true` (default): SQLite only; no Redis / executor peering.\n * - `false`: Postgres + Redis (defaults to local trueforge credentials /\n * `redis://localhost:6379`).\n */\nimport { existsSync } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport envPaths from 'env-paths';\n\nconst DEFAULT_PORT = 8790;\n/** Loopback default; container images set HOST=0.0.0.0 so probes and Service traffic reach the process. */\nconst DEFAULT_HOST = 'localhost';\n/** Default HTTP request body ceiling: 30 MB. */\nconst DEFAULT_MAX_REQUEST_BODY_BYTES = 30 * 1024 * 1024;\n/**\n * Package root whether this module runs as `src/config.ts` (tsx) or is bundled\n * into `dist/main.js` / `dist/cli.js` (`import.meta` → `dist/` → parent).\n */\nconst PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');\n/** Turn ids minted by a standalone process; no peer can ever own them. */\nconst LOCAL_EXECUTOR_ID = 'local';\n/** OS-standard data dir for SQLite in standalone mode. */\nconst ENV_PATHS_APP_NAME = 'trueforge';\nconst DEFAULT_POSTGRES_USER = 'trueforge';\nconst DEFAULT_POSTGRES_PASSWORD = 'trueforge';\nconst DEFAULT_POSTGRES_DB = 'trueforge';\nconst DEFAULT_POSTGRES_HOST = 'localhost';\nconst DEFAULT_POSTGRES_PORT = 5432;\nconst DEFAULT_REDIS_URL = 'redis://localhost:6379';\n\nconst DEFAULT_OIDC_USER_REFERENCE_CLAIM = 'sub';\nconst DEFAULT_OIDC_USER_DISPLAY_NAME_CLAIM = 'name';\nconst DEFAULT_OIDC_USER_ROLE_CLAIM = 'groups';\nconst DEFAULT_OIDC_ADMIN_ROLE_VALUE = 'admin';\nconst DEFAULT_OIDC_SCOPES = 'openid,profile,email';\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\nexport interface GetEnvOptions {\n defaultValue?: string;\n required?: boolean;\n}\n\nfunction getEnv(key: string, options?: GetEnvOptions): string | undefined {\n const value = process.env[key];\n if (value !== undefined) {\n return value;\n }\n\n // Checking for undefined as value can also be 0 or \"\"\n if (options?.defaultValue !== undefined) {\n return options.defaultValue;\n }\n\n if (options?.required) {\n throw new Error(`Environment variable ${key} is required but was not specified.`);\n }\n\n return undefined;\n}\n\nfunction randomAlphanumeric(length: number): string {\n return Array.from({ length }, () => Math.floor(Math.random() * 36).toString(36)).join('');\n}\n\nfunction parsePort(raw: string | undefined): number {\n if (raw === undefined || raw.trim() === '') {\n return DEFAULT_PORT;\n }\n const port = Number(raw);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Environment variable PORT must be an integer between 1 and 65535, got \"${raw}\"`);\n }\n return port;\n}\n\nexport function parseOidcScopes(raw: string): string[] {\n const scopes = raw\n .split(',')\n .map(part => part.trim())\n .filter(part => part.length > 0);\n if (scopes.length === 0) {\n throw new Error('OIDC_SCOPES must contain at least one scope.');\n }\n return scopes;\n}\n\n/**\n * Parses `OIDC_ALLOWED_EMAILS`: comma-separated exact addresses and/or globs\n * (`*@company.com`). Empty / unset → no allowlist (any authenticated user may sign in).\n */\nexport function parseOidcAllowedEmails(raw: string | undefined): string[] {\n if (raw === undefined || raw.trim() === '') {\n return [];\n }\n return raw\n .split(',')\n .map(part => part.trim())\n .filter(part => part.length > 0);\n}\n\n/** Parses a positive-integer env var, falling back to `defaultValue` when unset/blank. */\nfunction parsePositiveInt(options: { envKey: string; raw: string | undefined; defaultValue: number }): number {\n const { envKey, raw, defaultValue } = options;\n if (raw === undefined || raw.trim() === '') {\n return defaultValue;\n }\n const value = Number(raw);\n if (!Number.isInteger(value) || value < 1) {\n throw new Error(`Environment variable ${envKey} must be a positive integer, got \"${raw}\"`);\n }\n return value;\n}\n\n/** Parses a boolean env var; anything but `true`/`false` throws instead of reading as `false`. */\nfunction parseBoolean(options: { envKey: string; raw: string | undefined; defaultValue: boolean }): boolean {\n const { envKey, raw, defaultValue } = options;\n if (raw === undefined || raw.trim() === '') {\n return defaultValue;\n }\n const value = raw.trim().toLowerCase();\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n throw new Error(`Environment variable ${envKey} must be \"true\" or \"false\", got \"${raw}\"`);\n}\n\n/** Parses `POSTGRES_SSL_MODE`. Unset/blank → `''`. Unknown values throw. */\nfunction parsePostgresSslMode(raw: string | undefined): string {\n if (!raw) {\n return '';\n }\n const mode = raw.trim();\n if (mode === '') {\n return '';\n }\n switch (mode) {\n case 'disable':\n case 'prefer':\n case 'require':\n case 'verify-ca':\n case 'verify-full':\n case 'no-verify':\n return mode;\n default:\n throw new Error(\n 'Environment variable POSTGRES_SSL_MODE must be one of disable, prefer, require, verify-ca, ' +\n `verify-full, no-verify; got \"${mode}\"`,\n );\n }\n}\n\n/**\n * Prefer `dist/_frontend` shipped in the npm tarball (npx / `pnpm start`).\n * Fall back to the monorepo sibling `../frontend/dist` (host-dev before a copy).\n */\nfunction resolveDefaultFrontendDir(): string {\n const packaged = path.join(PACKAGE_ROOT, 'dist', '_frontend');\n if (existsSync(path.join(packaged, 'index.html'))) {\n return packaged;\n }\n return path.join(PACKAGE_ROOT, '..', 'frontend', 'dist');\n}\n\nfunction resolveFrontendDir(): string {\n const override = getEnv('FRONTEND_DIR');\n if (override !== undefined && override.trim() !== '') {\n return path.resolve(override);\n }\n return resolveDefaultFrontendDir();\n}\n\n/** Absolute path from an optional env override; unset/blank → `undefined`. */\nfunction resolveOptionalPathEnv(envKey: string): string | undefined {\n const override = getEnv(envKey);\n if (override === undefined || override.trim() === '') {\n return undefined;\n }\n return path.resolve(override);\n}\n\n/**\n * Absolute SQLite file path for standalone mode.\n * Env: `SQLITE_PATH` (optional). Default: `{env-paths data}/db/db.sqlite`.\n */\nfunction resolveSqlitePath(appDataDir: string): string {\n const override = getEnv('SQLITE_PATH');\n if (override !== undefined && override.trim() !== '') {\n return path.resolve(override);\n }\n return path.join(appDataDir, 'db', 'db.sqlite');\n}\n\n/** Parent for local sandbox roots. Same env-paths data dir as SQLite (`{suffix:''}`). */\nfunction resolveLocalSandboxRootParent(appDataDir: string): string {\n return path.join(appDataDir, 'sandboxes');\n}\n\n/** Short tmp parent for Code Mode UDS socks (≤65 bytes after realpath). */\nfunction resolveCodeModeSocketParent(): string {\n return path.join(os.tmpdir(), 'tf_cms');\n}\n\n/** Redis peering URL for distributed mode. Env: `REDIS_URL`. */\nfunction resolveRedisUrl(): string {\n const raw = getEnv('REDIS_URL', { defaultValue: DEFAULT_REDIS_URL }) ?? DEFAULT_REDIS_URL;\n if (raw.trim() === '') {\n throw new Error('Environment variable REDIS_URL must be non-empty when STANDALONE=false.');\n }\n return raw;\n}\n\n/**\n * Postgres connection string for distributed mode.\n * Prefers `DATABASE_URL` when set (Railway / managed Postgres); otherwise builds from `POSTGRES_*`.\n */\nfunction resolvePostgresDatabaseUrl(): string {\n const databaseUrl = getEnv('DATABASE_URL');\n if (databaseUrl !== undefined && databaseUrl.trim() !== '') {\n return databaseUrl.trim();\n }\n\n const postgresUser = getEnv('POSTGRES_USER', { defaultValue: DEFAULT_POSTGRES_USER }) ?? DEFAULT_POSTGRES_USER;\n const postgresPassword =\n getEnv('POSTGRES_PASSWORD', { defaultValue: DEFAULT_POSTGRES_PASSWORD }) ?? DEFAULT_POSTGRES_PASSWORD;\n const postgresDb = getEnv('POSTGRES_DB', { defaultValue: DEFAULT_POSTGRES_DB }) ?? DEFAULT_POSTGRES_DB;\n const postgresHost = getEnv('POSTGRES_HOST', { defaultValue: DEFAULT_POSTGRES_HOST }) ?? DEFAULT_POSTGRES_HOST;\n const postgresPort = parsePositiveInt({\n envKey: 'POSTGRES_PORT',\n raw: getEnv('POSTGRES_PORT'),\n defaultValue: DEFAULT_POSTGRES_PORT,\n });\n const postgresSslMode = parsePostgresSslMode(getEnv('POSTGRES_SSL_MODE'));\n if (\n postgresUser.trim() === '' ||\n postgresPassword.trim() === '' ||\n postgresDb.trim() === '' ||\n postgresHost.trim() === ''\n ) {\n throw new Error(\n 'Set DATABASE_URL, or set non-empty POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, and POSTGRES_HOST when STANDALONE=false.',\n );\n }\n\n return buildPostgresConnectionString({\n user: postgresUser,\n password: postgresPassword,\n host: postgresHost,\n port: postgresPort,\n database: postgresDb,\n sslMode: postgresSslMode,\n });\n}\n\n/** Builds a Postgres connection URL from discrete `POSTGRES_*` parts. */\nfunction buildPostgresConnectionString(parts: {\n user: string;\n password: string;\n host: string;\n port: number;\n database: string;\n sslMode: string;\n}): string {\n let connectionString = `postgres://${encodeURIComponent(parts.user)}:${encodeURIComponent(parts.password)}@${parts.host}:${String(parts.port)}/${encodeURIComponent(parts.database)}`;\n if (parts.sslMode !== '') {\n connectionString += `?sslmode=${encodeURIComponent(parts.sslMode)}`;\n }\n return connectionString;\n}\n\nfunction resolveOIDCConfig(): OIDCConfig | undefined {\n const issuerUrl = getEnv('OIDC_ISSUER_URL');\n const clientId = getEnv('OIDC_CLIENT_ID');\n const clientSecret = getEnv('OIDC_CLIENT_SECRET');\n\n if (!issuerUrl && !clientId && !clientSecret) {\n return undefined;\n }\n if (!issuerUrl || !clientId || !clientSecret) {\n throw new Error(\n 'OIDC_ISSUER_URL, OIDC_CLIENT_ID, and OIDC_CLIENT_SECRET must all be set together, or all left unset ' +\n '(unset = fixed local admin identity, no IdP).',\n );\n }\n return {\n OIDC_ISSUER_URL: issuerUrl,\n OIDC_CLIENT_ID: clientId,\n OIDC_CLIENT_SECRET: clientSecret,\n OIDC_USER_REFERENCE_CLAIM:\n getEnv('OIDC_USER_REFERENCE_CLAIM', { defaultValue: DEFAULT_OIDC_USER_REFERENCE_CLAIM }) ??\n DEFAULT_OIDC_USER_REFERENCE_CLAIM,\n OIDC_USER_DISPLAY_NAME_CLAIM:\n getEnv('OIDC_USER_DISPLAY_NAME_CLAIM', { defaultValue: DEFAULT_OIDC_USER_DISPLAY_NAME_CLAIM }) ??\n DEFAULT_OIDC_USER_DISPLAY_NAME_CLAIM,\n OIDC_USER_ROLE_CLAIM:\n getEnv('OIDC_USER_ROLE_CLAIM', { defaultValue: DEFAULT_OIDC_USER_ROLE_CLAIM }) ?? DEFAULT_OIDC_USER_ROLE_CLAIM,\n OIDC_ADMIN_ROLE_VALUE:\n getEnv('OIDC_ADMIN_ROLE_VALUE', { defaultValue: DEFAULT_OIDC_ADMIN_ROLE_VALUE }) ?? DEFAULT_OIDC_ADMIN_ROLE_VALUE,\n OIDC_SCOPES: parseOidcScopes(getEnv('OIDC_SCOPES', { defaultValue: DEFAULT_OIDC_SCOPES }) ?? DEFAULT_OIDC_SCOPES),\n OIDC_ALLOWED_EMAILS: parseOidcAllowedEmails(getEnv('OIDC_ALLOWED_EMAILS')),\n };\n}\n\n// ============================================================================\n// CONFIGURATION TYPES\n// ============================================================================\n\nexport interface OIDCConfig {\n /** e.g. an Okta custom authorization server, or an Azure AD tenant's v2.0 endpoint. Env: `OIDC_ISSUER_URL`. */\n OIDC_ISSUER_URL: string;\n /** Client ID for the OIDC client;*/\n OIDC_CLIENT_ID: string;\n /** Client secret for the OIDC client*/\n OIDC_CLIENT_SECRET: string;\n /** Claim to be used as the user reference; e.g. \"sub\" or \"email\"\n * Optional; defaults to \"sub\"\n */\n OIDC_USER_REFERENCE_CLAIM: string;\n /** Claim used as the display name; e.g. \"name\" or \"preferred_username\".\n * Optional; defaults to \"name\". Missing/empty falls back to the user reference.\n * Env: `OIDC_USER_DISPLAY_NAME_CLAIM`.\n */\n OIDC_USER_DISPLAY_NAME_CLAIM: string;\n /** Claim to be used as the user role; e.g. \"role\" or \"groups\"\n * Optional; defaults to \"groups\"\n */\n OIDC_USER_ROLE_CLAIM: string;\n /** Value of the user role claim that will be used to grant admin access to the server\n * Case sensitive. Optional; defaults to \"admin\"\n */\n OIDC_ADMIN_ROLE_VALUE: string;\n /** Comma-separated OAuth scopes for the authorization request. Env: `OIDC_SCOPES`.\n * Optional; defaults to \"openid,profile,email\". Whitespace around entries is stripped.\n * Okta `groups` claims require the `groups` scope; Azure AD app roles typically omit it.\n */\n OIDC_SCOPES: string[];\n /**\n * Optional allowlist of emails that may sign in. Env: `OIDC_ALLOWED_EMAILS`.\n * Comma-separated exact addresses and/or `*` globs (e.g. `alice@acme.com,*@partner.com`).\n * Matching is case-insensitive against the ID token `email` claim. Empty = unrestricted.\n */\n OIDC_ALLOWED_EMAILS: string[];\n}\n\nexport interface SharedServerConfiguration {\n /** Log level. Env: `LOG_LEVEL`. */\n LOG_LEVEL: string;\n /** Log one line per HTTP request (except `/healthz`). Env: `ACCESS_LOGS`. Default true. */\n ACCESS_LOGS: boolean;\n /** Node environment. Env: `NODE_ENV`. */\n NODE_ENV: string | undefined;\n /** HTTP port the server listens on. Env: `PORT`. */\n PORT: number;\n /** HTTP bind address. Env: `HOST`. Default `localhost`; production images use `0.0.0.0`. */\n HOST: string;\n /** Peering identity embedded in the turn ids this process mints; `local` in standalone mode. */\n EXECUTOR_ID: string;\n /**\n * Optional override for the model catalog YAML (discovery presets for\n * GET /catalogs/model-providers). When unset, the catalog inlined at build\n * time is used. Env: `MODEL_CATALOG_PATH`.\n */\n MODEL_CATALOG_PATH: string | undefined;\n /**\n * Optional override for the MCP catalog YAML (discovery presets for\n * GET /catalogs/mcp-servers). When unset, the catalog inlined at build\n * time is used. Env: `MCP_CATALOG_PATH`.\n */\n MCP_CATALOG_PATH: string | undefined;\n /**\n * Optional override for the skill catalog YAML (discovery presets for\n * GET /catalogs/skills). When unset, the catalog inlined at build\n * time is used. Env: `SKILL_CATALOG_PATH`.\n */\n SKILL_CATALOG_PATH: string | undefined;\n /**\n * Optional override for the sandbox catalog YAML (discovery presets for\n * GET /catalogs/sandbox-providers). When unset, the catalog inlined at build\n * time is used. Env: `SANDBOX_CATALOG_PATH`.\n */\n SANDBOX_CATALOG_PATH: string | undefined;\n /**\n * Frontend build served alongside the API; a missing directory leaves the server API-only.\n * Env: `FRONTEND_DIR`. Default: packaged `dist/_frontend` (npx tarball) or\n * monorepo `packages/frontend/dist` — always absolute, independent of CWD.\n */\n FRONTEND_DIR: string;\n /** Max milliseconds for one MCP request. Env: `MCP_REQUEST_TIMEOUT_MS`. Default 4 minutes. */\n MCP_REQUEST_TIMEOUT_MS: number;\n /** Max milliseconds for an MCP transport connection. Env: `MCP_CONNECT_TIMEOUT_MS`. Default 30 seconds. */\n MCP_CONNECT_TIMEOUT_MS: number;\n /**\n * Client name used for Dynamic Client Registration (DCR) of MCP servers.\n * This is the client name shown on authorization-server consent screens.\n * Env: `MCP_DCR_OAUTH_CLIENT_NAME`. Default: \"truefoundry-harness\".\n */\n MCP_DCR_OAUTH_CLIENT_NAME: string;\n /**\n * Max bytes for a single file download out of the sandbox.\n * Env: `SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD`. Default 20 MB (same as gateway).\n */\n SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD: number;\n /**\n * Max bytes for an HTTP request body. Env: `MAX_REQUEST_BODY_BYTES`. Default 30 MB.\n */\n MAX_REQUEST_BODY_BYTES: number;\n /**\n * Max seconds to wait for turn cancellation + connection drain on SIGTERM/SIGINT.\n * Env: `GRACEFUL_TIMEOUT_SECONDS`. Default 30.\n */\n GRACEFUL_TIMEOUT_SECONDS: number;\n /**\n * Max seconds a single turn may execute before it is cancelled with\n * `server-execution-timeout`. Env: `SERVER_EXECUTION_TIMEOUT_SECONDS`. Default 600 (10 minutes).\n */\n SERVER_EXECUTION_TIMEOUT_SECONDS: number;\n /**\n * TTL for a running turn's resumable event stream.\n * Env: `TURN_STREAM_TTL_SECONDS`. Default execution timeout + 300.\n */\n TURN_STREAM_TTL_SECONDS: number;\n /**\n * TTL retained after `turn.done` so subscribers can drain remaining events.\n * Env: `TURN_STREAM_POST_COMPLETION_TTL_SECONDS`. Default 300.\n */\n TURN_STREAM_POST_COMPLETION_TTL_SECONDS: number;\n /**\n * Max ms to keep a turn subscription open.\n * Env: `TURN_SUBSCRIBE_TIMEOUT_MS`. Default 600000.\n */\n TURN_SUBSCRIBE_TIMEOUT_MS: number;\n /**\n * Max ms to wait for a peer executor's reply before failing with 424.\n * Env: `REDIS_REQUEST_REPLY_TIMEOUT_MS`. Default 60000.\n * Only used when a Redis client is wired (distributed mode).\n */\n REDIS_REQUEST_REPLY_TIMEOUT_MS: number;\n /**\n * How often this process refreshes its peering heartbeat key.\n * Env: `REDIS_REQUEST_REPLY_HEARTBEAT_INTERVAL_MS`. Default 5000.\n * Only used when a Redis client is wired (distributed mode).\n */\n REDIS_REQUEST_REPLY_HEARTBEAT_INTERVAL_MS: number;\n /**\n * TTL for reply values so abandoned reply keys are reclaimed.\n * Env: `REDIS_REQUEST_REPLY_REPLY_TTL_MS`. Default 120000.\n * Only used when a Redis client is wired (distributed mode).\n */\n REDIS_REQUEST_REPLY_REPLY_TTL_MS: number;\n /**\n * Sleep between reply poll attempts while waiting on a peer.\n * Env: `REDIS_REQUEST_REPLY_POLL_INTERVAL_MS`. Default 500.\n * Only used when a Redis client is wired (distributed mode).\n */\n REDIS_REQUEST_REPLY_POLL_INTERVAL_MS: number;\n /**\n * Public base URL used as the origin of MCP OAuth and OIDC callbacks.\n * Optional at boot; MCP OAuth and OIDC callback construction fail if empty\n * outside standalone development. Env: `PUBLIC_BASE_URL`.\n */\n PUBLIC_BASE_URL: string;\n /**\n * Base URL the controller uses to reach the server's HTTP API when it runs as its\n * own process (`STANDALONE=false`, `dist/controller-main.js`). The control loops call\n * the server over HTTP(S); when `TRUEFORGE_MTLS_ENABLED` is true the controller upgrades an\n * `http://` URL to `https://` and presents the client cert. Env: `SERVER_URL`.\n * Default: `http://localhost:$PORT`, so in-cluster deployments MUST point this at\n * the server Service. Unused in standalone mode, where the server process owns the\n * controller and targets itself on localhost.\n */\n SERVER_URL: string;\n /**\n * Mutual TLS for this process's HTTPS listener and controller→server. When true, serves HTTPS\n * with client-cert enforcement (except `/healthz`) and the controller presents a client cert.\n * Env: `TRUEFORGE_MTLS_ENABLED`. Default false.\n */\n TRUEFORGE_MTLS_ENABLED: boolean;\n /**\n * Directory holding the TLS cert triple (`tls.crt` / `tls.key` / `ca.crt`) when\n * `TRUEFORGE_MTLS_ENABLED` is true. Env: `TRUEFORGE_MTLS_CERTS_DIR`. Default `/etc/tls`.\n */\n TRUEFORGE_MTLS_CERTS_DIR: string;\n}\n\nexport type StandaloneServerConfiguration = SharedServerConfiguration & {\n /**\n * Single-process topology: SQLite persistence, no Redis / executor peering.\n * Env: `STANDALONE`. Default: true.\n */\n STANDALONE: true;\n /**\n * Absolute SQLite database file path.\n * Env: `SQLITE_PATH` (optional). Default: env-paths data dir + `db/db.sqlite`.\n */\n SQLITE_PATH: string;\n /**\n * Parent directory for local sandbox roots (ULID children).\n * Derived: `{env-paths data}/sandboxes`.\n */\n LOCAL_SANDBOX_ROOT_PARENT: string;\n /**\n * Parent directory for Code Mode UDS sockets (`tf_cms` under os.tmpdir()).\n * Caller prepares/removes this directory; must stay ≤65 bytes after realpath.\n */\n CODE_MODE_SOCKET_PARENT: string;\n};\n\nexport type DistributedServerConfiguration = SharedServerConfiguration & {\n /**\n * Multi-replica topology: Postgres persistence + Redis executor peering.\n * Env: `STANDALONE`. Default: true (so this branch requires an explicit `false`).\n */\n STANDALONE: false;\n /**\n * Postgres connection string. Env: `DATABASE_URL` when set; otherwise built from `POSTGRES_*`\n * (including optional `POSTGRES_SSL_MODE` as `sslmode`).\n * Form: `postgres://USER:PASSWORD@HOST:PORT/DB` (or `postgresql://…`) with user/password URL-encoded.\n */\n DATABASE_URL: string;\n /** Max connections in the `pg` Pool. Env: `DATABASE_POOL_MAX`. Default 10. */\n DATABASE_POOL_MAX: number;\n /**\n * Postgres `statement_timeout` for app and migrations (same pool).\n * Env: `POSTGRES_STATEMENT_TIMEOUT_MS`. Default 60000.\n */\n POSTGRES_STATEMENT_TIMEOUT_MS: number;\n /**\n * Postgres `idle_in_transaction_session_timeout` for app and migrations (same pool).\n * Env: `POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS`. Default 60000.\n */\n POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS: number;\n /** Peering URL shared by all replicas. Env: `REDIS_URL`. Default `redis://localhost:6379`. */\n REDIS_URL: string;\n /**\n * OIDC configuration for server authentication.\n * Undefined means browser login is disabled.\n */\n OIDC: OIDCConfig | undefined;\n /**\n * When set, models/MCP/agents are backed by the TrueFoundry ServiceFoundry server with the\n * caller's token. Unset = local Postgres stores. Mutually exclusive with OIDC.\n * Env: `TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL`.\n */\n TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL: string | undefined;\n /** Max ms for non-agent ServiceFoundry HTTP calls. Env: `TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_TIMEOUT_MS`. Default 10000. */\n TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_TIMEOUT_MS: number;\n /** Max ms for agent CRUD ServiceFoundry HTTP calls. Env: `TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_AGENT_TIMEOUT_MS`. Default 3000. */\n TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_AGENT_TIMEOUT_MS: number;\n /**\n * Present this pod's client certificate on outbound calls to the ServiceFoundry server (internal\n * mutual TLS) and upgrade a mesh-direct peer URL from http to https. Off by default, so an\n * unconfigured deployment keeps calling over plain HTTP exactly as before.\n * Env: `TRUEFOUNDRY_MTLS_ENABLED`. Default false.\n */\n TRUEFOUNDRY_MTLS_ENABLED: boolean;\n /**\n * Directory holding the internal mTLS material used when `TRUEFOUNDRY_MTLS_ENABLED` is true — the\n * cert triple `tls.crt` / `tls.key` / `ca.crt`, so one chart value configures every component.\n * Env: `TRUEFOUNDRY_MTLS_CERTS_DIR`. Default `/etc/tls/truefoundry`.\n */\n TRUEFOUNDRY_MTLS_CERTS_DIR: string;\n};\n\nexport type ServerConfiguration = StandaloneServerConfiguration | DistributedServerConfiguration;\n\n// ============================================================================\n// CONFIGURATION VALUES\n// ============================================================================\n\nconst serverExecutionTimeoutSeconds = parsePositiveInt({\n envKey: 'SERVER_EXECUTION_TIMEOUT_SECONDS',\n raw: getEnv('SERVER_EXECUTION_TIMEOUT_SECONDS'),\n defaultValue: 600,\n});\n\nconst standalone = parseBoolean({\n envKey: 'STANDALONE',\n raw: getEnv('STANDALONE'),\n defaultValue: true,\n});\n\nconst appDataDirSuffix = getEnv('APP_DATA_DIR_SUFFIX', { defaultValue: '' }) ?? '';\nconst appDataDir = envPaths(ENV_PATHS_APP_NAME, { suffix: appDataDirSuffix }).data;\n\nconst port = parsePort(getEnv('PORT'));\nconst host = getEnv('HOST', { defaultValue: DEFAULT_HOST }) ?? DEFAULT_HOST;\n\nconst shared: SharedServerConfiguration = {\n LOG_LEVEL: getEnv('LOG_LEVEL', { defaultValue: 'info' }) ?? 'info',\n ACCESS_LOGS: parseBoolean({ envKey: 'ACCESS_LOGS', raw: getEnv('ACCESS_LOGS'), defaultValue: true }),\n NODE_ENV: getEnv('NODE_ENV'),\n PORT: port,\n HOST: host,\n EXECUTOR_ID: standalone ? LOCAL_EXECUTOR_ID : randomAlphanumeric(6),\n MODEL_CATALOG_PATH: resolveOptionalPathEnv('MODEL_CATALOG_PATH'),\n MCP_CATALOG_PATH: resolveOptionalPathEnv('MCP_CATALOG_PATH'),\n SKILL_CATALOG_PATH: resolveOptionalPathEnv('SKILL_CATALOG_PATH'),\n SANDBOX_CATALOG_PATH: resolveOptionalPathEnv('SANDBOX_CATALOG_PATH'),\n FRONTEND_DIR: resolveFrontendDir(),\n\n MCP_REQUEST_TIMEOUT_MS: parsePositiveInt({\n envKey: 'MCP_REQUEST_TIMEOUT_MS',\n raw: getEnv('MCP_REQUEST_TIMEOUT_MS'),\n defaultValue: 4 * 60 * 1000,\n }),\n MCP_CONNECT_TIMEOUT_MS: parsePositiveInt({\n envKey: 'MCP_CONNECT_TIMEOUT_MS',\n raw: getEnv('MCP_CONNECT_TIMEOUT_MS'),\n defaultValue: 30 * 1000,\n }),\n MCP_DCR_OAUTH_CLIENT_NAME:\n getEnv('MCP_DCR_OAUTH_CLIENT_NAME', { defaultValue: 'truefoundry-harness' }) ?? 'truefoundry-harness',\n SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD: parsePositiveInt({\n envKey: 'SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD',\n raw: getEnv('SANDBOX_FILE_MAX_BYTES_FOR_DOWNLOAD'),\n defaultValue: 20_971_520,\n }),\n MAX_REQUEST_BODY_BYTES: parsePositiveInt({\n envKey: 'MAX_REQUEST_BODY_BYTES',\n raw: getEnv('MAX_REQUEST_BODY_BYTES'),\n defaultValue: DEFAULT_MAX_REQUEST_BODY_BYTES,\n }),\n GRACEFUL_TIMEOUT_SECONDS: parsePositiveInt({\n envKey: 'GRACEFUL_TIMEOUT_SECONDS',\n raw: getEnv('GRACEFUL_TIMEOUT_SECONDS'),\n defaultValue: 30,\n }),\n SERVER_EXECUTION_TIMEOUT_SECONDS: serverExecutionTimeoutSeconds,\n TURN_STREAM_TTL_SECONDS: parsePositiveInt({\n envKey: 'TURN_STREAM_TTL_SECONDS',\n raw: getEnv('TURN_STREAM_TTL_SECONDS'),\n defaultValue: serverExecutionTimeoutSeconds + 300,\n }),\n TURN_STREAM_POST_COMPLETION_TTL_SECONDS: parsePositiveInt({\n envKey: 'TURN_STREAM_POST_COMPLETION_TTL_SECONDS',\n raw: getEnv('TURN_STREAM_POST_COMPLETION_TTL_SECONDS'),\n defaultValue: 300,\n }),\n TURN_SUBSCRIBE_TIMEOUT_MS: parsePositiveInt({\n envKey: 'TURN_SUBSCRIBE_TIMEOUT_MS',\n raw: getEnv('TURN_SUBSCRIBE_TIMEOUT_MS'),\n defaultValue: 600_000,\n }),\n REDIS_REQUEST_REPLY_TIMEOUT_MS: parsePositiveInt({\n envKey: 'REDIS_REQUEST_REPLY_TIMEOUT_MS',\n raw: getEnv('REDIS_REQUEST_REPLY_TIMEOUT_MS'),\n defaultValue: 60_000,\n }),\n REDIS_REQUEST_REPLY_HEARTBEAT_INTERVAL_MS: parsePositiveInt({\n envKey: 'REDIS_REQUEST_REPLY_HEARTBEAT_INTERVAL_MS',\n raw: getEnv('REDIS_REQUEST_REPLY_HEARTBEAT_INTERVAL_MS'),\n defaultValue: 5_000,\n }),\n REDIS_REQUEST_REPLY_REPLY_TTL_MS: parsePositiveInt({\n envKey: 'REDIS_REQUEST_REPLY_REPLY_TTL_MS',\n raw: getEnv('REDIS_REQUEST_REPLY_REPLY_TTL_MS'),\n defaultValue: 120_000,\n }),\n REDIS_REQUEST_REPLY_POLL_INTERVAL_MS: parsePositiveInt({\n envKey: 'REDIS_REQUEST_REPLY_POLL_INTERVAL_MS',\n raw: getEnv('REDIS_REQUEST_REPLY_POLL_INTERVAL_MS'),\n defaultValue: 500,\n }),\n PUBLIC_BASE_URL: getEnv('PUBLIC_BASE_URL', { defaultValue: '' }) ?? '',\n SERVER_URL:\n getEnv('SERVER_URL', { defaultValue: `http://localhost:${String(port)}` }) ?? `http://localhost:${String(port)}`,\n TRUEFORGE_MTLS_ENABLED: parseBoolean({\n envKey: 'TRUEFORGE_MTLS_ENABLED',\n raw: getEnv('TRUEFORGE_MTLS_ENABLED'),\n defaultValue: false,\n }),\n TRUEFORGE_MTLS_CERTS_DIR: getEnv('TRUEFORGE_MTLS_CERTS_DIR', { defaultValue: '/etc/tls' }) ?? '/etc/tls',\n};\n\nconst configuration: ServerConfiguration = standalone\n ? {\n ...shared,\n STANDALONE: true,\n SQLITE_PATH: resolveSqlitePath(appDataDir),\n LOCAL_SANDBOX_ROOT_PARENT: resolveLocalSandboxRootParent(appDataDir),\n CODE_MODE_SOCKET_PARENT: resolveCodeModeSocketParent(),\n }\n : {\n ...shared,\n STANDALONE: false,\n DATABASE_URL: resolvePostgresDatabaseUrl(),\n DATABASE_POOL_MAX: parsePositiveInt({\n envKey: 'DATABASE_POOL_MAX',\n raw: getEnv('DATABASE_POOL_MAX'),\n defaultValue: 10,\n }),\n POSTGRES_STATEMENT_TIMEOUT_MS: parsePositiveInt({\n envKey: 'POSTGRES_STATEMENT_TIMEOUT_MS',\n raw: getEnv('POSTGRES_STATEMENT_TIMEOUT_MS'),\n defaultValue: 60_000,\n }),\n POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS: parsePositiveInt({\n envKey: 'POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS',\n raw: getEnv('POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS'),\n defaultValue: 60_000,\n }),\n REDIS_URL: resolveRedisUrl(),\n OIDC: resolveOIDCConfig(),\n TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL: getEnv('TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL', { required: false }),\n TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_TIMEOUT_MS: parsePositiveInt({\n envKey: 'TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_TIMEOUT_MS',\n raw: getEnv('TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_TIMEOUT_MS'),\n defaultValue: 10_000,\n }),\n TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_AGENT_TIMEOUT_MS: parsePositiveInt({\n envKey: 'TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_AGENT_TIMEOUT_MS',\n raw: getEnv('TRUEFOUNDRY_SERVICEFOUNDRY_HTTP_AGENT_TIMEOUT_MS'),\n defaultValue: 3_000,\n }),\n TRUEFOUNDRY_MTLS_ENABLED: parseBoolean({\n envKey: 'TRUEFOUNDRY_MTLS_ENABLED',\n raw: getEnv('TRUEFOUNDRY_MTLS_ENABLED'),\n defaultValue: false,\n }),\n TRUEFOUNDRY_MTLS_CERTS_DIR:\n getEnv('TRUEFOUNDRY_MTLS_CERTS_DIR', { defaultValue: '/etc/tls/truefoundry' }) ?? '/etc/tls/truefoundry',\n };\n\nexport function isOidcConfigured(\n value: ServerConfiguration,\n): value is DistributedServerConfiguration & { OIDC: OIDCConfig } {\n return !value.STANDALONE && value.OIDC !== undefined;\n}\n\n/**\n * TrueFoundry mode: ServiceFoundry-backed models/MCP/agents. Only available on\n * distributed config when `TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL` is set.\n */\nexport function isTrueFoundryModeEnabled(\n config: ServerConfiguration = configuration,\n): config is DistributedServerConfiguration & { TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL: string } {\n return !config.STANDALONE && config.TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL !== undefined;\n}\n\n/** Runtime auth/integration mode for this process. */\nexport enum TrueForgeAuthMode {\n Standalone = 'standalone',\n Oidc = 'oidc',\n TrueFoundry = 'truefoundry',\n}\n\n/**\n * Resolve the active {@link TrueForgeAuthMode} from configuration.\n * TrueFoundry wins over OIDC when both would otherwise be set (startup already rejects that combo).\n */\nexport function getTrueForgeAuthMode(config: ServerConfiguration = configuration): TrueForgeAuthMode {\n if (isTrueFoundryModeEnabled(config)) {\n return TrueForgeAuthMode.TrueFoundry;\n }\n if (isOidcConfigured(config)) {\n return TrueForgeAuthMode.Oidc;\n }\n return TrueForgeAuthMode.Standalone;\n}\n\n// TrueFoundry authenticates each caller with their own gateway token, so browser SSO must be off.\nif (isTrueFoundryModeEnabled(configuration) && isOidcConfigured(configuration)) {\n throw new Error(\n 'TRUEFOUNDRY_SERVICEFOUNDRY_SERVER_URL (TrueFoundry mode) and OIDC (SSO) cannot both be enabled at once.',\n );\n}\n\n/**\n * Public origin for OAuth callbacks.\n * Standalone (non-development) → `http://localhost:$PORT`; otherwise `PUBLIC_BASE_URL`\n * (required in development and distributed; throws if empty).\n */\nexport function getPublicBaseUrl(config: ServerConfiguration = configuration): string {\n if (config.STANDALONE && config.NODE_ENV !== 'development') {\n return `http://localhost:${String(config.PORT)}`;\n }\n if (config.PUBLIC_BASE_URL === '') {\n throw new Error('PUBLIC_BASE_URL is required for OIDC callbacks but was empty');\n }\n return config.PUBLIC_BASE_URL;\n}\n\nexport default configuration;\n","import { TrueForge } from '@truefoundry/trueforge-sdk';\nimport type { Logger } from 'winston';\nimport { Controller } from './controller/Controller';\nimport { scheduleDispatchLoop } from './controller/scheduleDispatch';\nimport type { IScheduleStore } from './db/scheduleStore';\nimport type { WithTransaction } from './db/transaction';\nimport { createTlsFetch, normalizeTlsUrl, type TlsOptions } from './http/tls';\n\nfunction createScheduleApiClient(params: { baseUrl: string; tls: TlsOptions }): TrueForge {\n const baseUrl = normalizeTlsUrl({ url: params.baseUrl, enabled: params.tls.enabled });\n const fetchImpl = createTlsFetch(params.tls);\n return new TrueForge({\n baseUrl,\n auth: false,\n ...(fetchImpl !== undefined ? { fetch: fetchImpl } : {}),\n });\n}\n\n/**\n * The loops the controller runs.\n */\nexport function createController<TTransaction>(params: {\n scheduleStore: IScheduleStore<TTransaction>;\n withTransaction: WithTransaction<TTransaction>;\n logger: Logger;\n baseUrl: string;\n tls?: TlsOptions;\n}): Controller {\n const { scheduleStore, withTransaction, logger, baseUrl } = params;\n const tls = params.tls ?? { enabled: false, dir: '' };\n return new Controller({\n loops: [\n scheduleDispatchLoop({\n scheduleStore,\n client: createScheduleApiClient({ baseUrl, tls }),\n withTransaction,\n logger,\n }),\n ],\n logger,\n });\n}\n\n/**\n * Runs the controller: starts the loops and drains them on SIGTERM/SIGINT.\n */\nexport function runController<TTransaction>(params: {\n scheduleStore: IScheduleStore<TTransaction>;\n withTransaction: WithTransaction<TTransaction>;\n logger: Logger;\n baseUrl: string;\n tls?: TlsOptions;\n gracefulTimeoutSeconds: number;\n /** Releases what the caller opened for the loops, e.g. its database pool. */\n onStopped?: () => Promise<void>;\n}): Controller {\n const { logger, gracefulTimeoutSeconds, onStopped } = params;\n const controller = createController(params);\n controller.start();\n\n let shuttingDown = false;\n const shutdown = async (signal: NodeJS.Signals) => {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n logger.info(`Received ${signal}, stopping control loops`);\n\n // Passes only hold short transactions, so the deadline should never elapse.\n setTimeout(() => {\n logger.warn(`Controller drain timed out after ${String(gracefulTimeoutSeconds)}s, exiting`);\n process.exit(1);\n }, gracefulTimeoutSeconds * 1000).unref();\n\n await controller.stop();\n await onStopped?.();\n process.exit(0);\n };\n process.on('SIGTERM', signal => {\n void shutdown(signal);\n });\n process.on('SIGINT', signal => {\n void shutdown(signal);\n });\n\n return controller;\n}\n","/**\n * The controller: a set of periodic control loops and the timers that drive them.\n *\n * Loops are independent — each has its own interval, its own re-entrancy guard, and\n * its own error boundary, so a slow or failing loop cannot stall another.\n *\n * The controller runs in exactly ONE process per database. In standalone mode that is\n * the server itself; when `STANDALONE=false` it is the dedicated single-replica\n * process. Loops are written assuming this.\n */\nimport type { Logger } from 'winston';\n\n/** Reason passed to {@link AbortController.abort} when {@link Controller.stop} runs. */\nexport const CONTROLLER_STOPPED = 'controller-stopped';\n\n/** One periodic unit of work. */\nexport interface ControlLoop {\n /** Stable identifier; appears in logs and keys the controller's per-loop state. */\n readonly name: string;\n /** Gap between passes. Each loop chooses its own. */\n readonly intervalMs: number;\n /**\n * One pass. May throw — the controller logs it and keeps ticking, so a pass must\n * leave nothing half-applied that a later pass cannot recover from.\n */\n tick(signal: AbortSignal): Promise<void>;\n}\n\ninterface LoopState {\n timer: NodeJS.Timeout | undefined;\n /** In-flight pass, if any. Also the re-entrancy guard. */\n pass: Promise<void> | undefined;\n}\n\nexport class Controller {\n readonly #loops: readonly ControlLoop[];\n readonly #logger: Logger;\n readonly #state = new Map<string, LoopState>();\n readonly #abortController = new AbortController();\n\n constructor(params: { loops: readonly ControlLoop[]; logger: Logger }) {\n const names = new Set<string>();\n for (const loop of params.loops) {\n if (names.has(loop.name)) {\n throw new Error(`Duplicate control loop name: ${loop.name}`);\n }\n names.add(loop.name);\n }\n this.#loops = params.loops;\n this.#logger = params.logger;\n }\n\n /** Shared abort signal; aborted by {@link stop}. */\n get signal(): AbortSignal {\n return this.#abortController.signal;\n }\n\n /**\n * Starts every loop, each with an immediate first pass so a restart does not leave\n * work waiting a full interval.\n */\n start(): void {\n if (this.#abortController.signal.aborted || this.#state.size > 0) {\n return;\n }\n for (const loop of this.#loops) {\n const state: LoopState = { timer: undefined, pass: undefined };\n this.#state.set(loop.name, state);\n state.timer = setInterval(() => {\n void this.#tick(loop);\n }, loop.intervalMs);\n void this.#tick(loop);\n }\n this.#logger.info('Controller started', { loops: this.#loops.map(loop => loop.name) });\n }\n\n /**\n * Stops every loop: clears timers, aborts the shared signal, then waits for\n * in-flight passes to finish. Idempotent.\n */\n async stop(): Promise<void> {\n if (this.#abortController.signal.aborted) {\n return;\n }\n this.#abortController.abort(CONTROLLER_STOPPED);\n const passes: Promise<void>[] = [];\n for (const state of this.#state.values()) {\n if (state.timer) {\n clearInterval(state.timer);\n state.timer = undefined;\n }\n if (state.pass) {\n passes.push(state.pass);\n }\n }\n await Promise.all(passes);\n this.#logger.info('Controller stopped');\n }\n\n /**\n * One pass of one loop: never throws, never overlaps itself.\n *\n * A pass that outlives its interval skips the next tick rather than running twice.\n * Whatever it did not finish is picked up by the following pass — the same path a\n * restart takes.\n */\n async #tick(loop: ControlLoop): Promise<void> {\n const state = this.#state.get(loop.name);\n const { signal } = this.#abortController;\n // `state` is always set before the first #tick for that loop; guard is for types.\n if (!state || signal.aborted || state.pass) {\n return;\n }\n\n const pass = (async () => {\n try {\n await loop.tick(signal);\n } catch (error) {\n if (signal.aborted) {\n return;\n }\n this.#logger.error('Control loop pass failed', { loop: loop.name, error });\n }\n })();\n\n state.pass = pass;\n try {\n await pass;\n } finally {\n state.pass = undefined;\n }\n }\n}\n","/**\n * DB-backed schedules and their runs: one `schedule` row per cron binding, plus a\n * `schedule_run` row per run (pending or historical).\n *\n * One store covers both tables because they are never used apart — the dispatch\n * path needs a scheduled run and its schedule in the same query, and every schedule\n * mutation touches the pending run in the same transaction.\n *\n * Transactions are route-owned (see `WithTransaction`): a store method never opens\n * one. Create/resume/manifest-edit must pass the same transaction to the schedule\n * write and the run write, or a schedule can end up active with no pending run —\n * the silent-dead-schedule failure mode.\n *\n * Implementations: PostgresScheduleStore and SqliteScheduleStore.\n */\nimport type { CreatedBySubject, TokenPagination } from '@truefoundry/trueforge-core/agent-session';\nimport { randomUUID } from 'node:crypto';\nimport {\n ScheduleManifestSchema,\n type ScheduleManifest,\n type ScheduleRunStatus,\n type ScheduleStatus,\n} from '../schemas/schedule';\n\n/**\n * `sched-<unixSeconds>` or `manual-<token>` — one name per trigger time, which is what makes\n * `schedule_run_name_idx` reject a duplicated trigger.\n */\nexport function cronRunName(scheduledFor: Date): string {\n return `sched-${String(Math.floor(scheduledFor.getTime() / 1000))}`;\n}\n\n/** Unique run name for an immediate (run-now) trigger. */\nexport function manualRunName(): string {\n return `manual-${randomUUID()}`;\n}\n\nexport interface ScheduleRecord {\n id: string;\n tenant_id: string;\n /** Immutable FK to `agent.id`. */\n agent_id: string;\n /** Create-time snapshot of registry agent name. */\n agent_name: string;\n /** Slug-shaped label, unique per agent (`schedule_name_uq`). */\n name: string;\n manifest: ScheduleManifest;\n status: ScheduleStatus;\n created_by_subject: CreatedBySubject;\n /** ISO-8601 UTC instant. */\n created_at: string;\n /** ISO-8601 UTC instant. */\n updated_at: string;\n}\n\nexport interface ScheduleRunRecord {\n id: string;\n tenant_id: string;\n schedule_id: string;\n name: string;\n /** ISO-8601 UTC instant this run was scheduled for. Preserved even when `missed`. */\n scheduled_for: string;\n status: ScheduleRunStatus;\n created_by_subject: CreatedBySubject;\n triggered_at: string | null;\n created_at: string;\n updated_at: string;\n}\n\n/** Schedule row plus the pending run after a create/update that syncs it. */\nexport interface ScheduleWriteResult {\n schedule: ScheduleRecord;\n /** Set when the schedule is active; otherwise undefined (paused adds no pending run). */\n pendingRun: ScheduleRunRecord | undefined;\n}\n\n/** A scheduled run plus the schedule that owns it. */\nexport interface ScheduleDispatchItem {\n run: ScheduleRunRecord;\n schedule: ScheduleRecord;\n}\n\n/**\n * Re-parse persisted manifest JSON so schema defaults materialize. Rows written\n * before a manifest field existed omit it on disk; readers must not assume presence.\n */\nexport function parseStoredScheduleManifest(manifest: unknown): ScheduleManifest {\n return ScheduleManifestSchema.parse(manifest);\n}\n\nexport interface ListSchedulesInput {\n tenant_id: string;\n limit: number;\n page_token: string | undefined;\n /** When set, only schedules for these agent names */\n agent_names: readonly string[] | undefined;\n /** When set, match creator or agent binding. Empty `agent_ids` means creator-only. */\n created_by_or_agent_ids:\n | {\n created_by_subject_id: string;\n agent_ids: readonly string[];\n }\n | undefined;\n}\n\n/** User-facing run listing, scoped to one schedule. */\nexport interface ListRunsInput {\n tenant_id: string;\n schedule_id: string;\n}\n\nexport interface GetScheduleInput {\n tenant_id: string;\n id: string;\n}\n\nexport interface CreateScheduleInput {\n tenant_id: string;\n agent_id: string;\n agent_name: string;\n name: string;\n manifest: ScheduleManifest;\n created_by_subject: CreatedBySubject;\n /** Instant used to compute the first pending run when status is active. */\n runFrom: Date;\n}\n\n/** Replaces `name` + `manifest` for an existing schedule keyed by immutable id. */\nexport interface UpdateScheduleInput {\n tenant_id: string;\n id: string;\n name: string;\n manifest: ScheduleManifest;\n /**\n * Instant used to compute the next pending run when a sync runs (status/cron/timezone\n * change) and the schedule is active.\n */\n runFrom: Date;\n}\nexport interface DeleteScheduleInput {\n tenant_id: string;\n id: string;\n}\n\nexport interface CreateScheduleRunInput {\n tenant_id: string;\n schedule_id: string;\n name: string;\n scheduled_for: Date;\n created_by_subject: CreatedBySubject;\n status: ScheduleRunStatus;\n triggered_at?: Date | null;\n}\n\nexport interface ListScheduledRunsInput {\n until: Date;\n limit: number;\n}\n\nexport interface GetRunInput {\n tenant_id: string;\n /** Immutable run id. */\n id: string;\n}\n\nexport interface GetScheduledRunForInput {\n tenant_id: string;\n schedule_id: string;\n}\n\nexport interface UpdateScheduleRunStatusInput {\n tenant_id: string;\n id: string;\n status: ScheduleRunStatus;\n}\n\nexport class ScheduleRunConflictError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ScheduleRunConflictError';\n }\n}\n\n/** Schedule name already taken for this agent — violates `schedule_name_uq`. */\nexport class ScheduleNameConflictError extends Error {\n readonly tenant_id: string;\n readonly agent_name: string;\n readonly schedule_name: string;\n\n constructor(\n { tenant_id, agent_name, name }: { tenant_id: string; agent_name: string; name: string },\n options?: ErrorOptions,\n ) {\n super(`Schedule name already exists for agent ${agent_name}: ${name}`, options);\n this.name = 'ScheduleNameConflictError';\n this.tenant_id = tenant_id;\n this.agent_name = agent_name;\n this.schedule_name = name;\n }\n}\n\n/**\n * Pending run is replaced only when `status`, `cron`, or `timezone` change.\n * `name` and `task` edits leave the pending row alone.\n */\nexport function shouldSyncPendingRun(\n previous: Pick<ScheduleRecord, 'status' | 'manifest'>,\n next: Pick<ScheduleRecord, 'status' | 'manifest'>,\n): boolean {\n return (\n previous.status !== next.status ||\n previous.manifest.cron !== next.manifest.cron ||\n previous.manifest.timezone !== next.manifest.timezone\n );\n}\n\nexport interface IScheduleStore<TTransaction = never> {\n // --- schedule ---\n getSchedule(input: GetScheduleInput, transaction?: TTransaction): Promise<ScheduleRecord | undefined>;\n /**\n * Load one schedule while holding a row lock for the lifetime of `transaction`.\n * Postgres: `SELECT … FOR UPDATE`. SQLite: plain read under a write txn.\n */\n getScheduleForUpdate(input: GetScheduleInput, transaction: TTransaction): Promise<ScheduleRecord | undefined>;\n /**\n * Inserts a schedule (`status` mirrors `manifest.status`) and syncs the pending run\n * in the same call: active adds the next run from `runFrom`; paused adds nothing.\n */\n createScheduleAndRun(input: CreateScheduleInput, transaction?: TTransaction): Promise<ScheduleWriteResult>;\n /**\n * Updates a schedule, then syncs the pending run only when `status`, `cron`, or\n * `timezone` change. `name` / `task` edits leave the pending row alone.\n * Returns undefined if the schedule is gone.\n */\n updateScheduleAndRun(\n input: UpdateScheduleInput,\n transaction?: TTransaction,\n ): Promise<ScheduleWriteResult | undefined>;\n /** Deletes by immutable id; runs cascade. Idempotent if already missing. */\n deleteSchedule(input: DeleteScheduleInput, transaction?: TTransaction): Promise<void>;\n listSchedules(\n input: ListSchedulesInput,\n transaction?: TTransaction,\n ): Promise<{ data: ScheduleRecord[]; pagination: TokenPagination }>;\n\n // --- schedule_run ---\n /** One run by immutable id. */\n getRun(input: GetRunInput, transaction?: TTransaction): Promise<ScheduleRunRecord | undefined>;\n /** A schedule's single pending (`scheduled`) run, if it has one. */\n getScheduledRunFor(\n input: GetScheduledRunForInput,\n transaction?: TTransaction,\n ): Promise<ScheduleRunRecord | undefined>;\n /** Inserts a run. Throws {@link ScheduleRunConflictError} on either unique index. */\n createRun(input: CreateScheduleRunInput, transaction?: TTransaction): Promise<ScheduleRunRecord>;\n /**\n * Status transition. Stamps `triggered_at` when moving to `triggered`.\n * Returns undefined when the row is gone (e.g. pause deleted it).\n */\n updateRunStatus(\n input: UpdateScheduleRunStatusInput,\n transaction?: TTransaction,\n ): Promise<ScheduleRunRecord | undefined>;\n /**\n * `scheduled` runs with `scheduled_for <= now`, oldest first.\n * Triggered / terminal rows are never returned.\n */\n listScheduledRuns(input: ListScheduledRunsInput, transaction?: TTransaction): Promise<ScheduleRunRecord[]>;\n /**\n * Runs of one schedule (any status), newest `scheduled_for` first.\n */\n listRuns(input: ListRunsInput, transaction?: TTransaction): Promise<ScheduleRunRecord[]>;\n}\n","import { z } from '@hono/zod-openapi';\nimport { CreatedBySubjectSchema, TokenPaginationSchema } from '@truefoundry/trueforge-core/agent-session';\nimport { NameSchema } from './common';\n\n/**\n * Minimum gap between two triggers of one schedule.\n */\nexport const SCHEDULE_MIN_INTERVAL_SECONDS = 3600;\n\n/**\n * Standard 5-field cron (minute hour day-of-month month day-of-week).\n */\nconst CRON_FIELD = String.raw`[\\d*,\\-/]+`;\n\n/** Cron expression cannot produce a valid upcoming trigger, or violates schedule policy. */\nexport class InvalidCronError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'InvalidCronError';\n }\n}\n\nexport const CronExpressionSchema = z\n .string()\n .trim()\n .regex(\n new RegExp(`^${CRON_FIELD}(?:\\\\s+${CRON_FIELD}){4}$`),\n 'must be a 5-field cron expression: minute hour day-of-month month day-of-week',\n )\n .describe('Standard 5-field cron expression, evaluated in `timezone`.')\n .openapi('CronExpression');\n\n/**\n * IANA zone name — never a fixed UTC offset, which cannot represent DST.\n *\n * Optional in the manifest; defaults to UTC, which is also the recommendation when\n * the trigger instant matters more than the local hour.\n *\n * Cron is evaluated in this zone via `cron-parser`: a spring-forward gap maps a\n * missing local time onto the landing hour, and fall-back does not double-fire a\n * fixed hour. Prefer `UTC` when the trigger instant matters more than the local hour.\n */\nexport const TimezoneSchema = z\n .string()\n .trim()\n .min(1)\n .refine(value => {\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: value });\n return true;\n } catch {\n return false;\n }\n }, 'must be a valid IANA time zone name, e.g. \"America/New_York\"')\n .describe('IANA time zone the cron expression is evaluated in.')\n .openapi('Timezone');\n\n/**\n * Wire ISO-8601 instant on a response. Always UTC with milliseconds — every\n * timestamp the server emits comes from `Date.prototype.toISOString()`.\n */\nconst IsoTimestamp = z.iso.datetime().openapi({ type: 'string', format: 'date-time' });\n\nconst NullableIsoTimestamp = z.iso\n .datetime()\n .nullable()\n .openapi({ type: ['string', 'null'], format: 'date-time' });\n\nexport const ScheduleTaskSchema = z\n .string()\n .trim()\n .min(1)\n .describe('First user message sent to the agent on every run.');\n\nexport const ScheduleStatusSchema = z.enum(['active', 'paused']).openapi('ScheduleStatus');\n\n/**\n * Schedule document persisted as `schedule.manifest`.\n */\nexport const ScheduleManifestObjectSchema = z\n .object({\n task: ScheduleTaskSchema,\n cron: CronExpressionSchema,\n timezone: TimezoneSchema.default('UTC'),\n status: ScheduleStatusSchema.default('active'),\n })\n .strict();\n\nexport const ScheduleManifestSchema = ScheduleManifestObjectSchema.openapi('ScheduleManifest');\n\n/** List/get/create/update response item. */\nexport const ScheduleSchema = z\n .object({\n id: z.string(),\n agent_name: NameSchema,\n name: NameSchema,\n manifest: ScheduleManifestSchema,\n created_by_subject: CreatedBySubjectSchema,\n created_at: IsoTimestamp,\n updated_at: IsoTimestamp,\n })\n .strict()\n .openapi('Schedule');\n\nexport const CreateScheduleRequestSchema = z\n .object({\n agent_name: NameSchema,\n name: NameSchema,\n manifest: ScheduleManifestSchema,\n })\n .strict()\n .openapi('CreateScheduleRequest');\n\nexport const UpdateScheduleRequestSchema = z\n .object({\n name: NameSchema,\n manifest: ScheduleManifestSchema,\n })\n .strict()\n .openapi('UpdateScheduleRequest');\n\nexport const GetScheduleResponseSchema = z.object({ data: ScheduleSchema }).openapi('GetScheduleResponse');\nexport const ListSchedulesResponseSchema = z\n .object({\n data: z.array(ScheduleSchema),\n pagination: TokenPaginationSchema,\n })\n .openapi('ListSchedulesResponse');\nexport const DeleteScheduleResponseSchema = z.object({}).openapi('DeleteScheduleResponse');\n\n/**\n * Run lifecycle.\n * - `scheduled` the one pending run; at most one per schedule, enforced by\n * `schedule_run_pending_uq`\n * - `triggered` taken by dispatch via `updateRunStatus`\n * - `failed` errored, or hand-off to the executor failed\n */\nexport const ScheduleRunStatusSchema = z.enum(['scheduled', 'triggered', 'failed']).openapi('ScheduleRunStatus');\n\nexport const ScheduleRunSchema = z\n .object({\n id: z.string(),\n schedule_id: z.string(),\n name: z.string(),\n scheduled_for: IsoTimestamp,\n status: ScheduleRunStatusSchema,\n created_by_subject: CreatedBySubjectSchema,\n triggered_at: NullableIsoTimestamp,\n created_at: IsoTimestamp,\n updated_at: IsoTimestamp,\n })\n .strict()\n .openapi('ScheduleRun');\n\nexport const ListScheduleRunsResponseSchema = z\n .object({ data: z.array(ScheduleRunSchema) })\n .openapi('ListScheduleRunsResponse');\n\n/**\n * Identify the schedule to run. Task always comes from the schedule manifest.\n */\nexport const CreateScheduleRunRequestSchema = z\n .object({\n schedule_id: z.string().min(1).max(64).describe('Immutable schedule identifier.'),\n })\n .strict()\n .describe('Trigger an immediate run for the given schedule. The task is taken from the schedule manifest.')\n .openapi('CreateScheduleRunRequest');\n\nexport const CreateScheduleRunResponseSchema = z\n .object({ data: ScheduleRunSchema })\n .openapi('CreateScheduleRunResponse');\n\nexport type ScheduleStatus = z.infer<typeof ScheduleStatusSchema>;\nexport type ScheduleRunStatus = z.infer<typeof ScheduleRunStatusSchema>;\nexport type ScheduleManifest = z.infer<typeof ScheduleManifestSchema>;\nexport type Schedule = z.infer<typeof ScheduleSchema>;\nexport type ScheduleRun = z.infer<typeof ScheduleRunSchema>;\nexport type CreateScheduleRequest = z.infer<typeof CreateScheduleRequestSchema>;\nexport type UpdateScheduleRequest = z.infer<typeof UpdateScheduleRequestSchema>;\nexport type CreateScheduleRunRequest = z.infer<typeof CreateScheduleRunRequestSchema>;\n","/**\n * Server-wide shared Zod field schemas and refinements.\n */\nimport { z } from '@hono/zod-openapi';\n\n/**\n * Lowercase name, 2–64 chars: starts with a letter, ends with alphanumeric,\n * may contain \".\", \"_\" or \"-\" in between (aligned with SF model-integration names).\n */\nexport const NameSchema = z\n .string()\n .min(2)\n .max(64)\n .regex(\n /^[a-z](?:[a-z0-9._-]{0,62}[a-z0-9])$/,\n 'must be 2–64 lowercase chars: start with a letter, end with alphanumeric, optionally separated by \".\", \"_\" or \"-\"',\n )\n .openapi('ResourceName');\n\nexport type ResourceName = z.infer<typeof NameSchema>;\n\nexport const PAGE_LIMIT = 25;\n/** Session/turn event list page size (default = max). */\nexport const EVENTS_PAGE_LIMIT = 100;\n/** MCP server list default page size. */\nexport const MCP_SERVERS_PAGE_LIMIT = 100;\n/** MCP server list max page size. */\nexport const MCP_SERVERS_PAGE_LIMIT_MAX = 200;\n\n/** Adds a validation issue if two entries share a name. */\nexport function uniqueNames(entries: { name: string }[], ctx: z.RefinementCtx): void {\n const seen = new Set<string>();\n for (const entry of entries) {\n if (seen.has(entry.name)) {\n ctx.addIssue({\n code: 'custom',\n message: `Duplicate name \"${entry.name}\" — names must be unique`,\n });\n }\n seen.add(entry.name);\n }\n}\n\n/** Adds a validation issue if two entries share a type. */\nexport function uniqueTypes(entries: { type: string }[], ctx: z.RefinementCtx): void {\n const seen = new Set<string>();\n for (const entry of entries) {\n if (seen.has(entry.type)) {\n ctx.addIssue({\n code: 'custom',\n message: `Duplicate type \"${entry.type}\" — types must be unique`,\n });\n }\n seen.add(entry.type);\n }\n}\n\n/**\n * Normalize a CSV query value (`?foo=a,b`) into a string list.\n */\nexport function parseCommaSeparatedQuery(val: unknown): string[] | undefined {\n if (typeof val !== 'string') {\n return undefined;\n }\n return val\n .split(',')\n .map(part => part.trim())\n .filter(part => part.length > 0);\n}\n","/**\n * Cron evaluation for schedules.\n *\n * `cron-parser` is used for computation only; it owns no timers. Expressions are\n * evaluated in the schedule's IANA zone. On a spring-forward gap, a time that\n * does not exist (e.g. 02:30) maps onto the landing hour (03:30); fall-back\n * repeats are not double-fired for a fixed hour. Callers that care about the\n * exact UTC instant should prefer `timezone: \"UTC\"`.\n */\nimport { CronExpressionParser } from 'cron-parser';\nimport { InvalidCronError, type ScheduleManifest } from '../schemas/schedule';\n\n/** How many consecutive triggers to sample when measuring the tightest gap. */\nconst INTERVAL_PROBE_TRIGGERS = 5;\n\n/**\n * Next trigger time strictly after `from`, in `timezone`.\n *\n * Throws {@link InvalidCronError} when the expression parses structurally\n * but cannot produce a trigger time — e.g. `0 0 30 2 *`, February 30th.\n */\nexport function nextTriggerAfter(input: { cron: string; timezone: string; from: Date }): Date {\n const { cron, timezone, from } = input;\n try {\n const interval = CronExpressionParser.parse(cron, {\n currentDate: from,\n tz: timezone,\n });\n return interval.next().toDate();\n } catch (error) {\n throw new InvalidCronError(`Cron expression \"${cron}\" has no next trigger time in ${timezone}`, { cause: error });\n }\n}\n\n/**\n * Tightest gap the expression can produce, in seconds, measured over the next\n * {@link INTERVAL_PROBE_TRIGGERS} triggers.\n *\n * Sampling rather than analysis: a cron field can be irregular (`0 9,9 * * *`,\n * `*\\/7 * * * *`), and DST transitions can make some real gaps shorter than the\n * nominal one. Probing the actual sequence is both simpler and more honest than\n * reasoning about the fields.\n */\nexport function minIntervalSeconds(\n manifest: Pick<ScheduleManifest, 'cron' | 'timezone'>,\n from: Date = new Date(),\n): number {\n const interval = CronExpressionParser.parse(manifest.cron, {\n currentDate: from,\n tz: manifest.timezone,\n });\n\n let previous = interval.next().toDate();\n let tightest = Number.POSITIVE_INFINITY;\n for (let i = 0; i < INTERVAL_PROBE_TRIGGERS; i++) {\n const current = interval.next().toDate();\n tightest = Math.min(tightest, (current.getTime() - previous.getTime()) / 1000);\n previous = current;\n }\n return tightest;\n}\n","import type { SessionHandle, Sessions, TurnInputItem } from '@truefoundry/trueforge-core/agent-session';\nimport type { TrueForge } from '@truefoundry/trueforge-sdk';\nimport type { Logger } from 'winston';\nimport type { IAgentStore } from '../db/agentStore';\nimport {\n cronRunName,\n type IScheduleStore,\n type ScheduleDispatchItem,\n type ScheduleRunRecord,\n} from '../db/scheduleStore';\nimport type { WithTransaction } from '../db/transaction';\nimport { nextTriggerAfter } from '../runtime/cron';\nimport { InvalidCronError, type ScheduleRunStatus } from '../schemas/schedule';\nimport type { ControlLoop } from './Controller';\n\n/**\n * Rows examined per pass.\n *\n * TODO(controller): a backlog larger than this is left for the next tick rather\n * than drained in a loop. Fine while the tick is short relative to the minimum\n * interval; revisit if either changes.\n */\nexport const DISPATCH_BATCH_LIMIT = 20;\n\n/**\n * Gap between loop passes.\n *\n * Well below the minimum schedule interval, so a run is picked up within a tick of\n * `scheduled_for` passing, and cheap: an idle pass is one indexed query against\n * `schedule_run_scheduled_for_idx`.\n */\nconst SCHEDULE_DISPATCH_INTERVAL_MS = 60_000;\n\n/** The loop's name. */\nconst SCHEDULE_DISPATCH_LOOP_NAME = 'schedule-dispatch';\n\ntype ScheduleRunApiClient = Pick<TrueForge, 'sessions' | 'internal'>;\n\n/** Schedule's bound agent name is missing from the agent store. */\nexport class ScheduleAgentNotFoundError extends Error {\n readonly agent_name: string;\n\n constructor(agent_name: string, options?: ErrorOptions) {\n super(`Agent not found: ${agent_name}`, options);\n this.name = 'ScheduleAgentNotFoundError';\n this.agent_name = agent_name;\n }\n}\n\n/**\n * Hands a due schedule run to the API:\n * 1. Get or create a session keyed by `run.id`.\n * 2. Create a non-streaming turn only when that session has no turns.\n *\n * This call is hence idempotent.\n */\nfunction executeScheduledRun(client: ScheduleRunApiClient): (item: ScheduleDispatchItem) => Promise<void> {\n return async ({ run, schedule }) => {\n const { data: session } = await client.internal.sessions.getOrCreateByExternalId({\n externalId: run.id,\n agent: { name: schedule.agent_name },\n });\n\n const turns = await client.sessions.listTurns(session.id, { limit: 1 });\n if (turns.data.length > 0) {\n return;\n }\n\n await client.sessions.createTurn(session.id, {\n input: [{ type: 'user.message', content: schedule.manifest.task }],\n previousTurnId: 'none',\n });\n };\n}\n\n/**\n * Start a schedule run in-process: get-or-create a session keyed by `run.id`,\n * then create a non-streaming turn with the schedule task when that session has\n * none. Idempotent on retry. Session owner and turn `userRef` are the schedule\n * creator so ownership stays with the schedule even when an admin triggers run-now.\n */\nexport async function startScheduleRun(params: {\n item: ScheduleDispatchItem;\n sessions: Sessions;\n agentStore: IAgentStore;\n startTurn: (params: {\n session: SessionHandle;\n input: TurnInputItem[];\n previous_turn_id: string;\n userRef: string;\n }) => Promise<void>;\n}): Promise<void> {\n const {\n item: { run, schedule },\n sessions,\n agentStore,\n startTurn,\n } = params;\n\n const named = await agentStore.getAgent({ tenant_id: schedule.tenant_id, name: schedule.agent_name });\n if (named === undefined) {\n throw new ScheduleAgentNotFoundError(schedule.agent_name);\n }\n\n const { session } = await sessions.getOrCreateByExternalId({\n tenant_id: schedule.tenant_id,\n external_id: run.id,\n created_by_subject: schedule.created_by_subject,\n agent: { type: 'reference', id: named.id, name: named.name },\n });\n\n // idempotency check\n const { data: turns } = await session.listTurns({ limit: 1 });\n if (turns.length > 0) {\n return;\n }\n\n await startTurn({\n session,\n input: [{ type: 'user.message', content: schedule.manifest.task }],\n previous_turn_id: 'none',\n userRef: schedule.created_by_subject.subject_id,\n });\n}\n\n/**\n * Mark the current run with `status`, then add the schedule's next scheduled run\n * if the schedule is still active and its cron still has a later trigger time.\n *\n * ## LOCK ORDERING\n * The schedule row is locked FIRST, before the run row is touched. `updateScheduleAndRun`\n * (the PUT path) does the same: it locks the schedule, then deletes and inserts runs.\n * Both transactions therefore take schedule-then-run, and serialize cleanly.\n *\n */\nasync function finishScheduledRun<TTransaction>(params: {\n store: IScheduleStore<TTransaction>;\n run: ScheduleRunRecord;\n now: Date;\n status: ScheduleRunStatus;\n withTransaction: WithTransaction<TTransaction>;\n}): Promise<void> {\n const { store, withTransaction, run, status, now } = params;\n await withTransaction(async txn => {\n const latest = await store.getScheduleForUpdate({ tenant_id: run.tenant_id, id: run.schedule_id }, txn);\n\n const updated = await store.updateRunStatus({ tenant_id: run.tenant_id, id: run.id, status }, txn);\n if (updated === undefined) {\n return;\n }\n\n if (latest?.status !== 'active') {\n return;\n }\n\n // `now` selected this run (`scheduled_for <= now`), so anchoring here gives a\n // trigger time strictly later than the run being finished.\n const advanceFrom = new Date(Math.max(Date.parse(run.scheduled_for), now.getTime()));\n\n let nextTrigger: Date;\n try {\n nextTrigger = nextTriggerAfter({\n cron: latest.manifest.cron,\n timezone: latest.manifest.timezone,\n from: advanceFrom,\n });\n } catch (error) {\n if (!(error instanceof InvalidCronError)) {\n throw error;\n }\n // No later trigger time (calendar dead end). Ideally should not happen.\n // Still finish the current row; just do not add another.\n return;\n }\n\n await store.createRun(\n {\n tenant_id: latest.tenant_id,\n schedule_id: latest.id,\n name: cronRunName(nextTrigger),\n scheduled_for: nextTrigger,\n status: 'scheduled',\n created_by_subject: latest.created_by_subject,\n },\n txn,\n );\n });\n}\n\n/**\n * Schedule dispatch: turn `scheduled` runs with `scheduled_for <= now` into\n * triggered runs and add each schedule's next scheduled run.\n *\n * ## IDEMPOTENCY\n * If the process dies between steps, the same scheduled run is seen again on\n * the next tick — so `onTriggered` should ideally be idempotent (or otherwise safe to\n * call more than once).\n *\n * ## RACE conditions with the schedule API\n *\n * Dispatch and the API both write `schedule_run`. Cases below can drop a pending\n * run or leave an orphan session; that is accepted where noted. Two rules keep\n * pending rows from doubling: the schedule is re-read INSIDE the finish\n * transaction, and `schedule_run_pending_uq` index rejects a second `scheduled` row.\n *\n * - **pause**: drops the pending run in its own transaction, and stops the advance.\n * It never cancels a row that still exists: whatever pause did not delete is\n * executed (and recorded `triggered` or `failed`) so history has no unexplained gap.\n * If pause commits first, the row is gone and there is nothing to run.\n * If dispatch commits first, the run triggers and pause deletes the pending row\n * dispatch just added, so triggering stops from the next tick — at most one extra run.\n * - **resume **: no race condition; resume just adds a run.\n * - **cron expression change**: deletes the pending run and inserts a fresh one from the new cron.\n * If put commits first, the pending run is replaced; finish does not insert again.\n * Missing triggered history for that run is accepted.\n * If dispatch commits first, the run triggers and put deletes the pending row dispatch just added,\n * then inserts a fresh one. So the run that already handed off is kept; the next pending is put's.\n * - **delete**: cascades the runs away. Dispatch either sees the schedule gone\n * or holds the row and delete waits. A run already handed to the executor keeps going\n * and leaves an orphan session; the run row is gone, which is accepted.\n *\n * ## CONCURRENCY\n * NOT concurrency safe by design: call this from exactly ONE process.\n */\nexport async function dispatchScheduledRuns<TTransaction>(params: {\n store: IScheduleStore<TTransaction>;\n onTriggered: (item: ScheduleDispatchItem) => void | Promise<void>;\n logger: Logger;\n withTransaction: WithTransaction<TTransaction>;\n /** When aborted, stop before the next run; the current run still finishes. */\n signal?: AbortSignal;\n}): Promise<{ dispatched: number; failed: number }> {\n const { store, withTransaction, onTriggered, logger, signal } = params;\n // ONE clock for the whole pass: it selects the runs, judges lateness, and anchors\n // the next trigger time.\n const now = new Date();\n const scheduled = await store.listScheduledRuns({ limit: DISPATCH_BATCH_LIMIT, until: now });\n\n let dispatched = 0;\n let failed = 0;\n for (const run of scheduled) {\n if (signal?.aborted) {\n break;\n }\n try {\n const schedule = await store.getSchedule({\n tenant_id: run.tenant_id,\n id: run.schedule_id,\n });\n // Only a deleted schedule stops a row here. `paused` deliberately does NOT:\n // status decides whether the schedule gains a NEW row, never whether an\n // existing one runs. A row that exists was added while the schedule was\n // active, so it is honoured.\n if (schedule === undefined) {\n continue;\n }\n\n try {\n await onTriggered({ run, schedule });\n } catch (error) {\n logger.error('Failed to hand off triggered run', {\n schedule_id: schedule.id,\n run_id: run.id,\n error,\n });\n await finishScheduledRun({\n store,\n run,\n now,\n status: 'failed',\n withTransaction,\n });\n failed += 1;\n continue;\n }\n\n await finishScheduledRun({\n store,\n run,\n now,\n status: 'triggered',\n withTransaction,\n });\n dispatched += 1;\n } catch (error) {\n logger.error('Failed to process scheduled run', {\n schedule_id: run.schedule_id,\n run_id: run.id,\n error,\n });\n }\n }\n\n return { dispatched, failed };\n}\n\nexport function scheduleDispatchLoop<TTransaction>(params: {\n scheduleStore: IScheduleStore<TTransaction>;\n client: ScheduleRunApiClient;\n logger: Logger;\n withTransaction: WithTransaction<TTransaction>;\n}): ControlLoop {\n const { scheduleStore, client, withTransaction, logger } = params;\n return {\n name: SCHEDULE_DISPATCH_LOOP_NAME,\n intervalMs: SCHEDULE_DISPATCH_INTERVAL_MS,\n async tick(signal: AbortSignal): Promise<void> {\n const result = await dispatchScheduledRuns({\n store: scheduleStore,\n onTriggered: executeScheduledRun(client),\n logger,\n withTransaction,\n signal,\n });\n if (result.dispatched > 0 || result.failed > 0) {\n logger.debug('Scheduled runs dispatched or failed', result);\n }\n },\n };\n}\n","/**\n * Shared mutual-TLS helpers: outbound undici (controller → server, ServiceFoundry client) and\n * this process's HTTPS listener + client-cert middleware.\n *\n * Cert triple under the configured dir: `tls.crt` / `tls.key` / `ca.crt`.\n */\nimport type { HttpBindings } from '@hono/node-server';\nimport type { MiddlewareHandler } from 'hono';\nimport { readFileSync } from 'node:fs';\nimport { createServer as createHttpsServer, type ServerOptions as HttpsServerOptions } from 'node:https';\nimport { join } from 'node:path';\nimport { rootCertificates, TLSSocket } from 'node:tls';\n\nimport { Agent, fetch as undiciFetch, type Dispatcher } from 'undici';\nimport type { Logger } from 'winston';\n\nconst TLS_CERT_FILE = 'tls.crt';\nconst TLS_KEY_FILE = 'tls.key';\nconst TLS_CA_FILE = 'ca.crt';\n\nexport interface TlsOptions {\n enabled: boolean;\n dir: string;\n}\n\nfunction readTlsFile(input: { dir: string; fileName: string; enabledEnvKey: string }): string {\n const filePath = join(input.dir, input.fileName);\n try {\n return readFileSync(filePath, 'utf8');\n } catch (error) {\n throw new Error(\n `${input.enabledEnvKey} is true but ${filePath} could not be read. Check that the mTLS secret ` +\n `is mounted at the configured certs directory, or set ${input.enabledEnvKey}=false.`,\n { cause: error },\n );\n }\n}\n\nfunction isTlsSocket(socket: unknown): socket is TLSSocket {\n return socket instanceof TLSSocket;\n}\n\n/**\n * True when the peer presented a client certificate that our CA already verified.\n * Only meaningful when the listener was started with `requestCert: true`.\n */\nexport function hasAuthorizedClientCertificate(socket: unknown): boolean {\n return isTlsSocket(socket) && socket.authorized;\n}\n\n/** Upgrades http → https when mTLS is on. */\nexport function normalizeTlsUrl(input: { url: string; enabled: boolean }): string {\n if (!input.enabled) {\n return input.url;\n }\n const parsed = new URL(input.url);\n if (parsed.protocol === 'http:') {\n parsed.protocol = 'https:';\n }\n return parsed.href;\n}\n\n/** undici dispatcher presenting this process's client cert and trusting the CA (+ system roots). */\nexport function createTlsDispatcher(options: TlsOptions & { enabledEnvKey: string }): Dispatcher | undefined {\n if (!options.enabled) {\n return undefined;\n }\n const read = (fileName: string) => readTlsFile({ dir: options.dir, fileName, enabledEnvKey: options.enabledEnvKey });\n return new Agent({\n connect: {\n // Appended to the default roots, not replacing them: passing `ca` alone would override Node's\n // entire trust store for this dispatcher (breaks public HTTPS peers on the same agent).\n ca: [...rootCertificates, read(TLS_CA_FILE)],\n cert: read(TLS_CERT_FILE),\n key: read(TLS_KEY_FILE),\n },\n });\n}\n\n/** Resolves `fetch`'s first argument (`string | URL | Request`) to a URL string. */\nfunction requestUrlFromFetchInput(input: Parameters<typeof fetch>[0]): string {\n if (typeof input === 'string') {\n return input;\n }\n if (input instanceof URL) {\n return input.href;\n }\n return input.url;\n}\n\n/** `fetch` for the schedule controller SDK client. Undefined when mTLS is off. */\nexport function createTlsFetch(options: TlsOptions): typeof fetch | undefined {\n const dispatcher = createTlsDispatcher({\n ...options,\n enabledEnvKey: 'TRUEFORGE_MTLS_ENABLED',\n });\n if (dispatcher === undefined) {\n return undefined;\n }\n // Casts bridge undici ↔ DOM fetch types (Fern only needs string URL + init + dispatcher).\n return (input, init) => undiciFetch(requestUrlFromFetchInput(input), { ...(init as object), dispatcher });\n}\n\n/** HTTPS `serve` options when mTLS is on; undefined → plain HTTP. */\nexport function serverTlsServeOptions(\n options: TlsOptions,\n): { createServer: typeof createHttpsServer; serverOptions: HttpsServerOptions } | undefined {\n if (!options.enabled) {\n return undefined;\n }\n const read = (fileName: string) =>\n readTlsFile({ dir: options.dir, fileName, enabledEnvKey: 'TRUEFORGE_MTLS_ENABLED' });\n return {\n createServer: createHttpsServer,\n serverOptions: {\n key: Buffer.from(read(TLS_KEY_FILE)),\n cert: Buffer.from(read(TLS_CERT_FILE)),\n ca: Buffer.from(read(TLS_CA_FILE)),\n requestCert: true,\n // Do not reject at handshake so /healthz probes without a cert still connect.\n rejectUnauthorized: false,\n },\n };\n}\n\n/** Rejects certless requests except `/healthz`. Mount only when mTLS is enabled. */\nexport function createClientCertificateMiddleware(logger: Logger): MiddlewareHandler {\n return async (c, next) => {\n if (c.req.path === '/healthz') {\n await next();\n return;\n }\n if (hasAuthorizedClientCertificate((c.env as HttpBindings).incoming.socket)) {\n await next();\n return;\n }\n logger.warn('Rejected request without a valid client certificate', { path: c.req.path });\n return c.json({ error: { message: 'Client certificate required' } }, 403);\n };\n}\n","import { Kysely, PostgresDialect } from 'kysely';\nimport pg, { Pool } from 'pg';\n\nimport { TRUEFORGE_SCHEMA } from './schema';\nimport type { Database } from './types';\n\nconst INT8_OID = 20;\n/**\n * Postgres OID for `bigint[]` / `_int8`. Scalar int8 parser (OID 20) does NOT cover arrays.\n * Widened setter: node-pg's TypeId enum omits array OIDs.\n */\nconst setTypeParserByOid: (oid: number, parser: (value: string) => unknown) => void = pg.types.setTypeParser.bind(\n pg.types,\n);\n\n/**\n * Parse a Postgres array literal of int8 into number[].\n * Safe below Number.MAX_SAFE_INTEGER (2^53) — same contract as the scalar int8 parser.\n * Identity append_ids stay far below that bound.\n */\nfunction parseInt8Array(value: string): number[] {\n if (value === '{}' || value === '') {\n return [];\n }\n // Plain unquoted numeric elements (bigint[] never needs quotes).\n return value\n .slice(1, -1)\n .split(',')\n .map(element => Number(element));\n}\n\nfunction configurePgTypeParsers(): void {\n pg.types.setTypeParser(INT8_OID, Number);\n setTypeParserByOid(1016, parseInt8Array);\n}\n\nexport function createDb(options: {\n connectionString: string;\n poolMax: number;\n /** Postgres `statement_timeout` in ms. Applied to every pooled connection. */\n statementTimeoutMs: number;\n /** Postgres `idle_in_transaction_session_timeout` in ms. Applied to every pooled connection. */\n idleInTransactionSessionTimeoutMs: number;\n}): Kysely<Database> {\n const { connectionString, poolMax, statementTimeoutMs, idleInTransactionSessionTimeoutMs } = options;\n configurePgTypeParsers();\n return new Kysely<Database>({\n dialect: new PostgresDialect({\n pool: new Pool({\n connectionString,\n max: poolMax,\n statement_timeout: statementTimeoutMs,\n idle_in_transaction_session_timeout: idleInTransactionSessionTimeoutMs,\n options: `-c search_path=${TRUEFORGE_SCHEMA}`,\n }),\n }),\n });\n}\n\n/**\n * Match Postgres errors by SQLSTATE without `instanceof DatabaseError`.\n * instanceof breaks silently when two copies of pg-protocol load (version skew / dual CJS+ESM);\n * checking `code` is the conventional node-postgres pattern.\n */\nexport function isPgErrorCode(err: unknown, code: string): boolean {\n if (typeof err !== 'object' || err === null || !('code' in err)) {\n return false;\n }\n return err.code === code;\n}\n\nexport function isUniqueViolation(err: unknown): boolean {\n return isPgErrorCode(err, '23505');\n}\n\n/** Match a Postgres unique/PK violation to a named constraint or index. */\nexport function isPgConstraint(err: unknown, name: string): boolean {\n if (typeof err !== 'object' || err === null || !('constraint' in err)) {\n return false;\n }\n return err.constraint === name;\n}\n","import { type Kysely, sql } from 'kysely';\n\nimport type { Database } from './types';\n\nexport const TRUEFORGE_SCHEMA = 'trueforge';\n\nconst TABLES_TO_MOVE = [\n 'kysely_migration',\n 'kysely_migration_lock',\n 'session',\n 'turn',\n 'turn_thread',\n 'session_event',\n 'thread_context_log',\n 'thread_capability_state',\n 'model_provider',\n 'skill',\n 'sandbox_provider',\n 'agent',\n 'schedule',\n 'schedule_run',\n 'mcp_server',\n 'oauth_token',\n 'oauth_pending_authorization',\n] as const;\n\nexport async function ensureTrueforgeSchema(db: Kysely<Database>): Promise<void> {\n await db.transaction().execute(async txn => {\n await sql`SET LOCAL lock_timeout = '5s'`.execute(txn);\n await sql`SELECT pg_advisory_xact_lock(hashtext('trueforge_schema_bootstrap'))`.execute(txn);\n\n const result = await sql<{ exists: boolean }>`\n SELECT EXISTS (\n SELECT 1\n FROM pg_namespace\n WHERE nspname = ${TRUEFORGE_SCHEMA}\n ) AS exists\n `.execute(txn);\n if (result.rows[0]?.exists === true) {\n return;\n }\n\n await sql`CREATE SCHEMA IF NOT EXISTS ${sql.id(TRUEFORGE_SCHEMA)}`.execute(txn);\n for (const tableName of TABLES_TO_MOVE) {\n await sql`\n ALTER TABLE IF EXISTS ${sql.id('public', tableName)} SET SCHEMA ${sql.id(TRUEFORGE_SCHEMA)}\n `.execute(txn);\n }\n });\n}\n","import type { TokenPagination } from '@truefoundry/trueforge-core/agent-session';\nimport {\n decodeOffsetPageToken,\n paginateOffsetRows,\n} from '@truefoundry/trueforge-core/agent-session/store/OffsetPageToken';\nimport type { Kysely, Selectable, Transaction } from 'kysely';\nimport { nextTriggerAfter } from '../../../runtime/cron';\nimport { newId } from '../../../utils/id';\nimport { parseStoredCreatedBySubject } from '../../createdBySubject';\nimport {\n cronRunName,\n parseStoredScheduleManifest,\n ScheduleNameConflictError,\n ScheduleRunConflictError,\n shouldSyncPendingRun,\n type CreateScheduleInput,\n type CreateScheduleRunInput,\n type DeleteScheduleInput,\n type GetRunInput,\n type GetScheduledRunForInput,\n type GetScheduleInput,\n type IScheduleStore,\n type ListRunsInput,\n type ListScheduledRunsInput,\n type ListSchedulesInput,\n type ScheduleRecord,\n type ScheduleRunRecord,\n type ScheduleWriteResult,\n type UpdateScheduleInput,\n type UpdateScheduleRunStatusInput,\n} from '../../scheduleStore';\nimport { isUniqueViolation } from '../client';\nimport { json, now, whereCreatedByOrAgentIds } from '../sqlExpressions';\nimport type { Database, ScheduleRunTable, ScheduleTable } from '../types';\n\nfunction toScheduleRecord(row: Selectable<ScheduleTable>): ScheduleRecord {\n return {\n id: row.id,\n tenant_id: row.tenant_id,\n agent_id: row.agent_id,\n agent_name: row.agent_name,\n name: row.name,\n manifest: parseStoredScheduleManifest(row.manifest),\n status: row.status,\n created_by_subject: parseStoredCreatedBySubject(row.created_by_subject),\n created_at: row.created_at.toISOString(),\n updated_at: row.updated_at.toISOString(),\n };\n}\n\nfunction toRunRecord(row: Selectable<ScheduleRunTable>): ScheduleRunRecord {\n return {\n id: row.id,\n tenant_id: row.tenant_id,\n schedule_id: row.schedule_id,\n name: row.name,\n scheduled_for: row.scheduled_for.toISOString(),\n status: row.status,\n created_by_subject: parseStoredCreatedBySubject(row.created_by_subject),\n triggered_at: row.triggered_at === null ? null : row.triggered_at.toISOString(),\n created_at: row.created_at.toISOString(),\n updated_at: row.updated_at.toISOString(),\n };\n}\n\nexport class PostgresScheduleStore implements IScheduleStore<Transaction<Database>> {\n readonly #db: Kysely<Database>;\n\n constructor(db: Kysely<Database>) {\n this.#db = db;\n }\n\n async #syncPendingRun(\n schedule: ScheduleRecord,\n from: Date,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleRunRecord | undefined> {\n const db = transaction ?? this.#db;\n // Clear the pending run, if any; whether a replacement follows depends on status.\n await db\n .deleteFrom('schedule_run')\n .where('tenant_id', '=', schedule.tenant_id)\n .where('schedule_id', '=', schedule.id)\n .where('status', '=', 'scheduled')\n .execute();\n if (schedule.status !== 'active') {\n return undefined;\n }\n const nextTrigger = nextTriggerAfter({\n cron: schedule.manifest.cron,\n timezone: schedule.manifest.timezone,\n from,\n });\n return this.createRun(\n {\n tenant_id: schedule.tenant_id,\n schedule_id: schedule.id,\n name: cronRunName(nextTrigger),\n scheduled_for: nextTrigger,\n status: 'scheduled',\n created_by_subject: schedule.created_by_subject,\n },\n transaction,\n );\n }\n\n async getSchedule(input: GetScheduleInput, transaction?: Transaction<Database>): Promise<ScheduleRecord | undefined> {\n const db = transaction ?? this.#db;\n const row = await db\n .selectFrom('schedule')\n .selectAll()\n .where('tenant_id', '=', input.tenant_id)\n .where('id', '=', input.id)\n .executeTakeFirst();\n return row === undefined ? undefined : toScheduleRecord(row);\n }\n\n async getScheduleForUpdate(\n input: GetScheduleInput,\n transaction: Transaction<Database>,\n ): Promise<ScheduleRecord | undefined> {\n const row = await transaction\n .selectFrom('schedule')\n .selectAll()\n .where('tenant_id', '=', input.tenant_id)\n .where('id', '=', input.id)\n .forUpdate()\n .executeTakeFirst();\n return row === undefined ? undefined : toScheduleRecord(row);\n }\n\n async createScheduleAndRun(\n input: CreateScheduleInput,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleWriteResult> {\n const db = transaction ?? this.#db;\n let row;\n try {\n row = await db\n .insertInto('schedule')\n .values({\n id: newId(),\n tenant_id: input.tenant_id,\n agent_id: input.agent_id,\n agent_name: input.agent_name,\n name: input.name,\n manifest: json(input.manifest),\n // Column mirrors the manifest so the dispatch scan and API reads share one value.\n status: input.manifest.status,\n created_by_subject: json(input.created_by_subject),\n created_at: now(),\n updated_at: now(),\n })\n .returningAll()\n .executeTakeFirstOrThrow();\n } catch (error) {\n if (isUniqueViolation(error)) {\n throw new ScheduleNameConflictError(\n { tenant_id: input.tenant_id, agent_name: input.agent_name, name: input.name },\n { cause: error },\n );\n }\n throw error;\n }\n const schedule = toScheduleRecord(row);\n const pendingRun = await this.#syncPendingRun(schedule, input.runFrom, transaction);\n return { schedule, pendingRun };\n }\n\n async updateScheduleAndRun(\n input: UpdateScheduleInput,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleWriteResult | undefined> {\n // Lock first: this transaction writes the schedule AND its runs, and every such\n // transaction must take the schedule lock before touching a run row.\n const previous =\n transaction !== undefined\n ? await this.getScheduleForUpdate({ tenant_id: input.tenant_id, id: input.id }, transaction)\n : await this.getSchedule({ tenant_id: input.tenant_id, id: input.id });\n if (previous === undefined) {\n return undefined;\n }\n\n const db = transaction ?? this.#db;\n let row;\n try {\n row = await db\n .updateTable('schedule')\n .set({ name: input.name, manifest: json(input.manifest), status: input.manifest.status, updated_at: now() })\n .where('tenant_id', '=', input.tenant_id)\n .where('id', '=', input.id)\n .returningAll()\n .executeTakeFirst();\n } catch (error) {\n if (isUniqueViolation(error)) {\n throw new ScheduleNameConflictError(\n { tenant_id: input.tenant_id, agent_name: previous.agent_name, name: input.name },\n { cause: error },\n );\n }\n throw error;\n }\n if (row === undefined) {\n return undefined;\n }\n const schedule = toScheduleRecord(row);\n if (!shouldSyncPendingRun(previous, schedule)) {\n const pendingRun = await this.getScheduledRunFor(\n { tenant_id: schedule.tenant_id, schedule_id: schedule.id },\n transaction,\n );\n return { schedule, pendingRun };\n }\n const pendingRun = await this.#syncPendingRun(schedule, input.runFrom, transaction);\n return { schedule, pendingRun };\n }\n\n async deleteSchedule(input: DeleteScheduleInput, transaction?: Transaction<Database>): Promise<void> {\n const db = transaction ?? this.#db;\n await db.deleteFrom('schedule').where('tenant_id', '=', input.tenant_id).where('id', '=', input.id).execute();\n }\n\n async listSchedules(\n input: ListSchedulesInput,\n transaction?: Transaction<Database>,\n ): Promise<{ data: ScheduleRecord[]; pagination: TokenPagination }> {\n const offset = decodeOffsetPageToken(input.page_token);\n const db = transaction ?? this.#db;\n let query = db.selectFrom('schedule').selectAll().where('tenant_id', '=', input.tenant_id);\n if (input.agent_names !== undefined) {\n query = query.where('agent_name', 'in', [...input.agent_names]);\n }\n query = whereCreatedByOrAgentIds(query, input.created_by_or_agent_ids);\n const rows = await query\n .orderBy('created_at', 'desc')\n .orderBy('id')\n .limit(input.limit + 1)\n .offset(offset)\n .execute();\n const { data, pagination } = paginateOffsetRows(rows, input.limit, offset);\n return { data: data.map(toScheduleRecord), pagination };\n }\n\n async listRuns(input: ListRunsInput, transaction?: Transaction<Database>): Promise<ScheduleRunRecord[]> {\n const db = transaction ?? this.#db;\n const rows = await db\n .selectFrom('schedule_run')\n .selectAll()\n .where('tenant_id', '=', input.tenant_id)\n .where('schedule_id', '=', input.schedule_id)\n .orderBy('scheduled_for', 'desc')\n .orderBy('id')\n .execute();\n return rows.map(toRunRecord);\n }\n\n async getRun(input: GetRunInput, transaction?: Transaction<Database>): Promise<ScheduleRunRecord | undefined> {\n const db = transaction ?? this.#db;\n const row = await db\n .selectFrom('schedule_run')\n .selectAll()\n .where('tenant_id', '=', input.tenant_id)\n .where('id', '=', input.id)\n .executeTakeFirst();\n return row === undefined ? undefined : toRunRecord(row);\n }\n\n async getScheduledRunFor(\n input: GetScheduledRunForInput,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleRunRecord | undefined> {\n const db = transaction ?? this.#db;\n const row = await db\n .selectFrom('schedule_run')\n .selectAll()\n .where('tenant_id', '=', input.tenant_id)\n .where('schedule_id', '=', input.schedule_id)\n .where('status', '=', 'scheduled')\n .executeTakeFirst();\n return row === undefined ? undefined : toRunRecord(row);\n }\n\n async createRun(input: CreateScheduleRunInput, transaction?: Transaction<Database>): Promise<ScheduleRunRecord> {\n const db = transaction ?? this.#db;\n try {\n const row = await db\n .insertInto('schedule_run')\n .values({\n id: newId(),\n tenant_id: input.tenant_id,\n schedule_id: input.schedule_id,\n name: input.name,\n scheduled_for: input.scheduled_for,\n status: input.status,\n created_by_subject: json(input.created_by_subject),\n triggered_at: input.triggered_at ?? null,\n created_at: now(),\n updated_at: now(),\n })\n .returningAll()\n .executeTakeFirstOrThrow();\n return toRunRecord(row);\n } catch (error) {\n if (isUniqueViolation(error)) {\n throw new ScheduleRunConflictError(`Schedule run already exists: ${input.name}`, { cause: error });\n }\n throw error;\n }\n }\n\n async updateRunStatus(\n input: UpdateScheduleRunStatusInput,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleRunRecord | undefined> {\n const db = transaction ?? this.#db;\n const patch =\n input.status === 'triggered'\n ? { status: input.status, triggered_at: now(), updated_at: now() }\n : { status: input.status, updated_at: now() };\n const row = await db\n .updateTable('schedule_run')\n .set(patch)\n .where('tenant_id', '=', input.tenant_id)\n .where('id', '=', input.id)\n .returningAll()\n .executeTakeFirst();\n return row === undefined ? undefined : toRunRecord(row);\n }\n\n async listScheduledRuns(\n input: ListScheduledRunsInput,\n transaction?: Transaction<Database>,\n ): Promise<ScheduleRunRecord[]> {\n const db = transaction ?? this.#db;\n const rows = await db\n .selectFrom('schedule_run')\n .selectAll()\n .where('status', '=', 'scheduled')\n .where('scheduled_for', '<=', input.until)\n .orderBy('scheduled_for')\n .limit(input.limit)\n .execute();\n return rows.map(toRunRecord);\n }\n}\n","import { ulid } from 'ulid';\n\n/** Application-generated lowercase ULID for entity / resource ids. */\nexport function newId(): string {\n return ulid().toLowerCase();\n}\n","import { CreatedBySubjectSchema, type CreatedBySubject } from '@truefoundry/trueforge-core/agent-session';\n\n/** Re-parse persisted creator JSON so store readers validate on read. */\nexport function parseStoredCreatedBySubject(value: unknown): CreatedBySubject {\n return CreatedBySubjectSchema.parse(value);\n}\n","/**\n * Shared Kysely SQL expression helpers for Postgres stores.\n */\nimport { sql, type Expression, type RawBuilder, type SelectQueryBuilder } from 'kysely';\nimport type { Database } from './types';\n\n/** Bind a JS value as jsonb (stringified + cast). Required for arrays and for `||` / jsonb_set operands. */\nexport function json<T>(value: T): RawBuilder<T> {\n return sql`${JSON.stringify(value)}::jsonb`;\n}\n\n/**\n * `jsonb_set(target, path, new_value)`.\n * `path` may be a text[] expression (`sql\\`ARRAY['threads', ${id}]\\``) or a literal path\n * expression (`sql\\`'{sandbox_info}'\\`` / `sql\\`'{completion}'\\``).\n */\nexport function jsonbSet<T = unknown>(\n target: Expression<unknown>,\n path: Expression<unknown>,\n newValue: Expression<unknown>,\n): RawBuilder<T> {\n return sql<T>`jsonb_set(${target}, ${path}, ${newValue})`;\n}\n\n/** `now()` timestamptz expression. */\nexport function now(): RawBuilder<Date> {\n return sql<Date>`now()`;\n}\n\nexport function nowMinusMs(ms: number): RawBuilder<Date> {\n return sql<Date>`now() - ${ms}::double precision * interval '1 millisecond'`;\n}\n\n/** Creator match, or creator OR `agent_id IN agent_ids` when the list is non-empty. */\nexport function whereCreatedByOrAgentIds<TB extends 'session' | 'schedule', O>(\n query: SelectQueryBuilder<Database, TB, O>,\n filter:\n | {\n created_by_subject_id: string;\n agent_ids: readonly string[];\n }\n | undefined,\n): SelectQueryBuilder<Database, TB, O> {\n if (filter === undefined) {\n return query;\n }\n if (filter.agent_ids.length === 0) {\n return query.where(sql`created_by_subject->>'subject_id'`, '=', filter.created_by_subject_id);\n }\n return query.where(eb =>\n eb.or([\n eb(sql<string>`created_by_subject->>'subject_id'`, '=', filter.created_by_subject_id),\n eb(sql<string>`agent_id`, 'in', [...filter.agent_ids]),\n ]),\n );\n}\n","/**\n * Process logger: human-readable lines in standalone mode, JSON otherwise.\n * JSON output carries `version` and `component` ('server' | 'controller') in defaultMeta\n * so hosted aggregators can tell the two processes apart; both are omitted from the\n * human-readable standalone format to keep local logs terse.\n */\nimport winston, { type Logger } from 'winston';\n\nconst STANDALONE_META_SKIP = new Set(['level', 'message', 'timestamp', 'version', 'component', 'stack', 'splat']);\n\nexport function shouldColorize(): boolean {\n const noColor = process.env['NO_COLOR'];\n if (noColor !== undefined && noColor !== '') {\n return false;\n }\n const forceColor = process.env['FORCE_COLOR'];\n if (forceColor === '0') {\n return false;\n }\n if (forceColor !== undefined && forceColor !== '') {\n return true;\n }\n return process.stderr.isTTY;\n}\n\nfunction standaloneMeta(info: object): string {\n const copied: Record<string, unknown> = { ...info };\n const meta: Record<string, unknown> = {};\n for (const key of Object.keys(copied)) {\n if (STANDALONE_META_SKIP.has(key)) {\n continue;\n }\n meta[key] = copied[key];\n }\n if (Object.keys(meta).length === 0) {\n return '';\n }\n return ` ${JSON.stringify(meta)}`;\n}\n\nfunction standaloneFormat(color: boolean): winston.Logform.Format {\n const parts: winston.Logform.Format[] = [\n winston.format.timestamp({ format: 'HH:mm:ss' }),\n winston.format.errors({ stack: true }),\n ];\n if (color) {\n parts.push(winston.format.colorize({ level: true }));\n }\n parts.push(\n winston.format.printf(info => {\n const extra = standaloneMeta(info);\n const stack = typeof info['stack'] === 'string' ? `\\n${info['stack']}` : '';\n return `${String(info['timestamp'])} ${info.level} ${String(info.message)}${extra}${stack}`;\n }),\n );\n return winston.format.combine(...parts);\n}\n\nfunction jsonFormat(): winston.Logform.Format {\n return winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json(),\n );\n}\n\nfunction serverLogFormat(options: { standalone: boolean }): winston.Logform.Format {\n if (options.standalone) {\n return standaloneFormat(shouldColorize());\n }\n return jsonFormat();\n}\n\nfunction createLogger(options: {\n level: string;\n standalone: boolean;\n version: string;\n component: 'server' | 'controller';\n}): Logger {\n return winston.createLogger({\n level: options.level,\n defaultMeta: { version: options.version, component: options.component },\n format: serverLogFormat({ standalone: options.standalone }),\n transports: [new winston.transports.Console()],\n });\n}\n\nexport function createServerLogger(options: { level: string; standalone: boolean; version: string }): Logger {\n return createLogger({ ...options, component: 'server' });\n}\n\nexport function createControllerLogger(options: { level: string; standalone: boolean; version: string }): Logger {\n return createLogger({ ...options, component: 'controller' });\n}\n","/**\n * Package version for logs, the OpenAPI document, and the CLI.\n *\n * Read from `package.json` next to this module's package root — the same\n * `src/` vs `dist/` layout as `config.ts` (`import.meta` → parent).\n */\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');\n\nfunction readPackageVersion(): string {\n const packageJsonPath = path.join(PACKAGE_ROOT, 'package.json');\n const parsed: unknown = JSON.parse(readFileSync(packageJsonPath, 'utf8'));\n if (typeof parsed !== 'object' || parsed === null || !('version' in parsed)) {\n throw new Error(`${packageJsonPath} is missing a version field`);\n }\n const { version } = parsed;\n if (typeof version !== 'string' || version.length === 0) {\n throw new Error(`${packageJsonPath} version must be a non-empty string`);\n }\n return version;\n}\n\nexport const PACKAGE_VERSION = readPackageVersion();\n","/**\n * Controller entry point (`dist/controller-main.js`).\n *\n * Runs the periodic control loops (schedule dispatch, …) as a dedicated,\n * single-replica process for distributed mode (`STANDALONE=false`). The controller\n * must run in exactly ONE process per database (see `controller/Controller.ts`);\n * in standalone mode the server process already owns it, so this entry refuses to\n * start there.\n *\n * Migrations are owned by the server (`main.ts`). This process only connects to the\n * already-migrated database; the loops have per-pass error boundaries, so they retry\n * each tick until the schema is present. The loops call the server over HTTP(S) at\n * `SERVER_URL` (mutual TLS when `TRUEFORGE_MTLS_ENABLED`), so no Redis peering is wired here.\n */\nimport configuration from './config';\nimport { runController } from './controller';\nimport { createDb } from './db/postgres/client';\nimport { PostgresScheduleStore } from './db/postgres/schedule-store/PostgresScheduleStore';\nimport { createControllerLogger } from './logger';\nimport { PACKAGE_VERSION } from './packageVersion';\n\ntry {\n const logger = createControllerLogger({\n level: configuration.LOG_LEVEL,\n standalone: configuration.STANDALONE,\n version: PACKAGE_VERSION,\n });\n\n if (configuration.STANDALONE) {\n // Not an error: in standalone the server process owns the controller in-process, so a\n // dedicated controller has nothing to do. Exit cleanly (e.g. `pnpm standalone:dev` also\n // starts this script). Run with STANDALONE=false to use it as a dedicated process.\n logger.warn('Standalone mode (STANDALONE=true): the server runs the controller in-process; nothing to do here.');\n process.exit(0);\n }\n\n const db = createDb({\n connectionString: configuration.DATABASE_URL,\n poolMax: configuration.DATABASE_POOL_MAX,\n statementTimeoutMs: configuration.POSTGRES_STATEMENT_TIMEOUT_MS,\n idleInTransactionSessionTimeoutMs: configuration.POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT_MS,\n });\n\n const mtls = {\n enabled: configuration.TRUEFORGE_MTLS_ENABLED,\n dir: configuration.TRUEFORGE_MTLS_CERTS_DIR,\n };\n\n logger.info('Controller starting', {\n serverUrl: configuration.SERVER_URL,\n mTlsEnabled: mtls.enabled,\n });\n\n runController({\n scheduleStore: new PostgresScheduleStore(db),\n withTransaction: callback => db.transaction().execute(callback),\n logger,\n baseUrl: configuration.SERVER_URL,\n tls: mtls,\n gracefulTimeoutSeconds: configuration.GRACEFUL_TIMEOUT_SECONDS,\n onStopped: () => db.destroy(),\n });\n} catch (error) {\n console.error('Failed to start controller:', error instanceof Error ? error.message : error);\n process.exit(1);\n}\n"],"mappings":"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","names":["port","appDataDir","z","z","now","CreatedBySubjectSchema","sql","sql","sql","pendingRun","readFileSync","path","fileURLToPath","PACKAGE_ROOT"]}