@dxos/plugin-automation 0.8.4-staging.60fe92afc8 → 0.9.1-main.c7dcc2e112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/lib/neutral/{AutomationArticle-GN36NUX2.mjs → AutomationArticle-CG4ZML3C.mjs} +3 -2
  2. package/dist/lib/neutral/{AutomationCompanion-M26WR6VP.mjs → AutomationCompanion-67LW2WZS.mjs} +12 -13
  3. package/dist/lib/neutral/AutomationCompanion-67LW2WZS.mjs.map +7 -0
  4. package/dist/lib/neutral/AutomationPlugin.mjs +1 -1
  5. package/dist/lib/neutral/AutomationPlugin.node.mjs +4 -4
  6. package/dist/lib/neutral/AutomationPlugin.node.mjs.map +3 -3
  7. package/dist/lib/neutral/{AutomationSettings-YXUJDRQA.mjs → AutomationSettings-2XCCFX6X.mjs} +5 -5
  8. package/dist/lib/neutral/{AutomationSettings-YXUJDRQA.mjs.map → AutomationSettings-2XCCFX6X.mjs.map} +3 -3
  9. package/dist/lib/neutral/{TriggerSettings-XCHIZPOR.mjs → TriggerSettings-ABOTKRUA.mjs} +2 -2
  10. package/dist/lib/neutral/{app-graph-builder-BTTHS4VK.mjs → app-graph-builder-VX54SXD6.mjs} +6 -6
  11. package/dist/lib/neutral/app-graph-builder-VX54SXD6.mjs.map +7 -0
  12. package/dist/lib/neutral/capabilities/index.mjs +3 -3
  13. package/dist/lib/neutral/capabilities/node.mjs +1 -1
  14. package/dist/lib/neutral/{chunk-2JP77CMN.mjs → chunk-73DGSL37.mjs} +2 -2
  15. package/dist/lib/neutral/chunk-73DGSL37.mjs.map +7 -0
  16. package/dist/lib/neutral/{chunk-HPUHQ3L6.mjs → chunk-77QU5RSC.mjs} +3 -3
  17. package/dist/lib/neutral/chunk-77QU5RSC.mjs.map +7 -0
  18. package/dist/lib/neutral/chunk-D4RCXOP4.mjs +13 -0
  19. package/dist/lib/neutral/chunk-D4RCXOP4.mjs.map +7 -0
  20. package/dist/lib/neutral/{chunk-SONGOJRB.mjs → chunk-EJ5J22XS.mjs} +2 -2
  21. package/dist/lib/neutral/chunk-HHIFH3N3.mjs +45 -0
  22. package/dist/lib/neutral/chunk-HHIFH3N3.mjs.map +7 -0
  23. package/dist/lib/neutral/chunk-HQU5QWF4.mjs +349 -0
  24. package/dist/lib/neutral/chunk-HQU5QWF4.mjs.map +7 -0
  25. package/dist/lib/neutral/{chunk-FE7YFBX7.mjs → chunk-LVUL7GIN.mjs} +151 -60
  26. package/dist/lib/neutral/chunk-LVUL7GIN.mjs.map +7 -0
  27. package/dist/lib/neutral/{chunk-GARB7S5R.mjs → chunk-YHK7FWGV.mjs} +5 -3
  28. package/dist/lib/neutral/chunk-YHK7FWGV.mjs.map +7 -0
  29. package/dist/lib/neutral/components/index.mjs +36 -2
  30. package/dist/lib/neutral/components/index.mjs.map +3 -3
  31. package/dist/lib/neutral/containers/index.mjs +4 -4
  32. package/dist/lib/neutral/{create-automation-OE3TNXYE.mjs → create-automation-AGYTF62E.mjs} +5 -9
  33. package/dist/lib/neutral/create-automation-AGYTF62E.mjs.map +7 -0
  34. package/dist/lib/neutral/{create-trigger-from-template-TERHKWJM.mjs → create-trigger-from-template-TYGCSR3Z.mjs} +5 -5
  35. package/dist/lib/neutral/create-trigger-from-template-TYGCSR3Z.mjs.map +7 -0
  36. package/dist/lib/neutral/index.mjs +10 -2
  37. package/dist/lib/neutral/meta.json +1 -1
  38. package/dist/lib/neutral/meta.mjs +1 -1
  39. package/dist/lib/neutral/{navigation-resolver-I3L5FHJO.mjs → navigation-resolver-FSJNF3DQ.mjs} +3 -3
  40. package/dist/lib/neutral/navigation-resolver-FSJNF3DQ.mjs.map +7 -0
  41. package/dist/lib/neutral/operations/index.mjs +1 -1
  42. package/dist/lib/neutral/plugin.mjs +2 -2
  43. package/dist/lib/neutral/{react-surface-IBRWUKPC.mjs → react-surface-W3J3CDHA.mjs} +2 -2
  44. package/dist/lib/neutral/{react-surface-IBRWUKPC.mjs.map → react-surface-W3J3CDHA.mjs.map} +3 -3
  45. package/dist/lib/neutral/testing.mjs +1 -1
  46. package/dist/lib/neutral/translations.mjs +6 -2
  47. package/dist/lib/neutral/translations.mjs.map +3 -3
  48. package/dist/lib/neutral/types/index.mjs +1 -1
  49. package/dist/types/dx.config.d.ts +28 -0
  50. package/dist/types/dx.config.d.ts.map +1 -0
  51. package/dist/types/src/capabilities/index.d.ts +8 -13
  52. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  53. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -1
  54. package/dist/types/src/capabilities/node.d.ts +5 -5
  55. package/dist/types/src/capabilities/node.d.ts.map +1 -1
  56. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  57. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  58. package/dist/types/src/components/CronBuilder/CronBuilder.d.ts +16 -0
  59. package/dist/types/src/components/CronBuilder/CronBuilder.d.ts.map +1 -0
  60. package/dist/types/src/components/CronBuilder/CronBuilder.stories.d.ts +194 -0
  61. package/dist/types/src/components/CronBuilder/CronBuilder.stories.d.ts.map +1 -0
  62. package/dist/types/src/components/CronBuilder/cron.d.ts +17 -0
  63. package/dist/types/src/components/CronBuilder/cron.d.ts.map +1 -0
  64. package/dist/types/src/components/CronBuilder/cron.test.d.ts +2 -0
  65. package/dist/types/src/components/CronBuilder/cron.test.d.ts.map +1 -0
  66. package/dist/types/src/components/CronBuilder/index.d.ts +4 -0
  67. package/dist/types/src/components/CronBuilder/index.d.ts.map +1 -0
  68. package/dist/types/src/components/CronBuilder/schema.d.ts +96 -0
  69. package/dist/types/src/components/CronBuilder/schema.d.ts.map +1 -0
  70. package/dist/types/src/components/index.d.ts +1 -0
  71. package/dist/types/src/components/index.d.ts.map +1 -1
  72. package/dist/types/src/containers/AutomationArticle/AutomationArticle.d.ts +6 -0
  73. package/dist/types/src/containers/AutomationArticle/AutomationArticle.d.ts.map +1 -1
  74. package/dist/types/src/containers/AutomationArticle/AutomationArticle.stories.d.ts +120 -0
  75. package/dist/types/src/containers/AutomationArticle/AutomationArticle.stories.d.ts.map +1 -0
  76. package/dist/types/src/containers/AutomationCompanion/AutomationCompanion.d.ts.map +1 -1
  77. package/dist/types/src/index.d.ts +1 -0
  78. package/dist/types/src/index.d.ts.map +1 -1
  79. package/dist/types/src/meta.d.ts +28 -2
  80. package/dist/types/src/meta.d.ts.map +1 -1
  81. package/dist/types/src/paths.d.ts +2 -0
  82. package/dist/types/src/paths.d.ts.map +1 -1
  83. package/dist/types/src/translations.d.ts +9 -1
  84. package/dist/types/src/translations.d.ts.map +1 -1
  85. package/dist/types/src/types/AutomationCapabilities.d.ts +6 -1
  86. package/dist/types/src/types/AutomationCapabilities.d.ts.map +1 -1
  87. package/dist/types/tsconfig.tsbuildinfo +1 -1
  88. package/dx.config.ts +34 -0
  89. package/package.json +40 -38
  90. package/src/AutomationPlugin.test.ts +1 -1
  91. package/src/AutomationPlugin.tsx +1 -1
  92. package/src/capabilities/app-graph-builder.ts +5 -5
  93. package/src/capabilities/navigation-resolver.ts +2 -2
  94. package/src/capabilities/react-surface.tsx +1 -1
  95. package/src/commands/trigger/create/queue.ts +2 -2
  96. package/src/commands/trigger/update/queue.ts +2 -2
  97. package/src/components/CreateAutomationPanel/CreateAutomationPanel.tsx +1 -1
  98. package/src/components/CronBuilder/CronBuilder.stories.tsx +72 -0
  99. package/src/components/CronBuilder/CronBuilder.tsx +94 -0
  100. package/src/components/CronBuilder/cron.test.ts +131 -0
  101. package/src/components/CronBuilder/cron.ts +138 -0
  102. package/src/components/CronBuilder/index.ts +7 -0
  103. package/src/components/CronBuilder/schema.ts +119 -0
  104. package/src/components/index.ts +1 -0
  105. package/src/containers/AutomationArticle/AutomationArticle.stories.tsx +73 -0
  106. package/src/containers/AutomationArticle/AutomationArticle.tsx +186 -56
  107. package/src/containers/AutomationCompanion/AutomationCompanion.tsx +79 -72
  108. package/src/containers/AutomationSettings/AutomationSettings.tsx +3 -3
  109. package/src/containers/TriggerSettings/TriggerSettings.tsx +1 -1
  110. package/src/index.ts +1 -0
  111. package/src/meta.ts +2 -26
  112. package/src/operations/create-trigger-from-template.ts +3 -3
  113. package/src/paths.ts +7 -2
  114. package/src/translations.ts +7 -2
  115. package/src/types/AutomationCapabilities.ts +9 -1
  116. package/src/types/AutomationOperation.ts +1 -1
  117. package/src/types/schema.ts +1 -1
  118. package/dist/lib/neutral/AutomationCompanion-M26WR6VP.mjs.map +0 -7
  119. package/dist/lib/neutral/app-graph-builder-BTTHS4VK.mjs.map +0 -7
  120. package/dist/lib/neutral/chunk-2JP77CMN.mjs.map +0 -7
  121. package/dist/lib/neutral/chunk-DUGOIM7G.mjs +0 -36
  122. package/dist/lib/neutral/chunk-DUGOIM7G.mjs.map +0 -7
  123. package/dist/lib/neutral/chunk-FE7YFBX7.mjs.map +0 -7
  124. package/dist/lib/neutral/chunk-GARB7S5R.mjs.map +0 -7
  125. package/dist/lib/neutral/chunk-HPUHQ3L6.mjs.map +0 -7
  126. package/dist/lib/neutral/create-automation-OE3TNXYE.mjs.map +0 -7
  127. package/dist/lib/neutral/create-trigger-from-template-TERHKWJM.mjs.map +0 -7
  128. package/dist/lib/neutral/navigation-resolver-I3L5FHJO.mjs.map +0 -7
  129. /package/dist/lib/neutral/{AutomationArticle-GN36NUX2.mjs.map → AutomationArticle-CG4ZML3C.mjs.map} +0 -0
  130. /package/dist/lib/neutral/{TriggerSettings-XCHIZPOR.mjs.map → TriggerSettings-ABOTKRUA.mjs.map} +0 -0
  131. /package/dist/lib/neutral/{chunk-SONGOJRB.mjs.map → chunk-EJ5J22XS.mjs.map} +0 -0
@@ -1,19 +1,37 @@
1
+ import {
2
+ CronBuilder,
3
+ FrequencyDefaults,
4
+ describeCron,
5
+ fromCron,
6
+ toCron
7
+ } from "./chunk-HQU5QWF4.mjs";
8
+
1
9
  // src/containers/AutomationArticle/AutomationArticle.tsx
10
+ import * as Effect from "effect/Effect";
2
11
  import * as Schema from "effect/Schema";
3
- import React, { useCallback, useMemo } from "react";
4
- import { Operation, Routine, Trigger } from "@dxos/compute";
12
+ import React, { useCallback, useMemo, useState } from "react";
13
+ import { useProcessManagerRuntime } from "@dxos/app-framework/ui";
14
+ import { Operation, Routine, ServiceResolver, Trigger } from "@dxos/compute";
15
+ import { Context } from "@dxos/context";
5
16
  import { Feed, Filter, JsonSchema, Obj, Query, Ref, Scope, Type } from "@dxos/echo";
17
+ import { KEY_FEED_CURSOR, TriggerDispatcher } from "@dxos/functions-runtime";
18
+ import { FunctionsServiceClient } from "@dxos/functions-runtime/edge";
6
19
  import { DXN } from "@dxos/keys";
7
- import { useObject, useQuery } from "@dxos/react-client/echo";
8
- import { Button, Icon, Input, useTranslation } from "@dxos/react-ui";
20
+ import { log } from "@dxos/log";
21
+ import { useClient } from "@dxos/react-client";
22
+ import { getSpace, useObject, useQuery } from "@dxos/react-client/echo";
23
+ import { DropdownMenu, IconButton, Input, useTranslation } from "@dxos/react-ui";
9
24
  import { Form, RefField, SelectField, Settings } from "@dxos/react-ui-form";
25
+ import { Accordion } from "@dxos/react-ui-list";
10
26
  import { ParentLabelAnnotation } from "@dxos/schema";
11
27
  import { meta } from "#meta";
28
+ var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-automation/src/containers/AutomationArticle/AutomationArticle.tsx";
12
29
  var RUN_ROUTINE_DXN = "org.dxos.function.prompt";
13
30
  var AutomationArticle = ({ role, subject }) => {
14
- const { t } = useTranslation(meta.id);
31
+ const { t } = useTranslation(meta.profile.key);
15
32
  const db = Obj.getDatabase(subject);
16
33
  const trigger = usePrimaryTrigger(subject);
34
+ const space = getSpace(subject);
17
35
  if (!db) {
18
36
  return null;
19
37
  }
@@ -30,6 +48,9 @@ var AutomationArticle = ({ role, subject }) => {
30
48
  db,
31
49
  automation: subject,
32
50
  trigger
51
+ }), space && trigger && /* @__PURE__ */ React.createElement(TriggerTestingSection, {
52
+ space,
53
+ trigger
33
54
  }))), /* @__PURE__ */ React.createElement(Settings.Section, {
34
55
  title: t("action.title"),
35
56
  description: t("action.description")
@@ -58,7 +79,7 @@ var GeneralSection = ({ automation, trigger }) => {
58
79
  }, /* @__PURE__ */ React.createElement(Form.Content, null, /* @__PURE__ */ React.createElement(Form.FieldSet, null)));
59
80
  };
60
81
  var EnabledField = ({ canEnable, messageKey, ...props }) => {
61
- const { t } = useTranslation(meta.id);
82
+ const { t } = useTranslation(meta.profile.key);
62
83
  return /* @__PURE__ */ React.createElement("div", {
63
84
  className: "flex items-center gap-2 pt-form-padding"
64
85
  }, /* @__PURE__ */ React.createElement(Input.Root, null, /* @__PURE__ */ React.createElement(Input.Switch, {
@@ -71,6 +92,85 @@ var EnabledField = ({ canEnable, messageKey, ...props }) => {
71
92
  className: "text-sm text-description"
72
93
  }, t(messageKey)));
73
94
  };
95
+ var TESTING_ITEM = {
96
+ id: "testing"
97
+ };
98
+ var TriggerTestingSection = ({ space, trigger }) => {
99
+ const { t } = useTranslation(meta.profile.key);
100
+ const client = useClient();
101
+ const processManagerRuntime = useProcessManagerRuntime();
102
+ const [properties] = useObject(space.properties);
103
+ const computeEnvironment = properties.computeEnvironment ?? "local";
104
+ const functionsServiceClient = useMemo(() => FunctionsServiceClient.fromClient(client), [
105
+ client
106
+ ]);
107
+ const spec = Obj.getSnapshot(trigger).spec;
108
+ const kind = spec?.kind;
109
+ const cursor = kind === "feed" ? Obj.getKeys(trigger, KEY_FEED_CURSOR).at(0)?.id : void 0;
110
+ const handleForceRun = useCallback(async () => {
111
+ if (computeEnvironment === "disabled") {
112
+ return;
113
+ }
114
+ if (computeEnvironment === "local") {
115
+ await processManagerRuntime.runPromise(Effect.gen(function* () {
116
+ const dispatcher = yield* TriggerDispatcher;
117
+ yield* dispatcher.invokeTrigger({
118
+ trigger,
119
+ event: {
120
+ tick: Date.now()
121
+ }
122
+ });
123
+ }).pipe(Effect.provide(ServiceResolver.provide({
124
+ space: space.id
125
+ }, TriggerDispatcher)))).catch((error) => log.catch(error, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 132, S: void 0 }));
126
+ return;
127
+ }
128
+ await functionsServiceClient.forceRunCronTrigger(Context.default(void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 135 }), space.id, trigger.id).catch((error) => log.catch(error, void 0, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 135, S: void 0 }));
129
+ }, [
130
+ computeEnvironment,
131
+ functionsServiceClient,
132
+ processManagerRuntime,
133
+ space.id,
134
+ trigger
135
+ ]);
136
+ const handleResetCursor = useCallback(async () => {
137
+ Obj.update(trigger, (trigger2) => {
138
+ Obj.deleteKeys(trigger2, KEY_FEED_CURSOR);
139
+ });
140
+ await space.db.flush({
141
+ indexes: true
142
+ });
143
+ }, [
144
+ space.db,
145
+ trigger
146
+ ]);
147
+ if (kind !== "timer" && kind !== "feed") {
148
+ return null;
149
+ }
150
+ return /* @__PURE__ */ React.createElement(Accordion.Root, {
151
+ items: [
152
+ TESTING_ITEM
153
+ ]
154
+ }, ({ items }) => items.map((item) => /* @__PURE__ */ React.createElement(Accordion.Item, {
155
+ key: item.id,
156
+ item
157
+ }, /* @__PURE__ */ React.createElement(Accordion.ItemHeader, null, t("testing.title")), /* @__PURE__ */ React.createElement(Accordion.ItemBody, null, kind === "timer" && /* @__PURE__ */ React.createElement(IconButton, {
158
+ icon: "ph--play--regular",
159
+ label: t("force-run.label"),
160
+ disabled: computeEnvironment === "disabled",
161
+ onClick: handleForceRun
162
+ }), kind === "feed" && /* @__PURE__ */ React.createElement(DropdownMenu.Root, null, /* @__PURE__ */ React.createElement(DropdownMenu.Trigger, {
163
+ asChild: true
164
+ }, /* @__PURE__ */ React.createElement(IconButton, {
165
+ icon: "ph--arrow-clockwise--regular",
166
+ label: t("reset-cursor.label"),
167
+ disabled: !cursor
168
+ })), /* @__PURE__ */ React.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React.createElement(DropdownMenu.Content, {
169
+ side: "top"
170
+ }, /* @__PURE__ */ React.createElement(DropdownMenu.Viewport, null, /* @__PURE__ */ React.createElement(DropdownMenu.Item, {
171
+ onClick: handleResetCursor
172
+ }, t("reset-cursor-confirm.label"))), /* @__PURE__ */ React.createElement(DropdownMenu.Arrow, null))))))));
173
+ };
74
174
  var OperationAction = Schema.Struct({
75
175
  kind: Schema.Literal("operation"),
76
176
  operation: Ref.Ref(Operation.PersistentOperation).pipe(Schema.annotations({
@@ -103,7 +203,7 @@ var ActionSection = ({ db, automation, trigger }) => {
103
203
  }));
104
204
  };
105
205
  var ActionInputEditor = ({ db, operation, trigger }) => {
106
- const { t } = useTranslation(meta.id);
206
+ const { t } = useTranslation(meta.profile.key);
107
207
  const effectSchema = useMemo(() => operation.inputSchema ? JsonSchema.toEffectSchema(operation.inputSchema) : void 0, [
108
208
  operation.inputSchema
109
209
  ]);
@@ -126,7 +226,7 @@ var ActionInputEditor = ({ db, operation, trigger }) => {
126
226
  }
127
227
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Form.Label, {
128
228
  label: t("action-input.label"),
129
- asChild: true
229
+ standalone: true
130
230
  }), /* @__PURE__ */ React.createElement(Form.Root, {
131
231
  key: operation.id,
132
232
  schema: effectSchema,
@@ -155,16 +255,14 @@ var triggerFormValues = (spec) => spec?.kind === "feed" ? {
155
255
  kind: "timer",
156
256
  cron: spec?.kind === "timer" ? spec.cron : ""
157
257
  };
258
+ var DEFAULT_TIMER_CRON = toCron(FrequencyDefaults.daily);
158
259
  var triggerFormSpec = (values) => values.kind === "feed" ? {
159
260
  kind: "feed",
160
261
  feed: values.feed
161
- } : Trigger.specTimer(values.cron ?? "");
262
+ } : Trigger.specTimer(values.cron || DEFAULT_TIMER_CRON);
162
263
  var TriggerSection = ({ db, automation, trigger }) => {
163
- const { t } = useTranslation(meta.id);
164
- const { defaultValues, fieldMap, handleValuesChanged, handleRemove } = useTriggerForm(db, automation, trigger);
165
- return /* @__PURE__ */ React.createElement("div", {
166
- className: "flex flex-col gap-2"
167
- }, /* @__PURE__ */ React.createElement(Form.Root, {
264
+ const { defaultValues, fieldMap, handleValuesChanged } = useTriggerForm(db, automation, trigger);
265
+ return /* @__PURE__ */ React.createElement(Form.Root, {
168
266
  // Remount when the bound trigger changes so the uncontrolled form picks up its spec.
169
267
  key: trigger?.id ?? "new",
170
268
  schema: TriggerForm,
@@ -172,14 +270,7 @@ var TriggerSection = ({ db, automation, trigger }) => {
172
270
  db,
173
271
  fieldMap,
174
272
  onValuesChanged: handleValuesChanged
175
- }, /* @__PURE__ */ React.createElement(Form.Content, null, /* @__PURE__ */ React.createElement(Form.FieldSet, null))), trigger && /* @__PURE__ */ React.createElement(Button, {
176
- variant: "ghost",
177
- classNames: "gap-1 self-start",
178
- onClick: handleRemove
179
- }, /* @__PURE__ */ React.createElement(Icon, {
180
- icon: "ph--trash--regular",
181
- size: 4
182
- }), /* @__PURE__ */ React.createElement("span", null, t("remove-trigger.label"))));
273
+ }, /* @__PURE__ */ React.createElement(Form.Content, null, /* @__PURE__ */ React.createElement(Form.FieldSet, null)));
183
274
  };
184
275
  var InlineSection = ({ title, children }) => /* @__PURE__ */ React.createElement("div", {
185
276
  className: "flex flex-col gap-1"
@@ -187,7 +278,7 @@ var InlineSection = ({ title, children }) => /* @__PURE__ */ React.createElement
187
278
  className: "pli-1 text-sm font-medium text-description"
188
279
  }, title), /* @__PURE__ */ React.createElement(Settings.Panel, null, children));
189
280
  var AutomationInlineForm = ({ automation, db }) => {
190
- const { t } = useTranslation(meta.id);
281
+ const { t } = useTranslation(meta.profile.key);
191
282
  const trigger = usePrimaryTrigger(automation);
192
283
  return /* @__PURE__ */ React.createElement("div", {
193
284
  className: "flex flex-col gap-3"
@@ -210,6 +301,27 @@ var AutomationInlineForm = ({ automation, db }) => {
210
301
  trigger
211
302
  })));
212
303
  };
304
+ var CronField = (props) => {
305
+ const existingCron = props.getValue();
306
+ const initialSpec = useMemo(() => existingCron ? fromCron(existingCron) : FrequencyDefaults.daily, []);
307
+ const [description, setDescription] = useState(() => describeCron(existingCron ?? toCron(initialSpec)));
308
+ const handleChange = useCallback((spec, cron) => {
309
+ setDescription(describeCron(cron));
310
+ props.onValueChange(props.type, cron);
311
+ }, [
312
+ props.type,
313
+ props.onValueChange
314
+ ]);
315
+ return /* @__PURE__ */ React.createElement("div", {
316
+ className: "flex flex-col gap-1 mbs-2"
317
+ }, /* @__PURE__ */ React.createElement(CronBuilder, {
318
+ value: initialSpec,
319
+ onChange: handleChange
320
+ }), /* @__PURE__ */ React.createElement("p", {
321
+ className: "text-sm text-description pli-1 text-right"
322
+ }, description));
323
+ };
324
+ CronField.displayName = "AutomationArticle.CronField";
213
325
  var usePrimaryTrigger = (automation) => {
214
326
  const [snapshot] = useObject(automation);
215
327
  return useMemo(() => {
@@ -238,17 +350,13 @@ var useGeneralForm = (automation, trigger) => {
238
350
  canEnable,
239
351
  messageKey
240
352
  ]);
241
- const defaultValues = useMemo(
242
- () => ({
243
- name: auto.name,
244
- enabled: (trigger?.enabled ?? false) && canEnable
245
- }),
246
- // eslint-disable-next-line react-hooks/exhaustive-deps
247
- [
248
- automation,
249
- trigger
250
- ]
251
- );
353
+ const defaultValues = useMemo(() => ({
354
+ name: auto.name,
355
+ enabled: (trigger?.enabled ?? false) && canEnable
356
+ }), [
357
+ automation,
358
+ trigger
359
+ ]);
252
360
  const handleValuesChanged = useCallback((values) => {
253
361
  updateAuto((automation2) => {
254
362
  automation2.name = values.name;
@@ -270,7 +378,7 @@ var useGeneralForm = (automation, trigger) => {
270
378
  };
271
379
  };
272
380
  var useActionForm = (db, automation, trigger) => {
273
- const { t } = useTranslation(meta.id);
381
+ const { t } = useTranslation(meta.profile.key);
274
382
  const [auto, updateAuto] = useObject(automation);
275
383
  const operations = useQuery(
276
384
  db,
@@ -383,7 +491,7 @@ var useActionForm = (db, automation, trigger) => {
383
491
  };
384
492
  };
385
493
  var useTriggerForm = (db, automation, trigger) => {
386
- const { t } = useTranslation(meta.id);
494
+ const { t } = useTranslation(meta.profile.key);
387
495
  const kindOptions = useMemo(() => [
388
496
  {
389
497
  value: "timer",
@@ -400,17 +508,14 @@ var useTriggerForm = (db, automation, trigger) => {
400
508
  kind: (props) => /* @__PURE__ */ React.createElement(SelectField, {
401
509
  ...props,
402
510
  options: kindOptions
403
- })
511
+ }),
512
+ cron: (props) => /* @__PURE__ */ React.createElement(CronField, props)
404
513
  }), [
405
514
  kindOptions
406
515
  ]);
407
- const defaultValues = useMemo(
408
- () => triggerFormValues(trigger?.spec),
409
- // eslint-disable-next-line react-hooks/exhaustive-deps
410
- [
411
- trigger
412
- ]
413
- );
516
+ const defaultValues = useMemo(() => triggerFormValues(trigger?.spec), [
517
+ trigger
518
+ ]);
414
519
  const handleValuesChanged = useCallback((values) => {
415
520
  const spec = triggerFormSpec(values);
416
521
  if (trigger) {
@@ -436,24 +541,10 @@ var useTriggerForm = (db, automation, trigger) => {
436
541
  automation,
437
542
  trigger
438
543
  ]);
439
- const handleRemove = useCallback(() => {
440
- if (!trigger) {
441
- return;
442
- }
443
- Obj.update(automation, (automation2) => {
444
- automation2.triggers = automation2.triggers.filter((ref) => ref.target?.id !== trigger.id);
445
- });
446
- db.remove(trigger);
447
- }, [
448
- db,
449
- automation,
450
- trigger
451
- ]);
452
544
  return {
453
545
  defaultValues,
454
546
  fieldMap,
455
- handleValuesChanged,
456
- handleRemove
547
+ handleValuesChanged
457
548
  };
458
549
  };
459
550
  var getBoundRoutine = (trigger) => {
@@ -483,4 +574,4 @@ export {
483
574
  TriggerSection,
484
575
  AutomationInlineForm
485
576
  };
486
- //# sourceMappingURL=chunk-FE7YFBX7.mjs.map
577
+ //# sourceMappingURL=chunk-LVUL7GIN.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/containers/AutomationArticle/AutomationArticle.tsx"],
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\nimport React, { type ReactNode, useCallback, useMemo, useState } from 'react';\n\nimport { useProcessManagerRuntime } from '@dxos/app-framework/ui';\nimport { type AppSurface } from '@dxos/app-toolkit/ui';\nimport { Operation, Routine, ServiceResolver, Trigger, TriggerEvent } from '@dxos/compute';\nimport { Context } from '@dxos/context';\nimport { type Database, Entity, Feed, Filter, JsonSchema, Obj, Query, Ref, Scope, Type } from '@dxos/echo';\nimport { KEY_FEED_CURSOR, TriggerDispatcher } from '@dxos/functions-runtime';\nimport { FunctionsServiceClient } from '@dxos/functions-runtime/edge';\nimport { DXN } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { useClient } from '@dxos/react-client';\nimport { type Space, getSpace, useObject, useQuery } from '@dxos/react-client/echo';\nimport { DropdownMenu, IconButton, Input, useTranslation } from '@dxos/react-ui';\nimport {\n Form,\n type FormFieldRendererProps,\n type FormFieldMap,\n RefField,\n SelectField,\n Settings,\n} from '@dxos/react-ui-form';\nimport { Accordion } from '@dxos/react-ui-list';\nimport { ParentLabelAnnotation } from '@dxos/schema';\n\nimport { meta } from '#meta';\nimport { Automation } from '#types';\n\nimport { describeCron, fromCron, toCron } from '../../components/CronBuilder/cron';\nimport { CronBuilder } from '../../components/CronBuilder/CronBuilder';\nimport { type CronSpecType, FrequencyDefaults } from '../../components/CronBuilder/schema';\n\nconst RUN_ROUTINE_DXN = 'org.dxos.function.prompt';\n\nexport type AutomationArticleProps = AppSurface.ObjectArticleProps<Automation.Automation>;\n\nexport const AutomationArticle = ({ role, subject }: AutomationArticleProps) => {\n const { t } = useTranslation(meta.profile.key);\n const db = Obj.getDatabase(subject);\n const trigger = usePrimaryTrigger(subject);\n const space = getSpace(subject);\n\n if (!db) {\n return null;\n }\n\n return (\n <Settings.Viewport>\n <Settings.Section title={t('general.title')} description={t('general.description')}>\n <Settings.Panel>\n <GeneralSection automation={subject} trigger={trigger} />\n </Settings.Panel>\n </Settings.Section>\n\n <Settings.Section title={t('trigger-picker.title')} description={t('trigger-picker.description')}>\n <Settings.Panel>\n <TriggerSection db={db} automation={subject} trigger={trigger} />\n {space && trigger && <TriggerTestingSection space={space} trigger={trigger} />}\n </Settings.Panel>\n </Settings.Section>\n\n <Settings.Section title={t('action.title')} description={t('action.description')}>\n <Settings.Panel>\n <ActionSection db={db} automation={subject} trigger={trigger} />\n </Settings.Panel>\n </Settings.Section>\n </Settings.Viewport>\n );\n};\n\n//\n// General (name + enabled)\n//\n\nconst GeneralForm = Schema.Struct({\n name: Schema.String.pipe(Schema.annotations({ title: 'Name' }), Schema.optional),\n enabled: Schema.Boolean.annotations({ title: 'Enabled' }),\n});\ntype GeneralFormValues = Schema.Schema.Type<typeof GeneralForm>;\n\n/**\n * Top-level metadata: name plus the enabled toggle. The automation has no `enabled` field of its own —\n * enabling it toggles its trigger's `enabled` (the flag the dispatcher reads), so the switch is disabled\n * until both a trigger and an action exist.\n */\nexport const GeneralSection = ({\n automation,\n trigger,\n}: {\n automation: Automation.Automation;\n trigger?: Trigger.Trigger;\n}) => {\n const { defaultValues, fieldMap, handleValuesChanged } = useGeneralForm(automation, trigger);\n\n return (\n <Form.Root\n key={trigger?.id ?? 'new'}\n schema={GeneralForm}\n defaultValues={defaultValues}\n fieldMap={fieldMap}\n onValuesChanged={handleValuesChanged}\n >\n <Form.Content>\n <Form.FieldSet />\n </Form.Content>\n </Form.Root>\n );\n};\n\n/** Enabled switch field; disabled (with a hint) until the automation has both a trigger and an action. */\nconst EnabledField = ({\n canEnable,\n messageKey,\n ...props\n}: FormFieldRendererProps & { canEnable: boolean; messageKey?: string }) => {\n const { t } = useTranslation(meta.profile.key);\n return (\n <div className='flex items-center gap-2 pt-form-padding'>\n <Input.Root>\n <Input.Switch\n disabled={!canEnable}\n checked={Boolean(props.getValue()) && canEnable}\n onCheckedChange={(checked) => props.onValueChange(props.type, checked)}\n />\n </Input.Root>\n <span className='text-sm'>{props.label}</span>\n {!canEnable && messageKey && <span className='text-sm text-description'>{t(messageKey)}</span>}\n </div>\n );\n};\n\n//\n// Trigger testing section\n//\n\ntype TriggerTestingSectionProps = {\n space: Space;\n trigger: Trigger.Trigger;\n};\n\nconst TESTING_ITEM = { id: 'testing' };\n\n/**\n * Collapsed \"Testing\" section within the Trigger panel. Provides kind-specific manual\n * affordances: force-run for timer triggers, cursor reset for feed triggers.\n * Not rendered for trigger kinds with no applicable action (email, webhook, subscription).\n */\nconst TriggerTestingSection = ({ space, trigger }: TriggerTestingSectionProps) => {\n const { t } = useTranslation(meta.profile.key);\n const client = useClient();\n const processManagerRuntime = useProcessManagerRuntime();\n const [properties] = useObject(space.properties);\n const computeEnvironment = properties.computeEnvironment ?? 'local';\n const functionsServiceClient = useMemo(() => FunctionsServiceClient.fromClient(client), [client]);\n\n const spec = Obj.getSnapshot(trigger).spec;\n const kind = spec?.kind;\n\n const cursor = kind === 'feed' ? Obj.getKeys(trigger, KEY_FEED_CURSOR).at(0)?.id : undefined;\n\n const handleForceRun = useCallback(async () => {\n if (computeEnvironment === 'disabled') {\n return;\n }\n if (computeEnvironment === 'local') {\n await processManagerRuntime\n .runPromise(\n Effect.gen(function* () {\n const dispatcher = yield* TriggerDispatcher;\n yield* dispatcher.invokeTrigger({\n trigger,\n event: { tick: Date.now() } satisfies TriggerEvent.TimerEvent,\n });\n }).pipe(Effect.provide(ServiceResolver.provide({ space: space.id }, TriggerDispatcher))),\n )\n .catch((error: unknown) => log.catch(error));\n return;\n }\n await functionsServiceClient\n .forceRunCronTrigger(Context.default(), space.id, trigger.id)\n .catch((error: unknown) => log.catch(error));\n }, [computeEnvironment, functionsServiceClient, processManagerRuntime, space.id, trigger]);\n\n const handleResetCursor = useCallback(async () => {\n Obj.update(trigger, (trigger) => {\n Obj.deleteKeys(trigger, KEY_FEED_CURSOR);\n });\n await space.db.flush({ indexes: true });\n }, [space.db, trigger]);\n\n if (kind !== 'timer' && kind !== 'feed') {\n return null;\n }\n\n return (\n <Accordion.Root items={[TESTING_ITEM]}>\n {({ items }) =>\n items.map((item) => (\n <Accordion.Item key={item.id} item={item}>\n <Accordion.ItemHeader>{t('testing.title')}</Accordion.ItemHeader>\n <Accordion.ItemBody>\n {kind === 'timer' && (\n <IconButton\n icon='ph--play--regular'\n label={t('force-run.label')}\n disabled={computeEnvironment === 'disabled'}\n onClick={handleForceRun}\n />\n )}\n {kind === 'feed' && (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <IconButton\n icon='ph--arrow-clockwise--regular'\n label={t('reset-cursor.label')}\n disabled={!cursor}\n />\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content side='top'>\n <DropdownMenu.Viewport>\n <DropdownMenu.Item onClick={handleResetCursor}>\n {t('reset-cursor-confirm.label')}\n </DropdownMenu.Item>\n </DropdownMenu.Viewport>\n <DropdownMenu.Arrow />\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n )}\n </Accordion.ItemBody>\n </Accordion.Item>\n ))\n }\n </Accordion.Root>\n );\n};\n\n//\n// Action\n//\n\n// Two-part action form: pick a kind (operation | routine), then the specific object (a RefField object\n// picker for that type). Modeled as a top-level discriminated union so the Form renders the kind select and\n// the chosen kind's picker as one flat field set (no nested, bordered sub-fieldset). Selecting a routine\n// binds it as input to the \"Run Routine\" (AgentPrompt) operation, so the runnable a trigger points at is\n// always an Operation.\nconst OperationAction = Schema.Struct({\n kind: Schema.Literal('operation'),\n operation: Ref.Ref(Operation.PersistentOperation).pipe(Schema.annotations({ title: 'Operation' }), Schema.optional),\n});\nconst RoutineAction = Schema.Struct({\n kind: Schema.Literal('routine'),\n routine: Ref.Ref(Routine.Routine).pipe(Schema.annotations({ title: 'Routine' }), Schema.optional),\n});\nconst ActionForm = Schema.Union(OperationAction, RoutineAction);\ntype ActionFormValues = Schema.Schema.Type<typeof ActionForm>;\n\n// Flat view of the form values (see `TriggerFormInput`): reach the variant fields that `Partial<T>` drops.\ntype ActionFormInput = {\n readonly kind?: 'operation' | 'routine';\n readonly operation?: Ref.Ref<Operation.PersistentOperation>;\n readonly routine?: Ref.Ref<Routine.Routine>;\n};\n\nexport const ActionSection = ({\n db,\n automation,\n trigger,\n}: {\n db: Database.Database;\n automation: Automation.Automation;\n trigger?: Trigger.Trigger;\n}) => {\n const { defaultValues, fieldMap, handleValuesChanged, selectedOperation } = useActionForm(db, automation, trigger);\n\n return (\n <div className='flex flex-col gap-2'>\n <Form.Root\n // Remount when the bound trigger changes so the uncontrolled form picks up its action.\n key={trigger?.id ?? 'new'}\n schema={ActionForm}\n defaultValues={defaultValues}\n db={db}\n fieldMap={fieldMap}\n onValuesChanged={handleValuesChanged}\n >\n <Form.Content>\n <Form.FieldSet />\n </Form.Content>\n </Form.Root>\n\n {/* Bind the operation's inputs (e.g. an object ref) once a trigger exists — input lives on the trigger;\n a ref set here is what associates a non-feed object via `automationsForObject`. */}\n {trigger && selectedOperation && <ActionInputEditor db={db} operation={selectedOperation} trigger={trigger} />}\n </div>\n );\n};\n\nconst ActionInputEditor = ({\n db,\n operation,\n trigger,\n}: {\n db: Database.Database;\n operation: Operation.PersistentOperation;\n trigger: Trigger.Trigger;\n}) => {\n const { t } = useTranslation(meta.profile.key);\n const effectSchema = useMemo(\n () => (operation.inputSchema ? JsonSchema.toEffectSchema(operation.inputSchema) : undefined),\n [operation.inputSchema],\n );\n const propertyCount = operation.inputSchema?.properties ? Object.keys(operation.inputSchema.properties).length : 0;\n // Read the current input once per operation (key remounts the uncontrolled Form when the action changes).\n const defaultValues = useMemo(\n () => ({ ...((trigger.input as Record<string, unknown>) ?? {}) }),\n [operation.id, trigger],\n );\n const handleValuesChanged = useCallback(\n (values: Record<string, unknown>) => {\n Obj.update(trigger, (trigger) => {\n trigger.input = values;\n });\n },\n [trigger],\n );\n\n if (!effectSchema || propertyCount === 0) {\n return null;\n }\n\n return (\n <>\n <Form.Label label={t('action-input.label')} standalone />\n <Form.Root\n key={operation.id}\n schema={effectSchema}\n defaultValues={defaultValues}\n db={db}\n onValuesChanged={handleValuesChanged}\n >\n <Form.FieldSet />\n </Form.Root>\n </>\n );\n};\n\n//\n// Trigger\n//\n\n// Scoped trigger form: timer (cron) or feed, modeled as a top-level discriminated union so the Form renders\n// the kind select and the chosen kind's field as one flat field set (no nested, bordered sub-fieldset). The\n// feed field carries ParentLabelAnnotation so the built-in RefField labels feed options by their parent\n// object (e.g. the mailbox) — configured per field via the annotation rather than a hard-coded option mapper.\nconst TimerSpecForm = Schema.Struct({\n kind: Schema.Literal('timer'),\n cron: Schema.String.pipe(Schema.annotations({ title: 'Schedule (cron)' }), Schema.optional),\n});\nconst FeedSpecForm = Schema.Struct({\n kind: Schema.Literal('feed'),\n feed: Ref.Ref(Feed.Feed).pipe(\n ParentLabelAnnotation.set(true),\n Schema.annotations({ title: 'Feed' }),\n Schema.optional,\n ),\n});\nconst TriggerForm = Schema.Union(TimerSpecForm, FeedSpecForm);\ntype TriggerFormValues = Schema.Schema.Type<typeof TriggerForm>;\n\n// Flat view of the form values: `Partial<TriggerFormValues>` collapses a discriminated union to its common\n// key alone (`kind`), so reach the variant fields through this all-optional shape instead. `Partial<T>` is\n// assignable to it, so handlers/helpers can accept the Form's value verbatim and still read `cron`/`feed`.\ntype TriggerFormInput = {\n readonly kind?: 'timer' | 'feed';\n readonly cron?: string;\n readonly feed?: Ref.Ref<Feed.Feed>;\n};\n\n/** Project a trigger spec onto the form's discriminated-union members. */\nconst triggerFormValues = (spec?: Trigger.Spec): TriggerFormInput =>\n spec?.kind === 'feed'\n ? { kind: 'feed', feed: spec.feed }\n : { kind: 'timer', cron: spec?.kind === 'timer' ? spec.cron : '' };\n\n// Fallback cron used when no schedule has been set yet.\nconst DEFAULT_TIMER_CRON = toCron(FrequencyDefaults.daily);\n\n// Build a trigger spec from the form's values. Returned as just the two specs we construct (not the full\n// `Trigger.Spec` union) so the subscription spec's deep readonly query AST never enters the type and the\n// result stays assignable to the mutable `trigger.spec`.\nconst triggerFormSpec = (values: TriggerFormInput): Trigger.TimerSpec | Trigger.FeedSpec =>\n values.kind === 'feed' ? { kind: 'feed', feed: values.feed } : Trigger.specTimer(values.cron || DEFAULT_TIMER_CRON);\n\nexport const TriggerSection = ({\n db,\n automation,\n trigger,\n}: {\n db: Database.Database;\n automation: Automation.Automation;\n trigger?: Trigger.Trigger;\n}) => {\n const { defaultValues, fieldMap, handleValuesChanged } = useTriggerForm(db, automation, trigger);\n\n return (\n <Form.Root\n // Remount when the bound trigger changes so the uncontrolled form picks up its spec.\n key={trigger?.id ?? 'new'}\n schema={TriggerForm}\n defaultValues={defaultValues}\n db={db}\n fieldMap={fieldMap}\n onValuesChanged={handleValuesChanged}\n >\n <Form.Content>\n <Form.FieldSet />\n </Form.Content>\n </Form.Root>\n );\n};\n\n//\n// Inline form (companion)\n//\n\n/** Compact section heading for the inline form — just a small title, no description (cf. Settings.Section). */\nconst InlineSection = ({ title, children }: { title: string; children: ReactNode }) => (\n <div className='flex flex-col gap-1'>\n <h3 className='pli-1 text-sm font-medium text-description'>{title}</h3>\n <Settings.Panel>{children}</Settings.Panel>\n </div>\n);\n\n/**\n * Compact inline view used in the Automation companion. Renders the same three sections as the full article\n * (General / Trigger / Action) with condensed headings and no descriptions or scrolling Settings.Viewport.\n */\nexport const AutomationInlineForm = ({\n automation,\n db,\n}: {\n automation: Automation.Automation;\n db: Database.Database;\n}) => {\n const { t } = useTranslation(meta.profile.key);\n const trigger = usePrimaryTrigger(automation);\n\n return (\n <div className='flex flex-col gap-3'>\n <InlineSection title={t('general.title')}>\n <GeneralSection automation={automation} trigger={trigger} />\n </InlineSection>\n <InlineSection title={t('trigger-picker.title')}>\n <TriggerSection db={db} automation={automation} trigger={trigger} />\n </InlineSection>\n <InlineSection title={t('action.title')}>\n <ActionSection db={db} automation={automation} trigger={trigger} />\n </InlineSection>\n </div>\n );\n};\n\n//\n// Cron field\n//\n\n/** Renders the CronBuilder with a live cronstrue description below it. */\nconst CronField = (props: FormFieldRendererProps) => {\n const existingCron = props.getValue() as string | undefined;\n const initialSpec = useMemo(() => (existingCron ? fromCron(existingCron) : FrequencyDefaults.daily), []);\n const [description, setDescription] = useState(() => describeCron(existingCron ?? toCron(initialSpec)));\n\n const handleChange = useCallback(\n (spec: CronSpecType, cron: string) => {\n setDescription(describeCron(cron));\n props.onValueChange(props.type, cron);\n },\n [props.type, props.onValueChange],\n );\n\n return (\n <div className='flex flex-col gap-1 mbs-2'>\n <CronBuilder value={initialSpec} onChange={handleChange} />\n <p className='text-sm text-description pli-1 text-right'>{description}</p>\n </div>\n );\n};\n\nCronField.displayName = 'AutomationArticle.CronField';\n\n//\n// Hooks\n//\n\n/** Subscribe to the automation and derive its primary (first) trigger. */\nconst usePrimaryTrigger = (automation: Automation.Automation): Trigger.Trigger | undefined => {\n const [snapshot] = useObject(automation);\n return useMemo(() => {\n for (const ref of snapshot.triggers) {\n const target = ref.target;\n if (Obj.instanceOf(Trigger.Trigger, target)) {\n return target;\n }\n }\n return undefined;\n }, [snapshot.triggers]);\n};\n\n/** Form state for the General section: the name plus an enabled toggle that writes through to the trigger. */\nconst useGeneralForm = (automation: Automation.Automation, trigger?: Trigger.Trigger) => {\n const [auto, updateAuto] = useObject(automation);\n const canEnable = Boolean(trigger && auto.runnable);\n const messageKey = !trigger\n ? 'add-trigger-first.message'\n : !auto.runnable\n ? 'select-action-first.message'\n : undefined;\n\n const fieldMap = useMemo<FormFieldMap>(\n () => ({ enabled: (props) => <EnabledField {...props} canEnable={canEnable} messageKey={messageKey} /> }),\n [canEnable, messageKey],\n );\n\n // Read once per trigger identity; the uncontrolled form owns edits after mount.\n const defaultValues = useMemo<Partial<GeneralFormValues>>(\n () => ({ name: auto.name, enabled: (trigger?.enabled ?? false) && canEnable }),\n [automation, trigger],\n );\n\n const handleValuesChanged = useCallback(\n (values: Partial<GeneralFormValues>) => {\n updateAuto((automation) => {\n automation.name = values.name;\n });\n if (trigger && canEnable) {\n Obj.update(trigger, (trigger) => {\n trigger.enabled = values.enabled ?? false;\n });\n }\n },\n [updateAuto, trigger, canEnable],\n );\n\n return { defaultValues, fieldMap, handleValuesChanged };\n};\n\n/** Form state for the Action section: pick an operation|routine and bind it to the trigger's function/input. */\nconst useActionForm = (db: Database.Database, automation: Automation.Automation, trigger?: Trigger.Trigger) => {\n const { t } = useTranslation(meta.profile.key);\n const [auto, updateAuto] = useObject(automation);\n // Query by typename DXN so results stay untyped (`Entity.Any[]`), as RefField.useResults expects.\n const operations = useQuery(\n db,\n // Include registry operations (built-in / plugin-provided) alongside space-resident ones.\n Query.select(Filter.type(DXN.make(Type.getTypename(Operation.PersistentOperation)))).from(\n Scope.space(),\n Scope.registry(),\n ),\n );\n const routines = useQuery(\n db,\n Query.select(Filter.type(DXN.make(Type.getTypename(Routine.Routine)))).from(Scope.space(), Scope.registry()),\n );\n const runRoutineOp = useMemo(() => findRunRoutineOp(operations), [operations]);\n const boundRoutine = getBoundRoutine(trigger);\n const runnableTarget = auto.runnable?.target;\n\n const kindOptions = useMemo(\n () => [\n { value: 'operation', label: t('action-kind.operation.label') },\n { value: 'routine', label: t('action-kind.routine.label') },\n ],\n [t],\n );\n const fieldMap = useMemo<FormFieldMap>(\n () => ({\n kind: (props) => <SelectField {...props} options={kindOptions} />,\n // Custom useResults so pickers draw from the already-queried sets (space + registry for\n // operations; space-only for routines) rather than RefField's default typename query.\n operation: (props) => <RefField {...props} db={db} useResults={() => operations} />,\n routine: (props) => <RefField {...props} db={db} useResults={() => routines} />,\n }),\n [kindOptions, operations, routines, db],\n );\n\n // Read the current action once per trigger identity (the uncontrolled form owns edits after mount).\n const defaultValues = useMemo<Partial<ActionFormValues>>(() => {\n if (boundRoutine) {\n return { kind: 'routine', routine: Ref.make(boundRoutine) };\n }\n if (auto.runnable && Obj.instanceOf(Operation.PersistentOperation, runnableTarget)) {\n return { kind: 'operation', operation: auto.runnable };\n }\n return { kind: 'operation' };\n }, [automation, trigger]);\n\n const handleValuesChanged = useCallback(\n (values: Partial<ActionFormValues>) => {\n const action: ActionFormInput = values;\n if (action.kind === 'routine') {\n const routineRef = action.routine;\n if (!routineRef || !runRoutineOp) {\n return;\n }\n updateAuto((automation) => {\n automation.runnable = Ref.make(runRoutineOp);\n });\n if (trigger) {\n Obj.update(trigger, (trigger) => {\n trigger.function = Ref.make(runRoutineOp);\n trigger.input = { prompt: routineRef, input: {} };\n });\n }\n } else if (action.kind === 'operation' && action.operation) {\n const operationRef = action.operation;\n updateAuto((automation) => {\n automation.runnable = operationRef;\n });\n if (trigger) {\n Obj.update(trigger, (trigger) => {\n trigger.function = operationRef;\n trigger.input = undefined;\n });\n }\n }\n },\n [runRoutineOp, trigger, updateAuto],\n );\n\n // The directly-selected operation (not the routine-bound AgentPrompt case); its input schema drives the editor.\n const selectedOperation =\n !boundRoutine && Obj.instanceOf(Operation.PersistentOperation, runnableTarget) ? runnableTarget : undefined;\n\n return { defaultValues, fieldMap, handleValuesChanged, selectedOperation };\n};\n\n/** Form state for the Trigger section: the timer|feed spec, plus create-on-first-edit and remove handlers. */\nconst useTriggerForm = (db: Database.Database, automation: Automation.Automation, trigger?: Trigger.Trigger) => {\n const { t } = useTranslation(meta.profile.key);\n const kindOptions = useMemo(\n () => [\n { value: 'timer', label: t('trigger-kind.timer.label') },\n { value: 'feed', label: t('trigger-kind.feed.label') },\n ],\n [t],\n );\n const fieldMap = useMemo<FormFieldMap>(\n () => ({\n kind: (props) => <SelectField {...props} options={kindOptions} />,\n cron: (props) => <CronField {...props} />,\n }),\n [kindOptions],\n );\n // Read once per trigger identity (uncontrolled Form); default to an empty timer spec.\n const defaultValues = useMemo<Partial<TriggerFormValues>>(() => triggerFormValues(trigger?.spec), [trigger]);\n\n const handleValuesChanged = useCallback(\n (values: Partial<TriggerFormValues>) => {\n const spec = triggerFormSpec(values);\n if (trigger) {\n Obj.update(trigger, (trigger) => {\n trigger.spec = spec;\n });\n } else {\n // Create the trigger on first edit; `function` is wired by the action section, and it stays disabled\n // until an action is set, so a function-less trigger never dispatches. The trigger is owned by the\n // automation (it is only reachable via it), so it is parented and cascade-deletes with the automation.\n const created = db.add(Trigger.make({ function: automation.runnable, enabled: false, spec }));\n Obj.setParent(created, automation);\n Obj.update(automation, (automation) => {\n automation.triggers = [...automation.triggers, Ref.make(created)];\n });\n }\n },\n [db, automation, trigger],\n );\n\n return { defaultValues, fieldMap, handleValuesChanged };\n};\n\n//\n// Helpers\n//\n\n/** Read back the routine bound into a trigger's AgentPrompt input, if any. */\nconst getBoundRoutine = (trigger?: Trigger.Trigger): Routine.Routine | undefined => {\n const prompt = (trigger?.input as { prompt?: Ref.Ref<unknown> } | undefined)?.prompt;\n const target = Ref.isRef(prompt) ? prompt.target : undefined;\n return Obj.instanceOf(Routine.Routine, target) ? target : undefined;\n};\n\n/** Find the persisted \"Run Routine\" (AgentPrompt) operation by its DXN, avoiding a hard assistant-toolkit dep. */\nconst findRunRoutineOp = (operations: Entity.Any[]): Operation.PersistentOperation | undefined => {\n for (const op of operations) {\n if (!Obj.instanceOf(Operation.PersistentOperation, op)) {\n continue;\n }\n // Control-flow narrowed: op is Entity.Any & Operation.PersistentOperation.\n try {\n if (Operation.deserialize(op).meta.key.toString().includes(RUN_ROUTINE_DXN)) {\n return op;\n }\n } catch {\n // Not a valid/deserializable operation or key does not match.\n }\n }\n return undefined;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["Effect", "Schema", "React", "useCallback", "useMemo", "useState", "useProcessManagerRuntime", "Operation", "Routine", "ServiceResolver", "Trigger", "Context", "Feed", "Filter", "JsonSchema", "Obj", "Query", "Ref", "Scope", "Type", "KEY_FEED_CURSOR", "TriggerDispatcher", "FunctionsServiceClient", "DXN", "log", "useClient", "getSpace", "useObject", "useQuery", "DropdownMenu", "IconButton", "Input", "useTranslation", "Form", "RefField", "SelectField", "Settings", "Accordion", "ParentLabelAnnotation", "meta", "RUN_ROUTINE_DXN", "useTranslation", "db", "subject", "trigger", "usePrimaryTrigger", "space", "getSpace", "automation", "title", "optional", "enabled", "Schema", "Form", "key", "id", "GeneralForm", "defaultValues", "fieldMap", "onValuesChanged", "EnabledField", "div", "className", "Input", "disabled", "canEnable", "Boolean", "props", "onCheckedChange", "span", "messageKey", "t", "TESTING_ITEM", "client", "useClient", "processManagerRuntime", "useProcessManagerRuntime", "properties", "useObject", "computeEnvironment", "functionsServiceClient", "useMemo", "FunctionsServiceClient", "cursor", "kind", "Obj", "getKeys", "handleForceRun", "TriggerDispatcher", "invokeTrigger", "event", "Effect", "error", "catch", "KEY_FEED_CURSOR", "flush", "items", "item", "icon", "onClick", "asChild", "IconButton", "side", "DropdownMenu", "Viewport", "Item", "Arrow", "operation", "Operation", "PersistentOperation", "RoutineAction", "routine", "Routine", "ActionForm", "handleValuesChanged", "selectedOperation", "ActionInputEditor", "inputSchema", "propertyCount", "values", "standalone", "effectSchema", "cron", "annotations", "FeedSpecForm", "feed", "ParentLabelAnnotation", "TriggerForm", "Trigger", "TriggerSection", "h3", "InlineSection", "GeneralSection", "ActionSection", "existingCron", "FrequencyDefaults", "daily", "setDescription", "handleChange", "useCallback", "describeCron", "onValueChange", "type", "CronBuilder", "value", "initialSpec", "description", "CronField", "displayName", "ref", "snapshot", "target", "instanceOf", "updateAuto", "operations", "useQuery", "routines", "runRoutineOp", "findRunRoutineOp", "kindOptions", "useResults", "auto", "routineRef", "prompt", "input", "runnable", "operationRef", "undefined", "update", "spec", "setParent", "triggers", "make", "created"]
7
+ }
@@ -14,7 +14,7 @@ var TriggerTemplate = Schema.Union(Schema.Struct({
14
14
  feed: Schema.Any
15
15
  }));
16
16
  (function(AutomationAction2) {
17
- class CreateTriggerFromTemplate2 extends Schema.TaggedClass()(`${meta.id}.action.create-trigger-from-template`, {
17
+ class CreateTriggerFromTemplate2 extends Schema.TaggedClass()(`${meta.profile.key}.action.create-trigger-from-template`, {
18
18
  input: Schema.Struct({
19
19
  db: Database.Database,
20
20
  template: TriggerTemplate,
@@ -82,11 +82,13 @@ var make = (props) => Obj.make(Automation, props);
82
82
  // src/types/AutomationCapabilities.ts
83
83
  var AutomationCapabilities_exports = {};
84
84
  __export(AutomationCapabilities_exports, {
85
+ AgentCompletionGuard: () => AgentCompletionGuard,
85
86
  AgentDelegationStrategy: () => AgentDelegationStrategy,
86
87
  Template: () => Template
87
88
  });
88
89
  import { Capability } from "@dxos/app-framework";
89
90
  var AgentDelegationStrategy = Capability.make("org.dxos.plugin.automation.capability.agentDelegationStrategy");
91
+ var AgentCompletionGuard = Capability.make("org.dxos.plugin.automation.capability.agentCompletionGuard");
90
92
  var Template = Capability.make("org.dxos.plugin.automation.capability.template");
91
93
 
92
94
  // src/types/AutomationOperation.ts
@@ -102,7 +104,7 @@ import { Operation as Operation2 } from "@dxos/compute";
102
104
  import { Database as Database2, DXN as DXN2, Obj as Obj2 } from "@dxos/echo";
103
105
  import { EID as _EchoURIReference } from "@dxos/keys";
104
106
  import { meta as meta2 } from "#meta";
105
- var makeKey = (name) => DXN2.make(`${meta2.id}.operation.${name}`);
107
+ var makeKey = (name) => DXN2.make(`${meta2.profile.key}.operation.${name}`);
106
108
  var CreateTriggerFromTemplate = Operation2.make({
107
109
  meta: {
108
110
  key: makeKey("createTriggerFromTemplate"),
@@ -154,4 +156,4 @@ export {
154
156
  AutomationCapabilities_exports,
155
157
  AutomationOperation_exports
156
158
  };
157
- //# sourceMappingURL=chunk-GARB7S5R.mjs.map
159
+ //# sourceMappingURL=chunk-YHK7FWGV.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/types/schema.ts", "../../../src/types/Automation.ts", "../../../src/types/Runnable.ts", "../../../src/types/AutomationCapabilities.ts", "../../../src/types/AutomationOperation.ts"],
4
+ "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Schema from 'effect/Schema';\n\nimport { Database } from '@dxos/echo';\n\nimport { meta } from '#meta';\n\nexport const TriggerTemplate = Schema.Union(\n Schema.Struct({ type: Schema.Literal('timer'), cron: Schema.String }),\n Schema.Struct({ type: Schema.Literal('feed'), feed: Schema.Any }),\n);\n\nexport namespace AutomationAction {\n export class CreateTriggerFromTemplate extends Schema.TaggedClass<CreateTriggerFromTemplate>()(\n `${meta.profile.key}.action.create-trigger-from-template`,\n {\n input: Schema.Struct({\n db: Database.Database,\n template: TriggerTemplate,\n enabled: Schema.optional(Schema.Boolean),\n // TODO(wittjosiah): Improve how this lookup is done.\n scriptName: Schema.optional(Schema.String),\n input: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),\n }),\n output: Schema.Void,\n },\n ) {}\n}\n", "//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nimport { DXN, Annotation, Obj, Ref, Type } from '@dxos/echo';\nimport { LabelAnnotation } from '@dxos/echo/internal';\n\nimport * as Runnable from './Runnable';\n\n/**\n * User-facing automation: a thin aggregate of an action (`runnable`) and the triggers that fire it.\n * App-level only — EDGE stays unaware of it (triggers point directly at the runnable).\n */\nexport const Automation = Schema.Struct({\n name: Schema.String.pipe(Schema.optional),\n description: Schema.String.pipe(Schema.optional),\n /**\n * The action to run. A trigger's `function` Ref points directly at this (so EDGE/the dispatcher can run\n * it). `Runnable` is the type seam — currently just Operation; see Runnable.ts.\n */\n runnable: Ref.Ref(Runnable.Runnable).pipe(Schema.optional),\n /**\n * Explicit membership, bi-directional with `trigger.function → runnable`. Required (not derived by query)\n * because the runnable may be a shared registry operation referenced by multiple automations, which would\n * conflate triggers. MVP enforces length <= 1.\n *\n * Typed as `Obj.Unknown` (not `Trigger`) to avoid pulling query-AST types into the emitted declaration —\n * the same reason `Trigger.function` uses `Obj.Unknown`. Resolve and narrow with `Obj.instanceOf(Trigger)`.\n */\n triggers: Schema.Array(Ref.Ref(Obj.Unknown)),\n}).pipe(\n LabelAnnotation.set(['name']),\n Annotation.IconAnnotation.set({ icon: 'ph--lightning--regular', hue: 'amber' }),\n Type.makeObject(DXN.make('org.dxos.type.automation', '0.1.0')),\n);\n\nexport type Automation = Type.InstanceType<typeof Automation>;\n\nexport const instanceOf = (value: unknown): value is Automation => Obj.instanceOf(Automation, value);\n\nexport const make = (props: Obj.MakeProps<typeof Automation>) => Obj.make(Automation, props);\n", "//\n// Copyright 2026 DXOS.org\n//\n\n// @import-as-namespace\n\nimport { Operation } from '@dxos/compute';\n\n// TODO(wittjosiah): Currently just Operation. Widen to a union (Operation | ComputeGraph | …) once the\n// dispatcher/EDGE can run non-Operation runnables as a Process; factor down to @dxos/compute once\n// ComputeGraph's type moves there. Routines are NOT a direct member — they run via the AgentPrompt\n// operation (bound as input).\nexport type Runnable = Operation.PersistentOperation;\nexport const Runnable = Operation.PersistentOperation;\n", "//\n// Copyright 2026 DXOS.org\n//\n\nimport type * as Effect from 'effect/Effect';\n\nimport { Capability } from '@dxos/app-framework';\nimport type { Database, Obj } from '@dxos/echo';\nimport type { CompletionGuard, DelegationStrategy } from '@dxos/functions-runtime';\n\nimport * as Automation from './Automation';\n\n/**\n * Optional supervisor strategy for the agent chat service. When contributed (by a plugin that knows\n * the agent/plan model, e.g. plugin-assistant), the conversational agent delegates outstanding work\n * to sub-agents and folds their results back into the conversation. Consumed by the AgentService\n * LayerSpec; absent by default (a plain conversational agent).\n */\nexport const AgentDelegationStrategy = Capability.make<DelegationStrategy>(\n 'org.dxos.plugin.automation.capability.agentDelegationStrategy',\n);\n\n/**\n * Optional plan-completion guard for the agent chat service. When contributed, the agent process\n * runs an ephemeral stop/continue check before succeeding if open plan tasks remain.\n */\nexport const AgentCompletionGuard = Capability.make<CompletionGuard>(\n 'org.dxos.plugin.automation.capability.agentCompletionGuard',\n);\n\n/**\n * An automation template contributed by a plugin. The create dialog and the per-object \"Automations\"\n * companion list contributed templates (`Capability.getAll(AutomationCapabilities.Template)`) and run the\n * chosen template's `scaffold` to build the automation.\n */\nexport type Template = {\n /** Stable id (e.g. 'org.dxos.automation.blank'). */\n id: string;\n /** Human-readable label shown in the picker. */\n label: string;\n /** Optional Phosphor icon name. */\n icon?: string;\n /**\n * Whether this template applies to the given companion subject. The subject is the object whose\n * \"Automations\" companion is open, or undefined in the global create dialog. Templates that need a\n * specific subject (e.g. a feed-bearing Mailbox) gate themselves here. Defaults to always-applies.\n */\n appliesTo?: (subject?: Obj.Unknown) => boolean;\n /**\n * Build the Automation from the user's input. The returned Automation is added to the database by the\n * create flow; any auxiliary objects (runnable, triggers) must be added by the scaffold itself via\n * Database.Service. `subject` is set when scaffolding from an object's companion.\n */\n scaffold: (ctx: {\n name?: string;\n subject?: Obj.Unknown;\n }) => Effect.Effect<Automation.Automation, Error, Database.Service>;\n};\n\nexport const Template = Capability.make<Template>('org.dxos.plugin.automation.capability.template');\n", "//\n// Copyright 2025 DXOS.org\n//\n\n// @import-as-namespace\n\nimport * as Schema from 'effect/Schema';\n\nimport { Capability } from '@dxos/app-framework';\nimport { Operation } from '@dxos/compute';\nimport { Database, DXN, Obj } from '@dxos/echo';\n// Value-side `EID` import keeps TS declaration emit portable — `TriggerTemplate`\n// references `EID.Schema` and the inferred `CreateTriggerFromTemplate` type\n// otherwise needs a transitive `@dxos/keys` import that's hard for d.ts emit to surface.\nimport { EID as _EchoURIReference } from '@dxos/keys';\n\nimport { meta } from '#meta';\n\nimport { TriggerTemplate } from './schema';\nexport { _EchoURIReference };\n\nconst makeKey = (name: string) => DXN.make(`${meta.profile.key}.operation.${name}`);\n\nexport const CreateTriggerFromTemplate = Operation.make({\n meta: {\n key: makeKey('createTriggerFromTemplate'),\n name: 'Create Trigger From Template',\n icon: 'ph--lightning--regular',\n },\n services: [Capability.Service],\n input: Schema.Struct({\n db: Database.Database,\n template: TriggerTemplate,\n enabled: Schema.optional(Schema.Boolean),\n scriptName: Schema.optional(Schema.String),\n input: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),\n }),\n output: Schema.Void,\n});\n\n// The single creation entrypoint for every path (create dialog, companion, sidebar) so placement and\n// ownership are established in one place. Output mirrors `SpaceCapabilities.CreateObjectResult`.\nexport const CreateAutomation = Operation.make({\n meta: {\n key: makeKey('createAutomation'),\n name: 'Create Automation',\n icon: 'ph--lightning--regular',\n },\n services: [Capability.Service],\n input: Schema.Struct({\n db: Database.Database,\n templateId: Schema.String,\n name: Schema.optional(Schema.String),\n subject: Schema.optional(Obj.Unknown),\n }),\n output: Schema.Struct({\n id: Schema.String,\n subject: Schema.Array(Schema.String),\n object: Obj.Unknown,\n }),\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["Schema", "Database", "meta", "TriggerTemplate", "Union", "Struct", "type", "Literal", "cron", "String", "feed", "Any", "AutomationAction", "CreateTriggerFromTemplate", "TaggedClass", "profile", "key", "input", "db", "template", "enabled", "optional", "Boolean", "scriptName", "Record", "value", "output", "Void", "Schema", "DXN", "Annotation", "Obj", "Ref", "Type", "LabelAnnotation", "Operation", "Runnable", "PersistentOperation", "Automation", "Struct", "name", "String", "pipe", "optional", "description", "runnable", "Ref", "Runnable", "triggers", "Array", "Obj", "Unknown", "LabelAnnotation", "set", "Annotation", "IconAnnotation", "icon", "hue", "Type", "makeObject", "DXN", "make", "instanceOf", "value", "props", "Capability", "AgentDelegationStrategy", "make", "AgentCompletionGuard", "Template", "Schema", "Capability", "Operation", "Database", "DXN", "Obj", "EID", "_EchoURIReference", "meta", "makeKey", "name", "DXN", "make", "meta", "profile", "key", "CreateTriggerFromTemplate", "Operation", "icon", "services", "Capability", "Service", "input", "Struct", "db", "Database", "template", "TriggerTemplate", "enabled", "optional", "Boolean", "scriptName", "String", "Record", "value", "Any", "output", "Void", "CreateAutomation", "templateId", "subject", "Obj", "Unknown", "id", "Array", "object"]
7
+ }
@@ -1,3 +1,21 @@
1
+ import {
2
+ CronBuilder,
3
+ CronBuilderSchema,
4
+ CronSpec,
5
+ CustomSpec,
6
+ DailySpec,
7
+ DayOfWeek,
8
+ Frequencies,
9
+ FrequencyDefaults,
10
+ FrequencyLabels,
11
+ HourlySpec,
12
+ MinutelySpec,
13
+ MonthlySpec,
14
+ WeeklySpec,
15
+ describeCron,
16
+ fromCron,
17
+ toCron
18
+ } from "../chunk-HQU5QWF4.mjs";
1
19
  import "../chunk-J5LGTIGS.mjs";
2
20
 
3
21
  // src/components/CreateAutomationPanel/CreateAutomationPanel.tsx
@@ -8,7 +26,7 @@ import { SearchList, useSearchListResults } from "@dxos/react-ui-search";
8
26
  import { meta } from "#meta";
9
27
  import { AutomationCapabilities } from "#types";
10
28
  var CreateAutomationPanel = ({ onCreateObject, templates: templatesProp }) => {
11
- const { t } = useTranslation(meta.id);
29
+ const { t } = useTranslation(meta.profile.key);
12
30
  const capabilityTemplates = useCapabilities(AutomationCapabilities.Template);
13
31
  const templates = templatesProp ?? capabilityTemplates;
14
32
  const sorted = useMemo(() => [
@@ -43,6 +61,22 @@ var CreateAutomationPanel = ({ onCreateObject, templates: templatesProp }) => {
43
61
  }))));
44
62
  };
45
63
  export {
46
- CreateAutomationPanel
64
+ CreateAutomationPanel,
65
+ CronBuilder,
66
+ CronBuilderSchema,
67
+ CronSpec,
68
+ CustomSpec,
69
+ DailySpec,
70
+ DayOfWeek,
71
+ Frequencies,
72
+ FrequencyDefaults,
73
+ FrequencyLabels,
74
+ HourlySpec,
75
+ MinutelySpec,
76
+ MonthlySpec,
77
+ WeeklySpec,
78
+ describeCron,
79
+ fromCron,
80
+ toCron
47
81
  };
48
82
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/components/CreateAutomationPanel/CreateAutomationPanel.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { type SpaceCapabilities } from '@dxos/plugin-space';\nimport { useTranslation } from '@dxos/react-ui';\nimport { SearchList, useSearchListResults } from '@dxos/react-ui-search';\n\nimport { meta } from '#meta';\nimport { AutomationCapabilities } from '#types';\n\nexport type CreateAutomationPanelProps = SpaceCapabilities.CreateObjectCustomPanelProps & {\n /** Optional override (primarily for stories/tests). Defaults to AutomationCapabilities.Template. */\n templates?: AutomationCapabilities.Template[];\n};\n\n/**\n * Create panel for automations: a SearchList picker over contributed templates. Selecting one submits\n * `{ templateId }`; plugin-automation's CreateObjectEntry.createObject resolves the templateId and runs the\n * template's `scaffold`.\n */\nexport const CreateAutomationPanel = ({ onCreateObject, templates: templatesProp }: CreateAutomationPanelProps) => {\n const { t } = useTranslation(meta.id);\n const capabilityTemplates = useCapabilities(AutomationCapabilities.Template);\n const templates = templatesProp ?? capabilityTemplates;\n // The global create dialog has no subject, so subject-required templates (e.g. CRM, which needs a\n // Mailbox) are excluded; they are offered from the relevant object's Automation companion instead.\n const sorted = useMemo(\n () =>\n [...templates]\n .filter((template) => template.appliesTo?.(undefined) ?? true)\n .sort((a, b) => a.label.localeCompare(b.label)),\n [templates],\n );\n const { results, handleSearch } = useSearchListResults({ items: sorted, extract: (template) => template.label });\n\n const handleSelect = useCallback(\n (templateId: string) => {\n void onCreateObject({ templateId });\n },\n [onCreateObject],\n );\n\n return (\n <SearchList.Root onSearch={handleSearch}>\n <SearchList.Input\n classNames='mb-form-gap'\n autoFocus\n data-testid='create-automation-panel.template-input'\n placeholder={t('create-panel.template.placeholder')}\n />\n <SearchList.Viewport>\n {results.map((template) => (\n <SearchList.Item\n key={template.id}\n value={template.id}\n label={template.label}\n icon={template.icon ?? 'ph--lightning--regular'}\n onSelect={() => handleSelect(template.id)}\n />\n ))}\n </SearchList.Viewport>\n </SearchList.Root>\n );\n};\n"],
5
- "mappings": ";;;AAIA,OAAOA,SAASC,aAAaC,eAAe;AAE5C,SAASC,uBAAuB;AAEhC,SAASC,sBAAsB;AAC/B,SAASC,YAAYC,4BAA4B;AAEjD,SAASC,YAAY;AACrB,SAASC,8BAA8B;AAYhC,IAAMC,wBAAwB,CAAC,EAAEC,gBAAgBC,WAAWC,cAAa,MAA8B;AAC5G,QAAM,EAAEC,EAAC,IAAKT,eAAeG,KAAKO,EAAE;AACpC,QAAMC,sBAAsBZ,gBAAgBK,uBAAuBQ,QAAQ;AAC3E,QAAML,YAAYC,iBAAiBG;AAGnC,QAAME,SAASf,QACb,MACE;OAAIS;IACDO,OAAO,CAACC,aAAaA,SAASC,YAAYC,MAAAA,KAAc,IAAA,EACxDC,KAAK,CAACC,GAAGC,MAAMD,EAAEE,MAAMC,cAAcF,EAAEC,KAAK,CAAA,GACjD;IAACd;GAAU;AAEb,QAAM,EAAEgB,SAASC,aAAY,IAAKtB,qBAAqB;IAAEuB,OAAOZ;IAAQa,SAAS,CAACX,aAAaA,SAASM;EAAM,CAAA;AAE9G,QAAMM,eAAe9B,YACnB,CAAC+B,eAAAA;AACC,SAAKtB,eAAe;MAAEsB;IAAW,CAAA;EACnC,GACA;IAACtB;GAAe;AAGlB,SACE,sBAAA,cAACL,WAAW4B,MAAI;IAACC,UAAUN;KACzB,sBAAA,cAACvB,WAAW8B,OAAK;IACfC,YAAW;IACXC,WAAAA;IACAC,eAAY;IACZC,aAAa1B,EAAE,mCAAA;MAEjB,sBAAA,cAACR,WAAWmC,UAAQ,MACjBb,QAAQc,IAAI,CAACtB,aACZ,sBAAA,cAACd,WAAWqC,MAAI;IACdC,KAAKxB,SAASL;IACd8B,OAAOzB,SAASL;IAChBW,OAAON,SAASM;IAChBoB,MAAM1B,SAAS0B,QAAQ;IACvBC,UAAU,MAAMf,aAAaZ,SAASL,EAAE;;AAMpD;",
6
- "names": ["React", "useCallback", "useMemo", "useCapabilities", "useTranslation", "SearchList", "useSearchListResults", "meta", "AutomationCapabilities", "CreateAutomationPanel", "onCreateObject", "templates", "templatesProp", "t", "id", "capabilityTemplates", "Template", "sorted", "filter", "template", "appliesTo", "undefined", "sort", "a", "b", "label", "localeCompare", "results", "handleSearch", "items", "extract", "handleSelect", "templateId", "Root", "onSearch", "Input", "classNames", "autoFocus", "data-testid", "placeholder", "Viewport", "map", "Item", "key", "value", "icon", "onSelect"]
4
+ "sourcesContent": ["//\n// Copyright 2026 DXOS.org\n//\n\nimport React, { useCallback, useMemo } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/ui';\nimport { type SpaceCapabilities } from '@dxos/plugin-space';\nimport { useTranslation } from '@dxos/react-ui';\nimport { SearchList, useSearchListResults } from '@dxos/react-ui-search';\n\nimport { meta } from '#meta';\nimport { AutomationCapabilities } from '#types';\n\nexport type CreateAutomationPanelProps = SpaceCapabilities.CreateObjectCustomPanelProps & {\n /** Optional override (primarily for stories/tests). Defaults to AutomationCapabilities.Template. */\n templates?: AutomationCapabilities.Template[];\n};\n\n/**\n * Create panel for automations: a SearchList picker over contributed templates. Selecting one submits\n * `{ templateId }`; plugin-automation's CreateObjectEntry.createObject resolves the templateId and runs the\n * template's `scaffold`.\n */\nexport const CreateAutomationPanel = ({ onCreateObject, templates: templatesProp }: CreateAutomationPanelProps) => {\n const { t } = useTranslation(meta.profile.key);\n const capabilityTemplates = useCapabilities(AutomationCapabilities.Template);\n const templates = templatesProp ?? capabilityTemplates;\n // The global create dialog has no subject, so subject-required templates (e.g. CRM, which needs a\n // Mailbox) are excluded; they are offered from the relevant object's Automation companion instead.\n const sorted = useMemo(\n () =>\n [...templates]\n .filter((template) => template.appliesTo?.(undefined) ?? true)\n .sort((a, b) => a.label.localeCompare(b.label)),\n [templates],\n );\n const { results, handleSearch } = useSearchListResults({ items: sorted, extract: (template) => template.label });\n\n const handleSelect = useCallback(\n (templateId: string) => {\n void onCreateObject({ templateId });\n },\n [onCreateObject],\n );\n\n return (\n <SearchList.Root onSearch={handleSearch}>\n <SearchList.Input\n classNames='mb-form-gap'\n autoFocus\n data-testid='create-automation-panel.template-input'\n placeholder={t('create-panel.template.placeholder')}\n />\n <SearchList.Viewport>\n {results.map((template) => (\n <SearchList.Item\n key={template.id}\n value={template.id}\n label={template.label}\n icon={template.icon ?? 'ph--lightning--regular'}\n onSelect={() => handleSelect(template.id)}\n />\n ))}\n </SearchList.Viewport>\n </SearchList.Root>\n );\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;AAIA,OAAOA,SAASC,aAAaC,eAAe;AAE5C,SAASC,uBAAuB;AAEhC,SAASC,sBAAsB;AAC/B,SAASC,YAAYC,4BAA4B;AAEjD,SAASC,YAAY;AACrB,SAASC,8BAA8B;AAYhC,IAAMC,wBAAwB,CAAC,EAAEC,gBAAgBC,WAAWC,cAAa,MAA8B;AAC5G,QAAM,EAAEC,EAAC,IAAKT,eAAeG,KAAKO,QAAQC,GAAG;AAC7C,QAAMC,sBAAsBb,gBAAgBK,uBAAuBS,QAAQ;AAC3E,QAAMN,YAAYC,iBAAiBI;AAGnC,QAAME,SAAShB,QACb,MACE;OAAIS;IACDQ,OAAO,CAACC,aAAaA,SAASC,YAAYC,MAAAA,KAAc,IAAA,EACxDC,KAAK,CAACC,GAAGC,MAAMD,EAAEE,MAAMC,cAAcF,EAAEC,KAAK,CAAA,GACjD;IAACf;GAAU;AAEb,QAAM,EAAEiB,SAASC,aAAY,IAAKvB,qBAAqB;IAAEwB,OAAOZ;IAAQa,SAAS,CAACX,aAAaA,SAASM;EAAM,CAAA;AAE9G,QAAMM,eAAe/B,YACnB,CAACgC,eAAAA;AACC,SAAKvB,eAAe;MAAEuB;IAAW,CAAA;EACnC,GACA;IAACvB;GAAe;AAGlB,SACE,sBAAA,cAACL,WAAW6B,MAAI;IAACC,UAAUN;KACzB,sBAAA,cAACxB,WAAW+B,OAAK;IACfC,YAAW;IACXC,WAAAA;IACAC,eAAY;IACZC,aAAa3B,EAAE,mCAAA;MAEjB,sBAAA,cAACR,WAAWoC,UAAQ,MACjBb,QAAQc,IAAI,CAACtB,aACZ,sBAAA,cAACf,WAAWsC,MAAI;IACd5B,KAAKK,SAASwB;IACdC,OAAOzB,SAASwB;IAChBlB,OAAON,SAASM;IAChBoB,MAAM1B,SAAS0B,QAAQ;IACvBC,UAAU,MAAMf,aAAaZ,SAASwB,EAAE;;AAMpD;",
6
+ "names": ["React", "useCallback", "useMemo", "useCapabilities", "useTranslation", "SearchList", "useSearchListResults", "meta", "AutomationCapabilities", "CreateAutomationPanel", "onCreateObject", "templates", "templatesProp", "t", "profile", "key", "capabilityTemplates", "Template", "sorted", "filter", "template", "appliesTo", "undefined", "sort", "a", "b", "label", "localeCompare", "results", "handleSearch", "items", "extract", "handleSelect", "templateId", "Root", "onSearch", "Input", "classNames", "autoFocus", "data-testid", "placeholder", "Viewport", "map", "Item", "id", "value", "icon", "onSelect"]
7
7
  }
@@ -2,10 +2,10 @@ import "../chunk-J5LGTIGS.mjs";
2
2
 
3
3
  // src/containers/index.ts
4
4
  import { lazy } from "react";
5
- var AutomationArticle = lazy(() => import("../AutomationArticle-GN36NUX2.mjs"));
6
- var AutomationSettings = lazy(() => import("../AutomationSettings-YXUJDRQA.mjs"));
7
- var AutomationCompanion = lazy(() => import("../AutomationCompanion-M26WR6VP.mjs"));
8
- var TriggerSettings = lazy(() => import("../TriggerSettings-XCHIZPOR.mjs"));
5
+ var AutomationArticle = lazy(() => import("../AutomationArticle-CG4ZML3C.mjs"));
6
+ var AutomationSettings = lazy(() => import("../AutomationSettings-2XCCFX6X.mjs"));
7
+ var AutomationCompanion = lazy(() => import("../AutomationCompanion-67LW2WZS.mjs"));
8
+ var TriggerSettings = lazy(() => import("../TriggerSettings-ABOTKRUA.mjs"));
9
9
  export {
10
10
  AutomationArticle,
11
11
  AutomationCompanion,