@dxos/plugin-routine 0.10.0 → 0.11.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/PLUGIN.mdl +18 -13
- package/dist/lib/RoutinePlugin.mjs +2 -0
- package/dist/lib/RoutinePlugin.node.mjs +894 -0
- package/dist/lib/RoutinePlugin.node.mjs.map +1 -0
- package/dist/lib/RoutinePlugin.workerd.mjs +20 -0
- package/dist/lib/RoutinePlugin.workerd.mjs.map +1 -0
- package/dist/lib/capabilities/node.mjs +12 -0
- package/dist/lib/capabilities/node.mjs.map +1 -0
- package/dist/lib/capabilities.mjs +14 -0
- package/dist/lib/capabilities.mjs.map +1 -0
- package/dist/lib/chunk-RoutineArticle.mjs +79 -0
- package/dist/lib/chunk-RoutineArticle.mjs.map +1 -0
- package/dist/lib/chunk-RoutineCompanion.mjs +192 -0
- package/dist/lib/chunk-RoutineCompanion.mjs.map +1 -0
- package/dist/lib/chunk-RoutinePlugin.mjs +38 -0
- package/dist/lib/chunk-RoutinePlugin.mjs.map +1 -0
- package/dist/lib/chunk-RoutineSettings.mjs +50 -0
- package/dist/lib/chunk-RoutineSettings.mjs.map +1 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs +208 -0
- package/dist/lib/chunk-RoutineTraceCompanion.mjs.map +1 -0
- package/dist/lib/chunk-SkillArticle.mjs +28 -0
- package/dist/lib/chunk-SkillArticle.mjs.map +1 -0
- package/dist/lib/chunk-app-graph-builder.mjs +71 -0
- package/dist/lib/chunk-app-graph-builder.mjs.map +1 -0
- package/dist/lib/chunk-create-object.mjs +23 -0
- package/dist/lib/chunk-create-object.mjs.map +1 -0
- package/dist/lib/chunk-create-routine.mjs +34 -0
- package/dist/lib/chunk-create-routine.mjs.map +1 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs +48 -0
- package/dist/lib/chunk-create-trigger-from-template.mjs.map +1 -0
- package/dist/lib/chunk-layer-specs.mjs +179 -0
- package/dist/lib/chunk-layer-specs.mjs.map +1 -0
- package/dist/lib/{neutral/chunk-HLO4LYXT.mjs → chunk-meta.mjs} +19 -27
- package/dist/lib/chunk-meta.mjs.map +1 -0
- package/dist/lib/chunk-operation-handler.mjs +11 -0
- package/dist/lib/chunk-operation-handler.mjs.map +1 -0
- package/dist/lib/chunk-paths.mjs +11 -0
- package/dist/lib/chunk-paths.mjs.map +1 -0
- package/dist/lib/chunk-react-surface.mjs +64 -0
- package/dist/lib/chunk-react-surface.mjs.map +1 -0
- package/dist/lib/chunk-registry-sync.mjs +104 -0
- package/dist/lib/chunk-registry-sync.mjs.map +1 -0
- package/dist/lib/chunk-run-routine.mjs +57 -0
- package/dist/lib/chunk-run-routine.mjs.map +1 -0
- package/dist/lib/chunk-templates.mjs +37 -0
- package/dist/lib/chunk-templates.mjs.map +1 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs +73 -0
- package/dist/lib/chunk-trigger-runtime-controller.mjs.map +1 -0
- package/dist/lib/chunk-types.mjs +149 -0
- package/dist/lib/chunk-types.mjs.map +1 -0
- package/dist/lib/chunk-util.mjs +142 -0
- package/dist/lib/chunk-util.mjs.map +1 -0
- package/dist/lib/components.mjs +1645 -0
- package/dist/lib/components.mjs.map +1 -0
- package/dist/lib/containers.mjs +11 -0
- package/dist/lib/containers.mjs.map +1 -0
- package/dist/lib/hooks.mjs +37 -0
- package/dist/lib/hooks.mjs.map +1 -0
- package/dist/lib/index.mjs +5 -0
- package/dist/lib/meta.mjs +2 -0
- package/dist/lib/operations.mjs +7 -0
- package/dist/lib/operations.mjs.map +1 -0
- package/dist/lib/plugin.mjs +9 -0
- package/dist/lib/plugin.mjs.map +1 -0
- package/dist/lib/testing.mjs +2 -0
- package/dist/lib/translations.mjs +110 -0
- package/dist/lib/translations.mjs.map +1 -0
- package/dist/lib/types.mjs +2 -0
- package/dist/types/src/RoutinePlugin.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.node.d.ts.map +1 -1
- package/dist/types/src/RoutinePlugin.workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -1
- package/dist/types/src/capabilities/index.d.ts +0 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/layer-specs.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/registry-sync.d.ts +1 -1
- package/dist/types/src/capabilities/templates.d.ts +1 -1
- package/dist/types/src/capabilities/trigger-runtime-controller.d.ts +1 -1
- package/dist/types/src/commands/trigger/create/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/create/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/update/{queue.d.ts → feed.d.ts} +2 -2
- package/dist/types/src/commands/trigger/update/feed.d.ts.map +1 -0
- package/dist/types/src/commands/trigger/util.d.ts +1 -1
- package/dist/types/src/commands/trigger/util.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts +7 -5
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.d.ts.map +1 -1
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts +3 -3
- package/dist/types/src/components/InstructionsEditor/InstructionsEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts +9 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts +21 -0
- package/dist/types/src/components/RoutineCard/RoutineCard.stories.d.ts.map +1 -0
- package/dist/types/src/components/RoutineCard/index.d.ts +2 -0
- package/dist/types/src/components/RoutineCard/index.d.ts.map +1 -0
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts +7 -2
- package/dist/types/src/components/RoutineForm/RoutineForm.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/Schedule.d.ts +2 -26
- package/dist/types/src/components/Schedule/Schedule.d.ts.map +1 -1
- package/dist/types/src/components/Schedule/days.d.ts +24 -0
- package/dist/types/src/components/Schedule/days.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts +3 -0
- package/dist/types/src/components/Schedule/describe-schedule.d.ts.map +1 -0
- package/dist/types/src/components/Schedule/index.d.ts +2 -0
- package/dist/types/src/components/Schedule/index.d.ts.map +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts +1 -1
- package/dist/types/src/components/TemplateEditor/TemplateEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -2
- package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts +5 -2
- package/dist/types/src/components/TriggerEditor/TriggerKindSelector.d.ts.map +1 -1
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts +5 -0
- package/dist/types/src/components/TriggerEditor/trigger-kind-icon.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts +5 -10
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts +6 -2
- package/dist/types/src/containers/RoutineArticle/RoutineArticle.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts +4 -12
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineCompanion/RoutineCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts +4 -8
- package/dist/types/src/containers/RoutineSettings/RoutineSettings.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts +5 -3
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.d.ts.map +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts +1 -1
- package/dist/types/src/containers/RoutineTraceCompanion/useRoutineRuns.d.ts.map +1 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts +4 -1
- package/dist/types/src/containers/SkillArticle/SkillArticle.d.ts.map +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts +1 -1
- package/dist/types/src/hooks/useTriggerRuntimeControls.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.d.ts.map +1 -1
- package/dist/types/src/operations/run-routine.test.d.ts +2 -0
- package/dist/types/src/operations/run-routine.test.d.ts.map +1 -0
- package/dist/types/src/paths.d.ts.map +1 -1
- package/dist/types/src/templates/index.d.ts +1 -1
- package/dist/types/src/templates/index.d.ts.map +1 -1
- package/dist/types/src/testing/test-functions.d.ts +30 -6
- package/dist/types/src/testing/test-functions.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/RoutineCapabilities.d.ts +9 -3
- package/dist/types/src/types/RoutineCapabilities.d.ts.map +1 -1
- package/dist/types/src/types/RoutineOperation.d.ts +2 -3
- package/dist/types/src/types/RoutineOperation.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +0 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/routines-for-object.d.ts +6 -3
- package/dist/types/src/util/routines-for-object.d.ts.map +1 -1
- package/dist/types/src/util/wire.d.ts +21 -0
- package/dist/types/src/util/wire.d.ts.map +1 -0
- package/dist/types/src/util/wire.test.d.ts +2 -0
- package/dist/types/src/util/wire.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +3 -2
- package/package.json +73 -71
- package/src/RoutinePlugin.node.ts +1 -2
- package/src/RoutinePlugin.tsx +2 -4
- package/src/RoutinePlugin.workerd.ts +1 -2
- package/src/capabilities/app-graph-builder.ts +9 -7
- package/src/capabilities/create-object.ts +2 -2
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/layer-specs.ts +78 -12
- package/src/capabilities/{react-surface.tsx → react-surface.ts} +18 -22
- package/src/capabilities/trigger-runtime-controller.test.ts +12 -18
- package/src/capabilities/trigger-runtime-controller.ts +22 -25
- package/src/commands/trigger/create/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/create/index.ts +2 -2
- package/src/commands/trigger/update/{queue.ts → feed.ts} +1 -1
- package/src/commands/trigger/update/index.ts +2 -2
- package/src/commands/trigger/util.ts +1 -2
- package/src/components/InstructionsEditor/InstructionsEditor.stories.tsx +7 -6
- package/src/components/InstructionsEditor/InstructionsEditor.tsx +31 -19
- package/src/components/RoutineCard/RoutineCard.stories.tsx +95 -0
- package/src/components/RoutineCard/RoutineCard.tsx +60 -0
- package/src/components/{MasterDetail → RoutineCard}/index.ts +1 -1
- package/src/components/RoutineForm/RoutineForm.tsx +60 -52
- package/src/components/Schedule/Schedule.stories.tsx +1 -1
- package/src/components/Schedule/Schedule.tsx +4 -73
- package/src/components/Schedule/days.ts +18 -0
- package/src/components/Schedule/describe-schedule.ts +64 -0
- package/src/components/Schedule/index.ts +2 -0
- package/src/components/TemplateEditor/TemplateEditor.stories.tsx +1 -1
- package/src/components/TemplateEditor/TemplateForm.tsx +1 -1
- package/src/components/TriggerEditor/TriggerEditor.stories.tsx +3 -3
- package/src/components/TriggerEditor/TriggerEditor.tsx +79 -66
- package/src/components/TriggerEditor/TriggerKindSelector.tsx +4 -30
- package/src/components/TriggerEditor/trigger-kind-icon.ts +38 -0
- package/src/components/index.ts +1 -1
- package/src/containers/RoutineArticle/RoutineArticle.stories.tsx +78 -19
- package/src/containers/RoutineArticle/RoutineArticle.tsx +8 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.stories.tsx +5 -4
- package/src/containers/RoutineCompanion/RoutineCompanion.tsx +11 -7
- package/src/containers/RoutineSettings/RoutineSettings.tsx +22 -33
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.stories.tsx +6 -5
- package/src/containers/RoutineTraceCompanion/RoutineTraceCompanion.tsx +3 -1
- package/src/containers/RoutineTraceCompanion/useRoutineRuns.ts +3 -5
- package/src/containers/SkillArticle/SkillArticle.tsx +2 -0
- package/src/hooks/useTriggerRuntimeControls.ts +2 -2
- package/src/index.ts +1 -0
- package/src/operations/create-routine.ts +1 -1
- package/src/operations/create-trigger-from-template.ts +2 -2
- package/src/operations/run-routine.test.ts +150 -0
- package/src/operations/run-routine.ts +18 -2
- package/src/paths.ts +5 -5
- package/src/templates/index.ts +5 -3
- package/src/translations.ts +5 -6
- package/src/types/RoutineCapabilities.ts +10 -4
- package/src/types/RoutineOperation.ts +7 -6
- package/src/types/index.ts +0 -1
- package/src/util/index.ts +1 -0
- package/src/util/routines-for-object.test.ts +37 -5
- package/src/util/routines-for-object.ts +33 -8
- package/src/util/wire.test.ts +77 -0
- package/src/util/wire.ts +76 -0
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs +0 -95
- package/dist/lib/neutral/RoutineArticle-UNTMV4CC.mjs.map +0 -7
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs +0 -249
- package/dist/lib/neutral/RoutineCompanion-ZZ6WMY7I.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.mjs +0 -10
- package/dist/lib/neutral/RoutinePlugin.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.node.mjs +0 -1133
- package/dist/lib/neutral/RoutinePlugin.node.mjs.map +0 -7
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs +0 -36
- package/dist/lib/neutral/RoutinePlugin.workerd.mjs.map +0 -7
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs +0 -48
- package/dist/lib/neutral/RoutineSettings-ZJOM4F3S.mjs.map +0 -7
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs +0 -236
- package/dist/lib/neutral/RoutineTraceCompanion-5U6R7LJE.mjs.map +0 -7
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs +0 -27
- package/dist/lib/neutral/SkillArticle-WWDNKW2Z.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs +0 -90
- package/dist/lib/neutral/app-graph-builder-FALWLZTI.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/index.mjs +0 -25
- package/dist/lib/neutral/capabilities/index.mjs.map +0 -7
- package/dist/lib/neutral/capabilities/node.mjs +0 -19
- package/dist/lib/neutral/capabilities/node.mjs.map +0 -7
- package/dist/lib/neutral/chunk-674LDIUJ.mjs +0 -9
- package/dist/lib/neutral/chunk-674LDIUJ.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HLO4LYXT.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +0 -10
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs.map +0 -7
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs +0 -8
- package/dist/lib/neutral/chunk-P3TDQKOO.mjs.map +0 -7
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs +0 -263
- package/dist/lib/neutral/chunk-R7J2MU2M.mjs.map +0 -7
- package/dist/lib/neutral/chunk-WLNL77C7.mjs +0 -14
- package/dist/lib/neutral/chunk-WLNL77C7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs +0 -65
- package/dist/lib/neutral/chunk-YGWSAKLD.mjs.map +0 -7
- package/dist/lib/neutral/components/index.mjs +0 -1921
- package/dist/lib/neutral/components/index.mjs.map +0 -7
- package/dist/lib/neutral/containers/index.mjs +0 -17
- package/dist/lib/neutral/containers/index.mjs.map +0 -7
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs +0 -25
- package/dist/lib/neutral/create-object-V23KVDMJ.mjs.map +0 -7
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs +0 -38
- package/dist/lib/neutral/create-routine-6QBY6TWF.mjs.map +0 -7
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs +0 -70
- package/dist/lib/neutral/create-trigger-from-template-U3KNS77V.mjs.map +0 -7
- package/dist/lib/neutral/hooks/index.mjs +0 -47
- package/dist/lib/neutral/hooks/index.mjs.map +0 -7
- package/dist/lib/neutral/index.mjs +0 -27
- package/dist/lib/neutral/index.mjs.map +0 -7
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs +0 -135
- package/dist/lib/neutral/layer-specs-2TWJU5HI.mjs.map +0 -7
- package/dist/lib/neutral/meta.json +0 -1
- package/dist/lib/neutral/meta.mjs +0 -8
- package/dist/lib/neutral/meta.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs +0 -18
- package/dist/lib/neutral/navigation-resolver-KQIWUH6F.mjs.map +0 -7
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs +0 -13
- package/dist/lib/neutral/operation-handler-QKLJSDCQ.mjs.map +0 -7
- package/dist/lib/neutral/operations/index.mjs +0 -8
- package/dist/lib/neutral/operations/index.mjs.map +0 -7
- package/dist/lib/neutral/plugin.mjs +0 -16
- package/dist/lib/neutral/plugin.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs +0 -67
- package/dist/lib/neutral/react-surface-GMO7I7YE.mjs.map +0 -7
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs +0 -86
- package/dist/lib/neutral/registry-sync-DYPOC7ZG.mjs.map +0 -7
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs +0 -37
- package/dist/lib/neutral/run-routine-AEWO6SYD.mjs.map +0 -7
- package/dist/lib/neutral/templates-IIUCEBAX.mjs +0 -49
- package/dist/lib/neutral/templates-IIUCEBAX.mjs.map +0 -7
- package/dist/lib/neutral/testing.mjs +0 -8
- package/dist/lib/neutral/testing.mjs.map +0 -7
- package/dist/lib/neutral/translations.mjs +0 -115
- package/dist/lib/neutral/translations.mjs.map +0 -7
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs +0 -77
- package/dist/lib/neutral/trigger-runtime-controller-WIDDFGQT.mjs.map +0 -7
- package/dist/lib/neutral/types/index.mjs +0 -17
- package/dist/lib/neutral/types/index.mjs.map +0 -7
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -5
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/create/queue.d.ts.map +0 -1
- package/dist/types/src/commands/trigger/update/queue.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts +0 -51
- package/dist/types/src/components/MasterDetail/MasterDetail.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts +0 -16
- package/dist/types/src/components/MasterDetail/MasterDetail.stories.d.ts.map +0 -1
- package/dist/types/src/components/MasterDetail/index.d.ts +0 -2
- package/dist/types/src/components/MasterDetail/index.d.ts.map +0 -1
- package/dist/types/src/types/Routine.d.ts +0 -55
- package/dist/types/src/types/Routine.d.ts.map +0 -1
- package/dist/types/src/types/Routine.test.d.ts +0 -2
- package/dist/types/src/types/Routine.test.d.ts.map +0 -1
- package/src/capabilities/navigation-resolver.ts +0 -21
- package/src/components/MasterDetail/MasterDetail.stories.tsx +0 -100
- package/src/components/MasterDetail/MasterDetail.tsx +0 -175
- package/src/types/Routine.test.ts +0 -51
- package/src/types/Routine.ts +0 -144
|
@@ -6,9 +6,9 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
import { describe, test } from 'vitest';
|
|
7
7
|
|
|
8
8
|
import { ServiceResolver } from '@dxos/compute';
|
|
9
|
+
import { TriggerDispatcher } from '@dxos/compute-runtime';
|
|
9
10
|
import { Feed, Obj } from '@dxos/echo';
|
|
10
11
|
import { EffectEx } from '@dxos/effect';
|
|
11
|
-
import { TriggerDispatcher } from '@dxos/functions-runtime';
|
|
12
12
|
import type { SpaceId } from '@dxos/keys';
|
|
13
13
|
import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
|
|
14
14
|
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
@@ -30,7 +30,7 @@ const getDispatcher = (harness: Awaited<ReturnType<typeof createComposerTestApp>
|
|
|
30
30
|
);
|
|
31
31
|
|
|
32
32
|
describe('TriggerRuntimeController', () => {
|
|
33
|
-
test('toggles the per-space TriggerDispatcher as
|
|
33
|
+
test('toggles the per-space TriggerDispatcher as triggersDisabled changes', async ({ expect }) => {
|
|
34
34
|
await using harness = await createComposerTestApp({
|
|
35
35
|
plugins: [ClientPlugin({ types: [Feed.Feed] }), RoutinePlugin()],
|
|
36
36
|
});
|
|
@@ -51,36 +51,30 @@ describe('TriggerRuntimeController', () => {
|
|
|
51
51
|
immediate: true,
|
|
52
52
|
});
|
|
53
53
|
try {
|
|
54
|
-
//
|
|
54
|
+
// `triggersDisabled` is unset by default, so the controller should
|
|
55
55
|
// start the dispatcher shortly after the space becomes ready.
|
|
56
56
|
await expect.poll(() => harness.registry.get(dispatcher.state).enabled, { timeout: 5_000 }).toBe(true);
|
|
57
57
|
|
|
58
|
-
// `
|
|
58
|
+
// `triggersDisabled = true` → dispatcher should stop.
|
|
59
59
|
Obj.update(personalSpace.properties, (properties) => {
|
|
60
|
-
properties.
|
|
60
|
+
properties.triggersDisabled = true;
|
|
61
61
|
});
|
|
62
62
|
await expect.poll(() => harness.registry.get(dispatcher.state).enabled, { timeout: 5_000 }).toBe(false);
|
|
63
63
|
|
|
64
|
-
// Back to
|
|
64
|
+
// Back to enabled → dispatcher should start again.
|
|
65
65
|
Obj.update(personalSpace.properties, (properties) => {
|
|
66
|
-
properties.
|
|
66
|
+
properties.triggersDisabled = false;
|
|
67
67
|
});
|
|
68
68
|
await expect.poll(() => harness.registry.get(dispatcher.state).enabled, { timeout: 5_000 }).toBe(true);
|
|
69
69
|
|
|
70
|
-
// `edge` → dispatcher should stop (triggers run on the edge instead).
|
|
71
|
-
Obj.update(personalSpace.properties, (properties) => {
|
|
72
|
-
properties.computeEnvironment = 'edge';
|
|
73
|
-
});
|
|
74
|
-
await expect.poll(() => harness.registry.get(dispatcher.state).enabled, { timeout: 5_000 }).toBe(false);
|
|
75
|
-
|
|
76
70
|
// The atom subscription should have witnessed every transition.
|
|
77
|
-
expect(observedStates).toEqual(expect.arrayContaining([true, false, true
|
|
71
|
+
expect(observedStates).toEqual(expect.arrayContaining([true, false, true]));
|
|
78
72
|
} finally {
|
|
79
73
|
unsubscribe();
|
|
80
74
|
}
|
|
81
75
|
});
|
|
82
76
|
|
|
83
|
-
test('does not re-issue start when
|
|
77
|
+
test('does not re-issue start when triggersDisabled is reasserted to the same value', async ({ expect }) => {
|
|
84
78
|
await using harness = await createComposerTestApp({
|
|
85
79
|
plugins: [ClientPlugin({ types: [Feed.Feed] }), RoutinePlugin()],
|
|
86
80
|
});
|
|
@@ -94,11 +88,11 @@ describe('TriggerRuntimeController', () => {
|
|
|
94
88
|
|
|
95
89
|
await expect.poll(() => harness.registry.get(dispatcher.state).enabled, { timeout: 5_000 }).toBe(true);
|
|
96
90
|
|
|
97
|
-
// Writing the same
|
|
98
|
-
// dedupes via its `
|
|
91
|
+
// Writing the same enabled state should be a no-op: the controller
|
|
92
|
+
// dedupes via its `lastDisabled` tracker so the dispatcher stays
|
|
99
93
|
// running without an intervening stop/start flicker.
|
|
100
94
|
Obj.update(personalSpace.properties, (properties) => {
|
|
101
|
-
properties.
|
|
95
|
+
properties.triggersDisabled = false;
|
|
102
96
|
});
|
|
103
97
|
// Give any spurious transition a chance to land before we check.
|
|
104
98
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -6,10 +6,9 @@ import * as Effect from 'effect/Effect';
|
|
|
6
6
|
import * as Fiber from 'effect/Fiber';
|
|
7
7
|
|
|
8
8
|
import { Capabilities, Capability } from '@dxos/app-framework';
|
|
9
|
-
import { type ComputeEnvironment } from '@dxos/client-protocol';
|
|
10
9
|
import { ServiceResolver } from '@dxos/compute';
|
|
10
|
+
import { TriggerDispatcher } from '@dxos/compute-runtime';
|
|
11
11
|
import { Obj } from '@dxos/echo';
|
|
12
|
-
import { TriggerDispatcher } from '@dxos/functions-runtime';
|
|
13
12
|
import { type SpaceId } from '@dxos/keys';
|
|
14
13
|
import { log } from '@dxos/log';
|
|
15
14
|
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
@@ -18,30 +17,28 @@ import { type Space } from '@dxos/react-client/echo';
|
|
|
18
17
|
//
|
|
19
18
|
// Capability Module
|
|
20
19
|
//
|
|
21
|
-
// Watches `space.properties.
|
|
20
|
+
// Watches `space.properties.triggersDisabled` for every space and toggles
|
|
22
21
|
// the per-space {@link TriggerDispatcher} accordingly:
|
|
23
22
|
//
|
|
24
|
-
// - `
|
|
25
|
-
// -
|
|
23
|
+
// - disabled (`true`) → `dispatcher.stop()`
|
|
24
|
+
// - enabled (unset/`false`) → `dispatcher.start()`
|
|
26
25
|
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
26
|
+
// Per-trigger local/edge routing is handled by the trigger's `remote` flag
|
|
27
|
+
// (the dispatcher skips remote triggers); this space-wide flag is only the
|
|
28
|
+
// kill-switch for local execution. The dispatcher itself is contributed
|
|
29
|
+
// unconditionally via `TriggerDispatcherSpec` in `layer-specs.ts`, so this
|
|
30
|
+
// capability is only responsible for driving its lifecycle.
|
|
31
31
|
//
|
|
32
32
|
|
|
33
|
-
/** Trigger execution location the dispatcher should run locally. */
|
|
34
|
-
const LOCAL_ENVIRONMENT: ComputeEnvironment = 'local';
|
|
35
|
-
|
|
36
33
|
export default Capability.makeModule(
|
|
37
34
|
Effect.fnUntraced(function* () {
|
|
38
35
|
const client = yield* Capability.get(ClientCapabilities.Client);
|
|
39
36
|
const runtime = yield* Capability.get(Capabilities.ProcessManagerRuntime);
|
|
40
37
|
|
|
41
|
-
/** Per-space property-subscription unsubscribe, last-seen
|
|
38
|
+
/** Per-space property-subscription unsubscribe, last-seen disabled state, and in-flight transition fiber. */
|
|
42
39
|
type Tracker = {
|
|
43
40
|
unsubscribe: () => void;
|
|
44
|
-
|
|
41
|
+
lastDisabled?: boolean;
|
|
45
42
|
inFlight?: Fiber.RuntimeFiber<unknown, unknown>;
|
|
46
43
|
};
|
|
47
44
|
const trackers = new Map<SpaceId, Tracker>();
|
|
@@ -49,31 +46,31 @@ export default Capability.makeModule(
|
|
|
49
46
|
/**
|
|
50
47
|
* Resolve the per-space `TriggerDispatcher` from the process-manager
|
|
51
48
|
* runtime and invoke `start()` / `stop()` according to the requested
|
|
52
|
-
*
|
|
49
|
+
* disabled state. Returns a fiber so the caller can cancel a pending
|
|
53
50
|
* transition when a new one supersedes it.
|
|
54
51
|
*/
|
|
55
|
-
const transition = (spaceId: SpaceId,
|
|
52
|
+
const transition = (spaceId: SpaceId, disabled: boolean) =>
|
|
56
53
|
runtime.runFork(
|
|
57
54
|
Effect.gen(function* () {
|
|
58
55
|
const dispatcher = yield* TriggerDispatcher;
|
|
59
|
-
yield*
|
|
56
|
+
yield* disabled ? dispatcher.stop() : dispatcher.start();
|
|
60
57
|
}).pipe(
|
|
61
58
|
Effect.provide(ServiceResolver.provide({ space: spaceId }, TriggerDispatcher)),
|
|
62
59
|
Effect.tapErrorCause((cause) =>
|
|
63
|
-
Effect.sync(() => log.warn('trigger dispatcher transition failed', { spaceId,
|
|
60
|
+
Effect.sync(() => log.warn('trigger dispatcher transition failed', { spaceId, disabled, cause })),
|
|
64
61
|
),
|
|
65
62
|
),
|
|
66
63
|
);
|
|
67
64
|
|
|
68
|
-
const apply = (tracker: Tracker, spaceId: SpaceId,
|
|
69
|
-
if (tracker.
|
|
65
|
+
const apply = (tracker: Tracker, spaceId: SpaceId, disabled: boolean): void => {
|
|
66
|
+
if (tracker.lastDisabled === disabled) {
|
|
70
67
|
return;
|
|
71
68
|
}
|
|
72
|
-
tracker.
|
|
69
|
+
tracker.lastDisabled = disabled;
|
|
73
70
|
if (tracker.inFlight) {
|
|
74
71
|
runtime.runFork(Fiber.interrupt(tracker.inFlight));
|
|
75
72
|
}
|
|
76
|
-
tracker.inFlight = transition(spaceId,
|
|
73
|
+
tracker.inFlight = transition(spaceId, disabled);
|
|
77
74
|
};
|
|
78
75
|
|
|
79
76
|
const install = (space: Space): void => {
|
|
@@ -94,9 +91,9 @@ export default Capability.makeModule(
|
|
|
94
91
|
if (trackers.get(space.id) !== tracker) {
|
|
95
92
|
return;
|
|
96
93
|
}
|
|
97
|
-
const
|
|
98
|
-
tracker.unsubscribe = Obj.subscribe(space.properties, () => apply(tracker, space.id,
|
|
99
|
-
apply(tracker, space.id,
|
|
94
|
+
const readDisabled = (): boolean => space.properties.triggersDisabled ?? false;
|
|
95
|
+
tracker.unsubscribe = Obj.subscribe(space.properties, () => apply(tracker, space.id, readDisabled()));
|
|
96
|
+
apply(tracker, space.id, readDisabled());
|
|
100
97
|
})
|
|
101
98
|
.catch((err) => log.catch(err));
|
|
102
99
|
};
|
|
@@ -20,7 +20,7 @@ import { EID } from '@dxos/keys';
|
|
|
20
20
|
import { Enabled, Feed, Input } from '../options';
|
|
21
21
|
import { printTrigger, promptForSchemaInput, selectFeed, selectFunction } from '../util';
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const feed = Command.make(
|
|
24
24
|
'feed',
|
|
25
25
|
{
|
|
26
26
|
spaceId: Common.spaceId.pipe(Options.optional),
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Command from '@effect/cli/Command';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { feed } from './feed';
|
|
8
8
|
import { subscription } from './subscription';
|
|
9
9
|
import { timer } from './timer';
|
|
10
10
|
|
|
11
11
|
export const create = Command.make('create').pipe(
|
|
12
12
|
Command.withDescription('Create a trigger.'),
|
|
13
|
-
Command.withSubcommands([subscription, timer,
|
|
13
|
+
Command.withSubcommands([subscription, timer, feed]),
|
|
14
14
|
);
|
|
@@ -19,7 +19,7 @@ import { EID, type EntityId } from '@dxos/keys';
|
|
|
19
19
|
import { Enabled, Feed, Input, TriggerId } from '../options';
|
|
20
20
|
import { printTrigger, promptForSchemaInput, selectFeed, selectFunction, selectTrigger } from '../util';
|
|
21
21
|
|
|
22
|
-
export const
|
|
22
|
+
export const feed = Command.make(
|
|
23
23
|
'feed',
|
|
24
24
|
{
|
|
25
25
|
spaceId: Common.spaceId.pipe(Options.optional),
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
import * as Command from '@effect/cli/Command';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { feed } from './feed';
|
|
8
8
|
import { subscription } from './subscription';
|
|
9
9
|
import { timer } from './timer';
|
|
10
10
|
|
|
11
11
|
export const update = Command.make('update').pipe(
|
|
12
12
|
Command.withDescription('Update a trigger.'),
|
|
13
|
-
Command.withSubcommands([subscription, timer,
|
|
13
|
+
Command.withSubcommands([subscription, timer, feed]),
|
|
14
14
|
);
|
|
@@ -13,8 +13,7 @@ import * as SchemaAST from 'effect/SchemaAST';
|
|
|
13
13
|
|
|
14
14
|
import { FormBuilder } from '@dxos/cli-util';
|
|
15
15
|
import { Operation, Trigger } from '@dxos/compute';
|
|
16
|
-
|
|
17
|
-
import { Annotation, Database, Entity, Feed, Filter, Obj, Query, type QueryAST, Ref, Scope, Type } from '@dxos/echo';
|
|
16
|
+
import { Annotation, Database, Entity, Feed, Filter, Obj, Query, Ref, Scope, Type } from '@dxos/echo';
|
|
18
17
|
import { SchemaEx } from '@dxos/effect';
|
|
19
18
|
import { DXN } from '@dxos/keys';
|
|
20
19
|
import { FeedAnnotation } from '@dxos/schema';
|
|
@@ -7,7 +7,8 @@ import React from 'react';
|
|
|
7
7
|
|
|
8
8
|
import { Instructions, Skill } from '@dxos/compute';
|
|
9
9
|
import { Filter, Ref } from '@dxos/echo';
|
|
10
|
-
import {
|
|
10
|
+
import { useQuery } from '@dxos/echo-react';
|
|
11
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
11
12
|
import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
|
|
12
13
|
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
13
14
|
import { Text } from '@dxos/schema';
|
|
@@ -49,7 +50,7 @@ export default meta;
|
|
|
49
50
|
|
|
50
51
|
type Story = StoryObj<typeof meta>;
|
|
51
52
|
|
|
52
|
-
/** A routine with no skills
|
|
53
|
+
/** A routine with no skills: the form shows an empty add affordance. */
|
|
53
54
|
export const Default: Story = {
|
|
54
55
|
decorators: [
|
|
55
56
|
withSeededSpace((space) => {
|
|
@@ -58,12 +59,12 @@ export const Default: Story = {
|
|
|
58
59
|
],
|
|
59
60
|
};
|
|
60
61
|
|
|
61
|
-
/** A routine seeded with a
|
|
62
|
-
export const
|
|
62
|
+
/** A routine seeded with a skill: the Skills field renders the populated ref slot. */
|
|
63
|
+
export const WithSkill: Story = {
|
|
63
64
|
decorators: [
|
|
64
65
|
withSeededSpace((space) => {
|
|
65
|
-
const
|
|
66
|
-
space.db.add(Instructions.make({ name: 'Summarize notes',
|
|
66
|
+
const skill = space.db.add(Skill.make({ key: 'org.dxos.test.summarize', name: 'Summarize' }));
|
|
67
|
+
space.db.add(Instructions.make({ name: 'Summarize notes', skills: [Ref.make(skill)] }));
|
|
67
68
|
}),
|
|
68
69
|
],
|
|
69
70
|
};
|
|
@@ -12,50 +12,62 @@ import { Form } from '@dxos/react-ui-form';
|
|
|
12
12
|
|
|
13
13
|
const INSTRUCTIONS_SCHEMA = Type.getSchema(Instructions.Instructions);
|
|
14
14
|
|
|
15
|
-
// Owned-routine action fields surfaced
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
|
|
15
|
+
// Owned-routine action fields surfaced by default — the prompt text and the agent's `skills`. The
|
|
16
|
+
// context `objects` are excluded here so a routine form doesn't show a second, divergent list beside
|
|
17
|
+
// its owning subject; a surface that owns the context concern (e.g. a project's Context section)
|
|
18
|
+
// opts in via `fields`.
|
|
19
|
+
const DEFAULT_FIELDS: readonly string[] = ['text', 'skills'];
|
|
19
20
|
|
|
20
21
|
export type InstructionsEditorProps = {
|
|
21
|
-
db?: Database.Database;
|
|
22
|
+
db?: Database.Database; // TODO(burdon): Should not be optional if instructions are not.
|
|
22
23
|
instructions: Instructions.Instructions;
|
|
23
24
|
readonly?: boolean;
|
|
25
|
+
/** Instructions schema fields rendered AND written back; others are left untouched. */
|
|
26
|
+
fields?: readonly string[];
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
/**
|
|
27
|
-
* Sub-form: edits the owned Instructions in place — its `text` (Markdown)
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* Sub-form: edits the owned Instructions in place — by default its `text` (Markdown) and `skills`,
|
|
31
|
+
* both fields of the Instructions schema. A bare Form.Root + FieldSet (no Viewport) keeps these
|
|
32
|
+
* fields left-aligned with the sibling general/action forms; only the rendered fields are written
|
|
33
|
+
* back so a partial editor never clobbers the rest of the object.
|
|
31
34
|
*/
|
|
32
|
-
export const InstructionsEditor = ({
|
|
35
|
+
export const InstructionsEditor = ({
|
|
36
|
+
db: dbProp,
|
|
37
|
+
instructions,
|
|
38
|
+
readonly,
|
|
39
|
+
fields = DEFAULT_FIELDS,
|
|
40
|
+
}: InstructionsEditorProps) => {
|
|
33
41
|
// A draft routine is not yet attached to a database, so fall back to the explicit `db` for ref queries.
|
|
34
42
|
const db = dbProp ?? Obj.getDatabase(instructions);
|
|
35
43
|
|
|
36
|
-
// `objects` is optional; normalize to an array so the ref-array field renders its add affordance.
|
|
37
44
|
const defaultValues = useMemo<Partial<Instructions.Instructions>>(
|
|
38
|
-
() => ({ ...Obj.getSnapshot(instructions)
|
|
45
|
+
() => ({ ...Obj.getSnapshot(instructions) }),
|
|
39
46
|
[instructions],
|
|
40
47
|
);
|
|
41
48
|
|
|
49
|
+
const fieldSet = useMemo(() => new Set(fields), [fields]);
|
|
42
50
|
const handleValuesChanged = useCallback(
|
|
43
51
|
(values: Partial<Instructions.Instructions>, { isValid }: { isValid: boolean }) => {
|
|
44
|
-
// Skip while invalid (e.g. an empty ref slot just added by
|
|
45
|
-
//
|
|
52
|
+
// Skip while invalid (e.g. an empty ref slot just added by the skills array field) so a partial
|
|
53
|
+
// selection isn't persisted; the write lands once the slot is filled.
|
|
46
54
|
if (!isValid) {
|
|
47
55
|
return;
|
|
48
56
|
}
|
|
49
57
|
|
|
50
58
|
Obj.update(instructions, (instructions) => {
|
|
51
|
-
if (values.text) {
|
|
59
|
+
if (fieldSet.has('text') && values.text) {
|
|
52
60
|
instructions.text = values.text;
|
|
53
61
|
}
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
if (fieldSet.has('skills')) {
|
|
63
|
+
instructions.skills = [...(values.skills ?? [])];
|
|
64
|
+
}
|
|
65
|
+
if (fieldSet.has('objects')) {
|
|
66
|
+
instructions.objects = [...(values.objects ?? [])];
|
|
67
|
+
}
|
|
56
68
|
});
|
|
57
69
|
},
|
|
58
|
-
[instructions],
|
|
70
|
+
[instructions, fieldSet],
|
|
59
71
|
);
|
|
60
72
|
|
|
61
73
|
return (
|
|
@@ -68,7 +80,7 @@ export const InstructionsEditor = ({ db: dbProp, instructions, readonly }: Instr
|
|
|
68
80
|
getOptions={getRefOptions}
|
|
69
81
|
onValuesChanged={handleValuesChanged}
|
|
70
82
|
>
|
|
71
|
-
<Form.FieldSet filter={(props) => props.filter((prop) =>
|
|
83
|
+
<Form.FieldSet filter={(props) => props.filter((prop) => fieldSet.has(prop.name.toString()))} />
|
|
72
84
|
</Form.Root>
|
|
73
85
|
);
|
|
74
86
|
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { Instructions, Routine, Trigger } from '@dxos/compute';
|
|
9
|
+
import { Filter, Query } from '@dxos/echo';
|
|
10
|
+
import { useQuery } from '@dxos/echo-react';
|
|
11
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
12
|
+
import { useClientStory, withClientProvider } from '@dxos/react-client/testing';
|
|
13
|
+
import { Card } from '@dxos/react-ui';
|
|
14
|
+
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
15
|
+
import { Text } from '@dxos/schema';
|
|
16
|
+
|
|
17
|
+
import { translations } from '#translations';
|
|
18
|
+
|
|
19
|
+
import { makeRoutine } from '../../util';
|
|
20
|
+
import { RoutineCard } from './RoutineCard';
|
|
21
|
+
|
|
22
|
+
const types = [Routine.Routine, Instructions.Instructions, Trigger.Trigger, Text.Text];
|
|
23
|
+
|
|
24
|
+
const DefaultStory = () => {
|
|
25
|
+
const { space } = useClientStory();
|
|
26
|
+
const [routine] = useQuery(space?.db, Filter.type(Routine.Routine));
|
|
27
|
+
if (!space || !routine) {
|
|
28
|
+
return <Loading />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The surface host supplies Card.Root and the header; RoutineCard emits only the body.
|
|
32
|
+
return (
|
|
33
|
+
<Card.Root fullWidth>
|
|
34
|
+
<Card.Header>
|
|
35
|
+
<Card.Title>{routine.name ?? 'Untitled'}</Card.Title>
|
|
36
|
+
</Card.Header>
|
|
37
|
+
<RoutineCard subject={routine} />
|
|
38
|
+
</Card.Root>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const withSeededRoutine = ({ name, spec, enabled }: { name?: string; spec?: Trigger.Spec; enabled?: boolean } = {}) =>
|
|
43
|
+
withClientProvider({
|
|
44
|
+
createIdentity: true,
|
|
45
|
+
createSpace: true,
|
|
46
|
+
types,
|
|
47
|
+
onCreateSpace: async ({ space }: { space: Space }) => {
|
|
48
|
+
space.db.add(
|
|
49
|
+
makeRoutine({
|
|
50
|
+
name,
|
|
51
|
+
instructions: Instructions.make({ text: 'Summarize the day.' }),
|
|
52
|
+
trigger: Trigger.make({ spec, enabled }),
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const meta = {
|
|
59
|
+
title: 'plugins/plugin-routine/components/RoutineCard',
|
|
60
|
+
render: DefaultStory,
|
|
61
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
62
|
+
parameters: {
|
|
63
|
+
translations,
|
|
64
|
+
},
|
|
65
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
66
|
+
|
|
67
|
+
export default meta;
|
|
68
|
+
|
|
69
|
+
type Story = StoryObj<typeof meta>;
|
|
70
|
+
|
|
71
|
+
/** An active scheduled routine: the schedule summary, with the green check marking it switched on. */
|
|
72
|
+
export const Default: Story = {
|
|
73
|
+
decorators: [withSeededRoutine({ name: 'Daily Digest', spec: Trigger.specTimer('0 9 * * *'), enabled: true })],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** The same routine switched off: same summary, no check. */
|
|
77
|
+
export const Inactive: Story = {
|
|
78
|
+
decorators: [withSeededRoutine({ name: 'Daily Digest', spec: Trigger.specTimer('0 9 * * *') })],
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** A non-timer trigger has no parameters worth summarizing, so the kind description stands in. */
|
|
82
|
+
export const QueryTrigger: Story = {
|
|
83
|
+
decorators: [
|
|
84
|
+
withSeededRoutine({
|
|
85
|
+
name: 'Watch tasks',
|
|
86
|
+
spec: Trigger.specSubscription(Query.select(Filter.type(Text.Text))),
|
|
87
|
+
enabled: true,
|
|
88
|
+
}),
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/** A freshly created (blank-template) routine: the body prompts for a trigger. */
|
|
93
|
+
export const NoTrigger: Story = {
|
|
94
|
+
decorators: [withSeededRoutine()],
|
|
95
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
8
|
+
import { type Routine, type Trigger } from '@dxos/compute';
|
|
9
|
+
import { useObject } from '@dxos/echo-react';
|
|
10
|
+
import { Card, Icon, useTranslation } from '@dxos/react-ui';
|
|
11
|
+
|
|
12
|
+
import { meta } from '#meta';
|
|
13
|
+
|
|
14
|
+
import { cronToSchedule, describeSchedule } from '../Schedule';
|
|
15
|
+
|
|
16
|
+
export type RoutineCardProps = AppSurface.ObjectCardProps<Routine.Routine>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Compact preview of a {@link Routine.Routine}: when it runs. Rendered into the
|
|
20
|
+
* `AppSurface.CardContent` slot — Card.Root is supplied by the surface host (the project article's
|
|
21
|
+
* gallery, popovers, related-objects), so this emits Card.Body only. Without it a routine falls back
|
|
22
|
+
* to the generic form preview, which renders its `spec`/`triggers` internals rather than a summary.
|
|
23
|
+
*/
|
|
24
|
+
export const RoutineCard = ({ subject }: RoutineCardProps) => {
|
|
25
|
+
const { t } = useTranslation(meta.profile.key);
|
|
26
|
+
const [routine] = useObject(subject);
|
|
27
|
+
// MVP enforces at most one trigger; the summary describes it.
|
|
28
|
+
const [trigger] = useObject(routine.triggers.at(0));
|
|
29
|
+
|
|
30
|
+
// Active means the same thing as in the routines list: a trigger exists and is switched on.
|
|
31
|
+
const active = trigger?.enabled === true;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Card.Body>
|
|
35
|
+
<Card.Row>
|
|
36
|
+
{/* The gutter is reserved either way so the summary stays aligned across cards. */}
|
|
37
|
+
<Card.Block>{active && <Icon icon='ph--check-circle--regular' classNames='text-green-text' />}</Card.Block>
|
|
38
|
+
<Card.Text variant='description' classNames='line-clamp-2'>
|
|
39
|
+
{describeTrigger(trigger?.spec, t)}
|
|
40
|
+
</Card.Text>
|
|
41
|
+
</Card.Row>
|
|
42
|
+
</Card.Body>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
RoutineCard.displayName = 'RoutineCard';
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The same sentence the trigger editor shows above the schedule picker. Non-timer kinds have no
|
|
50
|
+
* parameters worth summarizing, so they reuse the kind description from the trigger-kind picker.
|
|
51
|
+
*/
|
|
52
|
+
const describeTrigger = (spec: Trigger.Spec | undefined, t: (key: string) => string): string => {
|
|
53
|
+
if (!spec) {
|
|
54
|
+
return t('add-trigger-first.message');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return spec.kind === 'timer'
|
|
58
|
+
? describeSchedule(cronToSchedule(spec.cron))
|
|
59
|
+
: t(`trigger-kind.${spec.kind}.description`);
|
|
60
|
+
};
|