dirigent-server 0.20.0__tar.gz → 0.22.0__tar.gz

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 (264) hide show
  1. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/PKG-INFO +5 -5
  2. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/THIRD_PARTY_NOTICES.md +1 -1
  3. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/pyproject.toml +5 -5
  4. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/pyproject.toml.orig +5 -5
  5. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/app.py +12 -11
  6. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/health.py +2 -1
  7. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/__init__.py +3 -0
  8. dirigent_server-0.22.0/src/dirigent_server/routes/labels.py +16 -0
  9. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/pipelines.py +18 -14
  10. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/runs.py +37 -13
  11. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/trigger_documents.py +7 -6
  12. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/triggers.py +114 -3
  13. dirigent_server-0.22.0/src/dirigent_server/static/assets/AdminOnly-Di7pCILM.js +1 -0
  14. dirigent_server-0.22.0/src/dirigent_server/static/assets/Alerting-CNkD2kQW.js +1 -0
  15. dirigent_server-0.22.0/src/dirigent_server/static/assets/Blocks-IZvOSgQU.js +1 -0
  16. dirigent_server-0.22.0/src/dirigent_server/static/assets/Breadcrumb-CctFxp-h.js +1 -0
  17. dirigent_server-0.20.0/src/dirigent_server/static/assets/CodeEditor-B9sClhqO.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/CodeEditor-DsxK1EAQ.js +2 -2
  18. dirigent_server-0.22.0/src/dirigent_server/static/assets/Connections-D7XEspuJ.js +1 -0
  19. dirigent_server-0.22.0/src/dirigent_server/static/assets/Dashboard-BIRNuuqI.js +1 -0
  20. dirigent_server-0.22.0/src/dirigent_server/static/assets/Description-C-byz7P3.js +2 -0
  21. dirigent_server-0.22.0/src/dirigent_server/static/assets/ExamplePanel-B8fMMGHT.js +1 -0
  22. dirigent_server-0.22.0/src/dirigent_server/static/assets/Examples-p3LtYgUq.js +2 -0
  23. dirigent_server-0.20.0/src/dirigent_server/static/assets/Instant-mr1E5jAK.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/Instant-9fAZuDCc.js +1 -1
  24. dirigent_server-0.22.0/src/dirigent_server/static/assets/JsonBlock-DLW6eaGe.js +1 -0
  25. dirigent_server-0.22.0/src/dirigent_server/static/assets/ListTable-vD3vfJJc.js +1 -0
  26. dirigent_server-0.20.0/src/dirigent_server/static/assets/Markdown-roa7jpVu.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/Markdown-D4x5xD_I.js +1 -1
  27. dirigent_server-0.22.0/src/dirigent_server/static/assets/Overview-BA7fmDg4.js +1 -0
  28. dirigent_server-0.22.0/src/dirigent_server/static/assets/PageState-Dqk77uol.js +1 -0
  29. dirigent_server-0.22.0/src/dirigent_server/static/assets/Panel-CdiywbkF.js +1 -0
  30. dirigent_server-0.22.0/src/dirigent_server/static/assets/Picker-DdukB8mz.js +1 -0
  31. dirigent_server-0.22.0/src/dirigent_server/static/assets/PipelineEditor-Cci7EXN8.js +2 -0
  32. dirigent_server-0.22.0/src/dirigent_server/static/assets/PipelineGraph-D_Hoq5jt.js +1 -0
  33. dirigent_server-0.22.0/src/dirigent_server/static/assets/PipelinePreview-DnTtggz_.js +1 -0
  34. dirigent_server-0.22.0/src/dirigent_server/static/assets/PipelineTab-DibWKiQR.js +105 -0
  35. dirigent_server-0.22.0/src/dirigent_server/static/assets/ProgramReference-BDstV6zZ.js +1 -0
  36. dirigent_server-0.20.0/src/dirigent_server/static/assets/Refusal-DickLwkO.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/Refusal-CkWHMyRD.js +1 -1
  37. dirigent_server-0.22.0/src/dirigent_server/static/assets/RunDetail-DXrFy7RR.js +3 -0
  38. dirigent_server-0.22.0/src/dirigent_server/static/assets/RunGraph-B_ptUBM0.js +1 -0
  39. dirigent_server-0.22.0/src/dirigent_server/static/assets/SchemaForm-DfQmkkf6.js +1 -0
  40. dirigent_server-0.22.0/src/dirigent_server/static/assets/Schemas-DwI-TOMn.js +10 -0
  41. dirigent_server-0.22.0/src/dirigent_server/static/assets/SettingsDialog-2ku_zJjo.js +1 -0
  42. dirigent_server-0.22.0/src/dirigent_server/static/assets/StarterPicker-BJw1pafi.js +1 -0
  43. dirigent_server-0.22.0/src/dirigent_server/static/assets/StepPorts-DUfs-QPy.js +7 -0
  44. dirigent_server-0.22.0/src/dirigent_server/static/assets/TileCard-XVHftgGm.js +1 -0
  45. dirigent_server-0.22.0/src/dirigent_server/static/assets/Triggers-CTV54kJX.js +1 -0
  46. dirigent_server-0.22.0/src/dirigent_server/static/assets/Users-DoAN95TI.js +1 -0
  47. dirigent_server-0.22.0/src/dirigent_server/static/assets/WindowedPane-r-8QnCb_.js +1 -0
  48. dirigent_server-0.22.0/src/dirigent_server/static/assets/Workers-oOWO1UN0.js +1 -0
  49. dirigent_server-0.22.0/src/dirigent_server/static/assets/WorkersTable-BXjGStKj.js +1 -0
  50. dirigent_server-0.22.0/src/dirigent_server/static/assets/api-BE2JXton.js +1 -0
  51. dirigent_server-0.22.0/src/dirigent_server/static/assets/auth-DdhSYe4e.js +1 -0
  52. dirigent_server-0.20.0/src/dirigent_server/static/assets/badge-BovCxjd1.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/badge-D5itJPkc.js +1 -1
  53. dirigent_server-0.22.0/src/dirigent_server/static/assets/blocks-Ch7prU7B.js +1 -0
  54. dirigent_server-0.22.0/src/dirigent_server/static/assets/chevron-down-BEKQnX9p.js +1 -0
  55. dirigent_server-0.20.0/src/dirigent_server/static/assets/chunk-OB3PAWPO-DOp4K52_.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/chunk-OB3PAWPO-m4Sckj1b.js +1 -1
  56. dirigent_server-0.22.0/src/dirigent_server/static/assets/connections-C45cNbZS.js +1 -0
  57. dirigent_server-0.22.0/src/dirigent_server/static/assets/copy-Bu7JXtPR.js +1 -0
  58. dirigent_server-0.22.0/src/dirigent_server/static/assets/dist-CvOdB3Md.js +1 -0
  59. dirigent_server-0.22.0/src/dirigent_server/static/assets/dropdown-menu-DV7wG0Bs.js +1 -0
  60. dirigent_server-0.22.0/src/dirigent_server/static/assets/examples-BPba0gMX.js +1 -0
  61. dirigent_server-0.22.0/src/dirigent_server/static/assets/file-braces-C7psBXD2.js +1 -0
  62. dirigent_server-0.22.0/src/dirigent_server/static/assets/format-BtF8uNWf.js +1 -0
  63. dirigent_server-0.22.0/src/dirigent_server/static/assets/glyphs-Cc7B_n1T.js +1 -0
  64. dirigent_server-0.22.0/src/dirigent_server/static/assets/index-BATxGpHo.css +2 -0
  65. dirigent_server-0.22.0/src/dirigent_server/static/assets/index-C1i6SZjT.js +53 -0
  66. dirigent_server-0.22.0/src/dirigent_server/static/assets/input-CjUmiL3f.js +1 -0
  67. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  68. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  69. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  70. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  71. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff +0 -0
  72. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2 +0 -0
  73. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  74. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  75. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  76. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  77. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2 +0 -0
  78. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff +0 -0
  79. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  80. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  81. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  82. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  83. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
  84. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
  85. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  86. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  87. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  88. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  89. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2 +0 -0
  90. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff +0 -0
  91. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  92. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  93. dirigent_server-0.22.0/src/dirigent_server/static/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff +0 -0
  94. dirigent_server-0.20.0/src/dirigent_server/static/assets/jsonMode-C2rhmYxE.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/jsonMode-DzxZa00C.js +1 -1
  95. dirigent_server-0.22.0/src/dirigent_server/static/assets/labels-D4COsPsJ.js +1 -0
  96. dirigent_server-0.22.0/src/dirigent_server/static/assets/nav-OVPYHMkU.js +1 -0
  97. dirigent_server-0.22.0/src/dirigent_server/static/assets/paging-DoahVifb.js +1 -0
  98. dirigent_server-0.22.0/src/dirigent_server/static/assets/panels-D1Fnei43.js +1 -0
  99. dirigent_server-0.22.0/src/dirigent_server/static/assets/pipelines-BO9VNBsW.js +1 -0
  100. dirigent_server-0.22.0/src/dirigent_server/static/assets/play-BR8D4K_V.js +1 -0
  101. dirigent_server-0.20.0/src/dirigent_server/static/assets/preferences-CEibwN5K.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/preferences-SNZNX5Se.js +1 -1
  102. dirigent_server-0.22.0/src/dirigent_server/static/assets/resolveAriaLabelledBy-P_cvqa1_.js +1 -0
  103. dirigent_server-0.22.0/src/dirigent_server/static/assets/schemas-C-PU1-EJ.js +1 -0
  104. dirigent_server-0.22.0/src/dirigent_server/static/assets/select-C8A0wT7K.js +1 -0
  105. dirigent_server-0.20.0/src/dirigent_server/static/assets/starters-CgC7I45V.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/starters-DexsdOaG.js +2 -2
  106. dirigent_server-0.22.0/src/dirigent_server/static/assets/status-BnsNd2jz.js +1 -0
  107. dirigent_server-0.20.0/src/dirigent_server/static/assets/react-CQOZoUwg.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/store-D-5yFBN1.js +1 -1
  108. dirigent_server-0.20.0/src/dirigent_server/static/assets/textarea-ljIbN_md.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/textarea-D86x5ut1.js +1 -1
  109. dirigent_server-0.22.0/src/dirigent_server/static/assets/tooltip-BUMTCKGt.js +1 -0
  110. dirigent_server-0.22.0/src/dirigent_server/static/assets/triggers-BNxqzLIW.js +1 -0
  111. dirigent_server-0.22.0/src/dirigent_server/static/assets/use-heartbeat-C3WWagro.js +1 -0
  112. dirigent_server-0.22.0/src/dirigent_server/static/assets/use-store-CZcp6jmY.js +1 -0
  113. dirigent_server-0.22.0/src/dirigent_server/static/assets/users-7jLF2mM8.js +1 -0
  114. dirigent_server-0.22.0/src/dirigent_server/static/assets/workers-BHK2ZmId.js +1 -0
  115. dirigent_server-0.22.0/src/dirigent_server/static/assets/x-CIbrmauw.js +1 -0
  116. dirigent_server-0.20.0/src/dirigent_server/static/assets/yaml-CLSOANGG.js → dirigent_server-0.22.0/src/dirigent_server/static/assets/yaml-D-Hjyunz.js +1 -1
  117. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/index.html +27 -27
  118. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/transactions.py +17 -1
  119. dirigent_server-0.20.0/src/dirigent_server/static/assets/AdminOnly-CWzFAkRQ.js +0 -1
  120. dirigent_server-0.20.0/src/dirigent_server/static/assets/Alerting-DaeWPtmD.js +0 -1
  121. dirigent_server-0.20.0/src/dirigent_server/static/assets/Blocks-CgKNmzTx.js +0 -1
  122. dirigent_server-0.20.0/src/dirigent_server/static/assets/Breadcrumb-x6p00HyX.js +0 -1
  123. dirigent_server-0.20.0/src/dirigent_server/static/assets/Connections-C8QLqabn.js +0 -1
  124. dirigent_server-0.20.0/src/dirigent_server/static/assets/Dashboard-Ctln2D1_.js +0 -1
  125. dirigent_server-0.20.0/src/dirigent_server/static/assets/Description-MmXUnb-9.js +0 -2
  126. dirigent_server-0.20.0/src/dirigent_server/static/assets/ExamplePanel-t52rV-xc.js +0 -1
  127. dirigent_server-0.20.0/src/dirigent_server/static/assets/Examples-D_GF1FoJ.js +0 -2
  128. dirigent_server-0.20.0/src/dirigent_server/static/assets/JsonBlock-ojXBf3xC.js +0 -1
  129. dirigent_server-0.20.0/src/dirigent_server/static/assets/ListTable-D-mI8v9Y.js +0 -1
  130. dirigent_server-0.20.0/src/dirigent_server/static/assets/Overview-DQDMn1kh.js +0 -1
  131. dirigent_server-0.20.0/src/dirigent_server/static/assets/PageState-BLuobMye.js +0 -1
  132. dirigent_server-0.20.0/src/dirigent_server/static/assets/Panel-CqrOYByl.js +0 -1
  133. dirigent_server-0.20.0/src/dirigent_server/static/assets/Picker-BzRYpj3s.js +0 -1
  134. dirigent_server-0.20.0/src/dirigent_server/static/assets/PipelineEditor-B8xKU23L.js +0 -2
  135. dirigent_server-0.20.0/src/dirigent_server/static/assets/PipelineGraph-DIcmE3aB.js +0 -1
  136. dirigent_server-0.20.0/src/dirigent_server/static/assets/PipelinePreview-DNIz5Oe9.js +0 -1
  137. dirigent_server-0.20.0/src/dirigent_server/static/assets/PipelineTab-Cq5YZYns.js +0 -105
  138. dirigent_server-0.20.0/src/dirigent_server/static/assets/ProgramReference-DF37mMAT.js +0 -1
  139. dirigent_server-0.20.0/src/dirigent_server/static/assets/RunDetail-DjOWNczO.js +0 -3
  140. dirigent_server-0.20.0/src/dirigent_server/static/assets/RunGraph-D6sxqM0W.js +0 -1
  141. dirigent_server-0.20.0/src/dirigent_server/static/assets/SchemaForm-oVYx_dDn.js +0 -1
  142. dirigent_server-0.20.0/src/dirigent_server/static/assets/Schemas-CkglczUH.js +0 -10
  143. dirigent_server-0.20.0/src/dirigent_server/static/assets/SettingsDialog-SxFoYOL5.js +0 -1
  144. dirigent_server-0.20.0/src/dirigent_server/static/assets/StarterPicker-BmoaI_cF.js +0 -1
  145. dirigent_server-0.20.0/src/dirigent_server/static/assets/StepPorts-Ct88rZ3W.js +0 -7
  146. dirigent_server-0.20.0/src/dirigent_server/static/assets/TileCard-UUULdrAd.js +0 -1
  147. dirigent_server-0.20.0/src/dirigent_server/static/assets/Triggers-4Qo_wwjX.js +0 -1
  148. dirigent_server-0.20.0/src/dirigent_server/static/assets/Users-C4q8b5-R.js +0 -1
  149. dirigent_server-0.20.0/src/dirigent_server/static/assets/WindowedPane-Dc5ox2RS.js +0 -1
  150. dirigent_server-0.20.0/src/dirigent_server/static/assets/Workers-D7LJK74x.js +0 -1
  151. dirigent_server-0.20.0/src/dirigent_server/static/assets/WorkersTable-BFuSEEhm.js +0 -1
  152. dirigent_server-0.20.0/src/dirigent_server/static/assets/api-Bm1JZLuC.js +0 -1
  153. dirigent_server-0.20.0/src/dirigent_server/static/assets/auth-CHgfcdt9.js +0 -1
  154. dirigent_server-0.20.0/src/dirigent_server/static/assets/blocks-CclbVd8c.js +0 -1
  155. dirigent_server-0.20.0/src/dirigent_server/static/assets/chevron-down-DAO3SUWv.js +0 -1
  156. dirigent_server-0.20.0/src/dirigent_server/static/assets/connections-Cp5WCruj.js +0 -1
  157. dirigent_server-0.20.0/src/dirigent_server/static/assets/copy-BeBwg8IR.js +0 -1
  158. dirigent_server-0.20.0/src/dirigent_server/static/assets/dist-DD8kpv1W.js +0 -1
  159. dirigent_server-0.20.0/src/dirigent_server/static/assets/dropdown-menu-B-6CcHKw.js +0 -1
  160. dirigent_server-0.20.0/src/dirigent_server/static/assets/examples-DB467CTN.js +0 -1
  161. dirigent_server-0.20.0/src/dirigent_server/static/assets/file-braces-Ep8AP5Yq.js +0 -1
  162. dirigent_server-0.20.0/src/dirigent_server/static/assets/format-B5YbYOY-.js +0 -1
  163. dirigent_server-0.20.0/src/dirigent_server/static/assets/glyphs-C1sjljkh.js +0 -1
  164. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  165. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  166. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  167. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  168. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-600-normal-CTOM6hUh.woff2 +0 -0
  169. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-600-normal-fLZuRloM.woff +0 -0
  170. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  171. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  172. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  173. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  174. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-600-normal-9HEixskS.woff +0 -0
  175. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-cyrillic-ext-600-normal-V-xxqcpd.woff2 +0 -0
  176. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  177. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  178. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  179. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  180. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  181. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  182. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  183. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  184. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  185. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  186. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-600-normal-D38SheWl.woff2 +0 -0
  187. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-latin-ext-600-normal-DmB0ttJJ.woff +0 -0
  188. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  189. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  190. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  191. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  192. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-600-normal-D2EvbN8M.woff2 +0 -0
  193. dirigent_server-0.20.0/src/dirigent_server/static/assets/ibm-plex-mono-vietnamese-600-normal-iLQfcSjf.woff +0 -0
  194. dirigent_server-0.20.0/src/dirigent_server/static/assets/index-CgkcXl1G.css +0 -2
  195. dirigent_server-0.20.0/src/dirigent_server/static/assets/index-CzO6Janm.js +0 -53
  196. dirigent_server-0.20.0/src/dirigent_server/static/assets/input-1fShkFXn.js +0 -1
  197. dirigent_server-0.20.0/src/dirigent_server/static/assets/nav-i7bJ0lrA.js +0 -1
  198. dirigent_server-0.20.0/src/dirigent_server/static/assets/paging-CpRIkEky.js +0 -1
  199. dirigent_server-0.20.0/src/dirigent_server/static/assets/pipelines-Pi3WL8R6.js +0 -1
  200. dirigent_server-0.20.0/src/dirigent_server/static/assets/play-CPVSEWx6.js +0 -1
  201. dirigent_server-0.20.0/src/dirigent_server/static/assets/resolveAriaLabelledBy-ClHvyYLK.js +0 -1
  202. dirigent_server-0.20.0/src/dirigent_server/static/assets/schemas-7KY_7aIc.js +0 -1
  203. dirigent_server-0.20.0/src/dirigent_server/static/assets/select-fQgkAQLW.js +0 -1
  204. dirigent_server-0.20.0/src/dirigent_server/static/assets/status-Ctx8x8Mf.js +0 -1
  205. dirigent_server-0.20.0/src/dirigent_server/static/assets/store-C2zgoyrT.js +0 -1
  206. dirigent_server-0.20.0/src/dirigent_server/static/assets/tooltip-D7_KwbOU.js +0 -1
  207. dirigent_server-0.20.0/src/dirigent_server/static/assets/triggers-BetQ4Leu.js +0 -1
  208. dirigent_server-0.20.0/src/dirigent_server/static/assets/use-heartbeat-CBT8848s.js +0 -1
  209. dirigent_server-0.20.0/src/dirigent_server/static/assets/use-store-CfRquqZF.js +0 -1
  210. dirigent_server-0.20.0/src/dirigent_server/static/assets/users-CTGHiHMA.js +0 -1
  211. dirigent_server-0.20.0/src/dirigent_server/static/assets/with-selector-BXYKoaOE.js +0 -1
  212. dirigent_server-0.20.0/src/dirigent_server/static/assets/workers-BH2Za19E.js +0 -1
  213. dirigent_server-0.20.0/src/dirigent_server/static/assets/x-Dltw6Vbs.js +0 -1
  214. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/LICENSE +0 -0
  215. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/README.md +0 -0
  216. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/__init__.py +0 -0
  217. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/dependencies.py +0 -0
  218. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/errors.py +0 -0
  219. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/logging.py +0 -0
  220. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/messages.py +0 -0
  221. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/pagination.py +0 -0
  222. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/py.typed +0 -0
  223. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/alerts.py +0 -0
  224. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/auth.py +0 -0
  225. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/blocks.py +0 -0
  226. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/connections.py +0 -0
  227. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/examples.py +0 -0
  228. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/hooks.py +0 -0
  229. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/playground.py +0 -0
  230. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/schema.py +0 -0
  231. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/schemas.py +0 -0
  232. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/system.py +0 -0
  233. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/users.py +0 -0
  234. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/routes/workers.py +0 -0
  235. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/security.py +0 -0
  236. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/.gitkeep +0 -0
  237. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/CodeEditor-C4OnjBMt.css +0 -0
  238. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/KindChip-CwU_Xxdy.js +0 -0
  239. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/Mark-DQR2php6.js +0 -0
  240. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/Segmented-KaDiGiyr.js +0 -0
  241. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/codicon-DCmgc-ay.ttf +0 -0
  242. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/docs-CCoB3shg.js +0 -0
  243. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/editor.worker-CIvRzd4O.js +0 -0
  244. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/elk-engine-Bm7I_NRI.js +0 -0
  245. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/elk-worker.min-DfmSo98M.js +0 -0
  246. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-cyrillic-ext-wght-normal-d45eAU9y.woff2 +0 -0
  247. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-cyrillic-wght-normal-BAAhND-U.woff2 +0 -0
  248. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-greek-wght-normal-CmyJS8uq.woff2 +0 -0
  249. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-latin-ext-wght-normal-CIII54If.woff2 +0 -0
  250. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-latin-wght-normal-IvpUvPa2.woff2 +0 -0
  251. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/ibm-plex-sans-vietnamese-wght-normal-Dg1JeJN0.woff2 +0 -0
  252. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/identity-BNZxCf_y.js +0 -0
  253. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/idle-DnO3aHK7.js +0 -0
  254. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/json.worker-fczZDBja.js +0 -0
  255. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/preload-helper-BZ1Pz5am.js +0 -0
  256. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/rolldown-runtime-Dd_uD5pT.js +0 -0
  257. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/shell-CC2rA5mh.js +0 -0
  258. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/sql-NEE52Syq.js +0 -0
  259. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/twig-De2hgUGE.js +0 -0
  260. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/utils-CT7ZGLfR.js +0 -0
  261. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/assets/yaml.worker-B2SaT_wA.js +0 -0
  262. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/favicon-32.png +0 -0
  263. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/static/logo.png +0 -0
  264. {dirigent_server-0.20.0 → dirigent_server-0.22.0}/src/dirigent_server/ui.py +0 -0
@@ -1,16 +1,16 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-server
3
- Version: 0.20.0
3
+ Version: 0.22.0
4
4
  Summary: Dirigent FastAPI server: the REST API, its authentication, and the health probes.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
7
7
  License-File: THIRD_PARTY_NOTICES.md
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Programming Language :: Python :: 3.13
10
- Requires-Dist: dirigent-client==0.20.0
11
- Requires-Dist: dirigent-common==0.20.0
12
- Requires-Dist: dirigent-core==0.20.0
13
- Requires-Dist: dirigent-examples==0.20.0
10
+ Requires-Dist: dirigent-client==0.22.0
11
+ Requires-Dist: dirigent-common==0.22.0
12
+ Requires-Dist: dirigent-core==0.22.0
13
+ Requires-Dist: dirigent-examples==0.22.0
14
14
  Requires-Dist: fastapi>=0.141.1
15
15
  Requires-Python: >=3.13
16
16
  Description-Content-Type: text/markdown
@@ -540,7 +540,7 @@ in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License
540
540
  ## SIL Open Font License 1.1
541
541
 
542
542
  - `@fontsource-variable/ibm-plex-sans` -- IBM Plex Sans, Copyright 2019 IBM Corp. All rights reserved.
543
- - `@fontsource/ibm-plex-mono` -- IBM Plex Mono, Copyright 2017 IBM Corp. All rights reserved.
543
+ - `@fontsource/jetbrains-mono` -- JetBrains Mono, Copyright 2020 The JetBrains Mono Project Authors, SIL Open Font License 1.1.
544
544
 
545
545
  ```
546
546
  SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-server"
3
- version = "0.20.0"
3
+ version = "0.22.0"
4
4
  description = "Dirigent FastAPI server: the REST API, its authentication, and the health probes."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -14,10 +14,10 @@ classifiers = [
14
14
  "Programming Language :: Python :: 3.13",
15
15
  ]
16
16
  dependencies = [
17
- "dirigent-client==0.20.0",
18
- "dirigent-common==0.20.0",
19
- "dirigent-core==0.20.0",
20
- "dirigent-examples==0.20.0",
17
+ "dirigent-client==0.22.0",
18
+ "dirigent-common==0.22.0",
19
+ "dirigent-core==0.22.0",
20
+ "dirigent-examples==0.22.0",
21
21
  "fastapi>=0.141.1",
22
22
  ]
23
23
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-server"
3
- version = "0.20.0"
3
+ version = "0.22.0"
4
4
  description = "Dirigent FastAPI server: the REST API, its authentication, and the health probes."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -11,10 +11,10 @@ classifiers = [
11
11
  "Programming Language :: Python :: 3.13",
12
12
  ]
13
13
  dependencies = [
14
- "dirigent-client==0.20.0",
15
- "dirigent-common==0.20.0",
16
- "dirigent-core==0.20.0",
17
- "dirigent-examples==0.20.0",
14
+ "dirigent-client==0.22.0",
15
+ "dirigent-common==0.22.0",
16
+ "dirigent-core==0.22.0",
17
+ "dirigent-examples==0.22.0",
18
18
  "fastapi>=0.141.1",
19
19
  ]
20
20
 
@@ -7,7 +7,7 @@ from contextlib import asynccontextmanager
7
7
 
8
8
  from fastapi import FastAPI
9
9
 
10
- from dirigent_core import __version__
10
+ from dirigent_core import __version__, wakeups
11
11
  from dirigent_core.auth import BOOTSTRAP_PASSWORD_ENV, bootstrap_admin
12
12
  from dirigent_core.config import Settings, get_settings
13
13
  from dirigent_core.database import create_engine, create_session_factory, session_scope
@@ -73,16 +73,17 @@ def create_app(
73
73
  app.state.scheduler = None
74
74
  clock: asyncio.Task[None] | None = None
75
75
  try:
76
- await _bootstrap(app)
77
- await _apply_startup_directory(app)
78
- clock = await _start_scheduler(app, embed=embed)
79
- _logger.info(
80
- "server starting",
81
- database="sqlite" if resolved.is_sqlite else "postgresql",
82
- blocks=len(app.state.services.host.block_ids),
83
- scheduler=embed,
84
- )
85
- yield
76
+ async with wakeups.listening(resolved.database_url):
77
+ await _bootstrap(app)
78
+ await _apply_startup_directory(app)
79
+ clock = await _start_scheduler(app, embed=embed)
80
+ _logger.info(
81
+ "server starting",
82
+ database="sqlite" if resolved.is_sqlite else "postgresql",
83
+ blocks=len(app.state.services.host.block_ids),
84
+ scheduler=embed,
85
+ )
86
+ yield
86
87
  finally:
87
88
  await _stop_scheduler(app, clock)
88
89
  await engine.dispose()
@@ -9,6 +9,7 @@ from fastapi import APIRouter, Request, Response, status
9
9
  from sqlalchemy.ext.asyncio import AsyncEngine
10
10
 
11
11
  from dirigent_client.schemas import CheckResult, CheckStatus, Health, Readiness
12
+ from dirigent_common import raised_detail
12
13
  from dirigent_core.database import ping
13
14
 
14
15
  router = APIRouter(tags=["health"])
@@ -73,7 +74,7 @@ async def run_checks(registry: HealthCheckRegistry) -> dict[str, CheckResult]:
73
74
  try:
74
75
  return await check.check()
75
76
  except Exception as error:
76
- return CheckResult(status=CheckStatus.UNHEALTHY, detail=f"{type(error).__name__}: {error}")
77
+ return CheckResult(status=CheckStatus.UNHEALTHY, detail=raised_detail(error))
77
78
 
78
79
  names = list(registry)
79
80
  results = await asyncio.gather(*(run(registry[name]) for name in names))
@@ -15,6 +15,7 @@ from dirigent_server.routes import (
15
15
  connections,
16
16
  examples,
17
17
  hooks,
18
+ labels,
18
19
  pipelines,
19
20
  playground,
20
21
  runs,
@@ -38,6 +39,7 @@ TAGS: list[dict[str, str]] = [
38
39
  {"name": "hooks", "description": "Webhook intake, authenticated by its own token."},
39
40
  {"name": "connections", "description": "Named credential records of contributed kinds."},
40
41
  {"name": "blocks", "description": "The catalog every plugin contributes to."},
42
+ {"name": "labels", "description": "The wording every installed pack refuses in."},
41
43
  {"name": "examples", "description": "The documents every installed plugin ships."},
42
44
  {"name": "schema", "description": "The shape a document is written against."},
43
45
  {"name": "schemas", "description": "Named JSON Schemas the instance holds."},
@@ -72,6 +74,7 @@ def build_router(settings: Settings | None = None) -> APIRouter:
72
74
  alerts,
73
75
  connections,
74
76
  blocks,
77
+ labels,
75
78
  examples,
76
79
  schema,
77
80
  schemas,
@@ -0,0 +1,16 @@
1
+ """The wording every installed pack refuses in, for a surface that renders its own sentences."""
2
+
3
+ from fastapi import APIRouter
4
+
5
+ from dirigent_client.schemas import Labels
6
+ from dirigent_server.dependencies import ServicesDep
7
+ from dirigent_server.security import PrincipalDep
8
+ from dirigent_server.transactions import Transactional
9
+
10
+ router = APIRouter(route_class=Transactional, tags=["labels"])
11
+
12
+
13
+ @router.get("/labels", operation_id="getLabels", summary="Contributed refusal wording", response_model=Labels)
14
+ async def get_labels(services: ServicesDep, principal: PrincipalDep) -> Labels:
15
+ """Serve every code an installed pack can refuse under, with the template it renders from."""
16
+ return Labels(templates={code: message.text for code, message in services.host.labels.items()})
@@ -28,6 +28,7 @@ from dirigent_core.documents import carried_refusal, load_document
28
28
  from dirigent_core.engine import Attribution, create_run
29
29
  from dirigent_core.engine.definition import load_definition
30
30
  from dirigent_core.engine.runs import Provenance, RunWindow
31
+ from dirigent_core.engine.services import EngineServices
31
32
  from dirigent_core.messages import PIPELINE_DEACTIVATED, PIPELINE_NO_VERSIONS
32
33
  from dirigent_core.models import Pipeline
33
34
  from dirigent_core.pipelines import (
@@ -64,6 +65,7 @@ def render(row: Pipeline, counts: PipelineCounts = NO_COUNTS, last: LastRun | No
64
65
  "active_runs": counts.active_runs,
65
66
  "schedules": counts.schedules,
66
67
  "webhooks": counts.webhooks,
68
+ "watches": counts.watches,
67
69
  "last_run": last,
68
70
  }
69
71
  )
@@ -113,7 +115,7 @@ async def apply(
113
115
  ) -> ApplyResult:
114
116
  """Validate a document against this instance and commit a new version, or plan one.
115
117
 
116
- ``pause_schedules`` on the request creates this apply's new schedules paused; one the
118
+ ``pause_schedules`` on the request creates this apply's new schedules and watches paused; one the
117
119
  instance already holds keeps the paused state it has.
118
120
  """
119
121
  raw = dict(payload.document)
@@ -147,6 +149,7 @@ async def apply(
147
149
  async def prune(
148
150
  payload: PruneRequest,
149
151
  session: SessionDep,
152
+ services: ServicesDep,
150
153
  principal: OperatorDep,
151
154
  dry_run: Annotated[bool, Query(description="Report what would be deactivated without writing.")] = False,
152
155
  ) -> PruneResult:
@@ -160,7 +163,7 @@ async def prune(
160
163
  """
161
164
  if not payload.keep and not dry_run:
162
165
  raise Refusal(PRUNE_NAMES_NOTHING, status=status.HTTP_422_UNPROCESSABLE_CONTENT)
163
- return await prune_absent(session, set(payload.keep), dry_run=dry_run)
166
+ return await prune_absent(session, services, set(payload.keep), dry_run=dry_run)
164
167
 
165
168
 
166
169
  @router.get(
@@ -243,9 +246,9 @@ async def validate_stored(
243
246
  summary="Activate a pipeline",
244
247
  response_model=PipelineOut,
245
248
  )
246
- async def activate(code: str, session: SessionDep, principal: OperatorDep) -> PipelineOut:
247
- """Make a pipeline runnable again, and let its schedules fire."""
248
- return render(await _act(session, code, active=True))
249
+ async def activate(code: str, session: SessionDep, services: ServicesDep, principal: OperatorDep) -> PipelineOut:
250
+ """Make a pipeline runnable again, let its schedules fire, and arm its watches."""
251
+ return render(await _act(session, services, code, active=True))
249
252
 
250
253
 
251
254
  @router.post(
@@ -254,9 +257,9 @@ async def activate(code: str, session: SessionDep, principal: OperatorDep) -> Pi
254
257
  summary="Deactivate a pipeline",
255
258
  response_model=PipelineOut,
256
259
  )
257
- async def deactivate(code: str, session: SessionDep, principal: OperatorDep) -> PipelineOut:
258
- """Deregister a pipeline: schedules pause, it stops being runnable, history is kept."""
259
- return render(await _act(session, code, active=False))
260
+ async def deactivate(code: str, session: SessionDep, services: ServicesDep, principal: OperatorDep) -> PipelineOut:
261
+ """Deregister a pipeline: schedules pause, watches stop waiting, it stops being runnable, history is kept."""
262
+ return render(await _act(session, services, code, active=False))
260
263
 
261
264
 
262
265
  @router.delete(
@@ -265,15 +268,16 @@ async def deactivate(code: str, session: SessionDep, principal: OperatorDep) ->
265
268
  summary="Delete a pipeline and its history",
266
269
  status_code=status.HTTP_204_NO_CONTENT,
267
270
  )
268
- async def delete(code: str, session: SessionDep, principal: AdminDep) -> Response:
271
+ async def delete(code: str, session: SessionDep, services: ServicesDep, principal: AdminDep) -> Response:
269
272
  """Delete a pipeline and every run ever attributed to it, in one transaction.
270
273
 
271
274
  Admin, unlike every other pipeline verb, and it takes the history with it: the runs,
272
- their items, attempts, logs and artifact references, plus the versions, schedules and
273
- webhooks the definition owns. Runs still in flight refuse the delete with a 409 --
275
+ their items, attempts, logs and artifact references, plus the versions, schedules,
276
+ webhooks and watches the definition owns. The run a watch has waiting is cancelled; any
277
+ other run still in flight refuses the delete with a 409 --
274
278
  finish or cancel them first. Deactivating is the reversible verb an operator has.
275
279
  """
276
- await delete_pipeline(session, code)
280
+ await delete_pipeline(session, services, code)
277
281
  return Response(status_code=status.HTTP_204_NO_CONTENT)
278
282
 
279
283
 
@@ -388,6 +392,6 @@ async def _require(session: AsyncSession, code: str) -> Pipeline:
388
392
  return await require_pipeline(session, code)
389
393
 
390
394
 
391
- async def _act(session: AsyncSession, code: str, *, active: bool) -> Pipeline:
395
+ async def _act(session: AsyncSession, services: EngineServices, code: str, *, active: bool) -> Pipeline:
392
396
  """Activate or deactivate, which refuses an unknown code as a 404 of its own."""
393
- return await set_active(session, code, active=active)
397
+ return await set_active(session, services, code, active=active)
@@ -1,6 +1,7 @@
1
1
  """Runs: the list, the detail with its DAG view model, cancellation, retry, logs, events, and a report."""
2
2
 
3
3
  import asyncio
4
+ import time
4
5
  from collections.abc import AsyncGenerator, Generator, Mapping, Sequence
5
6
  from contextlib import contextmanager
6
7
  from datetime import UTC, datetime, timedelta
@@ -12,7 +13,7 @@ from fastapi import APIRouter, Header, Query, Request, Response, status
12
13
  from fastapi.responses import PlainTextResponse, StreamingResponse
13
14
  from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker
14
15
 
15
- from dirigent_client.enums import AttemptStatus, LogLevel, RunItemStatus, RunStatus
16
+ from dirigent_client.enums import AttemptStatus, LogLevel, RunItemStatus, RunStatus, TriggerKind
16
17
  from dirigent_client.schemas import (
17
18
  TERMINAL_RUN_STATUSES,
18
19
  ArtifactOut,
@@ -29,12 +30,13 @@ from dirigent_client.schemas import (
29
30
  StepReport,
30
31
  )
31
32
  from dirigent_common.durations import DurationError, parse_duration
32
- from dirigent_core import telemetry
33
+ from dirigent_core import telemetry, wakeups
33
34
  from dirigent_core.artifacts import JSON_CONTENT_TYPE, TEXT_KEY, canonical_json, open_artifact
34
35
  from dirigent_core.database import session_scope
35
36
  from dirigent_core.engine.definition import PipelineDefinition, load_definition
36
37
  from dirigent_core.engine.runs import cancel_run, retry_step
37
38
  from dirigent_core.engine.state import StepCounts, attempt_counts, item_counts, step_states
39
+ from dirigent_core.messages import CANCELLED_BY
38
40
  from dirigent_core.models import (
39
41
  ArtifactRef,
40
42
  LogEntry,
@@ -63,7 +65,7 @@ from dirigent_server.messages import (
63
65
  )
64
66
  from dirigent_server.pagination import DEFAULT_PAGE, AfterParam, LimitParam, clip, int_cursor, uuid_cursor
65
67
  from dirigent_server.security import OperatorDep, PrincipalDep
66
- from dirigent_server.transactions import Transactional
68
+ from dirigent_server.transactions import Transactional, retried_on_deadlock
67
69
 
68
70
  router = APIRouter(route_class=Transactional, tags=["runs"])
69
71
 
@@ -119,10 +121,12 @@ def _render_run(run: Run, pipeline: Pipeline, version: PipelineVersion, failed:
119
121
  priority=run.priority,
120
122
  params=dict(run.params),
121
123
  triggered_by_kind=run.triggered_by_kind,
124
+ parent_run_id=run.triggered_by_id if run.triggered_by_kind is TriggerKind.PIPELINE else None,
122
125
  triggered_by_label=run.triggered_by_label,
123
126
  trace_id=telemetry.trace_id_of(run.traceparent),
124
127
  error=run.error or (failed.error if failed is not None else None),
125
128
  error_code=run.error_code or (failed.code if failed is not None else None),
129
+ error_params=run.error_params or (failed.params if failed is not None else None),
126
130
  failed_step=failed.step if failed is not None else None,
127
131
  started_at=run.started_at,
128
132
  finished_at=run.finished_at,
@@ -161,6 +165,7 @@ def _dag(
161
165
  depends_on=list(step.depends_on),
162
166
  rule=step.rule.value,
163
167
  fan_out=step.is_fan_out,
168
+ grid_source=definition.grid_source(name),
164
169
  items_total=sum(of_step.values()),
165
170
  items_failed=of_step.get(RunItemStatus.FAILED, 0),
166
171
  attempts=attempts[name].total if name in attempts else 0,
@@ -383,10 +388,14 @@ def _render_attempt(attempt: StepAttempt, spilled: dict[UUID, tuple[str, int | N
383
388
  @router.post("/runs/{run_id}/$cancel", operation_id="cancelRun", summary="Cancel a run", response_model=RunOut)
384
389
  async def cancel(run_id: UUID, session: SessionDep, services: ServicesDep, principal: OperatorDep) -> RunOut:
385
390
  """Stop what has not started, and tell the remote about what has."""
386
- run = await _run_row(session, run_id)
387
- pipeline, version, _ = await _context(session, run)
388
- await cancel_run(session, services, run, reason=f"cancelled by {principal.label}")
389
- return _render_run(run, pipeline, version)
391
+
392
+ async def cancel_once() -> RunOut:
393
+ run = await _run_row(session, run_id)
394
+ pipeline, version, _ = await _context(session, run)
395
+ await cancel_run(session, services, run, CANCELLED_BY, principal=principal.label)
396
+ return _render_run(run, pipeline, version)
397
+
398
+ return await retried_on_deadlock(session, cancel_once)
390
399
 
391
400
 
392
401
  @router.post(
@@ -480,6 +489,19 @@ def next_interval(current: float) -> float:
480
489
  return min(current * FOLLOW_BACKOFF, FOLLOW_MAX_INTERVAL_SECONDS)
481
490
 
482
491
 
492
+ async def quiet_wait(mark: wakeups.Mark, waited: float, interval: float) -> tuple[float, float]:
493
+ """Wait out one quiet interval, or less when the run moves, and say how long and what next.
494
+
495
+ A run that moved sends the stream back to its shortest interval.
496
+ """
497
+ started = time.monotonic()
498
+ moved = await wakeups.wait_settled(mark, timeout=interval)
499
+ elapsed = time.monotonic() - started
500
+ if moved:
501
+ return waited + elapsed, FOLLOW_INTERVAL_SECONDS
502
+ return waited + elapsed, next_interval(interval)
503
+
504
+
483
505
  def _claim(user_id: UUID) -> str:
484
506
  """Name the principal a stream is opened by, refusing one that already holds the cap.
485
507
 
@@ -547,6 +569,7 @@ async def _tail(
547
569
  waited = 0.0
548
570
  interval = FOLLOW_INTERVAL_SECONDS
549
571
  while waited < FOLLOW_MAX_SECONDS:
572
+ moved = wakeups.settled_mark(run_id)
550
573
  page, settled = await asyncio.shield(_tail_read(sessions, run_id, cursor, step))
551
574
  for entry in page.items:
552
575
  yield f"id: {entry.id}\nevent: log\ndata: {entry.model_dump_json()}\n\n"
@@ -557,9 +580,7 @@ async def _tail(
557
580
  if settled:
558
581
  yield "event: end\ndata: {}\n\n"
559
582
  return
560
- await asyncio.sleep(interval)
561
- waited += interval
562
- interval = next_interval(interval)
583
+ waited, interval = await quiet_wait(moved, waited, interval)
563
584
  yield "event: expired\ndata: {}\n\n"
564
585
 
565
586
 
@@ -735,6 +756,7 @@ async def _story(
735
756
  waited = 0.0
736
757
  interval = FOLLOW_INTERVAL_SECONDS
737
758
  while waited < FOLLOW_MAX_SECONDS:
759
+ changed = wakeups.settled_mark(run_id)
738
760
  # Shielded for the same reason _tail_read is: a disconnect lands between polls,
739
761
  # never inside a driver await holding the pooled connection.
740
762
  attempts, spilled, page, rendered, read_labels = await asyncio.shield(
@@ -778,9 +800,7 @@ async def _story(
778
800
  return
779
801
  drained = True
780
802
  continue
781
- await asyncio.sleep(interval)
782
- waited += interval
783
- interval = next_interval(interval)
803
+ waited, interval = await quiet_wait(changed, waited, interval)
784
804
  yield "event: expired\ndata: {}\n\n"
785
805
 
786
806
 
@@ -814,10 +834,14 @@ async def report(run_id: UUID, session: SessionDep, principal: PrincipalDep) ->
814
834
  warnings=step.warnings,
815
835
  duration_ms=step.duration_ms,
816
836
  error=step.error,
837
+ error_code=step.error_code,
838
+ error_params=step.error_params,
817
839
  )
818
840
  for step in facts.steps
819
841
  ],
820
842
  items_total=facts.items_total,
821
843
  items_failed=facts.items_failed,
822
844
  error=run.error,
845
+ error_code=run.error_code,
846
+ error_params=run.error_params,
823
847
  )
@@ -1,4 +1,4 @@
1
- """Triggers documents: the clocks and webhooks one document declares for another's pipeline.
1
+ """Triggers documents: the clocks, webhooks and watches one document declares for another's pipeline.
2
2
 
3
3
  A document is applied through ``POST /pipelines/$apply`` like any other; what is here is
4
4
  reading the ones the instance holds, and removing one with the rows it owns.
@@ -16,7 +16,7 @@ from dirigent_core.trigger_documents import (
16
16
  list_trigger_documents,
17
17
  owned_codes,
18
18
  )
19
- from dirigent_server.dependencies import SessionDep
19
+ from dirigent_server.dependencies import ServicesDep, SessionDep
20
20
  from dirigent_server.errors import Refusal
21
21
  from dirigent_server.messages import NO_TRIGGER_DOCUMENT
22
22
  from dirigent_server.pagination import DEFAULT_PAGE, AfterParam, LimitParam, clip
@@ -71,13 +71,14 @@ async def list_all(
71
71
  async def get_one(code: str, session: SessionDep, principal: PrincipalDep) -> TriggerDocumentDetail:
72
72
  """Read one triggers document, the document itself, and the rows it owns."""
73
73
  row = await _require(session, code)
74
- schedules, webhooks = await owned_codes(session, row.id)
74
+ schedules, webhooks, watches = await owned_codes(session, row.id)
75
75
  base = render(row, await _pipeline_code(session, row))
76
76
  return TriggerDocumentDetail(
77
77
  **base.model_dump(),
78
78
  document=dict(row.document),
79
79
  schedules=schedules,
80
80
  webhooks=webhooks,
81
+ watches=watches,
81
82
  )
82
83
 
83
84
 
@@ -87,13 +88,13 @@ async def get_one(code: str, session: SessionDep, principal: PrincipalDep) -> Tr
87
88
  summary="Delete a triggers document and its rows",
88
89
  status_code=status.HTTP_204_NO_CONTENT,
89
90
  )
90
- async def delete(code: str, session: SessionDep, principal: OperatorDep) -> Response:
91
- """Remove a triggers document, and with it every schedule and webhook it declared.
91
+ async def delete(code: str, session: SessionDep, services: ServicesDep, principal: OperatorDep) -> Response:
92
+ """Remove a triggers document, and with it every schedule, webhook and watch it declared.
92
93
 
93
94
  The pipeline it named is untouched, and so is anything the pipeline's own document or an
94
95
  operator declared on it.
95
96
  """
96
- await delete_trigger_document(session, await _require(session, code))
97
+ await delete_trigger_document(session, services, await _require(session, code))
97
98
  return Response(status_code=status.HTTP_204_NO_CONTENT)
98
99
 
99
100
 
@@ -1,4 +1,4 @@
1
- """A pipeline's persisted triggers: its schedules and its inbound webhooks.
1
+ """A pipeline's persisted triggers: its schedules, its inbound webhooks, and its watches.
2
2
 
3
3
  The instance keeps only the hash of a webhook's token, so the token is readable exactly
4
4
  once: when it is minted or rotated.
@@ -22,6 +22,7 @@ from dirigent_client.schemas import (
22
22
  ScheduleOut,
23
23
  SchedulePreview,
24
24
  SchedulePreviewRequest,
25
+ WatchOut,
25
26
  WebhookIn,
26
27
  WebhookOut,
27
28
  WebhookTokenOut,
@@ -34,6 +35,7 @@ from dirigent_core.models import (
34
35
  Schedule,
35
36
  ScheduleFiring,
36
37
  TriggerDocument,
38
+ Watch,
37
39
  WebhookDelivery,
38
40
  WebhookTrigger,
39
41
  )
@@ -41,6 +43,7 @@ from dirigent_core.pipelines import get_version, require_pipeline
41
43
  from dirigent_core.triggers import (
42
44
  ScheduleRequest,
43
45
  UnknownSchedule,
46
+ UnknownWatch,
44
47
  UnknownWebhook,
45
48
  WebhookRequest,
46
49
  check_schedule_params,
@@ -50,21 +53,24 @@ from dirigent_core.triggers import (
50
53
  delete_schedule,
51
54
  delete_webhook,
52
55
  find_schedule,
56
+ find_watch,
53
57
  find_webhook,
54
58
  list_deliveries,
55
59
  list_firings,
56
60
  list_schedules,
61
+ list_watches,
57
62
  list_webhooks,
58
63
  preview_firings,
59
64
  rotate_token,
60
65
  set_active,
61
66
  set_paused,
67
+ set_watch_paused,
62
68
  update_schedule,
63
69
  )
64
70
  from dirigent_server.dependencies import ServicesDep, SessionDep
65
71
  from dirigent_server.pagination import DEFAULT_PAGE, AfterParam, LimitParam, clip, int_cursor
66
72
  from dirigent_server.security import OperatorDep, PrincipalDep
67
- from dirigent_server.transactions import Transactional
73
+ from dirigent_server.transactions import Transactional, retried_on_deadlock
68
74
 
69
75
  router = APIRouter(route_class=Transactional, tags=["triggers"])
70
76
 
@@ -101,7 +107,7 @@ def _webhook_request(payload: WebhookIn) -> WebhookRequest:
101
107
  )
102
108
 
103
109
 
104
- async def owning_documents(session: AsyncSession, rows: Sequence[Schedule | WebhookTrigger]) -> dict[UUID, str]:
110
+ async def owning_documents(session: AsyncSession, rows: Sequence[Schedule | WebhookTrigger | Watch]) -> dict[UUID, str]:
105
111
  """Read the code of every triggers document that owns one of these rows."""
106
112
  wanted = {row.trigger_document_id for row in rows if row.trigger_document_id is not None}
107
113
  if not wanted:
@@ -158,6 +164,29 @@ def render_webhook(row: WebhookTrigger, documents: Mapping[UUID, str] = MappingP
158
164
  )
159
165
 
160
166
 
167
+ def render_watch(row: Watch, documents: Mapping[UUID, str] = MappingProxyType({})) -> WatchOut:
168
+ """Render a watch row: what it waits on, where it left off, and how its waits are going."""
169
+ return WatchOut(
170
+ id=row.id,
171
+ code=row.code,
172
+ name=row.name,
173
+ description=row.description,
174
+ step=row.step,
175
+ params=dict(row.params),
176
+ paused=row.paused,
177
+ managed=row.managed,
178
+ trigger_document=documents.get(row.trigger_document_id) if row.trigger_document_id else None,
179
+ cursor=dict(row.cursor) if row.cursor is not None else None,
180
+ waiting_run_id=row.waiting_run_id,
181
+ failures=row.failures,
182
+ last_error=row.last_error,
183
+ last_error_at=row.last_error_at,
184
+ rearm_at=row.rearm_at,
185
+ last_armed_at=row.last_armed_at,
186
+ created_at=row.created_at,
187
+ )
188
+
189
+
161
190
  async def _schedule_out(session: AsyncSession, row: Schedule) -> ScheduleOut:
162
191
  """Render one schedule, with the code of whichever triggers document owns it."""
163
192
  return render_schedule(row, await owning_documents(session, [row]))
@@ -463,6 +492,79 @@ async def remove_webhook(code: str, webhook: str, session: SessionDep, principal
463
492
  return Response(status_code=status.HTTP_204_NO_CONTENT)
464
493
 
465
494
 
495
+ @router.get(
496
+ "/pipelines/{code}/triggers/watches",
497
+ operation_id="listWatches",
498
+ summary="List a pipeline's watches",
499
+ response_model=Page[WatchOut],
500
+ )
501
+ async def watches(
502
+ code: str,
503
+ session: SessionDep,
504
+ principal: PrincipalDep,
505
+ after: AfterParam = None,
506
+ limit: LimitParam = DEFAULT_PAGE,
507
+ ) -> Page[WatchOut]:
508
+ """List every watch on a pipeline, with the run each one has waiting."""
509
+ pipeline = await _require(session, code)
510
+ rows = await list_watches(session, pipeline.id, after=after, limit=limit + 1)
511
+ documents = await owning_documents(session, rows)
512
+ items, following = clip([render_watch(row, documents) for row in rows], limit, lambda row: row.code)
513
+ return Page(items=items, next=following)
514
+
515
+
516
+ @router.get(
517
+ "/pipelines/{code}/triggers/watches/{watch}",
518
+ operation_id="getWatch",
519
+ summary="Read one watch",
520
+ response_model=WatchOut,
521
+ )
522
+ async def get_watch(code: str, watch: str, session: SessionDep, principal: PrincipalDep) -> WatchOut:
523
+ """Read one watch by code."""
524
+ return await _watch_out(session, await _require_watch(session, code, watch))
525
+
526
+
527
+ @router.post(
528
+ "/pipelines/{code}/triggers/watches/{watch}/$pause",
529
+ operation_id="pauseWatch",
530
+ summary="Pause a watch",
531
+ response_model=WatchOut,
532
+ )
533
+ async def pause_watch(
534
+ code: str, watch: str, session: SessionDep, services: ServicesDep, principal: OperatorDep
535
+ ) -> WatchOut:
536
+ """Stop a watch, cancelling the run it has waiting, and keep where it left off."""
537
+
538
+ async def pause_once() -> WatchOut:
539
+ row = await _require_watch(session, code, watch)
540
+ return await _watch_out(session, await set_watch_paused(session, services, row, paused=True))
541
+
542
+ return await retried_on_deadlock(session, pause_once)
543
+
544
+
545
+ @router.post(
546
+ "/pipelines/{code}/triggers/watches/{watch}/$resume",
547
+ operation_id="resumeWatch",
548
+ summary="Resume a watch",
549
+ response_model=WatchOut,
550
+ )
551
+ async def resume_watch(
552
+ code: str, watch: str, session: SessionDep, services: ServicesDep, principal: OperatorDep
553
+ ) -> WatchOut:
554
+ """Start a watch again, arming a run from where its last success left off."""
555
+
556
+ async def resume_once() -> WatchOut:
557
+ row = await _require_watch(session, code, watch)
558
+ return await _watch_out(session, await set_watch_paused(session, services, row, paused=False))
559
+
560
+ return await retried_on_deadlock(session, resume_once)
561
+
562
+
563
+ async def _watch_out(session: AsyncSession, row: Watch) -> WatchOut:
564
+ """Render one watch, with the code of whichever triggers document owns it."""
565
+ return render_watch(row, await owning_documents(session, [row]))
566
+
567
+
466
568
  async def _check_pins(session: AsyncSession, services: EngineServices, pipeline_id: UUID, payload: ScheduleIn) -> None:
467
569
  """Check a schedule's pinned parameters against the definition its firings will run.
468
570
 
@@ -501,6 +603,15 @@ async def _require_schedule(session: AsyncSession, pipeline_code: str, code: str
501
603
  return schedule
502
604
 
503
605
 
606
+ async def _require_watch(session: AsyncSession, pipeline_code: str, code: str) -> Watch:
607
+ """Read one watch within its pipeline, or say which half was not found."""
608
+ pipeline = await _require(session, pipeline_code)
609
+ watch = await find_watch(session, pipeline.id, code)
610
+ if watch is None:
611
+ raise UnknownWatch(pipeline_code, code)
612
+ return watch
613
+
614
+
504
615
  async def _require_webhook(session: AsyncSession, pipeline_code: str, code: str) -> WebhookTrigger:
505
616
  """Read one webhook within its pipeline, or say which half was not found."""
506
617
  pipeline = await _require(session, pipeline_code)
@@ -0,0 +1 @@
1
+ import{t as e}from"./labels-D4COsPsJ.js";import{n as t}from"./PageState-Dqk77uol.js";import{r as n}from"./utils-CT7ZGLfR.js";import{t as r}from"./use-store-CZcp6jmY.js";import{n as i,t as a}from"./auth-DdhSYe4e.js";var o=n(),s={status:403,title:e.refusal.admin_only,code:`server.forbidden`,params:{},detail:e.refusal.shut,problems:[],instance:null};function c({children:e}){let n=r(a);return i(n)?(0,o.jsx)(o.Fragment,{children:e}):(0,o.jsx)(t,{loading:!1,problem:s,empty:!1,children:null})}export{c as t};