@dxos/plugin-automation 0.7.1-staging.8709ba7 → 0.7.2-staging.6d26b2a

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 (50) hide show
  1. package/dist/lib/browser/index.mjs +436 -993
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node/index.cjs +425 -965
  5. package/dist/lib/node/index.cjs.map +4 -4
  6. package/dist/lib/node/meta.json +1 -1
  7. package/dist/lib/node-esm/index.mjs +436 -993
  8. package/dist/lib/node-esm/index.mjs.map +4 -4
  9. package/dist/lib/node-esm/meta.json +1 -1
  10. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts +1 -1
  11. package/dist/types/src/components/TriggerEditor/TriggerEditor.d.ts.map +1 -1
  12. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts +1 -1
  13. package/dist/types/src/components/TriggerEditor/TriggerEditor.stories.d.ts.map +1 -1
  14. package/dist/types/src/components/index.d.ts +0 -2
  15. package/dist/types/src/components/index.d.ts.map +1 -1
  16. package/dist/types/src/hooks/invocation-handler.d.ts.map +1 -1
  17. package/dist/types/src/hooks/useLocalTriggerManager.d.ts.map +1 -1
  18. package/dist/types/src/translations.d.ts +1 -1
  19. package/package.json +34 -34
  20. package/src/AutomationPlugin.tsx +3 -3
  21. package/src/components/TriggerEditor/TriggerEditor.stories.tsx +40 -22
  22. package/src/components/TriggerEditor/TriggerEditor.tsx +71 -322
  23. package/src/components/index.ts +0 -5
  24. package/src/hooks/invocation-handler.ts +6 -9
  25. package/src/hooks/useLocalTriggerManager.ts +2 -4
  26. package/src/translations.ts +1 -1
  27. package/dist/lib/browser/PromptContainer-6CBNCUKQ.mjs +0 -19
  28. package/dist/lib/browser/PromptContainer-6CBNCUKQ.mjs.map +0 -7
  29. package/dist/lib/browser/chunk-CJMV64XO.mjs +0 -217
  30. package/dist/lib/browser/chunk-CJMV64XO.mjs.map +0 -7
  31. package/dist/lib/node/PromptContainer-7RCGCU3K.cjs +0 -45
  32. package/dist/lib/node/PromptContainer-7RCGCU3K.cjs.map +0 -7
  33. package/dist/lib/node/chunk-YGRHTCOX.cjs +0 -240
  34. package/dist/lib/node/chunk-YGRHTCOX.cjs.map +0 -7
  35. package/dist/lib/node-esm/PromptContainer-4SCHQV5C.mjs +0 -20
  36. package/dist/lib/node-esm/PromptContainer-4SCHQV5C.mjs.map +0 -7
  37. package/dist/lib/node-esm/chunk-62AB5HXX.mjs +0 -218
  38. package/dist/lib/node-esm/chunk-62AB5HXX.mjs.map +0 -7
  39. package/dist/types/src/components/Chain.d.ts +0 -12
  40. package/dist/types/src/components/Chain.d.ts.map +0 -1
  41. package/dist/types/src/components/PromptContainer.d.ts +0 -6
  42. package/dist/types/src/components/PromptContainer.d.ts.map +0 -1
  43. package/dist/types/src/components/TriggerEditor/Form.d.ts +0 -5
  44. package/dist/types/src/components/TriggerEditor/Form.d.ts.map +0 -1
  45. package/dist/types/src/components/TriggerEditor/meta.d.ts +0 -25
  46. package/dist/types/src/components/TriggerEditor/meta.d.ts.map +0 -1
  47. package/src/components/Chain.tsx +0 -66
  48. package/src/components/PromptContainer.tsx +0 -19
  49. package/src/components/TriggerEditor/Form.tsx +0 -18
  50. package/src/components/TriggerEditor/meta.tsx +0 -226
@@ -1,6 +1,3 @@
1
- import {
2
- PromptEditor
3
- } from "./chunk-CJMV64XO.mjs";
4
1
  import {
5
2
  AutomationAction,
6
3
  ChainInputSchema,
@@ -14,17 +11,14 @@ import {
14
11
  } from "./chunk-PQLGYMNY.mjs";
15
12
 
16
13
  // packages/plugins/experimental/plugin-automation/src/AutomationPlugin.tsx
17
- import React6 from "react";
14
+ import React4 from "react";
18
15
  import { parseMetadataResolverPlugin, resolvePlugin } from "@dxos/app-framework";
19
- import { FunctionDef, FunctionTrigger as FunctionTrigger2 } from "@dxos/functions/types";
20
- import { invariant as invariant4 } from "@dxos/invariant";
16
+ import { FunctionTrigger } from "@dxos/functions";
17
+ import { invariant } from "@dxos/invariant";
21
18
  import { parseClientPlugin } from "@dxos/plugin-client";
22
19
  import { createExtension, toSignal } from "@dxos/plugin-graph";
23
20
  import { getTypename, loadObjectReferences, parseId } from "@dxos/react-client/echo";
24
21
 
25
- // packages/plugins/experimental/plugin-automation/src/components/index.ts
26
- import { lazy } from "react";
27
-
28
22
  // packages/plugins/experimental/plugin-automation/src/components/AutomationPanel.tsx
29
23
  import React from "react";
30
24
  import { Button, Icon, Toolbar } from "@dxos/react-ui";
@@ -42,12 +36,441 @@ var AutomationPanel = () => {
42
36
  }))));
43
37
  };
44
38
 
45
- // packages/plugins/experimental/plugin-automation/src/components/Chain.tsx
46
- import React2 from "react";
47
- import { getSpace } from "@dxos/react-client/echo";
48
- import { Select, useTranslation } from "@dxos/react-ui";
39
+ // packages/plugins/experimental/plugin-automation/src/components/PromptEditor/PromptEditor.tsx
40
+ import React2, { useEffect } from "react";
41
+ import { createDocAccessor } from "@dxos/react-client/echo";
42
+ import { Input, Select, useThemeContext, useTranslation } from "@dxos/react-ui";
43
+ import { createBasicExtensions, createDataExtensions, createThemeExtensions, useTextEditor } from "@dxos/react-ui-editor";
44
+ import { attentionSurface, groupBorder, mx as mx2 } from "@dxos/react-ui-theme";
49
45
  import { nonNullable } from "@dxos/util";
50
46
 
47
+ // packages/plugins/experimental/plugin-automation/src/components/PromptEditor/prompt-extension.ts
48
+ import { HighlightStyle, StreamLanguage, syntaxHighlighting } from "@codemirror/language";
49
+ import { tags } from "@dxos/react-ui-editor";
50
+ import { mx } from "@dxos/react-ui-theme";
51
+ var nameRegex = /\{([\w-]+)}/;
52
+ var parser = StreamLanguage.define({
53
+ token: (stream) => {
54
+ if (stream.eatSpace()) {
55
+ return null;
56
+ }
57
+ if (stream.match(/^#.*/)) {
58
+ return "lineComment";
59
+ }
60
+ if (stream.match(/^-+$/)) {
61
+ return "lineComment";
62
+ }
63
+ if (stream.match(nameRegex)) {
64
+ return "variableName";
65
+ }
66
+ stream.next();
67
+ return null;
68
+ }
69
+ });
70
+ var highlightStyles = HighlightStyle.define([
71
+ {
72
+ tag: tags.variableName,
73
+ class: mx("rounded border border-yellow-500 bg-yellow-100 text-black font-mono text-sm")
74
+ }
75
+ ]);
76
+ var promptExtension = [
77
+ parser,
78
+ syntaxHighlighting(highlightStyles)
79
+ ];
80
+
81
+ // packages/plugins/experimental/plugin-automation/src/components/PromptEditor/PromptEditor.tsx
82
+ var inputTypes = [
83
+ {
84
+ value: ChainInputType.VALUE,
85
+ label: "Value"
86
+ },
87
+ {
88
+ value: ChainInputType.PASS_THROUGH,
89
+ label: "Pass through"
90
+ },
91
+ {
92
+ value: ChainInputType.RETRIEVER,
93
+ label: "Retriever"
94
+ },
95
+ // {
96
+ // value: ChainInputType.FUNCTION,
97
+ // label: 'Function',
98
+ // },
99
+ // {
100
+ // value: ChainInputType.QUERY,
101
+ // label: 'Query',
102
+ // },
103
+ {
104
+ value: ChainInputType.RESOLVER,
105
+ label: "Resolver"
106
+ },
107
+ {
108
+ value: ChainInputType.CONTEXT,
109
+ label: "Context"
110
+ },
111
+ {
112
+ value: ChainInputType.SCHEMA,
113
+ label: "Schema"
114
+ }
115
+ ];
116
+ var getInputType = (type) => inputTypes.find(({ value }) => String(value) === type)?.value;
117
+ var usePromptInputs = (prompt) => {
118
+ useEffect(() => {
119
+ const text = prompt.template ?? "";
120
+ if (!prompt.inputs) {
121
+ prompt.inputs = [];
122
+ }
123
+ const regex = new RegExp(nameRegex, "g");
124
+ const variables = new Set([
125
+ ...text.matchAll(regex)
126
+ ].map((m) => m[1]));
127
+ const unclaimed = new Map(prompt.inputs?.filter(nonNullable).map((input) => [
128
+ input.name,
129
+ input
130
+ ]));
131
+ const missing = [];
132
+ Array.from(variables.values()).forEach((name) => {
133
+ if (unclaimed.has(name)) {
134
+ unclaimed.delete(name);
135
+ } else {
136
+ missing.push(name);
137
+ }
138
+ });
139
+ const values = unclaimed.values();
140
+ missing.forEach((name) => {
141
+ const next = values.next().value;
142
+ if (next) {
143
+ next.name = name;
144
+ } else {
145
+ prompt.inputs?.push({
146
+ name
147
+ });
148
+ }
149
+ });
150
+ for (const input of values) {
151
+ prompt.inputs.splice(prompt.inputs.indexOf(input), 1);
152
+ }
153
+ }, [
154
+ prompt.template
155
+ ]);
156
+ };
157
+ var PromptEditor = ({ prompt, commandEditable = true }) => {
158
+ const { t } = useTranslation(AUTOMATION_PLUGIN);
159
+ const { themeMode } = useThemeContext();
160
+ const { parentRef } = useTextEditor(() => ({
161
+ initialValue: prompt.template,
162
+ extensions: [
163
+ createDataExtensions({
164
+ id: prompt.id,
165
+ text: prompt.template !== void 0 ? createDocAccessor(prompt, [
166
+ "template"
167
+ ]) : void 0
168
+ }),
169
+ createBasicExtensions({
170
+ bracketMatching: false,
171
+ lineWrapping: true,
172
+ placeholder: t("template placeholder")
173
+ }),
174
+ createThemeExtensions({
175
+ themeMode,
176
+ slots: {
177
+ content: {
178
+ className: "!p-3"
179
+ }
180
+ }
181
+ }),
182
+ promptExtension
183
+ ]
184
+ }), [
185
+ themeMode,
186
+ prompt
187
+ ]);
188
+ usePromptInputs(prompt);
189
+ return /* @__PURE__ */ React2.createElement("div", {
190
+ className: mx2("flex flex-col w-full overflow-hidden gap-4", groupBorder)
191
+ }, commandEditable && /* @__PURE__ */ React2.createElement("div", {
192
+ className: "flex items-center pl-4"
193
+ }, /* @__PURE__ */ React2.createElement("span", {
194
+ className: "text-neutral-500"
195
+ }, "/"), /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.TextInput, {
196
+ placeholder: t("command placeholder"),
197
+ classNames: mx2("is-full bg-transparent m-2"),
198
+ value: prompt.command ?? "",
199
+ onChange: (event) => {
200
+ prompt.command = event.target.value.replace(/\w/g, "");
201
+ }
202
+ }))), /* @__PURE__ */ React2.createElement("div", {
203
+ ref: parentRef,
204
+ className: mx2(attentionSurface, "rounded", "min-h-[120px]")
205
+ }), (prompt.inputs?.length ?? 0) > 0 && /* @__PURE__ */ React2.createElement("div", {
206
+ className: "flex flex-col"
207
+ }, /* @__PURE__ */ React2.createElement("table", {
208
+ className: "w-full table-fixed border-collapse my-2"
209
+ }, /* @__PURE__ */ React2.createElement("tbody", null, prompt.inputs?.filter(nonNullable).map((input) => /* @__PURE__ */ React2.createElement("tr", {
210
+ key: input.name
211
+ }, /* @__PURE__ */ React2.createElement("td", {
212
+ className: "w-[160px] p-1 font-mono text-sm whitespace-nowrap truncate"
213
+ }, /* @__PURE__ */ React2.createElement("code", {
214
+ className: "px-2"
215
+ }, input.name)), /* @__PURE__ */ React2.createElement("td", {
216
+ className: "w-[120px] p-1"
217
+ }, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Select.Root, {
218
+ value: String(input.type),
219
+ onValueChange: (type) => {
220
+ input.type = getInputType(type) ?? ChainInputType.VALUE;
221
+ }
222
+ }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
223
+ placeholder: "Type",
224
+ classNames: "is-full"
225
+ }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, inputTypes.map(({ value, label }) => /* @__PURE__ */ React2.createElement(Select.Option, {
226
+ key: value,
227
+ value: String(value)
228
+ }, label)))))))), /* @__PURE__ */ React2.createElement("td", {
229
+ className: "p-1 pr-2"
230
+ }, input.type !== void 0 && [
231
+ ChainInputType.VALUE,
232
+ ChainInputType.CONTEXT,
233
+ ChainInputType.RESOLVER,
234
+ ChainInputType.SCHEMA
235
+ ].includes(input.type) && /* @__PURE__ */ React2.createElement("div", null, /* @__PURE__ */ React2.createElement(Input.Root, null, /* @__PURE__ */ React2.createElement(Input.TextInput, {
236
+ placeholder: t("command placeholder"),
237
+ classNames: mx2("is-full bg-transparent"),
238
+ value: input.value ?? "",
239
+ onChange: (event) => {
240
+ input.value = event.target.value;
241
+ }
242
+ }))))))))));
243
+ };
244
+
245
+ // packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/TriggerEditor.tsx
246
+ import React3 from "react";
247
+ import { FunctionTriggerSchema, TriggerKind } from "@dxos/functions";
248
+ import { FunctionType } from "@dxos/plugin-script/types";
249
+ import { Filter, useQuery } from "@dxos/react-client/echo";
250
+ import { useTranslation as useTranslation2 } from "@dxos/react-ui";
251
+ import { Form, SelectInput } from "@dxos/react-ui-form";
252
+ var TriggerEditor = ({ space, trigger }) => {
253
+ const { t } = useTranslation2(AUTOMATION_PLUGIN);
254
+ const functions = useQuery(space, Filter.schema(FunctionType));
255
+ return /* @__PURE__ */ React3.createElement(Form, {
256
+ schema: FunctionTriggerSchema,
257
+ values: trigger,
258
+ filter: (props) => props.filter((p) => p.name !== "meta"),
259
+ Custom: {
260
+ ["function"]: (props) => /* @__PURE__ */ React3.createElement(SelectInput, {
261
+ ...props,
262
+ options: functions.map(({ name }) => ({
263
+ value: name,
264
+ label: name
265
+ }))
266
+ }),
267
+ ["spec.type"]: (props) => /* @__PURE__ */ React3.createElement(SelectInput, {
268
+ ...props,
269
+ options: Object.values(TriggerKind).map((kind) => ({
270
+ value: kind,
271
+ label: t(`trigger type ${kind}`)
272
+ }))
273
+ })
274
+ }
275
+ });
276
+ };
277
+
278
+ // packages/plugins/experimental/plugin-automation/src/translations.ts
279
+ var translations_default = [
280
+ {
281
+ "en-US": {
282
+ [AUTOMATION_PLUGIN]: {
283
+ "plugin name": "Automation",
284
+ "object placeholder": "New prompt",
285
+ "create object label": "Create prompt",
286
+ "create trigger label": "Create trigger",
287
+ "create stack section label": "Create prompt",
288
+ "command placeholder": "Enter slash command...",
289
+ "template placeholder": "Enter template...",
290
+ "value placeholder": "Enter value...",
291
+ "select preset template placeholder": "Select preset",
292
+ "open automation panel label": "Show Automations",
293
+ "function select label": "Function",
294
+ "function select placeholder": "Select function",
295
+ "function enabled": "Enabled",
296
+ "trigger select label": "Trigger",
297
+ "trigger select placeholder": "Trigger type",
298
+ "trigger type timer": "Timer",
299
+ "trigger type webhook": "Webhook",
300
+ "trigger type websocket": "Websocket",
301
+ "trigger type subscription": "Subscription",
302
+ "trigger filter": "Filter",
303
+ "trigger cron": "Cron",
304
+ "trigger method": "Method",
305
+ "trigger endpoint": "Endpoint"
306
+ }
307
+ }
308
+ }
309
+ ];
310
+
311
+ // packages/plugins/experimental/plugin-automation/src/AutomationPlugin.tsx
312
+ var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/AutomationPlugin.tsx";
313
+ var AutomationPlugin = () => {
314
+ return {
315
+ meta: meta_default,
316
+ provides: {
317
+ metadata: {
318
+ records: {
319
+ [ChainType.typename]: {
320
+ placeholder: [
321
+ "object placeholder",
322
+ {
323
+ ns: AUTOMATION_PLUGIN
324
+ }
325
+ ],
326
+ icon: "ph--magic-wand--regular",
327
+ // TODO(wittjosiah): Move out of metadata.
328
+ loadReferences: (chain) => loadObjectReferences(chain, (chain2) => chain2.prompts)
329
+ }
330
+ }
331
+ },
332
+ translations: translations_default,
333
+ echo: {
334
+ schema: [
335
+ ChainType,
336
+ ChainPromptType,
337
+ FunctionTrigger
338
+ ]
339
+ },
340
+ complementary: {
341
+ panels: [
342
+ {
343
+ id: "automation",
344
+ label: [
345
+ "open automation panel label",
346
+ {
347
+ ns: AUTOMATION_PLUGIN
348
+ }
349
+ ],
350
+ icon: "ph--flow-arrow--regular"
351
+ }
352
+ ]
353
+ },
354
+ graph: {
355
+ builder: (plugins) => {
356
+ const clientPlugin = resolvePlugin(plugins, parseClientPlugin);
357
+ const metadataPlugin = resolvePlugin(plugins, parseMetadataResolverPlugin);
358
+ const resolve = metadataPlugin?.provides.metadata.resolver;
359
+ const client = clientPlugin?.provides.client;
360
+ invariant(resolve, void 0, {
361
+ F: __dxlog_file,
362
+ L: 52,
363
+ S: void 0,
364
+ A: [
365
+ "resolve",
366
+ ""
367
+ ]
368
+ });
369
+ invariant(client, void 0, {
370
+ F: __dxlog_file,
371
+ L: 53,
372
+ S: void 0,
373
+ A: [
374
+ "client",
375
+ ""
376
+ ]
377
+ });
378
+ return [
379
+ // Create nodes for object settings.
380
+ createExtension({
381
+ id: `${AUTOMATION_PLUGIN}/automation-for-subject`,
382
+ resolver: ({ id }) => {
383
+ if (!id.endsWith("~automation")) {
384
+ return;
385
+ }
386
+ const type = "orphan-settings-for-subject";
387
+ const icon = "ph--flow-arrow--regular";
388
+ const [subjectId] = id.split("~");
389
+ const { spaceId, objectId } = parseId(subjectId);
390
+ const space = client.spaces.get().find((space2) => space2.id === spaceId);
391
+ if (!objectId) {
392
+ const label2 = space ? space.properties.name || [
393
+ "unnamed space label",
394
+ {
395
+ ns: AUTOMATION_PLUGIN
396
+ }
397
+ ] : [
398
+ "unnamed object settings label",
399
+ {
400
+ ns: AUTOMATION_PLUGIN
401
+ }
402
+ ];
403
+ return {
404
+ id,
405
+ type,
406
+ data: null,
407
+ properties: {
408
+ icon,
409
+ label: label2,
410
+ showResolvedThreads: false,
411
+ object: null,
412
+ space
413
+ }
414
+ };
415
+ }
416
+ const object = toSignal((onChange) => {
417
+ const timeout = setTimeout(async () => {
418
+ await space?.db.query({
419
+ id: objectId
420
+ }).first();
421
+ onChange();
422
+ });
423
+ return () => clearTimeout(timeout);
424
+ }, () => space?.db.getObjectById(objectId), subjectId);
425
+ if (!object || !subjectId) {
426
+ return;
427
+ }
428
+ const meta = resolve(getTypename(object) ?? "");
429
+ const label = meta.label?.(object) || object.name || meta.placeholder || [
430
+ "unnamed object settings label",
431
+ {
432
+ ns: AUTOMATION_PLUGIN
433
+ }
434
+ ];
435
+ return {
436
+ id,
437
+ type,
438
+ data: null,
439
+ properties: {
440
+ icon,
441
+ label,
442
+ object
443
+ }
444
+ };
445
+ }
446
+ })
447
+ ];
448
+ }
449
+ },
450
+ surface: {
451
+ component: ({ data, role }) => {
452
+ switch (role) {
453
+ // case 'article':
454
+ // return data.object instanceof ChainType ? <ChainArticle chain={data.object} /> : null;
455
+ case "complementary--automation":
456
+ return /* @__PURE__ */ React4.createElement(AutomationPanel, null);
457
+ }
458
+ return null;
459
+ }
460
+ },
461
+ intent: {
462
+ resolver: (intent) => {
463
+ switch (intent.action) {
464
+ case AutomationAction.CREATE: {
465
+ return {};
466
+ }
467
+ }
468
+ }
469
+ }
470
+ }
471
+ };
472
+ };
473
+
51
474
  // packages/plugins/experimental/plugin-automation/src/presets.ts
52
475
  import { create } from "@dxos/echo-schema";
53
476
  var str = (...text) => text.filter((value) => value !== void 0 && value !== false).flat().join("\n");
@@ -266,996 +689,16 @@ var chainPresets = [
266
689
  }
267
690
  ];
268
691
 
269
- // packages/plugins/experimental/plugin-automation/src/components/Chain.tsx
270
- var Chain = ({ chain }) => {
271
- const space = getSpace(chain);
272
- if (!space) {
273
- return null;
274
- }
275
- const handleSelectPreset = (preset) => {
276
- chain.name = preset.title;
277
- chain.prompts?.filter(nonNullable).forEach((prompt) => space.db.remove(prompt));
278
- chain.prompts = [
279
- preset.createPrompt()
280
- ];
281
- };
282
- return /* @__PURE__ */ React2.createElement("div", {
283
- className: "flex flex-col my-2 gap-4"
284
- }, chain.prompts?.filter(nonNullable).map((prompt, i) => /* @__PURE__ */ React2.createElement(PromptEditor, {
285
- key: i,
286
- prompt
287
- })), /* @__PURE__ */ React2.createElement("div", {
288
- className: "p-2"
289
- }, /* @__PURE__ */ React2.createElement(ChainPresets, {
290
- presets: chainPresets,
291
- onSelect: handleSelectPreset
292
- })));
293
- };
294
- var ChainPresets = ({ presets, onSelect }) => {
295
- const { t } = useTranslation(AUTOMATION_PLUGIN);
296
- return /* @__PURE__ */ React2.createElement(Select.Root, {
297
- onValueChange: (value) => {
298
- onSelect(presets.find(({ id }) => id === value));
299
- }
300
- }, /* @__PURE__ */ React2.createElement(Select.TriggerButton, {
301
- classNames: "w-full",
302
- placeholder: t("select preset template placeholder")
303
- }), /* @__PURE__ */ React2.createElement(Select.Portal, null, /* @__PURE__ */ React2.createElement(Select.Content, null, /* @__PURE__ */ React2.createElement(Select.Viewport, null, presets.map(({ id, title }) => /* @__PURE__ */ React2.createElement(Select.Option, {
304
- key: id,
305
- value: id
306
- }, title))))));
307
- };
308
-
309
- // packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/TriggerEditor.tsx
310
- import React5, { useEffect as useEffect2, useMemo } from "react";
311
- import { FunctionTriggerSchema } from "@dxos/functions/types";
312
- import { invariant as invariant3 } from "@dxos/invariant";
313
- import { ScriptType } from "@dxos/plugin-script/types";
314
- import { Filter as Filter3, useQuery as useQuery2 } from "@dxos/react-client/echo";
315
- import { Input as Input3, Select as Select2, useTranslation as useTranslation2 } from "@dxos/react-ui";
316
- import { Form, SelectInput } from "@dxos/react-ui-form";
317
- import { distinctBy } from "@dxos/util";
318
-
319
- // packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/Form.tsx
320
- import React3 from "react";
321
- import { Input } from "@dxos/react-ui";
322
- var InputRow = ({ label, children }) => /* @__PURE__ */ React3.createElement(Input.Root, null, /* @__PURE__ */ React3.createElement("tr", null, /* @__PURE__ */ React3.createElement("td", {
323
- className: "w-[80px] px-2 text-right align-top pt-3 overflow-hidden"
324
- }, /* @__PURE__ */ React3.createElement(Input.Label, {
325
- classNames: "truncate text-xs"
326
- }, label)), /* @__PURE__ */ React3.createElement("td", {
327
- className: "p-1 pr-2"
328
- }, children)));
329
-
330
- // packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/meta.tsx
331
- import React4 from "react";
332
- import { create as create2, getMeta as getEchoMeta } from "@dxos/echo-schema";
333
- import { GameType } from "@dxos/plugin-chess/types";
334
- import { FileType } from "@dxos/plugin-ipfs/types";
335
- import { DocumentType } from "@dxos/plugin-markdown";
336
- import { DiagramType } from "@dxos/plugin-sketch/types";
337
- import { CollectionType, MessageType } from "@dxos/plugin-space";
338
- import { Input as Input2 } from "@dxos/react-ui";
339
- import { safeParseInt } from "@dxos/util";
340
- var stateInitialValues = {
341
- schemas: [
342
- // TODO(burdon): Get all schema from API.
343
- DocumentType,
344
- FileType,
345
- GameType,
346
- MessageType,
347
- DiagramType,
348
- CollectionType
349
- ],
350
- selectedSchema: {}
351
- };
352
- var state = create2(stateInitialValues);
353
- var USERFUNCTIONS_PRESET_META_KEY = "dxos.org/service/function-preset";
354
- var getFunctionMetaExtension = (trigger, script) => {
355
- if (script) {
356
- const meta = getEchoMeta(script).keys.find((key) => key.source === USERFUNCTIONS_PRESET_META_KEY);
357
- const extension = meta && metaExtensions[meta.id];
358
- if (extension) {
359
- return extension;
360
- }
361
- }
362
- return trigger?.function ? metaExtensions[trigger.function] : metaExtensions["dxos.org/function/gpt"];
363
- };
364
- var DefaultMetaProps = ({ meta }) => {
365
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null);
366
- };
367
- var ChessMetaProps = ({ meta }) => {
368
- if (!meta) {
369
- return null;
370
- }
371
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(InputRow, {
372
- label: "Level"
373
- }, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
374
- type: "number",
375
- value: meta.level ?? 1,
376
- onChange: (event) => meta.level = safeParseInt(event.target.value),
377
- placeholder: "Engine strength."
378
- })));
379
- };
380
- var EmailWorkerMetaProps = ({ meta }) => {
381
- if (!meta) {
382
- return null;
383
- }
384
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(InputRow, {
385
- label: "Account"
386
- }, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
387
- value: meta.account ?? "",
388
- onChange: (event) => meta.account = event.target.value,
389
- placeholder: "https://"
390
- })));
391
- };
392
- var ChainPromptMetaProps = ({ meta, triggerId }) => {
393
- const schema = triggerId ? state.selectedSchema[triggerId] : void 0;
394
- if (!meta) {
395
- return null;
396
- }
397
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(InputRow, {
398
- label: "Model"
399
- }, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
400
- value: meta.model ?? "",
401
- onChange: (event) => meta.model = event.target.value,
402
- placeholder: "llama2"
403
- })), /* @__PURE__ */ React4.createElement(InputRow, {
404
- label: "Presets"
405
- }, /* @__PURE__ */ React4.createElement(ChainPresets, {
406
- presets: chainPresets,
407
- onSelect: (preset) => {
408
- meta.prompt = preset.createPrompt();
409
- }
410
- })), meta.prompt && /* @__PURE__ */ React4.createElement(InputRow, {
411
- label: "Prompt"
412
- }, /* @__PURE__ */ React4.createElement(PromptEditor, {
413
- prompt: meta.prompt,
414
- schema
415
- })));
416
- };
417
- var EmbeddingMetaProps = ({ meta }) => {
418
- if (!meta) {
419
- return null;
420
- }
421
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(InputRow, {
422
- label: "Model"
423
- }, /* @__PURE__ */ React4.createElement(Input2.TextInput, {
424
- value: meta.model ?? "",
425
- onChange: (event) => meta.model = event.target.value,
426
- placeholder: "llama2"
427
- })));
428
- };
429
- var metaExtensions = {
430
- __DEFAULT__: {
431
- initialValue: () => ({}),
432
- component: DefaultMetaProps
433
- },
434
- "dxos.org/function/chess": {
435
- initialValue: () => ({
436
- level: 2
437
- }),
438
- component: ChessMetaProps
439
- },
440
- "dxos.org/function/email-worker": {
441
- initialValue: () => ({
442
- account: "hello@dxos.network"
443
- }),
444
- component: EmailWorkerMetaProps
445
- },
446
- "dxos.org/function/gpt": {
447
- initialValue: () => ({
448
- model: "llama2"
449
- }),
450
- component: ChainPromptMetaProps
451
- },
452
- "dxos.org/function/embedding": {
453
- initialValue: () => ({
454
- model: "llama2"
455
- }),
456
- component: EmbeddingMetaProps
457
- }
458
- };
459
-
460
- // packages/plugins/experimental/plugin-automation/src/hooks/useLocalTriggerManager.ts
461
- import { useEffect, useState } from "react";
462
- import { Mutex } from "@dxos/async";
463
- import { Context } from "@dxos/context";
464
- import { createSubscriptionTrigger, createWebsocketTrigger } from "@dxos/functions";
465
- import { FunctionTrigger } from "@dxos/functions/types";
466
- import { invariant as invariant2 } from "@dxos/invariant";
467
- import { log as log3 } from "@dxos/log";
468
- import { useClient } from "@dxos/react-client";
469
- import { Filter as Filter2, useQuery } from "@dxos/react-client/echo";
470
-
471
- // packages/plugins/experimental/plugin-automation/src/hooks/invocation-handler.ts
472
- import { sleep } from "@dxos/async";
473
- import { getObjectCore } from "@dxos/echo-db";
474
- import { invariant } from "@dxos/invariant";
475
- import { DXN, LOCAL_SPACE_TAG } from "@dxos/keys";
476
- import { log as log2 } from "@dxos/log";
477
- import { FunctionType } from "@dxos/plugin-script";
478
-
479
- // packages/plugins/experimental/plugin-automation/src/hooks/email.ts
480
- import { findObjectWithForeignKey } from "@dxos/echo-db";
481
- import { create as create3, foreignKey } from "@dxos/echo-schema";
482
- import { log } from "@dxos/log";
483
- import { MailboxType } from "@dxos/plugin-inbox/types";
484
- import { MessageType as MessageType2 } from "@dxos/plugin-space/types";
485
- import { Filter } from "@dxos/react-client/echo";
486
- var __dxlog_file = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/hooks/email.ts";
487
- var SOURCE_ID = "hub.dxos.network/api/mailbox";
488
- var handleEmail = async (space, data) => {
489
- const { messages } = data;
490
- const { objects: mailboxes } = await space.db.query(Filter.schema(MailboxType)).run();
491
- const mailbox = mailboxes[0] ?? space.db.add(create3(MailboxType, {
492
- messages: []
493
- }));
494
- log.info("messages", {
495
- count: messages.length,
496
- existingMailbox: mailboxes.length > 0
497
- }, {
498
- F: __dxlog_file,
499
- L: 21,
500
- S: void 0,
501
- C: (f, a) => f(...a)
502
- });
503
- const { objects } = await space.db.query(Filter.schema(MessageType2)).run();
504
- for (const message of messages) {
505
- let object = findObjectWithForeignKey(objects, {
506
- source: SOURCE_ID,
507
- id: String(message.id)
508
- });
509
- if (!object) {
510
- object = space.db.add(create3(MessageType2, {
511
- sender: {
512
- email: message.from
513
- },
514
- timestamp: new Date(message.created).toISOString(),
515
- text: message.body,
516
- properties: {
517
- subject: message.subject,
518
- to: [
519
- {
520
- email: message.to
521
- }
522
- ]
523
- }
524
- }, {
525
- keys: [
526
- foreignKey(SOURCE_ID, String(message.id))
527
- ]
528
- }));
529
- mailbox.messages?.push(object);
530
- }
531
- }
532
- return 200;
533
- };
534
-
535
- // packages/plugins/experimental/plugin-automation/src/hooks/invocation-handler.ts
536
- var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/hooks/invocation-handler.ts";
537
- var MAX_RETRIES = 3;
538
- var RETRY_DELAY = 1e3;
539
- var callFunction = async (funcUrl, trigger, data) => {
540
- const body = {
541
- event: "trigger",
542
- trigger,
543
- data
544
- };
545
- let retryCount = 0;
546
- while (retryCount < MAX_RETRIES) {
547
- log2.info("exec", {
548
- funcUrl,
549
- body,
550
- retryCount
551
- }, {
552
- F: __dxlog_file2,
553
- L: 26,
554
- S: void 0,
555
- C: (f, a) => f(...a)
556
- });
557
- const response = await fetch(funcUrl, {
558
- method: "POST",
559
- headers: {
560
- "Content-Type": "application/json"
561
- },
562
- body: JSON.stringify(body)
563
- });
564
- const data2 = await response.text();
565
- log2.info("response", {
566
- status: response.status,
567
- body: data2
568
- }, {
569
- F: __dxlog_file2,
570
- L: 36,
571
- S: void 0,
572
- C: (f, a) => f(...a)
573
- });
574
- if (response.status === 409) {
575
- retryCount++;
576
- await sleep(RETRY_DELAY * Math.min(retryCount, 2));
577
- continue;
578
- }
579
- return {
580
- status: response.status,
581
- data: data2
582
- };
583
- }
584
- return {
585
- status: 500
586
- };
587
- };
588
- var invokeFunction = async (client, space, trigger, data) => {
589
- try {
590
- invariant(trigger.spec, void 0, {
591
- F: __dxlog_file2,
592
- L: 50,
593
- S: void 0,
594
- A: [
595
- "trigger.spec",
596
- ""
597
- ]
598
- });
599
- invariant(trigger.function, void 0, {
600
- F: __dxlog_file2,
601
- L: 51,
602
- S: void 0,
603
- A: [
604
- "trigger.function",
605
- ""
606
- ]
607
- });
608
- if (trigger.spec.type === "websocket") {
609
- return handleEmail(space, data.data);
610
- }
611
- const script = await space.crud.query({
612
- id: trigger.function
613
- }).first();
614
- const { objects: functions } = await space.crud.query({
615
- __typename: FunctionType.typename
616
- }).run();
617
- const func = functions.find((fn) => referenceEquals(fn.source, trigger.function));
618
- const funcSlug = func?.__meta.keys.find((key) => key.source === USERFUNCTIONS_META_KEY)?.id;
619
- if (!funcSlug) {
620
- log2.warn("function not deployed", {
621
- scriptId: script.id,
622
- name: script.name
623
- }, {
624
- F: __dxlog_file2,
625
- L: 61,
626
- S: void 0,
627
- C: (f, a) => f(...a)
628
- });
629
- return 404;
630
- }
631
- const funcUrl = getFunctionUrl(client.config, funcSlug, space.id);
632
- const triggerData = {
633
- ...getObjectCore(trigger).toPlainObject(),
634
- // TODO: Remove when functions can query by DXN.
635
- promptId: trigger.meta?.prompt?.id
636
- };
637
- return (await callFunction(funcUrl, triggerData, data)).status;
638
- } catch (err) {
639
- return 400;
640
- }
641
- };
642
- var USERFUNCTIONS_META_KEY = "dxos.org/service/function";
643
- var getFunctionUrl = (config, slug, spaceId) => {
644
- const baseUrl = new URL("functions/", config.values.runtime?.services?.edge?.url);
645
- const relativeUrl = slug.replace(/^\//, "");
646
- const url = new URL(`./${relativeUrl}`, baseUrl.toString());
647
- spaceId && url.searchParams.set("spaceId", spaceId);
648
- url.protocol = "https";
649
- return url.toString();
650
- };
651
- var referenceEquals = (a, b) => {
652
- const aDXN = toDXN(a);
653
- const bDXN = toDXN(b);
654
- return aDXN.toString() === bDXN.toString();
655
- };
656
- var toDXN = (ref) => {
657
- if (typeof ref === "string") {
658
- if (ref.startsWith("dxn:")) {
659
- return DXN.parse(ref);
660
- } else {
661
- return new DXN(DXN.kind.ECHO, [
662
- LOCAL_SPACE_TAG,
663
- ref
664
- ]);
665
- }
666
- }
667
- invariant(typeof ref["/"] === "string", void 0, {
668
- F: __dxlog_file2,
669
- L: 110,
670
- S: void 0,
671
- A: [
672
- "typeof ref['/'] === 'string'",
673
- ""
674
- ]
675
- });
676
- return DXN.parse(ref["/"]);
677
- };
678
-
679
- // packages/plugins/experimental/plugin-automation/src/hooks/useLocalTriggerManager.ts
680
- var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/hooks/useLocalTriggerManager.ts";
681
- var registerTriggersMutex = new Mutex();
682
- var useLocalTriggerManager = (space) => {
683
- const client = useClient();
684
- const [registry] = useState(/* @__PURE__ */ new Map());
685
- const triggers = useQuery(space, Filter2.schema(FunctionTrigger));
686
- useEffect(() => {
687
- setTimeout(async () => {
688
- await registerTriggersMutex.executeSynchronized(async () => {
689
- const deprecated = new Set(Array.from(registry.keys()));
690
- log3("triggers", {
691
- deprecated,
692
- all: triggers.map((t) => t.id),
693
- enabled: triggers.filter((t) => t.enabled).map((t) => t.id)
694
- }, {
695
- F: __dxlog_file3,
696
- L: 31,
697
- S: void 0,
698
- C: (f, a) => f(...a)
699
- });
700
- for (const trigger of triggers) {
701
- if (trigger.enabled) {
702
- if (registry.has(trigger.id)) {
703
- deprecated.delete(trigger.id);
704
- continue;
705
- }
706
- log3.info("activating trigger", trigger.id, {
707
- F: __dxlog_file3,
708
- L: 43,
709
- S: void 0,
710
- C: (f, a) => f(...a)
711
- });
712
- const ctx = new Context(void 0, {
713
- F: __dxlog_file3,
714
- L: 45
715
- });
716
- registry.set(trigger.id, ctx);
717
- const triggerSpec = trigger.spec;
718
- invariant2(triggerSpec, void 0, {
719
- F: __dxlog_file3,
720
- L: 48,
721
- S: void 0,
722
- A: [
723
- "triggerSpec",
724
- ""
725
- ]
726
- });
727
- let triggerFactory;
728
- if (triggerSpec.type === "subscription") {
729
- triggerFactory = createSubscriptionTrigger;
730
- } else if (triggerSpec.type === "websocket") {
731
- triggerFactory = createWebsocketTrigger;
732
- } else {
733
- log3.info("unsupported trigger", {
734
- type: triggerSpec.type
735
- }, {
736
- F: __dxlog_file3,
737
- L: 56,
738
- S: void 0,
739
- C: (f, a) => f(...a)
740
- });
741
- continue;
742
- }
743
- await triggerFactory(ctx, space, trigger.spec, (data) => {
744
- return invokeFunction(client, space, trigger, data);
745
- });
746
- }
747
- }
748
- for (const id of deprecated) {
749
- const ctx = registry.get(id);
750
- if (ctx) {
751
- await ctx.dispose();
752
- registry.delete(id);
753
- }
754
- }
755
- });
756
- });
757
- }, [
758
- JSON.stringify(triggers)
759
- ]);
760
- useEffect(() => {
761
- return () => {
762
- for (const ctx of registry.values()) {
763
- void ctx.dispose();
764
- }
765
- };
766
- }, []);
767
- };
768
-
769
- // packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/TriggerEditor.tsx
770
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/components/TriggerEditor/TriggerEditor.tsx";
771
- var triggerTypes = [
772
- "timer",
773
- "webhook",
774
- "websocket",
775
- "subscription"
776
- ];
777
- var TriggerEditor = ({ space, trigger }) => {
778
- const { t } = useTranslation2(AUTOMATION_PLUGIN);
779
- const scripts = useQuery2(space, Filter3.schema(ScriptType));
780
- const script = useMemo(() => scripts.find((script2) => script2.id === trigger.function), [
781
- trigger.function,
782
- scripts
783
- ]);
784
- useLocalTriggerManager(space);
785
- const triggerLabels = {
786
- subscription: t("trigger type subscription"),
787
- timer: t("trigger type timer"),
788
- webhook: t("trigger type webhook"),
789
- websocket: t("trigger type websocket")
790
- };
791
- useEffect2(() => {
792
- void space.db.schemaRegistry.query().then((schemas) => {
793
- state.schemas = distinctBy([
794
- ...state.schemas,
795
- ...schemas
796
- ], (schema) => schema.typename).sort((a, b) => a.typename < b.typename ? -1 : 1);
797
- }).catch(() => {
798
- });
799
- }, [
800
- space
801
- ]);
802
- useEffect2(() => {
803
- const spec = trigger.spec;
804
- invariant3(spec, void 0, {
805
- F: __dxlog_file4,
806
- L: 65,
807
- S: void 0,
808
- A: [
809
- "spec",
810
- ""
811
- ]
812
- });
813
- if (spec.type === "subscription") {
814
- if (spec.filter) {
815
- const type = spec.filter.type;
816
- const foundSchema = state.schemas.find((schema) => schema.typename === type);
817
- if (foundSchema) {
818
- state.selectedSchema[trigger.id] = foundSchema;
819
- }
820
- }
821
- }
822
- }, [
823
- JSON.stringify(trigger.spec),
824
- state.schemas
825
- ]);
826
- useEffect2(() => {
827
- if (!trigger.meta) {
828
- const extension = getFunctionMetaExtension(trigger, script);
829
- trigger.meta = extension?.initialValue?.();
830
- }
831
- }, [
832
- trigger.function,
833
- trigger.meta
834
- ]);
835
- const handleSelectFunction = (value) => {
836
- const match = scripts.find((fn) => fn.id === value);
837
- if (match) {
838
- trigger.function = match.id;
839
- }
840
- };
841
- const handleSelectTriggerType = (triggerType) => {
842
- switch (triggerType) {
843
- case "subscription": {
844
- trigger.spec = {
845
- type: "subscription",
846
- filter: {}
847
- };
848
- break;
849
- }
850
- case "timer": {
851
- trigger.spec = {
852
- type: "timer",
853
- cron: "0 0 * * *"
854
- };
855
- break;
856
- }
857
- case "webhook": {
858
- trigger.spec = {
859
- type: "webhook",
860
- method: "GET"
861
- };
862
- break;
863
- }
864
- case "websocket": {
865
- trigger.spec = {
866
- type: "websocket",
867
- url: "",
868
- init: {
869
- type: "sync"
870
- }
871
- };
872
- break;
873
- }
874
- }
875
- };
876
- const TriggerMeta = getFunctionMetaExtension(trigger, script)?.component;
877
- const test = true;
878
- if (test) {
879
- const object = {
880
- spec: {
881
- // type: 'timer',
882
- type: "subscription",
883
- // cron: '0 0 * * *'
884
- filter: {
885
- type: "dxos.org/type/Event"
886
- }
887
- }
888
- };
889
- return /* @__PURE__ */ React5.createElement(Form, {
890
- schema: FunctionTriggerSchema,
891
- values: object,
892
- filter: (props) => props.filter((p) => p.name !== "meta"),
893
- Custom: {
894
- ["function"]: (props) => /* @__PURE__ */ React5.createElement(SelectInput, {
895
- ...props,
896
- // TODO(burdon): Query for functions.
897
- options: [].map((value) => ({
898
- value,
899
- label: value
900
- }))
901
- }),
902
- ["spec.type"]: (props) => /* @__PURE__ */ React5.createElement(SelectInput, {
903
- ...props,
904
- options: [
905
- "timer",
906
- "subscription"
907
- ].map((value) => ({
908
- value,
909
- label: value
910
- }))
911
- })
912
- }
913
- });
914
- }
915
- return /* @__PURE__ */ React5.createElement("div", {
916
- className: "flex flex-col py-1"
917
- }, /* @__PURE__ */ React5.createElement("table", {
918
- className: "is-full table-fixed"
919
- }, /* @__PURE__ */ React5.createElement("tbody", null, /* @__PURE__ */ React5.createElement(InputRow, {
920
- label: t("function select label")
921
- }, /* @__PURE__ */ React5.createElement(Select2.Root, {
922
- value: script?.id,
923
- onValueChange: handleSelectFunction
924
- }, /* @__PURE__ */ React5.createElement(Select2.TriggerButton, {
925
- classNames: "w-full",
926
- placeholder: t("function select placeholder")
927
- }), /* @__PURE__ */ React5.createElement(Select2.Portal, null, /* @__PURE__ */ React5.createElement(Select2.Content, null, /* @__PURE__ */ React5.createElement(Select2.Viewport, null, scripts.map(({ id, name }) => /* @__PURE__ */ React5.createElement(Select2.Option, {
928
- key: id,
929
- value: id
930
- }, name ?? id))))))), script?.description?.length && /* @__PURE__ */ React5.createElement(InputRow, null, /* @__PURE__ */ React5.createElement("div", {
931
- className: "px-2"
932
- }, /* @__PURE__ */ React5.createElement("p", {
933
- className: "text-sm text-description"
934
- }, script?.description?.length))), /* @__PURE__ */ React5.createElement(InputRow, {
935
- label: t("trigger select label")
936
- }, /* @__PURE__ */ React5.createElement(Select2.Root, {
937
- value: trigger.spec?.type,
938
- onValueChange: handleSelectTriggerType
939
- }, /* @__PURE__ */ React5.createElement(Select2.TriggerButton, {
940
- placeholder: t("trigger select placeholder")
941
- }), /* @__PURE__ */ React5.createElement(Select2.Portal, null, /* @__PURE__ */ React5.createElement(Select2.Content, null, /* @__PURE__ */ React5.createElement(Select2.Viewport, null, triggerTypes.map((trigger2) => /* @__PURE__ */ React5.createElement(Select2.Option, {
942
- key: trigger2,
943
- value: trigger2
944
- }, triggerLabels[trigger2])))))))), /* @__PURE__ */ React5.createElement("tbody", null, trigger.spec && /* @__PURE__ */ React5.createElement(TriggerType, {
945
- space,
946
- spec: trigger.spec
947
- }), /* @__PURE__ */ React5.createElement(InputRow, {
948
- label: t("function enabled")
949
- }, /* @__PURE__ */ React5.createElement("div", {
950
- className: "flex items-center h-8"
951
- }, /* @__PURE__ */ React5.createElement(Input3.Switch, {
952
- checked: trigger.enabled,
953
- onCheckedChange: (checked) => trigger.enabled = !!checked
954
- })))), TriggerMeta && trigger.meta && /* @__PURE__ */ React5.createElement("tbody", null, /* @__PURE__ */ React5.createElement("tr", null, /* @__PURE__ */ React5.createElement("td", null), /* @__PURE__ */ React5.createElement("td", {
955
- className: "py-2"
956
- }, /* @__PURE__ */ React5.createElement("div", {
957
- className: "border-b border-separator"
958
- }))), /* @__PURE__ */ React5.createElement(TriggerMeta, {
959
- meta: trigger.meta
960
- }))));
961
- };
962
- var TriggerSpecSubscription = ({ spec }) => {
963
- const { t } = useTranslation2(AUTOMATION_PLUGIN);
964
- if (!spec.filter) {
965
- return null;
966
- }
967
- const handleValueChange = (typename) => {
968
- spec.filter = {
969
- type: typename
970
- };
971
- };
972
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(InputRow, {
973
- label: t("trigger filter")
974
- }, /* @__PURE__ */ React5.createElement(Select2.Root, {
975
- value: spec.filter?.type,
976
- onValueChange: handleValueChange
977
- }, /* @__PURE__ */ React5.createElement(Select2.TriggerButton, {
978
- classNames: "w-full",
979
- placeholder: "Select type"
980
- }), /* @__PURE__ */ React5.createElement(Select2.Portal, null, /* @__PURE__ */ React5.createElement(Select2.Content, null, /* @__PURE__ */ React5.createElement(Select2.Viewport, null, state.schemas.map(({ typename }) => /* @__PURE__ */ React5.createElement(Select2.Option, {
981
- key: typename,
982
- value: typename
983
- }, typename))))))));
984
- };
985
- var TriggerSpecTimer = ({ spec }) => {
986
- const { t } = useTranslation2(AUTOMATION_PLUGIN);
987
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(InputRow, {
988
- label: t("trigger cron")
989
- }, /* @__PURE__ */ React5.createElement(Input3.TextInput, {
990
- value: spec.cron,
991
- onChange: (event) => spec.cron = event.target.value
992
- })));
993
- };
994
- var methods = [
995
- "GET",
996
- "POST"
997
- ];
998
- var TriggerSpecWebhook = ({ spec }) => {
999
- const { t } = useTranslation2(AUTOMATION_PLUGIN);
1000
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(InputRow, {
1001
- label: t("trigger method")
1002
- }, /* @__PURE__ */ React5.createElement(Select2.Root, {
1003
- value: spec.method,
1004
- onValueChange: (value) => spec.method = value
1005
- }, /* @__PURE__ */ React5.createElement(Select2.TriggerButton, {
1006
- placeholder: "type"
1007
- }), /* @__PURE__ */ React5.createElement(Select2.Portal, null, /* @__PURE__ */ React5.createElement(Select2.Content, null, /* @__PURE__ */ React5.createElement(Select2.Viewport, null, methods.map((method) => /* @__PURE__ */ React5.createElement(Select2.Option, {
1008
- key: method,
1009
- value: method
1010
- }, method))))))));
1011
- };
1012
- var TriggerSpecWebsocket = ({ spec }) => {
1013
- const { t } = useTranslation2(AUTOMATION_PLUGIN);
1014
- const handleChangeInit = (event) => {
1015
- try {
1016
- spec.init = JSON.parse(event.target.value);
1017
- } catch (err) {
1018
- }
1019
- };
1020
- return /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(InputRow, {
1021
- label: t("trigger method")
1022
- }, /* @__PURE__ */ React5.createElement(Input3.TextInput, {
1023
- value: spec.url,
1024
- onChange: (event) => spec.url = event.target.value,
1025
- placeholder: "https://"
1026
- })), /* @__PURE__ */ React5.createElement(InputRow, {
1027
- label: "Init"
1028
- }, /* @__PURE__ */ React5.createElement(Input3.TextInput, {
1029
- value: JSON.stringify(spec.init),
1030
- onChange: handleChangeInit,
1031
- placeholder: "Initial message."
1032
- })));
1033
- };
1034
- var triggerRenderers = {
1035
- subscription: TriggerSpecSubscription,
1036
- timer: TriggerSpecTimer,
1037
- webhook: TriggerSpecWebhook,
1038
- websocket: TriggerSpecWebsocket
1039
- };
1040
- var TriggerType = ({ space, spec }) => {
1041
- const Component = triggerRenderers[spec.type];
1042
- return Component ? /* @__PURE__ */ React5.createElement(Component, {
1043
- space,
1044
- spec
1045
- }) : null;
1046
- };
1047
-
1048
- // packages/plugins/experimental/plugin-automation/src/components/index.ts
1049
- var PromptContainer = lazy(() => import("./PromptContainer-6CBNCUKQ.mjs"));
1050
-
1051
- // packages/plugins/experimental/plugin-automation/src/translations.ts
1052
- var translations_default = [
1053
- {
1054
- "en-US": {
1055
- [AUTOMATION_PLUGIN]: {
1056
- "plugin name": "Automation",
1057
- "object placeholder": "New prompt",
1058
- "create object label": "Create prompt",
1059
- "create trigger label": "Create trigger",
1060
- "create stack section label": "Create prompt",
1061
- "command placeholder": "Enter slash command...",
1062
- "template placeholder": "Enter template...",
1063
- "value placeholder": "Enter value...",
1064
- "select preset template placeholder": "Select preset",
1065
- "open automation panel label": "Show Automations",
1066
- "function select label": "Function",
1067
- "function select placeholder": "Select function",
1068
- "function enabled": "Enabled",
1069
- "trigger select label": "Trigger",
1070
- "trigger select placeholder": "Trigger type",
1071
- "trigger type subscription": "Subscription",
1072
- "trigger type timer": "Timer",
1073
- "trigger type webhook": "Webhook",
1074
- "trigger type websocket": "Websocket",
1075
- "trigger filter": "Filter",
1076
- "trigger cron": "Cron",
1077
- "trigger method": "Method",
1078
- "trigger endpoint": "Endpoint"
1079
- }
1080
- }
1081
- }
1082
- ];
1083
-
1084
- // packages/plugins/experimental/plugin-automation/src/AutomationPlugin.tsx
1085
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/plugins/experimental/plugin-automation/src/AutomationPlugin.tsx";
1086
- var AutomationPlugin = () => {
1087
- return {
1088
- meta: meta_default,
1089
- provides: {
1090
- metadata: {
1091
- records: {
1092
- [ChainType.typename]: {
1093
- placeholder: [
1094
- "object placeholder",
1095
- {
1096
- ns: AUTOMATION_PLUGIN
1097
- }
1098
- ],
1099
- icon: "ph--magic-wand--regular",
1100
- // TODO(wittjosiah): Move out of metadata.
1101
- loadReferences: (chain) => loadObjectReferences(chain, (chain2) => chain2.prompts)
1102
- }
1103
- }
1104
- },
1105
- translations: translations_default,
1106
- echo: {
1107
- schema: [
1108
- ChainType,
1109
- ChainPromptType,
1110
- FunctionDef,
1111
- FunctionTrigger2
1112
- ]
1113
- },
1114
- complementary: {
1115
- panels: [
1116
- {
1117
- id: "automation",
1118
- label: [
1119
- "open automation panel label",
1120
- {
1121
- ns: AUTOMATION_PLUGIN
1122
- }
1123
- ],
1124
- icon: "ph--flow-arrow--regular"
1125
- }
1126
- ]
1127
- },
1128
- graph: {
1129
- builder: (plugins) => {
1130
- const clientPlugin = resolvePlugin(plugins, parseClientPlugin);
1131
- const metadataPlugin = resolvePlugin(plugins, parseMetadataResolverPlugin);
1132
- const resolve = metadataPlugin?.provides.metadata.resolver;
1133
- const client = clientPlugin?.provides.client;
1134
- invariant4(resolve, void 0, {
1135
- F: __dxlog_file5,
1136
- L: 52,
1137
- S: void 0,
1138
- A: [
1139
- "resolve",
1140
- ""
1141
- ]
1142
- });
1143
- invariant4(client, void 0, {
1144
- F: __dxlog_file5,
1145
- L: 53,
1146
- S: void 0,
1147
- A: [
1148
- "client",
1149
- ""
1150
- ]
1151
- });
1152
- return [
1153
- // Create nodes for object settings.
1154
- createExtension({
1155
- id: `${AUTOMATION_PLUGIN}/automation-for-subject`,
1156
- resolver: ({ id }) => {
1157
- if (!id.endsWith("~automation")) {
1158
- return;
1159
- }
1160
- const type = "orphan-settings-for-subject";
1161
- const icon = "ph--flow-arrow--regular";
1162
- const [subjectId] = id.split("~");
1163
- const { spaceId, objectId } = parseId(subjectId);
1164
- const space = client.spaces.get().find((space2) => space2.id === spaceId);
1165
- if (!objectId) {
1166
- const label2 = space ? space.properties.name || [
1167
- "unnamed space label",
1168
- {
1169
- ns: AUTOMATION_PLUGIN
1170
- }
1171
- ] : [
1172
- "unnamed object settings label",
1173
- {
1174
- ns: AUTOMATION_PLUGIN
1175
- }
1176
- ];
1177
- return {
1178
- id,
1179
- type,
1180
- data: null,
1181
- properties: {
1182
- icon,
1183
- label: label2,
1184
- showResolvedThreads: false,
1185
- object: null,
1186
- space
1187
- }
1188
- };
1189
- }
1190
- const object = toSignal((onChange) => {
1191
- const timeout = setTimeout(async () => {
1192
- await space?.db.loadObjectById(objectId);
1193
- onChange();
1194
- });
1195
- return () => clearTimeout(timeout);
1196
- }, () => space?.db.getObjectById(objectId), subjectId);
1197
- if (!object || !subjectId) {
1198
- return;
1199
- }
1200
- const meta = resolve(getTypename(object) ?? "");
1201
- const label = meta.label?.(object) || object.name || meta.placeholder || [
1202
- "unnamed object settings label",
1203
- {
1204
- ns: AUTOMATION_PLUGIN
1205
- }
1206
- ];
1207
- return {
1208
- id,
1209
- type,
1210
- data: null,
1211
- properties: {
1212
- icon,
1213
- label,
1214
- object
1215
- }
1216
- };
1217
- }
1218
- })
1219
- ];
1220
- }
1221
- },
1222
- surface: {
1223
- component: ({ data, role }) => {
1224
- switch (role) {
1225
- // case 'article':
1226
- // return data.object instanceof ChainType ? <ChainArticle chain={data.object} /> : null;
1227
- case "complementary--automation":
1228
- return /* @__PURE__ */ React6.createElement(AutomationPanel, null);
1229
- }
1230
- return null;
1231
- }
1232
- },
1233
- intent: {
1234
- resolver: (intent) => {
1235
- switch (intent.action) {
1236
- case AutomationAction.CREATE: {
1237
- return {};
1238
- }
1239
- }
1240
- }
1241
- }
1242
- }
1243
- };
1244
- };
1245
-
1246
692
  // packages/plugins/experimental/plugin-automation/src/index.ts
1247
693
  var src_default = AutomationPlugin;
1248
694
  export {
1249
695
  AutomationAction,
1250
696
  AutomationPanel,
1251
697
  AutomationPlugin,
1252
- Chain,
1253
698
  ChainInputSchema,
1254
699
  ChainInputType,
1255
- ChainPresets,
1256
700
  ChainPromptType,
1257
701
  ChainType,
1258
- PromptContainer,
1259
702
  PromptEditor,
1260
703
  TriggerEditor,
1261
704
  chainPresets,