@dxos/plugin-routine 0.0.0

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 (403) hide show
  1. package/LICENSE +105 -0
  2. package/PLUGIN.mdl +475 -0
  3. package/README.md +15 -0
  4. package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs +95 -0
  5. package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs.map +7 -0
  6. package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs +249 -0
  7. package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs.map +7 -0
  8. package/dist/lib/neutral/RoutinePlugin.mjs +10 -0
  9. package/dist/lib/neutral/RoutinePlugin.mjs.map +7 -0
  10. package/dist/lib/neutral/RoutinePlugin.node.mjs +1133 -0
  11. package/dist/lib/neutral/RoutinePlugin.node.mjs.map +7 -0
  12. package/dist/lib/neutral/RoutinePlugin.workerd.mjs +36 -0
  13. package/dist/lib/neutral/RoutinePlugin.workerd.mjs.map +7 -0
  14. package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs +48 -0
  15. package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs.map +7 -0
  16. package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs +236 -0
  17. package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs.map +7 -0
  18. package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs +27 -0
  19. package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs.map +7 -0
  20. package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs +90 -0
  21. package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs.map +7 -0
  22. package/dist/lib/neutral/capabilities/index.mjs +25 -0
  23. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  24. package/dist/lib/neutral/capabilities/node.mjs +19 -0
  25. package/dist/lib/neutral/capabilities/node.mjs.map +7 -0
  26. package/dist/lib/neutral/chunk-674LDIUJ.mjs +9 -0
  27. package/dist/lib/neutral/chunk-674LDIUJ.mjs.map +7 -0
  28. package/dist/lib/neutral/chunk-CNYAPXUW.mjs +65 -0
  29. package/dist/lib/neutral/chunk-CNYAPXUW.mjs.map +7 -0
  30. package/dist/lib/neutral/chunk-HLO4LYXT.mjs +44 -0
  31. package/dist/lib/neutral/chunk-HLO4LYXT.mjs.map +7 -0
  32. package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
  33. package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
  34. package/dist/lib/neutral/chunk-ODQDVFMZ.mjs +8 -0
  35. package/dist/lib/neutral/chunk-ODQDVFMZ.mjs.map +7 -0
  36. package/dist/lib/neutral/chunk-R7J2MU2M.mjs +263 -0
  37. package/dist/lib/neutral/chunk-R7J2MU2M.mjs.map +7 -0
  38. package/dist/lib/neutral/chunk-WLNL77C7.mjs +14 -0
  39. package/dist/lib/neutral/chunk-WLNL77C7.mjs.map +7 -0
  40. package/dist/lib/neutral/components/index.mjs +1921 -0
  41. package/dist/lib/neutral/components/index.mjs.map +7 -0
  42. package/dist/lib/neutral/containers/index.mjs +17 -0
  43. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  44. package/dist/lib/neutral/create-object-V23KVDMJ.mjs +25 -0
  45. package/dist/lib/neutral/create-object-V23KVDMJ.mjs.map +7 -0
  46. package/dist/lib/neutral/create-routine-I67BYJA2.mjs +38 -0
  47. package/dist/lib/neutral/create-routine-I67BYJA2.mjs.map +7 -0
  48. package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs +70 -0
  49. package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs.map +7 -0
  50. package/dist/lib/neutral/hooks/index.mjs +47 -0
  51. package/dist/lib/neutral/hooks/index.mjs.map +7 -0
  52. package/dist/lib/neutral/index.mjs +27 -0
  53. package/dist/lib/neutral/index.mjs.map +7 -0
  54. package/dist/lib/neutral/layer-specs-ADQCTTRT.mjs +135 -0
  55. package/dist/lib/neutral/layer-specs-ADQCTTRT.mjs.map +7 -0
  56. package/dist/lib/neutral/meta.json +1 -0
  57. package/dist/lib/neutral/meta.mjs +8 -0
  58. package/dist/lib/neutral/meta.mjs.map +7 -0
  59. package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs +18 -0
  60. package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs.map +7 -0
  61. package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs +13 -0
  62. package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs.map +7 -0
  63. package/dist/lib/neutral/operations/index.mjs +8 -0
  64. package/dist/lib/neutral/operations/index.mjs.map +7 -0
  65. package/dist/lib/neutral/plugin.mjs +16 -0
  66. package/dist/lib/neutral/plugin.mjs.map +7 -0
  67. package/dist/lib/neutral/react-surface-GMO7I7YE.mjs +67 -0
  68. package/dist/lib/neutral/react-surface-GMO7I7YE.mjs.map +7 -0
  69. package/dist/lib/neutral/registry-sync-PHBU6CH2.mjs +86 -0
  70. package/dist/lib/neutral/registry-sync-PHBU6CH2.mjs.map +7 -0
  71. package/dist/lib/neutral/run-routine-HJWXIWLJ.mjs +37 -0
  72. package/dist/lib/neutral/run-routine-HJWXIWLJ.mjs.map +7 -0
  73. package/dist/lib/neutral/templates-IIUCEBAX.mjs +49 -0
  74. package/dist/lib/neutral/templates-IIUCEBAX.mjs.map +7 -0
  75. package/dist/lib/neutral/testing.mjs +8 -0
  76. package/dist/lib/neutral/testing.mjs.map +7 -0
  77. package/dist/lib/neutral/translations.mjs +115 -0
  78. package/dist/lib/neutral/translations.mjs.map +7 -0
  79. package/dist/lib/neutral/trigger-runtime-controller-7FOTH2NP.mjs +77 -0
  80. package/dist/lib/neutral/trigger-runtime-controller-7FOTH2NP.mjs.map +7 -0
  81. package/dist/lib/neutral/types/index.mjs +17 -0
  82. package/dist/lib/neutral/types/index.mjs.map +7 -0
  83. package/dist/types/dx.config.d.ts +28 -0
  84. package/dist/types/dx.config.d.ts.map +1 -0
  85. package/dist/types/src/RoutinePlugin.d.ts +4 -0
  86. package/dist/types/src/RoutinePlugin.d.ts.map +1 -0
  87. package/dist/types/src/RoutinePlugin.node.d.ts +4 -0
  88. package/dist/types/src/RoutinePlugin.node.d.ts.map +1 -0
  89. package/dist/types/src/RoutinePlugin.test.d.ts +2 -0
  90. package/dist/types/src/RoutinePlugin.test.d.ts.map +1 -0
  91. package/dist/types/src/RoutinePlugin.workerd.d.ts +4 -0
  92. package/dist/types/src/RoutinePlugin.workerd.d.ts.map +1 -0
  93. package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
  94. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  95. package/dist/types/src/capabilities/create-object.d.ts +5 -0
  96. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  97. package/dist/types/src/capabilities/create-object.test.d.ts +2 -0
  98. package/dist/types/src/capabilities/create-object.test.d.ts.map +1 -0
  99. package/dist/types/src/capabilities/index.d.ts +12 -0
  100. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  101. package/dist/types/src/capabilities/layer-specs.d.ts +5 -0
  102. package/dist/types/src/capabilities/layer-specs.d.ts.map +1 -0
  103. package/dist/types/src/capabilities/navigation-resolver.d.ts +5 -0
  104. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -0
  105. package/dist/types/src/capabilities/node.d.ts +9 -0
  106. package/dist/types/src/capabilities/node.d.ts.map +1 -0
  107. package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
  108. package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
  109. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  110. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  111. package/dist/types/src/capabilities/registry-sync.d.ts +21 -0
  112. package/dist/types/src/capabilities/registry-sync.d.ts.map +1 -0
  113. package/dist/types/src/capabilities/templates.d.ts +5 -0
  114. package/dist/types/src/capabilities/templates.d.ts.map +1 -0
  115. package/dist/types/src/capabilities/trigger-runtime-controller.d.ts +5 -0
  116. package/dist/types/src/capabilities/trigger-runtime-controller.d.ts.map +1 -0
  117. package/dist/types/src/capabilities/trigger-runtime-controller.test.d.ts +2 -0
  118. package/dist/types/src/capabilities/trigger-runtime-controller.test.d.ts.map +1 -0
  119. package/dist/types/src/commands/index.d.ts +2 -0
  120. package/dist/types/src/commands/index.d.ts.map +1 -0
  121. package/dist/types/src/commands/trigger/create/index.d.ts +25 -0
  122. package/dist/types/src/commands/trigger/create/index.d.ts.map +1 -0
  123. package/dist/types/src/commands/trigger/create/queue.d.ts +13 -0
  124. package/dist/types/src/commands/trigger/create/queue.d.ts.map +1 -0
  125. package/dist/types/src/commands/trigger/create/subscription.d.ts +15 -0
  126. package/dist/types/src/commands/trigger/create/subscription.d.ts.map +1 -0
  127. package/dist/types/src/commands/trigger/create/timer.d.ts +13 -0
  128. package/dist/types/src/commands/trigger/create/timer.d.ts.map +1 -0
  129. package/dist/types/src/commands/trigger/index.d.ts +57 -0
  130. package/dist/types/src/commands/trigger/index.d.ts.map +1 -0
  131. package/dist/types/src/commands/trigger/list.d.ts +7 -0
  132. package/dist/types/src/commands/trigger/list.d.ts.map +1 -0
  133. package/dist/types/src/commands/trigger/options.d.ts +10 -0
  134. package/dist/types/src/commands/trigger/options.d.ts.map +1 -0
  135. package/dist/types/src/commands/trigger/remove.d.ts +8 -0
  136. package/dist/types/src/commands/trigger/remove.d.ts.map +1 -0
  137. package/dist/types/src/commands/trigger/update/index.d.ts +28 -0
  138. package/dist/types/src/commands/trigger/update/index.d.ts.map +1 -0
  139. package/dist/types/src/commands/trigger/update/queue.d.ts +13 -0
  140. package/dist/types/src/commands/trigger/update/queue.d.ts.map +1 -0
  141. package/dist/types/src/commands/trigger/update/subscription.d.ts +15 -0
  142. package/dist/types/src/commands/trigger/update/subscription.d.ts.map +1 -0
  143. package/dist/types/src/commands/trigger/update/timer.d.ts +13 -0
  144. package/dist/types/src/commands/trigger/update/timer.d.ts.map +1 -0
  145. package/dist/types/src/commands/trigger/util.d.ts +46 -0
  146. package/dist/types/src/commands/trigger/util.d.ts.map +1 -0
  147. package/dist/types/src/components/CreateRoutinePanel/CreateRoutinePanel.d.ts +14 -0
  148. package/dist/types/src/components/CreateRoutinePanel/CreateRoutinePanel.d.ts.map +1 -0
  149. package/dist/types/src/components/CreateRoutinePanel/index.d.ts +2 -0
  150. package/dist/types/src/components/CreateRoutinePanel/index.d.ts.map +1 -0
  151. package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts +16 -0
  152. package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts.map +1 -0
  153. package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts +17 -0
  154. package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts.map +1 -0
  155. package/dist/types/src/components/InstructionsEditor/index.d.ts +2 -0
  156. package/dist/types/src/components/InstructionsEditor/index.d.ts.map +1 -0
  157. package/dist/types/src/components/MasterDetail/MasterDetail.d.ts +51 -0
  158. package/dist/types/src/components/MasterDetail/MasterDetail.d.ts.map +1 -0
  159. package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts +16 -0
  160. package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts.map +1 -0
  161. package/dist/types/src/components/MasterDetail/index.d.ts +2 -0
  162. package/dist/types/src/components/MasterDetail/index.d.ts.map +1 -0
  163. package/dist/types/src/components/RoutineForm/RoutineForm.d.ts +25 -0
  164. package/dist/types/src/components/RoutineForm/RoutineForm.d.ts.map +1 -0
  165. package/dist/types/src/components/RoutineForm/index.d.ts +2 -0
  166. package/dist/types/src/components/RoutineForm/index.d.ts.map +1 -0
  167. package/dist/types/src/components/Schedule/Schedule.d.ts +80 -0
  168. package/dist/types/src/components/Schedule/Schedule.d.ts.map +1 -0
  169. package/dist/types/src/components/Schedule/Schedule.stories.d.ts +23 -0
  170. package/dist/types/src/components/Schedule/Schedule.stories.d.ts.map +1 -0
  171. package/dist/types/src/components/Schedule/cron.d.ts +44 -0
  172. package/dist/types/src/components/Schedule/cron.d.ts.map +1 -0
  173. package/dist/types/src/components/Schedule/cron.test.d.ts +2 -0
  174. package/dist/types/src/components/Schedule/cron.test.d.ts.map +1 -0
  175. package/dist/types/src/components/Schedule/index.d.ts +4 -0
  176. package/dist/types/src/components/Schedule/index.d.ts.map +1 -0
  177. package/dist/types/src/components/Schedule/types.d.ts +66 -0
  178. package/dist/types/src/components/Schedule/types.d.ts.map +1 -0
  179. package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +13 -0
  180. package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -0
  181. package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts +19 -0
  182. package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts.map +1 -0
  183. package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts +21 -0
  184. package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts.map +1 -0
  185. package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts +16 -0
  186. package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts.map +1 -0
  187. package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts +12 -0
  188. package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts.map +1 -0
  189. package/dist/types/src/components/TemplateEditor/extensions/index.d.ts +3 -0
  190. package/dist/types/src/components/TemplateEditor/extensions/index.d.ts.map +1 -0
  191. package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts +8 -0
  192. package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts.map +1 -0
  193. package/dist/types/src/components/TemplateEditor/index.d.ts +2 -0
  194. package/dist/types/src/components/TemplateEditor/index.d.ts.map +1 -0
  195. package/dist/types/src/components/TemplateEditor/types.d.ts +18 -0
  196. package/dist/types/src/components/TemplateEditor/types.d.ts.map +1 -0
  197. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +24 -0
  198. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -0
  199. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +25 -0
  200. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -0
  201. package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts +15 -0
  202. package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts.map +1 -0
  203. package/dist/types/src/components/TriggerEditor/TriggerKindSelector.stories.d.ts +15 -0
  204. package/dist/types/src/components/TriggerEditor/TriggerKindSelector.stories.d.ts.map +1 -0
  205. package/dist/types/src/components/TriggerEditor/index.d.ts +2 -0
  206. package/dist/types/src/components/TriggerEditor/index.d.ts.map +1 -0
  207. package/dist/types/src/components/index.d.ts +8 -0
  208. package/dist/types/src/components/index.d.ts.map +1 -0
  209. package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +14 -0
  210. package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -0
  211. package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts +20 -0
  212. package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts.map +1 -0
  213. package/dist/types/src/containers/RoutineArticle/index.d.ts +2 -0
  214. package/dist/types/src/containers/RoutineArticle/index.d.ts.map +1 -0
  215. package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts +17 -0
  216. package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts.map +1 -0
  217. package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts +15 -0
  218. package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts.map +1 -0
  219. package/dist/types/src/containers/RoutineCompanion/index.d.ts +3 -0
  220. package/dist/types/src/containers/RoutineCompanion/index.d.ts.map +1 -0
  221. package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts +10 -0
  222. package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts.map +1 -0
  223. package/dist/types/src/containers/RoutineSettings/index.d.ts +2 -0
  224. package/dist/types/src/containers/RoutineSettings/index.d.ts.map +1 -0
  225. package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts +9 -0
  226. package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts.map +1 -0
  227. package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts +15 -0
  228. package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts.map +1 -0
  229. package/dist/types/src/containers/RoutineTraceCompanion/index.d.ts +2 -0
  230. package/dist/types/src/containers/RoutineTraceCompanion/index.d.ts.map +1 -0
  231. package/dist/types/src/containers/RoutineTraceCompanion/runs.d.ts +34 -0
  232. package/dist/types/src/containers/RoutineTraceCompanion/runs.d.ts.map +1 -0
  233. package/dist/types/src/containers/RoutineTraceCompanion/runs.test.d.ts +2 -0
  234. package/dist/types/src/containers/RoutineTraceCompanion/runs.test.d.ts.map +1 -0
  235. package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts +11 -0
  236. package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts.map +1 -0
  237. package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts +6 -0
  238. package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts.map +1 -0
  239. package/dist/types/src/containers/SkillArticle/index.d.ts +2 -0
  240. package/dist/types/src/containers/SkillArticle/index.d.ts.map +1 -0
  241. package/dist/types/src/containers/index.d.ts +7 -0
  242. package/dist/types/src/containers/index.d.ts.map +1 -0
  243. package/dist/types/src/hooks/index.d.ts +2 -0
  244. package/dist/types/src/hooks/index.d.ts.map +1 -0
  245. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +12 -0
  246. package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -0
  247. package/dist/types/src/index.d.ts +4 -0
  248. package/dist/types/src/index.d.ts.map +1 -0
  249. package/dist/types/src/meta.d.ts +33 -0
  250. package/dist/types/src/meta.d.ts.map +1 -0
  251. package/dist/types/src/operations/create-routine.d.ts +5 -0
  252. package/dist/types/src/operations/create-routine.d.ts.map +1 -0
  253. package/dist/types/src/operations/create-trigger-from-template.d.ts +5 -0
  254. package/dist/types/src/operations/create-trigger-from-template.d.ts.map +1 -0
  255. package/dist/types/src/operations/index.d.ts +3 -0
  256. package/dist/types/src/operations/index.d.ts.map +1 -0
  257. package/dist/types/src/operations/run-routine.d.ts +5 -0
  258. package/dist/types/src/operations/run-routine.d.ts.map +1 -0
  259. package/dist/types/src/paths.d.ts +5 -0
  260. package/dist/types/src/paths.d.ts.map +1 -0
  261. package/dist/types/src/plugin.d.ts +4 -0
  262. package/dist/types/src/plugin.d.ts.map +1 -0
  263. package/dist/types/src/templates/index.d.ts +11 -0
  264. package/dist/types/src/templates/index.d.ts.map +1 -0
  265. package/dist/types/src/testing/index.d.ts +2 -0
  266. package/dist/types/src/testing/index.d.ts.map +1 -0
  267. package/dist/types/src/testing/test-functions.d.ts +328 -0
  268. package/dist/types/src/testing/test-functions.d.ts.map +1 -0
  269. package/dist/types/src/testing.d.ts +2 -0
  270. package/dist/types/src/testing.d.ts.map +1 -0
  271. package/dist/types/src/translations.d.ts +3 -0
  272. package/dist/types/src/translations.d.ts.map +1 -0
  273. package/dist/types/src/types/Routine.d.ts +55 -0
  274. package/dist/types/src/types/Routine.d.ts.map +1 -0
  275. package/dist/types/src/types/Routine.test.d.ts +2 -0
  276. package/dist/types/src/types/Routine.test.d.ts.map +1 -0
  277. package/dist/types/src/types/RoutineCapabilities.d.ts +44 -0
  278. package/dist/types/src/types/RoutineCapabilities.d.ts.map +1 -0
  279. package/dist/types/src/types/RoutineOperation.d.ts +45 -0
  280. package/dist/types/src/types/RoutineOperation.d.ts.map +1 -0
  281. package/dist/types/src/types/index.d.ts +5 -0
  282. package/dist/types/src/types/index.d.ts.map +1 -0
  283. package/dist/types/src/types/schema.d.ts +33 -0
  284. package/dist/types/src/types/schema.d.ts.map +1 -0
  285. package/dist/types/src/util/index.d.ts +3 -0
  286. package/dist/types/src/util/index.d.ts.map +1 -0
  287. package/dist/types/src/util/routines-for-object.d.ts +22 -0
  288. package/dist/types/src/util/routines-for-object.d.ts.map +1 -0
  289. package/dist/types/src/util/routines-for-object.test.d.ts +2 -0
  290. package/dist/types/src/util/routines-for-object.test.d.ts.map +1 -0
  291. package/dist/types/src/util/run-instructions.d.ts +5 -0
  292. package/dist/types/src/util/run-instructions.d.ts.map +1 -0
  293. package/dist/types/src/util/run-instructions.test.d.ts +2 -0
  294. package/dist/types/src/util/run-instructions.test.d.ts.map +1 -0
  295. package/dist/types/tsconfig.tsbuildinfo +1 -0
  296. package/dx.config.ts +33 -0
  297. package/package.json +196 -0
  298. package/src/RoutinePlugin.node.ts +48 -0
  299. package/src/RoutinePlugin.test.ts +27 -0
  300. package/src/RoutinePlugin.tsx +58 -0
  301. package/src/RoutinePlugin.workerd.ts +24 -0
  302. package/src/capabilities/app-graph-builder.ts +80 -0
  303. package/src/capabilities/create-object.test.ts +18 -0
  304. package/src/capabilities/create-object.ts +26 -0
  305. package/src/capabilities/index.ts +22 -0
  306. package/src/capabilities/layer-specs.ts +190 -0
  307. package/src/capabilities/navigation-resolver.ts +21 -0
  308. package/src/capabilities/node.ts +19 -0
  309. package/src/capabilities/operation-handler.ts +16 -0
  310. package/src/capabilities/react-surface.tsx +66 -0
  311. package/src/capabilities/registry-sync.ts +114 -0
  312. package/src/capabilities/templates.ts +17 -0
  313. package/src/capabilities/trigger-runtime-controller.test.ts +107 -0
  314. package/src/capabilities/trigger-runtime-controller.ts +126 -0
  315. package/src/commands/index.ts +5 -0
  316. package/src/commands/trigger/create/index.ts +14 -0
  317. package/src/commands/trigger/create/queue.ts +87 -0
  318. package/src/commands/trigger/create/subscription.ts +126 -0
  319. package/src/commands/trigger/create/timer.ts +90 -0
  320. package/src/commands/trigger/index.ts +16 -0
  321. package/src/commands/trigger/list.ts +69 -0
  322. package/src/commands/trigger/options.ts +47 -0
  323. package/src/commands/trigger/remove.ts +45 -0
  324. package/src/commands/trigger/update/index.ts +14 -0
  325. package/src/commands/trigger/update/queue.ts +191 -0
  326. package/src/commands/trigger/update/subscription.ts +278 -0
  327. package/src/commands/trigger/update/timer.ts +194 -0
  328. package/src/commands/trigger/util.ts +412 -0
  329. package/src/components/CreateRoutinePanel/CreateRoutinePanel.tsx +68 -0
  330. package/src/components/CreateRoutinePanel/index.ts +5 -0
  331. package/src/components/InstructionsEditor/InstructionsEditor.stories.tsx +69 -0
  332. package/src/components/InstructionsEditor/InstructionsEditor.tsx +107 -0
  333. package/src/components/InstructionsEditor/index.ts +5 -0
  334. package/src/components/MasterDetail/MasterDetail.stories.tsx +100 -0
  335. package/src/components/MasterDetail/MasterDetail.tsx +175 -0
  336. package/src/components/MasterDetail/index.ts +5 -0
  337. package/src/components/RoutineForm/RoutineForm.tsx +293 -0
  338. package/src/components/RoutineForm/index.ts +5 -0
  339. package/src/components/Schedule/Schedule.stories.tsx +73 -0
  340. package/src/components/Schedule/Schedule.tsx +527 -0
  341. package/src/components/Schedule/cron.test.ts +230 -0
  342. package/src/components/Schedule/cron.ts +337 -0
  343. package/src/components/Schedule/index.ts +8 -0
  344. package/src/components/Schedule/types.ts +124 -0
  345. package/src/components/TemplateEditor/TemplateEditor.stories.tsx +93 -0
  346. package/src/components/TemplateEditor/TemplateEditor.tsx +77 -0
  347. package/src/components/TemplateEditor/TemplateForm.stories.tsx +76 -0
  348. package/src/components/TemplateEditor/TemplateForm.tsx +204 -0
  349. package/src/components/TemplateEditor/extensions/handlebars-extension.ts +274 -0
  350. package/src/components/TemplateEditor/extensions/index.ts +6 -0
  351. package/src/components/TemplateEditor/extensions/xml-extension.ts +64 -0
  352. package/src/components/TemplateEditor/index.ts +5 -0
  353. package/src/components/TemplateEditor/types.tsx +28 -0
  354. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +122 -0
  355. package/src/components/TriggerEditor/TriggerEditor.tsx +365 -0
  356. package/src/components/TriggerEditor/TriggerKindSelector.stories.tsx +42 -0
  357. package/src/components/TriggerEditor/TriggerKindSelector.tsx +87 -0
  358. package/src/components/TriggerEditor/index.ts +5 -0
  359. package/src/components/index.ts +11 -0
  360. package/src/containers/RoutineArticle/RoutineArticle.stories.tsx +146 -0
  361. package/src/containers/RoutineArticle/RoutineArticle.tsx +109 -0
  362. package/src/containers/RoutineArticle/index.ts +5 -0
  363. package/src/containers/RoutineCompanion/RoutineCompanion.stories.tsx +82 -0
  364. package/src/containers/RoutineCompanion/RoutineCompanion.tsx +342 -0
  365. package/src/containers/RoutineCompanion/index.ts +6 -0
  366. package/src/containers/RoutineSettings/RoutineSettings.tsx +65 -0
  367. package/src/containers/RoutineSettings/index.ts +5 -0
  368. package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.tsx +133 -0
  369. package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.tsx +125 -0
  370. package/src/containers/RoutineTraceCompanion/index.ts +5 -0
  371. package/src/containers/RoutineTraceCompanion/runs.test.ts +140 -0
  372. package/src/containers/RoutineTraceCompanion/runs.ts +135 -0
  373. package/src/containers/RoutineTraceCompanion/useRoutineRuns.ts +50 -0
  374. package/src/containers/SkillArticle/SkillArticle.tsx +29 -0
  375. package/src/containers/SkillArticle/index.ts +5 -0
  376. package/src/containers/index.ts +11 -0
  377. package/src/hooks/index.ts +6 -0
  378. package/src/hooks/useTriggerRuntimeControls.ts +70 -0
  379. package/src/index.ts +7 -0
  380. package/src/meta.ts +9 -0
  381. package/src/operations/create-routine.ts +39 -0
  382. package/src/operations/create-trigger-from-template.ts +68 -0
  383. package/src/operations/index.ts +11 -0
  384. package/src/operations/run-routine.ts +45 -0
  385. package/src/paths.ts +18 -0
  386. package/src/plugin.ts +11 -0
  387. package/src/templates/index.ts +48 -0
  388. package/src/testing/index.ts +5 -0
  389. package/src/testing/test-functions.ts +76 -0
  390. package/src/testing.ts +7 -0
  391. package/src/translations.ts +125 -0
  392. package/src/types/Routine.test.ts +51 -0
  393. package/src/types/Routine.ts +144 -0
  394. package/src/types/RoutineCapabilities.ts +51 -0
  395. package/src/types/RoutineOperation.ts +104 -0
  396. package/src/types/index.ts +9 -0
  397. package/src/types/schema.ts +31 -0
  398. package/src/util/index.ts +6 -0
  399. package/src/util/routines-for-object.test.ts +109 -0
  400. package/src/util/routines-for-object.ts +89 -0
  401. package/src/util/run-instructions.test.ts +23 -0
  402. package/src/util/run-instructions.ts +12 -0
  403. package/src/vite-env.d.ts +10 -0
@@ -0,0 +1,365 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import * as Schema from 'effect/Schema';
6
+ import React, { useCallback, useMemo, useState } from 'react';
7
+
8
+ import { Trigger } from '@dxos/compute';
9
+ import { type Database, DXN, Feed, Filter, Obj, Query, Ref, Scope, Type } from '@dxos/echo';
10
+ import { useQuery } from '@dxos/react-client/echo';
11
+ import { IconButton, Input, ThemedClassName, useTranslation } from '@dxos/react-ui';
12
+ import { Form, type FormFieldMap, type FormFieldRendererProps, SelectField } from '@dxos/react-ui-form';
13
+ import { ParentLabelAnnotation } from '@dxos/schema';
14
+ import { mx } from '@dxos/ui-theme';
15
+
16
+ import { meta } from '#meta';
17
+ import { Routine } from '#types';
18
+
19
+ import {
20
+ FrequencyDefaults,
21
+ Schedule,
22
+ type ScheduleKind,
23
+ type ScheduleValue,
24
+ cronToSchedule,
25
+ scheduleToCron,
26
+ toCron,
27
+ } from '../Schedule';
28
+ import { type TriggerKind, TriggerKindSelector } from './TriggerKindSelector';
29
+
30
+ // A recurring trigger fires on a cron, so the one-time `once` kind is not offered here.
31
+ const RECURRING_KINDS = ['hourly', 'daily', 'weekly', 'monthly', 'custom'] as const satisfies readonly ScheduleKind[];
32
+
33
+ // The `enabled` toggle is a field of the Trigger object (sibling of `spec`), not of any spec variant. It is
34
+ // reused from the Trigger schema (rather than redeclared) and extended onto every form member so the editor
35
+ // surfaces it once a kind is chosen; the value is written back to `trigger.enabled`, not the spec.
36
+ const EnabledForm = Type.getSchema(Trigger.Trigger).pipe(Schema.pick('enabled'));
37
+
38
+ // Scoped trigger form, modeled as a top-level discriminated union (one member per pluggable variant) so the
39
+ // Form renders the chosen kind's fields as one flat field set (no nested, bordered sub-fieldset). The kind
40
+ // itself is chosen by `TriggerKindPicker` (a radio-card list) rather than a select. The feed field carries
41
+ // ParentLabelAnnotation so the built-in RefField labels feed options by their parent object (e.g. the mailbox).
42
+ const TimerSpecForm = Schema.extend(
43
+ Schema.Struct({
44
+ kind: Schema.Literal('timer'),
45
+ cron: Schema.String.pipe(Schema.annotations({ title: 'Schedule (cron)' }), Schema.optional),
46
+ }),
47
+ EnabledForm,
48
+ );
49
+
50
+ const SubscriptionSpecForm = Schema.extend(
51
+ Schema.Struct({
52
+ kind: Schema.Literal('subscription'),
53
+ // The object type to watch; converted to a `Filter.type` query. `typename` renders via a custom select of
54
+ // the space/registry types (see `TypeSelectField`); `deep`/`delay` map to the subscription's options.
55
+ typename: Schema.String.pipe(Schema.annotations({ title: 'Type' }), Schema.optional),
56
+ deep: Schema.Boolean.pipe(Schema.annotations({ title: 'Nested' }), Schema.optional),
57
+ delay: Schema.Number.pipe(Schema.annotations({ title: 'Delay (ms)' }), Schema.optional),
58
+ }),
59
+ EnabledForm,
60
+ );
61
+
62
+ const WebhookSpecForm = Schema.extend(
63
+ Schema.Struct({
64
+ kind: Schema.Literal('webhook'),
65
+ method: Schema.String.pipe(Schema.annotations({ title: 'Method' }), Schema.optional),
66
+ port: Schema.Number.pipe(Schema.annotations({ title: 'Port' }), Schema.optional),
67
+ }),
68
+ EnabledForm,
69
+ );
70
+
71
+ const FeedSpecForm = Schema.extend(
72
+ Schema.Struct({
73
+ kind: Schema.Literal('feed'),
74
+ feed: Ref.Ref(Feed.Feed).pipe(
75
+ ParentLabelAnnotation.set(true),
76
+ Schema.annotations({ title: 'Feed' }),
77
+ Schema.optional,
78
+ ),
79
+ }),
80
+ EnabledForm,
81
+ );
82
+
83
+ const EmailSpecForm = Schema.extend(
84
+ Schema.Struct({
85
+ kind: Schema.Literal('email'),
86
+ }),
87
+ EnabledForm,
88
+ );
89
+
90
+ const TriggerForm = Schema.Union(TimerSpecForm, SubscriptionSpecForm, WebhookSpecForm, FeedSpecForm, EmailSpecForm);
91
+ type TriggerFormValues = Schema.Schema.Type<typeof TriggerForm>;
92
+
93
+ // Flat view of the form values: `Partial<TriggerFormValues>` collapses a discriminated union to its common
94
+ // key alone (`kind`), so reach the variant fields through this all-optional shape instead. `Partial<T>` is
95
+ // assignable to it, so handlers/helpers can accept the Form's value verbatim and still read the variant fields.
96
+ type TriggerFormInput = {
97
+ readonly kind?: TriggerKind;
98
+ readonly enabled?: boolean;
99
+ readonly cron?: string;
100
+ readonly method?: string;
101
+ readonly port?: number;
102
+ readonly feed?: Ref.Ref<Feed.Feed>;
103
+ readonly typename?: string;
104
+ readonly deep?: boolean;
105
+ readonly delay?: number;
106
+ };
107
+
108
+ /** Project a trigger spec onto the form's discriminated-union members. */
109
+ const triggerFormValues = (spec?: Trigger.Spec): TriggerFormInput => {
110
+ switch (spec?.kind) {
111
+ case 'subscription':
112
+ // The watched typename is preserved in `query.raw` so the Type select can round-trip it.
113
+ return {
114
+ kind: 'subscription',
115
+ typename: spec.query?.raw,
116
+ deep: spec.options?.deep,
117
+ delay: spec.options?.delay,
118
+ };
119
+ case 'feed':
120
+ return {
121
+ kind: 'feed',
122
+ feed: spec.feed,
123
+ };
124
+ case 'webhook':
125
+ return {
126
+ kind: 'webhook',
127
+ method: spec.method,
128
+ port: spec.port,
129
+ };
130
+ case 'email':
131
+ return {
132
+ kind: 'email',
133
+ };
134
+ case 'timer':
135
+ return {
136
+ kind: 'timer',
137
+ cron: spec.cron,
138
+ };
139
+ default:
140
+ // No spec yet: leave the kind unset so the editor shows the variant picker (nothing selected).
141
+ return {};
142
+ }
143
+ };
144
+
145
+ // Fallback cron used when no schedule has been set yet.
146
+ const DEFAULT_TIMER_CRON = toCron(FrequencyDefaults.daily);
147
+
148
+ /** Build the subscription query: filter by the chosen type, or match everything until one is picked. */
149
+ const subscriptionQuery = (typename?: string): Query.Any =>
150
+ typename ? Query.select(Filter.type(DXN.make(typename))) : Query.select(Filter.everything());
151
+
152
+ /** Build a trigger spec from the form's values. */
153
+ const triggerFormSpec = (values: TriggerFormInput): Trigger.Spec => {
154
+ switch (values.kind) {
155
+ case 'subscription': {
156
+ const hasOptions = values.deep != null || values.delay != null;
157
+ return {
158
+ kind: 'subscription',
159
+ // Carry the typename in `raw` so the editor can recover the Type selection on reopen.
160
+ query: { raw: values.typename, ast: subscriptionQuery(values.typename).ast },
161
+ options: hasOptions ? { deep: values.deep, delay: values.delay } : undefined,
162
+ };
163
+ }
164
+ case 'feed':
165
+ return {
166
+ kind: 'feed',
167
+ feed: values.feed,
168
+ };
169
+ case 'webhook':
170
+ return Trigger.specWebhook({ method: values.method, port: values.port });
171
+ case 'email':
172
+ return Trigger.specEmail();
173
+ case 'timer':
174
+ default:
175
+ return Trigger.specTimer(values.cron || DEFAULT_TIMER_CRON);
176
+ }
177
+ };
178
+
179
+ export type TriggerEditorProps = ThemedClassName<{
180
+ db: Database.Database;
181
+ routine: Routine.Routine;
182
+ trigger?: Trigger.Trigger;
183
+ /** Render the trigger for display only (no variant picker, clear, or field edits). */
184
+ readonly?: boolean;
185
+ }>;
186
+
187
+ export const TriggerEditor = ({ classNames, db, routine, trigger, readonly }: TriggerEditorProps) => {
188
+ const { t } = useTranslation(meta.profile.key);
189
+ const { defaultValues, fieldMap, kind, resetNonce, handleClose, handleValuesChanged } = useTriggerForm(
190
+ routine,
191
+ trigger,
192
+ );
193
+
194
+ // TODO(burdon): Not persistent; need to memo
195
+ return (
196
+ <Form.Root
197
+ // Remount when the bound trigger changes (picks up its spec) or on reset (reverts to the picker).
198
+ key={`${trigger?.id ?? 'new'}:${resetNonce}`}
199
+ schema={TriggerForm}
200
+ db={db}
201
+ readonly={readonly}
202
+ fieldMap={fieldMap}
203
+ defaultValues={defaultValues}
204
+ onValuesChanged={handleValuesChanged}
205
+ >
206
+ <Form.Content classNames={mx(kind && 'pb-2 bg-card-surface border border-separator rounded-xs', classNames)}>
207
+ {/* TODO(burdon): Generalize indented section for discriminated unions. */}
208
+ {(kind && (
209
+ <>
210
+ <div className='flex items-center'>
211
+ <Input.Root>
212
+ <Input.Label classNames='pl-2 grow truncate'>{t(`trigger-kind.${kind}.label`)}</Input.Label>
213
+ </Input.Root>
214
+ {!readonly && (
215
+ <IconButton
216
+ iconOnly
217
+ variant='ghost'
218
+ square
219
+ icon='ph--x--regular'
220
+ label={t('trigger-kind.clear.label')}
221
+ onClick={handleClose}
222
+ />
223
+ )}
224
+ </div>
225
+ <Form.FieldSet classNames='px-2' />
226
+ </>
227
+ )) || <Form.FieldSet />}
228
+
229
+ {/* Email triggers have no configuration; surface an explanatory note instead of an empty body. */}
230
+ {kind === 'email' && <p className='px-2 text-sm text-description'>{t('trigger-kind.email-note.message')}</p>}
231
+ </Form.Content>
232
+ </Form.Root>
233
+ );
234
+ };
235
+
236
+ /** Selects the ECHO object type to watch (subscription `typename`) from the space + registry schemas. */
237
+ const TypeSelectField = (props: FormFieldRendererProps) => {
238
+ const types = useQuery(props.db, Query.select(Filter.type(Type.Type)).from(Scope.space(), Scope.registry()));
239
+ const options = useMemo(
240
+ () =>
241
+ types
242
+ .filter((type) => !Type.isTypeKind(type))
243
+ .map((type) => Type.getTypename(type))
244
+ .filter((typename): typename is string => !!typename)
245
+ .map((typename) => ({ value: typename, label: typename })),
246
+ [types],
247
+ );
248
+ return <SelectField {...props} options={options} />;
249
+ };
250
+
251
+ TypeSelectField.displayName = 'TriggerEditor.TypeSelectField';
252
+
253
+ /** Edits the cron via the Schedule picker (recurring kinds only) with a live cronstrue description below it. */
254
+ const CronField = (props: FormFieldRendererProps) => {
255
+ const cron = (props.getValue() as string | undefined) || DEFAULT_TIMER_CRON;
256
+ // Read once per mount; the Schedule owns its state and emits cron changes via `handleChange`.
257
+ const initial = useMemo(() => cronToSchedule(cron), []);
258
+
259
+ const handleChange = useCallback(
260
+ (value: ScheduleValue) => {
261
+ const next = scheduleToCron(value);
262
+ if (next) {
263
+ props.onValueChange(props.type, next);
264
+ }
265
+ },
266
+ [props.type, props.onValueChange],
267
+ );
268
+
269
+ // TODO(wittjosiah): Add read-only support.
270
+ return (
271
+ <Schedule.Root kinds={RECURRING_KINDS} defaultValue={initial} onValueChange={handleChange}>
272
+ <Schedule.Header />
273
+ <Schedule.Kind />
274
+ <Schedule.Body />
275
+ </Schedule.Root>
276
+ );
277
+ };
278
+
279
+ CronField.displayName = 'TriggerEditor.CronField';
280
+
281
+ /** Form state for the Trigger section: the chosen variant spec, plus create-on-first-edit handler. */
282
+ const useTriggerForm = (routine: Routine.Routine, trigger?: Trigger.Trigger) => {
283
+ const methodOptions = useMemo(
284
+ () => [
285
+ { value: 'GET', label: 'GET' },
286
+ { value: 'POST', label: 'POST' },
287
+ ],
288
+ [],
289
+ );
290
+
291
+ const fieldMap = useMemo<FormFieldMap>(
292
+ () => ({
293
+ // Show the variant picker only until a kind is chosen; once selected the row is replaced by that
294
+ // variant's editor (the kind field renders nothing).
295
+ kind: (props) =>
296
+ props.getValue() ? null : <TriggerKindSelector onChange={(next) => props.onValueChange(props.type, next)} />,
297
+ cron: (props) => <CronField {...props} />,
298
+ method: (props) => <SelectField {...props} options={methodOptions} />,
299
+ typename: (props) => <TypeSelectField {...props} />,
300
+ }),
301
+ [methodOptions],
302
+ );
303
+
304
+ // Bumping this remounts the uncontrolled Form so it re-reads `defaultValues` (used to revert to the picker).
305
+ const [resetNonce, setResetNonce] = useState(0);
306
+ // Read per trigger identity / reset; a trigger with no spec yet starts with no kind (shows the picker).
307
+ // `enabled` is a Trigger-level field, seeded alongside the spec-derived variant values.
308
+ const defaultValues = useMemo<Partial<TriggerFormValues>>(
309
+ () => ({ ...triggerFormValues(trigger?.spec), enabled: trigger?.enabled }),
310
+ [trigger, resetNonce],
311
+ );
312
+
313
+ // Mirror the active kind: gates the variant picker (shown only while unset) and the variant-specific notes.
314
+ const [kind, setKind] = useState<TriggerKind | undefined>(() => triggerFormValues(trigger?.spec).kind);
315
+
316
+ // Revert the kind selection: clear the trigger's spec and remount the Form so the picker reappears.
317
+ const handleClose = useCallback(() => {
318
+ setKind(undefined);
319
+ setResetNonce((nonce) => nonce + 1);
320
+ if (trigger) {
321
+ Obj.update(trigger, (trigger) => {
322
+ trigger.spec = undefined;
323
+ });
324
+ }
325
+ }, [trigger]);
326
+
327
+ const handleValuesChanged = useCallback(
328
+ (values: Partial<TriggerFormValues>) => {
329
+ // Ignore changes until a kind is picked, so the unselected picker never seeds a default trigger.
330
+ if (!values.kind) {
331
+ return;
332
+ }
333
+
334
+ const spec = triggerFormSpec(values);
335
+ setKind(spec.kind);
336
+ const enabled = values.enabled === true;
337
+ // Edit the spec and `enabled` on the trigger; the trigger's `function` and `input` (including the
338
+ // instructions binding and any operation-specific bindings like `{ magazine }`) are wired once by
339
+ // `Routine.make`, so they are not re-derived here.
340
+ if (trigger) {
341
+ Obj.update(trigger, (trigger) => {
342
+ // The subscription spec's QueryAST is deeply readonly while the live ECHO draft's `spec` is mutable;
343
+ // the structures are identical at runtime, so a readonly->mutable boundary coercion is required here
344
+ // (mirrors commands/trigger/update/subscription.ts).
345
+ trigger.spec = spec as typeof trigger.spec;
346
+ trigger.enabled = enabled;
347
+ });
348
+ } else {
349
+ // Defensive: the draft normally carries an owned trigger already (see `Routine.make`). If absent,
350
+ // create one in memory and attach it to the routine graph — nothing is persisted until save.
351
+ const created = Trigger.make({ spec, enabled });
352
+ Obj.setParent(created, routine);
353
+ Obj.update(routine, (routine) => {
354
+ routine.triggers.push(Ref.make(created));
355
+ });
356
+ // Wire the new trigger's `function`/`input` to dispatch the routine's action (RunInstructions binds the
357
+ // owned instructions; an operation binds directly).
358
+ Routine.wireTriggers(routine);
359
+ }
360
+ },
361
+ [routine, trigger],
362
+ );
363
+
364
+ return { defaultValues, fieldMap, kind, resetNonce, handleClose, handleValuesChanged };
365
+ };
@@ -0,0 +1,42 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import React, { useState } from 'react';
7
+
8
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
9
+
10
+ import { translations } from '#translations';
11
+
12
+ import { type TriggerKind, TriggerKindSelector } from './TriggerKindSelector';
13
+
14
+ const DefaultStory = () => {
15
+ const [kind, setKind] = useState<TriggerKind | undefined>();
16
+
17
+ return (
18
+ <div className='p-4 flex flex-col gap-3'>
19
+ <TriggerKindSelector onChange={setKind} />
20
+ <div className='flex flex-col gap-1'>
21
+ <p className='text-xs text-subdued'>Selected kind</p>
22
+ <pre className='font-mono text-sm bg-base-surface rounded p-2'>{kind ?? '(none)'}</pre>
23
+ </div>
24
+ </div>
25
+ );
26
+ };
27
+
28
+ const meta = {
29
+ title: 'plugins/plugin-routine/components/TriggerKindSelector',
30
+ render: DefaultStory,
31
+ decorators: [withTheme(), withLayout({ layout: 'column' })],
32
+ parameters: {
33
+ layout: 'fullscreen',
34
+ translations,
35
+ },
36
+ } satisfies Meta<typeof DefaultStory>;
37
+
38
+ export default meta;
39
+
40
+ type Story = StoryObj<typeof meta>;
41
+
42
+ export const Default: Story = {};
@@ -0,0 +1,87 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import React, { useCallback } from 'react';
6
+
7
+ import { Icon, useTranslation } from '@dxos/react-ui';
8
+ import { Listbox } from '@dxos/react-ui-list';
9
+
10
+ import { meta } from '#meta';
11
+
12
+ /** Trigger spec kinds surfaced as selectable variants. Matches the discriminants of `Trigger.Spec`. */
13
+ export type TriggerKind = 'timer' | 'feed' | 'subscription' | 'webhook' | 'email';
14
+
15
+ type TriggerKindOption = {
16
+ kind: TriggerKind;
17
+ icon: string;
18
+ disabled?: boolean;
19
+ };
20
+
21
+ // Ordered as presented; labels and descriptions are resolved from translations keyed by `kind`.
22
+ const OPTIONS: readonly TriggerKindOption[] = [
23
+ {
24
+ kind: 'timer',
25
+ icon: 'ph--clock-countdown--regular',
26
+ },
27
+ {
28
+ kind: 'feed',
29
+ icon: 'ph--cards-three--regular',
30
+ },
31
+ {
32
+ kind: 'subscription',
33
+ icon: 'ph--funnel--regular',
34
+ },
35
+ {
36
+ kind: 'webhook',
37
+ icon: 'ph--webhooks-logo--regular',
38
+ disabled: true,
39
+ },
40
+ {
41
+ kind: 'email',
42
+ icon: 'ph--envelope--regular',
43
+ disabled: true,
44
+ },
45
+ ];
46
+
47
+ /** Icon for a trigger kind, shared by the picker rows and the selected-variant editor header. */
48
+ export const getTriggerKindIcon = (kind: TriggerKind): string =>
49
+ OPTIONS.find((option) => option.kind === kind)?.icon ?? 'ph--lightning--regular';
50
+
51
+ export type TriggerKindSelectorProps = {
52
+ onChange: (kind: TriggerKind) => void;
53
+ };
54
+
55
+ /**
56
+ * Single-select list of pluggable trigger variants (Schedule / Feed / Query / Webhook / Email): each row
57
+ * shows an icon, title and description. Built on {@link Listbox} (role=listbox/option, arrow-key navigation);
58
+ * selecting a row emits its kind. Selection is transient — the parent swaps in the variant editor on change.
59
+ */
60
+ export const TriggerKindSelector = ({ onChange }: TriggerKindSelectorProps) => {
61
+ const { t } = useTranslation(meta.profile.key);
62
+ const handleValueChange = useCallback(
63
+ (id: string) => {
64
+ const option = OPTIONS.find((option) => option.kind === id);
65
+ if (option) {
66
+ onChange(option.kind);
67
+ }
68
+ },
69
+ [onChange],
70
+ );
71
+
72
+ return (
73
+ <Listbox.Root onValueChange={handleValueChange}>
74
+ <Listbox.Content classNames='gap-1' aria-label={t('trigger-kind.placeholder')}>
75
+ {OPTIONS.map(({ kind, icon, disabled }) => (
76
+ <Listbox.Item key={kind} id={kind} disabled={disabled} classNames='bg-input-surface rounded-sm'>
77
+ <Listbox.ItemContent
78
+ icon={<Icon icon={icon} size={5} classNames='text-description' />}
79
+ title={<span className='font-medium'>{t(`trigger-kind.${kind}.label`)}</span>}
80
+ description={t(`trigger-kind.${kind}.description`)}
81
+ />
82
+ </Listbox.Item>
83
+ ))}
84
+ </Listbox.Content>
85
+ </Listbox.Root>
86
+ );
87
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ export * from './TriggerEditor';
@@ -0,0 +1,11 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ export * from './RoutineForm';
6
+ export * from './CreateRoutinePanel';
7
+ export * from './MasterDetail';
8
+ export * from './InstructionsEditor';
9
+ export * from './Schedule';
10
+ export * from './TemplateEditor';
11
+ export * from './TriggerEditor';
@@ -0,0 +1,146 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Effect from 'effect/Effect';
7
+ import React from 'react';
8
+
9
+ import { withPluginManager } from '@dxos/app-framework/testing';
10
+ import { Instructions, Skill, Trigger } from '@dxos/compute';
11
+ import { Feed, Filter, Obj, Ref } from '@dxos/echo';
12
+ import { ClientPlugin } from '@dxos/plugin-client/testing';
13
+ import { RoutinePlugin } from '@dxos/plugin-routine/testing';
14
+ import { corePlugins } from '@dxos/plugin-testing';
15
+ import { type Space, useQuery, useSpaces } from '@dxos/react-client/echo';
16
+ import { ObjectProperties } from '@dxos/react-ui-form';
17
+ import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
18
+
19
+ import { translations } from '#translations';
20
+ import { Routine } from '#types';
21
+
22
+ import { RoutineArticle } from './RoutineArticle';
23
+
24
+ const types = [Routine.Routine, Trigger.Trigger, Instructions.Instructions, Feed.Feed, Skill.Skill];
25
+
26
+ /** Seed a few fake skills so the routine action's Skills picker has options. */
27
+ const seedSkills = (space: Space) => {
28
+ space.db.add(
29
+ Skill.make({
30
+ key: 'example.com/skill/research',
31
+ name: 'Research',
32
+ description: 'Research an organization.',
33
+ }),
34
+ );
35
+ space.db.add(
36
+ Skill.make({
37
+ key: 'example.com/skill/summarize',
38
+ name: 'Summarize',
39
+ description: 'Summarize the selected content.',
40
+ }),
41
+ );
42
+ space.db.add(
43
+ Skill.make({
44
+ key: 'example.com/skill/translate',
45
+ name: 'Translate',
46
+ description: 'Translate text to another language.',
47
+ }),
48
+ );
49
+ };
50
+
51
+ /** Empty automation — no trigger or action yet. */
52
+ const seedDefault = (space: Space) => {
53
+ seedSkills(space);
54
+ space.db.add(Routine.make({ name: 'Morning Report', triggers: [] }));
55
+ };
56
+
57
+ /** Automation with a timer trigger pre-configured for a daily 9 AM schedule. */
58
+ const seedWithTimerTrigger = (space: Space) => {
59
+ seedSkills(space);
60
+ const trigger = space.db.add(Trigger.make({ enabled: false, spec: { kind: 'timer', cron: '0 9 * * *' } }));
61
+ const automation = space.db.add(Routine.make({ name: 'Daily Digest', triggers: [] }));
62
+ // Wire the trigger into the automation after both are in the db.
63
+ Obj.update(automation, (automation) => {
64
+ automation.triggers = [...automation.triggers, Ref.make(trigger)];
65
+ });
66
+ };
67
+
68
+ /**
69
+ * `withPluginManager` (rather than `withClientProvider`) so the article's `useOperationInvoker` resolves
70
+ * the `OperationInvoker` capability the Run toolbar action depends on.
71
+ */
72
+ const withAutomation = (seed: (space: Space) => void) =>
73
+ withPluginManager({
74
+ plugins: [
75
+ ...corePlugins(),
76
+ ClientPlugin({
77
+ types,
78
+ onClientInitialized: ({ client }) =>
79
+ Effect.gen(function* () {
80
+ yield* Effect.promise(() => client.halo.createIdentity());
81
+ const space = yield* Effect.promise(() => client.spaces.create());
82
+ yield* Effect.promise(() => space.waitUntilReady());
83
+ seed(space);
84
+ }),
85
+ }),
86
+ RoutinePlugin(),
87
+ ],
88
+ });
89
+
90
+ const DefaultStory = () => {
91
+ const spaces = useSpaces();
92
+ const space = spaces[spaces.length - 1];
93
+ const [automation] = useQuery(space?.db, Filter.type(Routine.Routine));
94
+ if (!automation) {
95
+ return <Loading />;
96
+ }
97
+ return <RoutineArticle role='article' subject={automation} attendableId='story' />;
98
+ };
99
+
100
+ /** Two-column layout: the composite RoutineArticle on the left, raw object properties on the right. */
101
+ const TwoColumnStory = () => {
102
+ const spaces = useSpaces();
103
+ const space = spaces[spaces.length - 1];
104
+ const [automation] = useQuery(space?.db, Filter.type(Routine.Routine));
105
+ if (!automation) {
106
+ return <Loading />;
107
+ }
108
+ return (
109
+ <div role='none' className='w-full grid grid-cols-2 gap-px'>
110
+ <RoutineArticle role='article' subject={automation} attendableId='story' />
111
+ <div role='none' className='overflow-y-auto p-2 bg-baseSurface'>
112
+ <ObjectProperties object={automation} />
113
+ </div>
114
+ </div>
115
+ );
116
+ };
117
+
118
+ const meta = {
119
+ title: 'plugins/plugin-routine/containers/RoutineArticle',
120
+ render: DefaultStory,
121
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
122
+ parameters: {
123
+ layout: 'fullscreen',
124
+ translations,
125
+ },
126
+ } satisfies Meta<typeof DefaultStory>;
127
+
128
+ export default meta;
129
+
130
+ type Story = StoryObj<typeof meta>;
131
+
132
+ /** Empty automation — no trigger or action yet. The Run action is disabled until a runnable is set. */
133
+ export const Empty: Story = {
134
+ decorators: [withAutomation(seedDefault)],
135
+ };
136
+
137
+ /** Side-by-side: the composite editor alongside the underlying object's raw properties. */
138
+ export const TwoColumn: Story = {
139
+ render: TwoColumnStory,
140
+ decorators: [withAutomation(seedDefault)],
141
+ };
142
+
143
+ /** Automation with a timer trigger pre-configured for a daily 9 AM schedule. */
144
+ export const WithTimerTrigger: Story = {
145
+ decorators: [withAutomation(seedWithTimerTrigger)],
146
+ };