@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.
- package/LICENSE +105 -0
- package/PLUGIN.mdl +475 -0
- package/README.md +15 -0
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs +95 -0
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs.map +7 -0
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs +249 -0
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs.map +7 -0
- package/dist/lib/neutral/RoutinePlugin.mjs +10 -0
- package/dist/lib/neutral/RoutinePlugin.mjs.map +7 -0
- package/dist/lib/neutral/RoutinePlugin.node.mjs +1133 -0
- package/dist/lib/neutral/RoutinePlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs +36 -0
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs +48 -0
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs.map +7 -0
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs +236 -0
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs.map +7 -0
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs +27 -0
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs.map +7 -0
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs +90 -0
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +25 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/node.mjs +19 -0
- package/dist/lib/neutral/capabilities/node.mjs.map +7 -0
- package/dist/lib/neutral/chunk-674LDIUJ.mjs +9 -0
- package/dist/lib/neutral/chunk-674LDIUJ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-CNYAPXUW.mjs +65 -0
- package/dist/lib/neutral/chunk-CNYAPXUW.mjs.map +7 -0
- package/dist/lib/neutral/chunk-HLO4LYXT.mjs +44 -0
- package/dist/lib/neutral/chunk-HLO4LYXT.mjs.map +7 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/neutral/chunk-ODQDVFMZ.mjs +8 -0
- package/dist/lib/neutral/chunk-ODQDVFMZ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs +263 -0
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs.map +7 -0
- package/dist/lib/neutral/chunk-WLNL77C7.mjs +14 -0
- package/dist/lib/neutral/chunk-WLNL77C7.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +1921 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +17 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs +25 -0
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs.map +7 -0
- package/dist/lib/neutral/create-routine-I67BYJA2.mjs +38 -0
- package/dist/lib/neutral/create-routine-I67BYJA2.mjs.map +7 -0
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs +70 -0
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +47 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +27 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/layer-specs-ADQCTTRT.mjs +135 -0
- package/dist/lib/neutral/layer-specs-ADQCTTRT.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +8 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs +18 -0
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs +13 -0
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs +67 -0
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs.map +7 -0
- package/dist/lib/neutral/registry-sync-PHBU6CH2.mjs +86 -0
- package/dist/lib/neutral/registry-sync-PHBU6CH2.mjs.map +7 -0
- package/dist/lib/neutral/run-routine-HJWXIWLJ.mjs +37 -0
- package/dist/lib/neutral/run-routine-HJWXIWLJ.mjs.map +7 -0
- package/dist/lib/neutral/templates-IIUCEBAX.mjs +49 -0
- package/dist/lib/neutral/templates-IIUCEBAX.mjs.map +7 -0
- package/dist/lib/neutral/testing.mjs +8 -0
- package/dist/lib/neutral/testing.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +115 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/trigger-runtime-controller-7FOTH2NP.mjs +77 -0
- package/dist/lib/neutral/trigger-runtime-controller-7FOTH2NP.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +17 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/RoutinePlugin.d.ts +4 -0
- package/dist/types/src/RoutinePlugin.d.ts.map +1 -0
- package/dist/types/src/RoutinePlugin.node.d.ts +4 -0
- package/dist/types/src/RoutinePlugin.node.d.ts.map +1 -0
- package/dist/types/src/RoutinePlugin.test.d.ts +2 -0
- package/dist/types/src/RoutinePlugin.test.d.ts.map +1 -0
- package/dist/types/src/RoutinePlugin.workerd.d.ts +4 -0
- package/dist/types/src/RoutinePlugin.workerd.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/create-object.d.ts +5 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/create-object.test.d.ts +2 -0
- package/dist/types/src/capabilities/create-object.test.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +12 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/layer-specs.d.ts +5 -0
- package/dist/types/src/capabilities/layer-specs.d.ts.map +1 -0
- package/dist/types/src/capabilities/navigation-resolver.d.ts +5 -0
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/node.d.ts +9 -0
- package/dist/types/src/capabilities/node.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/registry-sync.d.ts +21 -0
- package/dist/types/src/capabilities/registry-sync.d.ts.map +1 -0
- package/dist/types/src/capabilities/templates.d.ts +5 -0
- package/dist/types/src/capabilities/templates.d.ts.map +1 -0
- package/dist/types/src/capabilities/trigger-runtime-controller.d.ts +5 -0
- package/dist/types/src/capabilities/trigger-runtime-controller.d.ts.map +1 -0
- package/dist/types/src/capabilities/trigger-runtime-controller.test.d.ts +2 -0
- package/dist/types/src/capabilities/trigger-runtime-controller.test.d.ts.map +1 -0
- package/dist/types/src/commands/index.d.ts +2 -0
- package/dist/types/src/commands/index.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/create/index.d.ts +25 -0
- package/dist/types/src/commands/trigger/create/index.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/create/queue.d.ts +13 -0
- package/dist/types/src/commands/trigger/create/queue.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/create/subscription.d.ts +15 -0
- package/dist/types/src/commands/trigger/create/subscription.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/create/timer.d.ts +13 -0
- package/dist/types/src/commands/trigger/create/timer.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/index.d.ts +57 -0
- package/dist/types/src/commands/trigger/index.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/list.d.ts +7 -0
- package/dist/types/src/commands/trigger/list.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/options.d.ts +10 -0
- package/dist/types/src/commands/trigger/options.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/remove.d.ts +8 -0
- package/dist/types/src/commands/trigger/remove.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/index.d.ts +28 -0
- package/dist/types/src/commands/trigger/update/index.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/queue.d.ts +13 -0
- package/dist/types/src/commands/trigger/update/queue.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/subscription.d.ts +15 -0
- package/dist/types/src/commands/trigger/update/subscription.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/timer.d.ts +13 -0
- package/dist/types/src/commands/trigger/update/timer.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/util.d.ts +46 -0
- package/dist/types/src/commands/trigger/util.d.ts.map +1 -0
- package/dist/types/src/components/CreateRoutinePanel/CreateRoutinePanel.d.ts +14 -0
- package/dist/types/src/components/CreateRoutinePanel/CreateRoutinePanel.d.ts.map +1 -0
- package/dist/types/src/components/CreateRoutinePanel/index.d.ts +2 -0
- package/dist/types/src/components/CreateRoutinePanel/index.d.ts.map +1 -0
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts +16 -0
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts.map +1 -0
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts +17 -0
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/InstructionsEditor/index.d.ts +2 -0
- package/dist/types/src/components/InstructionsEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts +51 -0
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts.map +1 -0
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts +16 -0
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts.map +1 -0
- package/dist/types/src/components/MasterDetail/index.d.ts +2 -0
- package/dist/types/src/components/MasterDetail/index.d.ts.map +1 -0
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts +25 -0
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts.map +1 -0
- package/dist/types/src/components/RoutineForm/index.d.ts +2 -0
- package/dist/types/src/components/RoutineForm/index.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/Schedule.d.ts +80 -0
- package/dist/types/src/components/Schedule/Schedule.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/Schedule.stories.d.ts +23 -0
- package/dist/types/src/components/Schedule/Schedule.stories.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/cron.d.ts +44 -0
- package/dist/types/src/components/Schedule/cron.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/cron.test.d.ts +2 -0
- package/dist/types/src/components/Schedule/cron.test.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/index.d.ts +4 -0
- package/dist/types/src/components/Schedule/index.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/types.d.ts +66 -0
- package/dist/types/src/components/Schedule/types.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +13 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts +19 -0
- package/dist/types/src/components/TemplateEditor/TemplateEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts +21 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts +16 -0
- package/dist/types/src/components/TemplateEditor/TemplateForm.stories.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts +12 -0
- package/dist/types/src/components/TemplateEditor/extensions/handlebars-extension.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/extensions/index.d.ts +3 -0
- package/dist/types/src/components/TemplateEditor/extensions/index.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts +8 -0
- package/dist/types/src/components/TemplateEditor/extensions/xml-extension.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/index.d.ts +2 -0
- package/dist/types/src/components/TemplateEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/TemplateEditor/types.d.ts +18 -0
- package/dist/types/src/components/TemplateEditor/types.d.ts.map +1 -0
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +24 -0
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -0
- package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +25 -0
- package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -0
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts +15 -0
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts.map +1 -0
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.stories.d.ts +15 -0
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.stories.d.ts.map +1 -0
- package/dist/types/src/components/TriggerEditor/index.d.ts +2 -0
- package/dist/types/src/components/TriggerEditor/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +8 -0
- package/dist/types/src/components/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +14 -0
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts +20 -0
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineArticle/index.d.ts +2 -0
- package/dist/types/src/containers/RoutineArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts +17 -0
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts +15 -0
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineCompanion/index.d.ts +3 -0
- package/dist/types/src/containers/RoutineCompanion/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts +10 -0
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineSettings/index.d.ts +2 -0
- package/dist/types/src/containers/RoutineSettings/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts +9 -0
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts +15 -0
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/index.d.ts +2 -0
- package/dist/types/src/containers/RoutineTraceCompanion/index.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/runs.d.ts +34 -0
- package/dist/types/src/containers/RoutineTraceCompanion/runs.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/runs.test.d.ts +2 -0
- package/dist/types/src/containers/RoutineTraceCompanion/runs.test.d.ts.map +1 -0
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts +11 -0
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts.map +1 -0
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts +6 -0
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts.map +1 -0
- package/dist/types/src/containers/SkillArticle/index.d.ts +2 -0
- package/dist/types/src/containers/SkillArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +7 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -0
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +12 -0
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +4 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/src/meta.d.ts +33 -0
- package/dist/types/src/meta.d.ts.map +1 -0
- package/dist/types/src/operations/create-routine.d.ts +5 -0
- package/dist/types/src/operations/create-routine.d.ts.map +1 -0
- package/dist/types/src/operations/create-trigger-from-template.d.ts +5 -0
- package/dist/types/src/operations/create-trigger-from-template.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/run-routine.d.ts +5 -0
- package/dist/types/src/operations/run-routine.d.ts.map +1 -0
- package/dist/types/src/paths.d.ts +5 -0
- package/dist/types/src/paths.d.ts.map +1 -0
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/templates/index.d.ts +11 -0
- package/dist/types/src/templates/index.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +2 -0
- package/dist/types/src/testing/index.d.ts.map +1 -0
- package/dist/types/src/testing/test-functions.d.ts +328 -0
- package/dist/types/src/testing/test-functions.d.ts.map +1 -0
- package/dist/types/src/testing.d.ts +2 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +3 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types/Routine.d.ts +55 -0
- package/dist/types/src/types/Routine.d.ts.map +1 -0
- package/dist/types/src/types/Routine.test.d.ts +2 -0
- package/dist/types/src/types/Routine.test.d.ts.map +1 -0
- package/dist/types/src/types/RoutineCapabilities.d.ts +44 -0
- package/dist/types/src/types/RoutineCapabilities.d.ts.map +1 -0
- package/dist/types/src/types/RoutineOperation.d.ts +45 -0
- package/dist/types/src/types/RoutineOperation.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +5 -0
- package/dist/types/src/types/index.d.ts.map +1 -0
- package/dist/types/src/types/schema.d.ts +33 -0
- package/dist/types/src/types/schema.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +3 -0
- package/dist/types/src/util/index.d.ts.map +1 -0
- package/dist/types/src/util/routines-for-object.d.ts +22 -0
- package/dist/types/src/util/routines-for-object.d.ts.map +1 -0
- package/dist/types/src/util/routines-for-object.test.d.ts +2 -0
- package/dist/types/src/util/routines-for-object.test.d.ts.map +1 -0
- package/dist/types/src/util/run-instructions.d.ts +5 -0
- package/dist/types/src/util/run-instructions.d.ts.map +1 -0
- package/dist/types/src/util/run-instructions.test.d.ts +2 -0
- package/dist/types/src/util/run-instructions.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/dx.config.ts +33 -0
- package/package.json +196 -0
- package/src/RoutinePlugin.node.ts +48 -0
- package/src/RoutinePlugin.test.ts +27 -0
- package/src/RoutinePlugin.tsx +58 -0
- package/src/RoutinePlugin.workerd.ts +24 -0
- package/src/capabilities/app-graph-builder.ts +80 -0
- package/src/capabilities/create-object.test.ts +18 -0
- package/src/capabilities/create-object.ts +26 -0
- package/src/capabilities/index.ts +22 -0
- package/src/capabilities/layer-specs.ts +190 -0
- package/src/capabilities/navigation-resolver.ts +21 -0
- package/src/capabilities/node.ts +19 -0
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-surface.tsx +66 -0
- package/src/capabilities/registry-sync.ts +114 -0
- package/src/capabilities/templates.ts +17 -0
- package/src/capabilities/trigger-runtime-controller.test.ts +107 -0
- package/src/capabilities/trigger-runtime-controller.ts +126 -0
- package/src/commands/index.ts +5 -0
- package/src/commands/trigger/create/index.ts +14 -0
- package/src/commands/trigger/create/queue.ts +87 -0
- package/src/commands/trigger/create/subscription.ts +126 -0
- package/src/commands/trigger/create/timer.ts +90 -0
- package/src/commands/trigger/index.ts +16 -0
- package/src/commands/trigger/list.ts +69 -0
- package/src/commands/trigger/options.ts +47 -0
- package/src/commands/trigger/remove.ts +45 -0
- package/src/commands/trigger/update/index.ts +14 -0
- package/src/commands/trigger/update/queue.ts +191 -0
- package/src/commands/trigger/update/subscription.ts +278 -0
- package/src/commands/trigger/update/timer.ts +194 -0
- package/src/commands/trigger/util.ts +412 -0
- package/src/components/CreateRoutinePanel/CreateRoutinePanel.tsx +68 -0
- package/src/components/CreateRoutinePanel/index.ts +5 -0
- package/src/components/InstructionsEditor/InstructionsEditor.stories.tsx +69 -0
- package/src/components/InstructionsEditor/InstructionsEditor.tsx +107 -0
- package/src/components/InstructionsEditor/index.ts +5 -0
- package/src/components/MasterDetail/MasterDetail.stories.tsx +100 -0
- package/src/components/MasterDetail/MasterDetail.tsx +175 -0
- package/src/components/MasterDetail/index.ts +5 -0
- package/src/components/RoutineForm/RoutineForm.tsx +293 -0
- package/src/components/RoutineForm/index.ts +5 -0
- package/src/components/Schedule/Schedule.stories.tsx +73 -0
- package/src/components/Schedule/Schedule.tsx +527 -0
- package/src/components/Schedule/cron.test.ts +230 -0
- package/src/components/Schedule/cron.ts +337 -0
- package/src/components/Schedule/index.ts +8 -0
- package/src/components/Schedule/types.ts +124 -0
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +93 -0
- package/src/components/TemplateEditor/TemplateEditor.tsx +77 -0
- package/src/components/TemplateEditor/TemplateForm.stories.tsx +76 -0
- package/src/components/TemplateEditor/TemplateForm.tsx +204 -0
- package/src/components/TemplateEditor/extensions/handlebars-extension.ts +274 -0
- package/src/components/TemplateEditor/extensions/index.ts +6 -0
- package/src/components/TemplateEditor/extensions/xml-extension.ts +64 -0
- package/src/components/TemplateEditor/index.ts +5 -0
- package/src/components/TemplateEditor/types.tsx +28 -0
- package/src/components/TriggerEditor/TriggerEditor.stories.tsx +122 -0
- package/src/components/TriggerEditor/TriggerEditor.tsx +365 -0
- package/src/components/TriggerEditor/TriggerKindSelector.stories.tsx +42 -0
- package/src/components/TriggerEditor/TriggerKindSelector.tsx +87 -0
- package/src/components/TriggerEditor/index.ts +5 -0
- package/src/components/index.ts +11 -0
- package/src/containers/RoutineArticle/RoutineArticle.stories.tsx +146 -0
- package/src/containers/RoutineArticle/RoutineArticle.tsx +109 -0
- package/src/containers/RoutineArticle/index.ts +5 -0
- package/src/containers/RoutineCompanion/RoutineCompanion.stories.tsx +82 -0
- package/src/containers/RoutineCompanion/RoutineCompanion.tsx +342 -0
- package/src/containers/RoutineCompanion/index.ts +6 -0
- package/src/containers/RoutineSettings/RoutineSettings.tsx +65 -0
- package/src/containers/RoutineSettings/index.ts +5 -0
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.tsx +133 -0
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.tsx +125 -0
- package/src/containers/RoutineTraceCompanion/index.ts +5 -0
- package/src/containers/RoutineTraceCompanion/runs.test.ts +140 -0
- package/src/containers/RoutineTraceCompanion/runs.ts +135 -0
- package/src/containers/RoutineTraceCompanion/useRoutineRuns.ts +50 -0
- package/src/containers/SkillArticle/SkillArticle.tsx +29 -0
- package/src/containers/SkillArticle/index.ts +5 -0
- package/src/containers/index.ts +11 -0
- package/src/hooks/index.ts +6 -0
- package/src/hooks/useTriggerRuntimeControls.ts +70 -0
- package/src/index.ts +7 -0
- package/src/meta.ts +9 -0
- package/src/operations/create-routine.ts +39 -0
- package/src/operations/create-trigger-from-template.ts +68 -0
- package/src/operations/index.ts +11 -0
- package/src/operations/run-routine.ts +45 -0
- package/src/paths.ts +18 -0
- package/src/plugin.ts +11 -0
- package/src/templates/index.ts +48 -0
- package/src/testing/index.ts +5 -0
- package/src/testing/test-functions.ts +76 -0
- package/src/testing.ts +7 -0
- package/src/translations.ts +125 -0
- package/src/types/Routine.test.ts +51 -0
- package/src/types/Routine.ts +144 -0
- package/src/types/RoutineCapabilities.ts +51 -0
- package/src/types/RoutineOperation.ts +104 -0
- package/src/types/index.ts +9 -0
- package/src/types/schema.ts +31 -0
- package/src/util/index.ts +6 -0
- package/src/util/routines-for-object.test.ts +109 -0
- package/src/util/routines-for-object.ts +89 -0
- package/src/util/run-instructions.test.ts +23 -0
- package/src/util/run-instructions.ts +12 -0
- package/src/vite-env.d.ts +10 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { Instructions, Runnable, Trigger } from '@dxos/compute';
|
|
10
|
+
// Operation is imported so TypeScript can name Operation.PersistentOperation in the emitted .d.ts
|
|
11
|
+
// (Runnable is an alias for Operation.PersistentOperation, so Routine's class type references it).
|
|
12
|
+
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
13
|
+
import { Operation } from '@dxos/compute';
|
|
14
|
+
import { Annotation, DXN, Obj, Ref, Type } from '@dxos/echo';
|
|
15
|
+
import { LabelAnnotation } from '@dxos/echo/internal';
|
|
16
|
+
|
|
17
|
+
import { runInstructionsRef } from '../util/run-instructions';
|
|
18
|
+
|
|
19
|
+
const Kinds = ['runnable', 'instructions'] as const;
|
|
20
|
+
export const Kind = Schema.Literal(...Kinds);
|
|
21
|
+
export type Kind = (typeof Kinds)[number];
|
|
22
|
+
|
|
23
|
+
const RunnableSpec = Schema.Struct({
|
|
24
|
+
kind: Schema.Literal('runnable'),
|
|
25
|
+
runnable: Ref.Ref(Runnable.Runnable),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const InstructionsSpec = Schema.Struct({
|
|
29
|
+
kind: Schema.Literal('instructions'),
|
|
30
|
+
instructions: Ref.Ref(Instructions.Instructions),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const RoutineSpec = Schema.Union(RunnableSpec, InstructionsSpec);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* User-facing routine: a thin aggregate of an action (`runnable`) and the triggers that fire it.
|
|
37
|
+
* App-level only — EDGE stays unaware of it (triggers point directly at the runnable).
|
|
38
|
+
*/
|
|
39
|
+
export class Routine extends Type.makeObject<Routine>(DXN.make('org.dxos.type.routine', '0.2.0'))(
|
|
40
|
+
Schema.Struct({
|
|
41
|
+
name: Schema.String.pipe(Schema.optional),
|
|
42
|
+
description: Schema.String.pipe(Schema.optional),
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The action to run: either an Operation (`spec.runnable`, bound directly) or the routine's own owned
|
|
46
|
+
* Instructions (`spec.instructions`). For an Operation action the trigger's `runnable` points at this
|
|
47
|
+
* Operation. For an Instructions action `spec.instructions` is the owned Instructions object (the operation
|
|
48
|
+
* is implicitly the static RunInstructions, so no separate operation ref is stored), and the trigger's
|
|
49
|
+
* `runnable` is RunInstructions with this instructions bound as its input.
|
|
50
|
+
*/
|
|
51
|
+
// TODO(burdon): Change to Array? Or handle that case with a ComputeGraph runnable.
|
|
52
|
+
spec: RoutineSpec.pipe(Schema.optional),
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Explicit membership, bi-directional with `trigger.runnable → runnable`. Required (not derived by query)
|
|
56
|
+
* because the runnable may be a shared registry operation referenced by multiple automations, which would
|
|
57
|
+
* conflate triggers. MVP enforces length <= 1.
|
|
58
|
+
*/
|
|
59
|
+
triggers: Schema.Array(Ref.Ref(Trigger.Trigger)),
|
|
60
|
+
}).pipe(
|
|
61
|
+
LabelAnnotation.set(['name']),
|
|
62
|
+
Annotation.IconAnnotation.set({ icon: 'ph--lightning--regular', hue: 'amber' }),
|
|
63
|
+
),
|
|
64
|
+
) {}
|
|
65
|
+
|
|
66
|
+
/** Returns true when value is a Routine object. */
|
|
67
|
+
export const instanceOf = (value: unknown): value is Routine => Obj.instanceOf(Routine, value);
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The owned Instructions ref of an instructions-action routine, or undefined for an operation action.
|
|
71
|
+
* Classification is explicit in `spec.kind`, so this needs no `.target` dereference; callers resolve the ref
|
|
72
|
+
* reactively (`useObject`) or asynchronously (`Database.load`) as appropriate.
|
|
73
|
+
*/
|
|
74
|
+
export const instructionsRef = (routine: Pick<Routine, 'spec'>): Ref.Ref<Instructions.Instructions> | undefined =>
|
|
75
|
+
routine.spec?.kind === 'instructions' ? routine.spec.instructions : undefined;
|
|
76
|
+
|
|
77
|
+
/** The Operation (runnable) ref of an operation-action routine, or undefined for an instructions action. */
|
|
78
|
+
export const runnableRef = (routine: Pick<Routine, 'spec'>): Ref.Ref<Runnable.Runnable> | undefined =>
|
|
79
|
+
routine.spec?.kind === 'runnable' ? routine.spec.runnable : undefined;
|
|
80
|
+
|
|
81
|
+
/** Strip a stale `instructions` binding from a trigger input. */
|
|
82
|
+
const withoutInstructions = (input: Record<string, unknown> | undefined): Record<string, unknown> | undefined => {
|
|
83
|
+
if (!input || !('instructions' in input)) {
|
|
84
|
+
return input;
|
|
85
|
+
}
|
|
86
|
+
const { instructions: _drop, ...rest } = input;
|
|
87
|
+
return rest;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Wire the routine's owned triggers to dispatch its current action (`spec`): an instructions action sets each
|
|
92
|
+
* trigger's `runnable` to RunInstructions with the owned instructions bound into `input`; an operation action
|
|
93
|
+
* binds the operation directly and drops any stale instructions binding. Call after the action (`spec`) changes
|
|
94
|
+
* so a trigger never keeps a binding for the previous action.
|
|
95
|
+
*/
|
|
96
|
+
export const wireTriggers = (routine: Routine): void => {
|
|
97
|
+
const instructions = instructionsRef(routine);
|
|
98
|
+
const fn = instructions ? runInstructionsRef() : runnableRef(routine);
|
|
99
|
+
for (const ref of routine.triggers) {
|
|
100
|
+
const trigger = ref.target;
|
|
101
|
+
if (!trigger) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
Obj.update(trigger, (trigger) => {
|
|
105
|
+
trigger.runnable = fn;
|
|
106
|
+
const base = withoutInstructions(trigger.input);
|
|
107
|
+
trigger.input = instructions ? { input: {}, ...base, instructions } : base;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Creates a fully-wired in-memory routine graph. `instructions` and `trigger` are optional extras beyond the
|
|
114
|
+
* schema fields: when provided they are parented under the routine and wired together (runnable, trigger
|
|
115
|
+
* runnable, the trigger's instructions input binding, and the `triggers` ref) so that a single `Database.add`
|
|
116
|
+
* cascades the whole graph. `triggers` defaults to `[]` so callers that supply a `trigger` need not provide it.
|
|
117
|
+
*/
|
|
118
|
+
export const make = ({
|
|
119
|
+
instructions,
|
|
120
|
+
trigger,
|
|
121
|
+
triggers = [],
|
|
122
|
+
...props
|
|
123
|
+
}: Omit<Obj.MakeProps<typeof Routine>, 'triggers'> & {
|
|
124
|
+
triggers?: ReadonlyArray<Ref.Ref<Trigger.Trigger>>;
|
|
125
|
+
instructions?: Instructions.Instructions;
|
|
126
|
+
trigger?: Trigger.Trigger;
|
|
127
|
+
}): Routine => {
|
|
128
|
+
const routine = Obj.make(Routine, { ...props, triggers });
|
|
129
|
+
if (instructions) {
|
|
130
|
+
Obj.setParent(instructions, routine);
|
|
131
|
+
Obj.update(routine, (routine) => {
|
|
132
|
+
routine.spec = { kind: 'instructions', instructions: Ref.make(instructions) };
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (trigger) {
|
|
136
|
+
Obj.setParent(trigger, routine);
|
|
137
|
+
Obj.update(routine, (routine) => {
|
|
138
|
+
routine.triggers.push(Ref.make(trigger));
|
|
139
|
+
});
|
|
140
|
+
// Wire the trigger's `runnable`/`input` from the action (`spec`); preserves any template-provided input.
|
|
141
|
+
wireTriggers(routine);
|
|
142
|
+
}
|
|
143
|
+
return routine;
|
|
144
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import type * as Effect from 'effect/Effect';
|
|
6
|
+
|
|
7
|
+
import { Capability } from '@dxos/app-framework';
|
|
8
|
+
import type { Database, Obj } from '@dxos/echo';
|
|
9
|
+
import type { DelegationStrategy } from '@dxos/functions-runtime';
|
|
10
|
+
|
|
11
|
+
import * as Routine from './Routine';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Optional supervisor strategy for the agent chat service. When contributed (by a plugin that knows
|
|
15
|
+
* the agent/plan model, e.g. plugin-assistant), the conversational agent delegates outstanding work
|
|
16
|
+
* to sub-agents and folds their results back into the conversation. Consumed by the AgentService
|
|
17
|
+
* LayerSpec; absent by default (a plain conversational agent).
|
|
18
|
+
*/
|
|
19
|
+
export const AgentDelegationStrategy = Capability.make<DelegationStrategy>(
|
|
20
|
+
'org.dxos.plugin.routine.capability.agentDelegationStrategy',
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* An automation template contributed by a plugin. The create dialog and the per-object "Automations"
|
|
25
|
+
* companion list contributed templates (`Capability.getAll(RoutineCapabilities.Template)`) and run the
|
|
26
|
+
* chosen template's `scaffold` to build the automation.
|
|
27
|
+
*/
|
|
28
|
+
export type Template = {
|
|
29
|
+
/** Stable id (e.g. 'org.dxos.routine.blank'). */
|
|
30
|
+
id: string;
|
|
31
|
+
/** Human-readable label shown in the picker. */
|
|
32
|
+
label: string;
|
|
33
|
+
/** Optional Phosphor icon name. */
|
|
34
|
+
icon?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Whether this template applies to the given companion subject. The subject is the object whose
|
|
37
|
+
* "Automations" companion is open, or undefined in the global create dialog. Templates that need a
|
|
38
|
+
* specific subject (e.g. a feed-bearing Mailbox) gate themselves here. Defaults to always-applies.
|
|
39
|
+
*/
|
|
40
|
+
appliesTo?: (subject?: Obj.Unknown) => boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Build the routine as a fully-wired in-memory {@link Routine.Routine} graph — the routine plus its owned
|
|
43
|
+
* trigger and instructions, assembled by `Routine.make`. The create flow persists it with a single
|
|
44
|
+
* `Database.add` (which cascades the owned children); scaffold must NOT call `Database.add` itself.
|
|
45
|
+
* `Database.Service` may still be used for read-only lookups (e.g. loading a feed ref). `subject` is set
|
|
46
|
+
* when scaffolding from an object's companion.
|
|
47
|
+
*/
|
|
48
|
+
scaffold: (ctx: { name?: string; subject?: Obj.Unknown }) => Effect.Effect<Routine.Routine, Error, Database.Service>;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const Template = Capability.make<Template>('org.dxos.plugin.routine.capability.template');
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { Capability } from '@dxos/app-framework';
|
|
10
|
+
import { Chat } from '@dxos/assistant-toolkit';
|
|
11
|
+
import { Instructions, Operation } from '@dxos/compute';
|
|
12
|
+
import { Database, DXN, Obj, Ref, Type } from '@dxos/echo';
|
|
13
|
+
// Value-side `EID` import keeps TS declaration emit portable — `TriggerTemplate`
|
|
14
|
+
// references `EID.Schema` and the inferred `CreateTriggerFromTemplate` type
|
|
15
|
+
// otherwise needs a transitive `@dxos/keys` import that's hard for d.ts emit to surface.
|
|
16
|
+
import { EID as _EchoURIReference } from '@dxos/keys';
|
|
17
|
+
|
|
18
|
+
import { meta } from '#meta';
|
|
19
|
+
|
|
20
|
+
import * as Routine from './Routine';
|
|
21
|
+
import { TriggerTemplate } from './schema';
|
|
22
|
+
export { _EchoURIReference };
|
|
23
|
+
|
|
24
|
+
const makeKey = (name: string) => DXN.make(`${meta.profile.key}.operation.${name}`);
|
|
25
|
+
|
|
26
|
+
export const CreateTriggerFromTemplate = Operation.make({
|
|
27
|
+
meta: {
|
|
28
|
+
key: makeKey('createTriggerFromTemplate'),
|
|
29
|
+
name: 'Create Trigger From Template',
|
|
30
|
+
icon: 'ph--lightning--regular',
|
|
31
|
+
},
|
|
32
|
+
services: [Capability.Service],
|
|
33
|
+
input: Schema.Struct({
|
|
34
|
+
db: Database.Database,
|
|
35
|
+
template: TriggerTemplate,
|
|
36
|
+
enabled: Schema.optional(Schema.Boolean),
|
|
37
|
+
scriptName: Schema.optional(Schema.String),
|
|
38
|
+
input: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
39
|
+
}),
|
|
40
|
+
output: Schema.Void,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// The single creation entrypoint for every path (create dialog, companion, sidebar) so placement and
|
|
44
|
+
// ownership are established in one place. Output mirrors `SpaceCapabilities.CreateObjectResult`.
|
|
45
|
+
export const CreateRoutine = Operation.make({
|
|
46
|
+
meta: {
|
|
47
|
+
key: makeKey('createAutomation'),
|
|
48
|
+
name: 'Create Routine',
|
|
49
|
+
icon: 'ph--lightning--regular',
|
|
50
|
+
},
|
|
51
|
+
services: [Capability.Service],
|
|
52
|
+
input: Schema.Struct({
|
|
53
|
+
db: Database.Database,
|
|
54
|
+
templateId: Schema.String,
|
|
55
|
+
name: Schema.optional(Schema.String),
|
|
56
|
+
subject: Schema.optional(Obj.Unknown),
|
|
57
|
+
}),
|
|
58
|
+
output: Schema.Struct({
|
|
59
|
+
id: Schema.String,
|
|
60
|
+
subject: Schema.Array(Schema.String),
|
|
61
|
+
object: Obj.Unknown,
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export const RunPromptInNewChat = Operation.make({
|
|
66
|
+
meta: {
|
|
67
|
+
key: makeKey('runPromptInNewChat'),
|
|
68
|
+
name: 'Run Prompt In New Chat',
|
|
69
|
+
icon: 'ph--chat-text--regular',
|
|
70
|
+
},
|
|
71
|
+
services: [Capability.Service],
|
|
72
|
+
input: Schema.Struct({
|
|
73
|
+
db: Database.Database,
|
|
74
|
+
/** Context objects to bind to the new chat. */
|
|
75
|
+
objects: Schema.optional(Schema.Array(Obj.Unknown)),
|
|
76
|
+
/** Skill keys to look up and bind to the new chat. */
|
|
77
|
+
skills: Schema.optional(Schema.Array(Schema.String)),
|
|
78
|
+
/** Raw instructions or an existing Routine object reference. */
|
|
79
|
+
instructions: Schema.Union(Schema.String, Ref.Ref(Instructions.Instructions)),
|
|
80
|
+
/**
|
|
81
|
+
* When true, skips opening the chat: runs the Agent prompt operation against the new chat via the compute runtime (traced).
|
|
82
|
+
*/
|
|
83
|
+
background: Schema.optional(Schema.Boolean),
|
|
84
|
+
}),
|
|
85
|
+
output: Schema.Struct({
|
|
86
|
+
object: Type.getSchema(Chat.Chat),
|
|
87
|
+
}),
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Runs a routine's `runnable` directly (bypassing its triggers). The runnable receives no input;
|
|
91
|
+
// the trigger-driven path is what supplies event-mapped input, so manual runs target runnables that
|
|
92
|
+
// need none.
|
|
93
|
+
export const RunRoutine = Operation.make({
|
|
94
|
+
meta: {
|
|
95
|
+
key: makeKey('runAutomation'),
|
|
96
|
+
name: 'Run Routine',
|
|
97
|
+
icon: 'ph--play--regular',
|
|
98
|
+
},
|
|
99
|
+
services: [Capability.Service],
|
|
100
|
+
input: Schema.Struct({
|
|
101
|
+
routine: Ref.Ref(Routine.Routine),
|
|
102
|
+
}),
|
|
103
|
+
output: Schema.Void,
|
|
104
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
|
|
7
|
+
import { Database } from '@dxos/echo';
|
|
8
|
+
|
|
9
|
+
import { meta } from '#meta';
|
|
10
|
+
|
|
11
|
+
export const TriggerTemplate = Schema.Union(
|
|
12
|
+
Schema.Struct({ type: Schema.Literal('timer'), cron: Schema.String }),
|
|
13
|
+
Schema.Struct({ type: Schema.Literal('feed'), feed: Schema.Any }),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export namespace AutomationAction {
|
|
17
|
+
export class CreateTriggerFromTemplate extends Schema.TaggedClass<CreateTriggerFromTemplate>()(
|
|
18
|
+
`${meta.profile.key}.action.create-trigger-from-template`,
|
|
19
|
+
{
|
|
20
|
+
input: Schema.Struct({
|
|
21
|
+
db: Database.Database,
|
|
22
|
+
template: TriggerTemplate,
|
|
23
|
+
enabled: Schema.optional(Schema.Boolean),
|
|
24
|
+
// TODO(wittjosiah): Improve how this lookup is done.
|
|
25
|
+
scriptName: Schema.optional(Schema.String),
|
|
26
|
+
input: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
27
|
+
}),
|
|
28
|
+
output: Schema.Void,
|
|
29
|
+
},
|
|
30
|
+
) {}
|
|
31
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
|
+
import { describe, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { Instructions, Trigger } from '@dxos/compute';
|
|
9
|
+
import { type Database, DXN, Feed, Obj, Ref, Type } from '@dxos/echo';
|
|
10
|
+
import { EffectEx } from '@dxos/effect';
|
|
11
|
+
import { EID, URI } from '@dxos/keys';
|
|
12
|
+
import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
|
|
13
|
+
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
14
|
+
import { createComposerTestApp } from '@dxos/plugin-testing/harness';
|
|
15
|
+
|
|
16
|
+
import { Routine } from '#types';
|
|
17
|
+
|
|
18
|
+
import { connectedRoutinesQuery, routinesForObject } from './routines-for-object';
|
|
19
|
+
|
|
20
|
+
// A minimal feed-annotated host (like a mailbox): an object holding a `feed` ref.
|
|
21
|
+
const FeedHost = Type.makeObject(DXN.make('org.dxos.test.feedHost', '0.1.0'))(
|
|
22
|
+
Schema.Struct({
|
|
23
|
+
name: Schema.optional(Schema.String),
|
|
24
|
+
feed: Ref.Ref(Feed.Feed),
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const types = [Routine.Routine, Trigger.Trigger, Instructions.Instructions, Feed.Feed, FeedHost];
|
|
29
|
+
|
|
30
|
+
const initSpace = async (harness: Awaited<ReturnType<typeof createComposerTestApp>>) => {
|
|
31
|
+
const { personalSpace } = await EffectEx.runAndForwardErrors(
|
|
32
|
+
initializeIdentity(harness.get(ClientCapabilities.Client)),
|
|
33
|
+
);
|
|
34
|
+
await harness.waitForEvent(ClientEvents.SpacesReady);
|
|
35
|
+
return personalSpace.db;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const connectedIds = (db: Database.Database, object: Obj.Unknown) =>
|
|
39
|
+
db
|
|
40
|
+
.query(connectedRoutinesQuery(object))
|
|
41
|
+
.run()
|
|
42
|
+
.then((routines) => routines.map((routine) => routine.id).sort());
|
|
43
|
+
|
|
44
|
+
// Build a space-qualified ref like the RefField object picker does (from the entity's fully-qualified URI),
|
|
45
|
+
// rather than the bare ref `Ref.make` produces — this is the encoding real triggers carry, and it exercises
|
|
46
|
+
// the reverse-ref EID normalization that lets qualified refs match a space-less anchor.
|
|
47
|
+
const qualifiedRef = (db: Database.Database, object: Obj.Unknown) =>
|
|
48
|
+
Ref.fromURI(URI.make(EID.make({ spaceId: db.spaceId, entityId: object.id })));
|
|
49
|
+
|
|
50
|
+
describe('routines connected to an object', () => {
|
|
51
|
+
test('input-ref: trigger whose nested input references the object', async ({ expect }) => {
|
|
52
|
+
await using harness = await createComposerTestApp({ plugins: [ClientPlugin({ types })] });
|
|
53
|
+
const db = await initSpace(harness);
|
|
54
|
+
|
|
55
|
+
const target = db.add(Routine.make({ name: 'target', triggers: [] }));
|
|
56
|
+
const other = db.add(Routine.make({ name: 'other', triggers: [] }));
|
|
57
|
+
// The target ref is nested in the trigger's untyped `input` record, and is space-qualified like a
|
|
58
|
+
// picker-created ref.
|
|
59
|
+
const trigger = db.add(Trigger.make({ input: { subject: qualifiedRef(db, target) } }));
|
|
60
|
+
const owner = db.add(Routine.make({ name: 'owner', triggers: [Ref.make(trigger)] }));
|
|
61
|
+
await db.flush();
|
|
62
|
+
|
|
63
|
+
expect(routinesForObject(target, [owner, other]).map((routine) => routine.id)).toEqual([owner.id]);
|
|
64
|
+
expect(routinesForObject(other, [owner])).toEqual([]);
|
|
65
|
+
|
|
66
|
+
// Poll to absorb index latency; the query resolves via the reverse-ref index.
|
|
67
|
+
await expect.poll(() => connectedIds(db, target), { timeout: 5_000 }).toEqual([owner.id]);
|
|
68
|
+
await expect.poll(() => connectedIds(db, other), { timeout: 5_000 }).toEqual([]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("feed-ref: feed trigger bound to the object's feed", async ({ expect }) => {
|
|
72
|
+
await using harness = await createComposerTestApp({ plugins: [ClientPlugin({ types })] });
|
|
73
|
+
const db = await initSpace(harness);
|
|
74
|
+
|
|
75
|
+
const feed = db.add(Feed.make());
|
|
76
|
+
const host = db.add(Obj.make(FeedHost, { name: 'mailbox', feed: Ref.make(feed) }));
|
|
77
|
+
const other = db.add(Routine.make({ name: 'other', triggers: [] }));
|
|
78
|
+
// Picker-created feed refs are space-qualified (unlike `Trigger.specFeed`'s bare `Ref.make`); the host's
|
|
79
|
+
// own feed ref is bare (code-created). They must still match through the reverse-ref index.
|
|
80
|
+
const feedTrigger = db.add(Trigger.make({ spec: { kind: 'feed', feed: qualifiedRef(db, feed) } }));
|
|
81
|
+
const owner = db.add(Routine.make({ name: 'feed-owner', triggers: [Ref.make(feedTrigger)] }));
|
|
82
|
+
await db.flush();
|
|
83
|
+
|
|
84
|
+
expect(routinesForObject(host, [owner, other]).map((routine) => routine.id)).toEqual([owner.id]);
|
|
85
|
+
|
|
86
|
+
await expect.poll(() => connectedIds(db, host), { timeout: 5_000 }).toEqual([owner.id]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('instructions-ref: routine whose runnable instructions list the object in their `objects`', async ({
|
|
90
|
+
expect,
|
|
91
|
+
}) => {
|
|
92
|
+
await using harness = await createComposerTestApp({ plugins: [ClientPlugin({ types })] });
|
|
93
|
+
const db = await initSpace(harness);
|
|
94
|
+
|
|
95
|
+
const target = db.add(Routine.make({ name: 'target', triggers: [] }));
|
|
96
|
+
const other = db.add(Routine.make({ name: 'other', triggers: [] }));
|
|
97
|
+
// The routine's action is owned instructions that bind the object as a context object — the second
|
|
98
|
+
// connection path (O ← Instructions.objects ← Routine via spec.instructions), with no trigger involved.
|
|
99
|
+
const instructions = db.add(Instructions.make({ objects: [qualifiedRef(db, target)] }));
|
|
100
|
+
const owner = db.add(Routine.make({ name: 'owner', instructions }));
|
|
101
|
+
await db.flush();
|
|
102
|
+
|
|
103
|
+
expect(routinesForObject(target, [owner, other]).map((routine) => routine.id)).toEqual([owner.id]);
|
|
104
|
+
expect(routinesForObject(other, [owner])).toEqual([]);
|
|
105
|
+
|
|
106
|
+
await expect.poll(() => connectedIds(db, target), { timeout: 5_000 }).toEqual([owner.id]);
|
|
107
|
+
await expect.poll(() => connectedIds(db, other), { timeout: 5_000 }).toEqual([]);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Instructions, Trigger } from '@dxos/compute';
|
|
6
|
+
import { Filter, Obj, Query, Ref } from '@dxos/echo';
|
|
7
|
+
|
|
8
|
+
import { Routine } from '#types';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Reactive query for all routines connected to an object O, via two structural paths:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Trigger path** (two hops): O is referenced by a Trigger (via `input` or `spec.feed`), and that
|
|
14
|
+
* Trigger is referenced by a Routine's `triggers` array.
|
|
15
|
+
* 2. **Instructions path** (two hops): O is listed in an Instructions' `objects` context array, and those
|
|
16
|
+
* Instructions are the Routine's action (`spec.instructions`). Both hops traverse `Ref` fields, so they are
|
|
17
|
+
* fully queryable — no JavaScript parent-symbol traversal needed.
|
|
18
|
+
*
|
|
19
|
+
* ECHO's reverse-ref index is structural — it tracks every `Ref` regardless of schema path, including
|
|
20
|
+
* nested untyped records and union fields — so all variants are covered.
|
|
21
|
+
*/
|
|
22
|
+
export const connectedRoutinesQuery = (object: Obj.Unknown): Query.Query<Routine.Routine> => {
|
|
23
|
+
// Trigger path: O ← Trigger (any ref path, incl. nested `input`) ← Routine.triggers.
|
|
24
|
+
const byInput = Query.select(Filter.id(object.id)).referencedBy(Trigger.Trigger);
|
|
25
|
+
// Feed variant: O's feed ← Trigger.spec.feed ← Routine.triggers.
|
|
26
|
+
// `.reference('feed')` is empty for objects without a feed prop, so this adds nothing for non-feed objects.
|
|
27
|
+
const byFeed = Query.select(Filter.id(object.id)).reference('feed').referencedBy(Trigger.Trigger);
|
|
28
|
+
const byTrigger = Query.all(byInput, byFeed).referencedBy(Routine.Routine, 'triggers');
|
|
29
|
+
|
|
30
|
+
// Instructions path: O ← Instructions.objects ← Routine (via `spec.instructions`). The second hop drops the
|
|
31
|
+
// property key: the instructions ref is nested in the `spec` union, and the reverse-ref index is structural,
|
|
32
|
+
// so a keyless `referencedBy` matches it (a routine only references its own owned instructions here).
|
|
33
|
+
const byInstructions = Query.select(Filter.id(object.id))
|
|
34
|
+
.referencedBy(Instructions.Instructions, 'objects')
|
|
35
|
+
.referencedBy(Routine.Routine);
|
|
36
|
+
|
|
37
|
+
return Query.all(byTrigger, byInstructions);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Pure predicate equivalent of {@link connectedRoutinesQuery}, over a pre-queried list of routines.
|
|
42
|
+
* Kept for unit tests (asserting the query and predicate agree) and the deferred quick-association check.
|
|
43
|
+
*/
|
|
44
|
+
export const routinesForObject = (object: Obj.Unknown, routines: Routine.Routine[]): Routine.Routine[] =>
|
|
45
|
+
routines.filter((routine) => routineReferencesObject(routine, object));
|
|
46
|
+
|
|
47
|
+
export const routineReferencesObject = (routine: Routine.Routine, object: Obj.Unknown): boolean =>
|
|
48
|
+
referencesViaTrigger(routine, object) || referencesViaInstructions(routine, object);
|
|
49
|
+
|
|
50
|
+
/** Trigger path: a trigger's `input` references O, or a feed trigger is bound to O's feed. */
|
|
51
|
+
const referencesViaTrigger = (routine: Routine.Routine, object: Obj.Unknown): boolean => {
|
|
52
|
+
const objectFeedId = getFeedId(object);
|
|
53
|
+
return routine.triggers.some((ref) => {
|
|
54
|
+
const trigger = ref.target;
|
|
55
|
+
if (!Obj.instanceOf(Trigger.Trigger, trigger)) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (trigger.spec?.kind === 'feed' && objectFeedId && trigger.spec.feed?.target?.id === objectFeedId) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return trigger.input != null && referencesId(trigger.input, object.id);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** Instructions path: the routine's owned instructions list O in their `objects` context array. */
|
|
68
|
+
const referencesViaInstructions = (routine: Routine.Routine, object: Obj.Unknown): boolean =>
|
|
69
|
+
Routine.instructionsRef(routine)?.target?.objects?.some((ref) => ref.target?.id === object.id) ?? false;
|
|
70
|
+
|
|
71
|
+
/** The feed id a feed-annotated object points at (e.g. `mailbox.feed`), if any. */
|
|
72
|
+
const getFeedId = (object: Obj.Unknown): string | undefined => {
|
|
73
|
+
const feedRef = (object as { feed?: Ref.Ref<unknown> }).feed;
|
|
74
|
+
return Ref.isRef(feedRef) ? feedRef.target?.id : undefined;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** Recursively scan a value for a Ref whose target is the given object id. */
|
|
78
|
+
const referencesId = (value: unknown, id: string): boolean => {
|
|
79
|
+
if (Ref.isRef(value)) {
|
|
80
|
+
return value.target?.id === id;
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
return value.some((entry) => referencesId(entry, id));
|
|
84
|
+
}
|
|
85
|
+
if (value && typeof value === 'object') {
|
|
86
|
+
return Object.values(value).some((entry) => referencesId(entry, id));
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { RunInstructions } from '@dxos/assistant-toolkit';
|
|
8
|
+
import { Ref, URI } from '@dxos/echo';
|
|
9
|
+
|
|
10
|
+
import { isRunInstructions, runInstructionsRef } from './run-instructions';
|
|
11
|
+
|
|
12
|
+
describe('RunInstructions registry reference', () => {
|
|
13
|
+
test('runInstructionsRef targets the RunInstructions registry DXN', ({ expect }) => {
|
|
14
|
+
const ref = runInstructionsRef();
|
|
15
|
+
expect(ref.uri).toBe(RunInstructions.meta.key);
|
|
16
|
+
expect(isRunInstructions(ref)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('isRunInstructions rejects other refs and non-refs', ({ expect }) => {
|
|
20
|
+
expect(isRunInstructions(undefined)).toBe(false);
|
|
21
|
+
expect(isRunInstructions(Ref.fromURI(URI.make('dxn:org.dxos.test.otherOperation')))).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { RunInstructions } from '@dxos/assistant-toolkit';
|
|
6
|
+
import { Ref } from '@dxos/echo';
|
|
7
|
+
|
|
8
|
+
/** A ref to the shared RunInstructions operation in the registry (resolved via the registry, not the database). */
|
|
9
|
+
export const runInstructionsRef = () => Ref.fromURI(RunInstructions.meta.key);
|
|
10
|
+
|
|
11
|
+
/** Whether a trigger's `function` ref targets the registry RunInstructions operation (i.e. an instructions action). */
|
|
12
|
+
export const isRunInstructions = (fn: unknown): boolean => Ref.isRef(fn) && fn.uri === RunInstructions.meta.key;
|