@dxos/plugin-automation 0.9.0 → 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.
- package/dist/lib/neutral/{AutomationArticle-GN36NUX2.mjs → AutomationArticle-CG4ZML3C.mjs} +3 -2
- package/dist/lib/neutral/{AutomationCompanion-M26WR6VP.mjs → AutomationCompanion-67LW2WZS.mjs} +12 -13
- package/dist/lib/neutral/AutomationCompanion-67LW2WZS.mjs.map +7 -0
- package/dist/lib/neutral/AutomationPlugin.mjs +1 -1
- package/dist/lib/neutral/AutomationPlugin.node.mjs +4 -4
- package/dist/lib/neutral/AutomationPlugin.node.mjs.map +3 -3
- package/dist/lib/neutral/{AutomationSettings-YXUJDRQA.mjs → AutomationSettings-2XCCFX6X.mjs} +5 -5
- package/dist/lib/neutral/{AutomationSettings-YXUJDRQA.mjs.map → AutomationSettings-2XCCFX6X.mjs.map} +3 -3
- package/dist/lib/neutral/{TriggerSettings-XCHIZPOR.mjs → TriggerSettings-ABOTKRUA.mjs} +2 -2
- package/dist/lib/neutral/{app-graph-builder-BTTHS4VK.mjs → app-graph-builder-VX54SXD6.mjs} +6 -6
- package/dist/lib/neutral/app-graph-builder-VX54SXD6.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +3 -3
- package/dist/lib/neutral/capabilities/node.mjs +1 -1
- package/dist/lib/neutral/{chunk-2JP77CMN.mjs → chunk-73DGSL37.mjs} +2 -2
- package/dist/lib/neutral/chunk-73DGSL37.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-HPUHQ3L6.mjs → chunk-77QU5RSC.mjs} +3 -3
- package/dist/lib/neutral/chunk-77QU5RSC.mjs.map +7 -0
- package/dist/lib/neutral/chunk-D4RCXOP4.mjs +13 -0
- package/dist/lib/neutral/chunk-D4RCXOP4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-SONGOJRB.mjs → chunk-EJ5J22XS.mjs} +2 -2
- package/dist/lib/neutral/chunk-HHIFH3N3.mjs +45 -0
- package/dist/lib/neutral/chunk-HHIFH3N3.mjs.map +7 -0
- package/dist/lib/neutral/chunk-HQU5QWF4.mjs +349 -0
- package/dist/lib/neutral/chunk-HQU5QWF4.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-FE7YFBX7.mjs → chunk-LVUL7GIN.mjs} +151 -60
- package/dist/lib/neutral/chunk-LVUL7GIN.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-GARB7S5R.mjs → chunk-YHK7FWGV.mjs} +5 -3
- package/dist/lib/neutral/chunk-YHK7FWGV.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +36 -2
- package/dist/lib/neutral/components/index.mjs.map +3 -3
- package/dist/lib/neutral/containers/index.mjs +4 -4
- package/dist/lib/neutral/{create-automation-OE3TNXYE.mjs → create-automation-AGYTF62E.mjs} +5 -9
- package/dist/lib/neutral/create-automation-AGYTF62E.mjs.map +7 -0
- package/dist/lib/neutral/{create-trigger-from-template-TERHKWJM.mjs → create-trigger-from-template-TYGCSR3Z.mjs} +5 -5
- package/dist/lib/neutral/create-trigger-from-template-TYGCSR3Z.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +10 -2
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/meta.mjs +1 -1
- package/dist/lib/neutral/{navigation-resolver-I3L5FHJO.mjs → navigation-resolver-FSJNF3DQ.mjs} +3 -3
- package/dist/lib/neutral/navigation-resolver-FSJNF3DQ.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +2 -2
- package/dist/lib/neutral/{react-surface-IBRWUKPC.mjs → react-surface-W3J3CDHA.mjs} +2 -2
- package/dist/lib/neutral/{react-surface-IBRWUKPC.mjs.map → react-surface-W3J3CDHA.mjs.map} +3 -3
- package/dist/lib/neutral/testing.mjs +1 -1
- package/dist/lib/neutral/translations.mjs +6 -2
- package/dist/lib/neutral/translations.mjs.map +3 -3
- package/dist/lib/neutral/types/index.mjs +1 -1
- package/dist/types/dx.config.d.ts +28 -0
- package/dist/types/dx.config.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +8 -13
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/node.d.ts +5 -5
- package/dist/types/src/capabilities/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +2 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/CronBuilder/CronBuilder.d.ts +16 -0
- package/dist/types/src/components/CronBuilder/CronBuilder.d.ts.map +1 -0
- package/dist/types/src/components/CronBuilder/CronBuilder.stories.d.ts +194 -0
- package/dist/types/src/components/CronBuilder/CronBuilder.stories.d.ts.map +1 -0
- package/dist/types/src/components/CronBuilder/cron.d.ts +17 -0
- package/dist/types/src/components/CronBuilder/cron.d.ts.map +1 -0
- package/dist/types/src/components/CronBuilder/cron.test.d.ts +2 -0
- package/dist/types/src/components/CronBuilder/cron.test.d.ts.map +1 -0
- package/dist/types/src/components/CronBuilder/index.d.ts +4 -0
- package/dist/types/src/components/CronBuilder/index.d.ts.map +1 -0
- package/dist/types/src/components/CronBuilder/schema.d.ts +96 -0
- package/dist/types/src/components/CronBuilder/schema.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -0
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/AutomationArticle/AutomationArticle.d.ts +6 -0
- package/dist/types/src/containers/AutomationArticle/AutomationArticle.d.ts.map +1 -1
- package/dist/types/src/containers/AutomationArticle/AutomationArticle.stories.d.ts +120 -0
- package/dist/types/src/containers/AutomationArticle/AutomationArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/AutomationCompanion/AutomationCompanion.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/meta.d.ts +28 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/paths.d.ts +2 -0
- package/dist/types/src/paths.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -1
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/AutomationCapabilities.d.ts +6 -1
- package/dist/types/src/types/AutomationCapabilities.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +34 -0
- package/package.json +40 -38
- package/src/AutomationPlugin.test.ts +1 -1
- package/src/AutomationPlugin.tsx +1 -1
- package/src/capabilities/app-graph-builder.ts +5 -5
- package/src/capabilities/navigation-resolver.ts +2 -2
- package/src/capabilities/react-surface.tsx +1 -1
- package/src/commands/trigger/create/queue.ts +2 -2
- package/src/commands/trigger/update/queue.ts +2 -2
- package/src/components/CreateAutomationPanel/CreateAutomationPanel.tsx +1 -1
- package/src/components/CronBuilder/CronBuilder.stories.tsx +72 -0
- package/src/components/CronBuilder/CronBuilder.tsx +94 -0
- package/src/components/CronBuilder/cron.test.ts +131 -0
- package/src/components/CronBuilder/cron.ts +138 -0
- package/src/components/CronBuilder/index.ts +7 -0
- package/src/components/CronBuilder/schema.ts +119 -0
- package/src/components/index.ts +1 -0
- package/src/containers/AutomationArticle/AutomationArticle.stories.tsx +73 -0
- package/src/containers/AutomationArticle/AutomationArticle.tsx +186 -56
- package/src/containers/AutomationCompanion/AutomationCompanion.tsx +79 -72
- package/src/containers/AutomationSettings/AutomationSettings.tsx +3 -3
- package/src/containers/TriggerSettings/TriggerSettings.tsx +1 -1
- package/src/index.ts +1 -0
- package/src/meta.ts +2 -26
- package/src/operations/create-trigger-from-template.ts +3 -3
- package/src/paths.ts +7 -2
- package/src/translations.ts +7 -2
- package/src/types/AutomationCapabilities.ts +9 -1
- package/src/types/AutomationOperation.ts +1 -1
- package/src/types/schema.ts +1 -1
- package/dist/lib/neutral/AutomationCompanion-M26WR6VP.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-BTTHS4VK.mjs.map +0 -7
- package/dist/lib/neutral/chunk-2JP77CMN.mjs.map +0 -7
- package/dist/lib/neutral/chunk-DUGOIM7G.mjs +0 -36
- package/dist/lib/neutral/chunk-DUGOIM7G.mjs.map +0 -7
- package/dist/lib/neutral/chunk-FE7YFBX7.mjs.map +0 -7
- package/dist/lib/neutral/chunk-GARB7S5R.mjs.map +0 -7
- package/dist/lib/neutral/chunk-HPUHQ3L6.mjs.map +0 -7
- package/dist/lib/neutral/create-automation-OE3TNXYE.mjs.map +0 -7
- package/dist/lib/neutral/create-trigger-from-template-TERHKWJM.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-I3L5FHJO.mjs.map +0 -7
- /package/dist/lib/neutral/{AutomationArticle-GN36NUX2.mjs.map → AutomationArticle-CG4ZML3C.mjs.map} +0 -0
- /package/dist/lib/neutral/{TriggerSettings-XCHIZPOR.mjs.map → TriggerSettings-ABOTKRUA.mjs.map} +0 -0
- /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 {
|
|
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 {
|
|
8
|
-
import {
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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 {
|
|
164
|
-
|
|
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)))
|
|
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.
|
|
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
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
409
|
-
|
|
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-
|
|
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.
|
|
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.
|
|
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-
|
|
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.
|
|
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.
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["React", "useCallback", "useMemo", "useCapabilities", "useTranslation", "SearchList", "useSearchListResults", "meta", "AutomationCapabilities", "CreateAutomationPanel", "onCreateObject", "templates", "templatesProp", "t", "
|
|
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-
|
|
6
|
-
var AutomationSettings = lazy(() => import("../AutomationSettings-
|
|
7
|
-
var AutomationCompanion = lazy(() => import("../AutomationCompanion-
|
|
8
|
-
var TriggerSettings = lazy(() => import("../TriggerSettings-
|
|
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,
|