@arbidocs/blocks 0.4.75 → 0.4.77

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 (113) hide show
  1. package/dist/agents/index.cjs +341 -253
  2. package/dist/agents/index.js +3 -3
  3. package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
  4. package/dist/agents/tasks/WorkflowThreadStrip.d.ts +44 -1
  5. package/dist/agents/tasks/index.d.ts +2 -1
  6. package/dist/agents/tasks/linkedRuns.d.ts +31 -0
  7. package/dist/agents/workflows/SchemaForm.d.ts +6 -1
  8. package/dist/agents/workflows/StepParts.d.ts +109 -0
  9. package/dist/agents/workflows/WorkflowRunner.d.ts +11 -2
  10. package/dist/agents/workflows/index.d.ts +3 -2
  11. package/dist/agents/workflows/planSteps.d.ts +10 -1
  12. package/dist/agents/workflows/run.d.ts +61 -8
  13. package/dist/agents/workflows/types.d.ts +160 -4
  14. package/dist/agents/workflows/useWorkflowPreview.d.ts +2 -1
  15. package/dist/agents/workflows/useWorkflowView.d.ts +19 -0
  16. package/dist/chat/ChatPage.d.ts +1 -1
  17. package/dist/chat/WorkflowStepChip.d.ts +24 -0
  18. package/dist/chat/chat-page-types.d.ts +4 -0
  19. package/dist/chat/index.cjs +130 -122
  20. package/dist/chat/index.d.ts +1 -0
  21. package/dist/chat/index.js +2 -2
  22. package/dist/{chunk-YWYVIQ7T.js → chunk-34UW6XUQ.js} +948 -38
  23. package/dist/chunk-34UW6XUQ.js.map +1 -0
  24. package/dist/{chunk-P2RBE3FD.cjs → chunk-3XR3IEGU.cjs} +965 -35
  25. package/dist/chunk-3XR3IEGU.cjs.map +1 -0
  26. package/dist/{chunk-ZWA7UUZL.cjs → chunk-7YUFMNFW.cjs} +2 -54
  27. package/dist/chunk-7YUFMNFW.cjs.map +1 -0
  28. package/dist/chunk-A24C6BNA.js +92 -0
  29. package/dist/chunk-A24C6BNA.js.map +1 -0
  30. package/dist/chunk-AINNADMT.cjs +62 -0
  31. package/dist/chunk-AINNADMT.cjs.map +1 -0
  32. package/dist/{chunk-7CVF3DK2.cjs → chunk-EKIUMNCN.cjs} +5 -5
  33. package/dist/{chunk-7CVF3DK2.cjs.map → chunk-EKIUMNCN.cjs.map} +1 -1
  34. package/dist/chunk-FE4ULGOR.js +151 -0
  35. package/dist/chunk-FE4ULGOR.js.map +1 -0
  36. package/dist/chunk-FT5FFXSJ.js +60 -0
  37. package/dist/chunk-FT5FFXSJ.js.map +1 -0
  38. package/dist/{chunk-HITAN7JF.cjs → chunk-GTXOV7IJ.cjs} +4 -4
  39. package/dist/{chunk-HITAN7JF.cjs.map → chunk-GTXOV7IJ.cjs.map} +1 -1
  40. package/dist/{chunk-LT2UORRG.js → chunk-HEVVT6IT.js} +205 -38
  41. package/dist/chunk-HEVVT6IT.js.map +1 -0
  42. package/dist/{chunk-IPGKTUF7.cjs → chunk-HOD6OM7L.cjs} +68 -3
  43. package/dist/chunk-HOD6OM7L.cjs.map +1 -0
  44. package/dist/{chunk-F4LUD3YC.cjs → chunk-JFUN4D7D.cjs} +229 -60
  45. package/dist/chunk-JFUN4D7D.cjs.map +1 -0
  46. package/dist/{chunk-UIWLDSTF.js → chunk-NIP5BOP7.js} +68 -5
  47. package/dist/chunk-NIP5BOP7.js.map +1 -0
  48. package/dist/{chunk-MK6NJQGF.js → chunk-OEM5ARVM.js} +3 -3
  49. package/dist/{chunk-MK6NJQGF.js.map → chunk-OEM5ARVM.js.map} +1 -1
  50. package/dist/{chunk-5EBGRG3X.js → chunk-OPA2Y6YZ.js} +3 -54
  51. package/dist/chunk-OPA2Y6YZ.js.map +1 -0
  52. package/dist/chunk-TZR36PPP.cjs +95 -0
  53. package/dist/chunk-TZR36PPP.cjs.map +1 -0
  54. package/dist/{chunk-WJEKRSPH.js → chunk-UEU23PTW.js} +3 -3
  55. package/dist/{chunk-WJEKRSPH.js.map → chunk-UEU23PTW.js.map} +1 -1
  56. package/dist/chunk-ZVBPRMHJ.cjs +153 -0
  57. package/dist/chunk-ZVBPRMHJ.cjs.map +1 -0
  58. package/dist/connect/docx.cjs +10 -88
  59. package/dist/connect/docx.cjs.map +1 -1
  60. package/dist/connect/docx.js +6 -86
  61. package/dist/connect/docx.js.map +1 -1
  62. package/dist/connect/index.cjs +295 -32
  63. package/dist/connect/index.cjs.map +1 -1
  64. package/dist/connect/index.js +280 -17
  65. package/dist/connect/index.js.map +1 -1
  66. package/dist/connection/ConnectedWorkflowRunner.d.ts +16 -2
  67. package/dist/connection/WorkflowRunnerDialogs.d.ts +37 -0
  68. package/dist/connection/useWorkflowThread.d.ts +12 -0
  69. package/dist/document-tools/index.cjs +7 -143
  70. package/dist/document-tools/index.cjs.map +1 -1
  71. package/dist/document-tools/index.js +5 -144
  72. package/dist/document-tools/index.js.map +1 -1
  73. package/dist/docx/index.cjs +18 -17
  74. package/dist/docx/index.cjs.map +1 -1
  75. package/dist/docx/index.js +3 -2
  76. package/dist/docx/index.js.map +1 -1
  77. package/dist/facts/index.cjs +1 -1
  78. package/dist/facts/index.js +1 -1
  79. package/dist/files/index.cjs +1 -1
  80. package/dist/files/index.js +1 -1
  81. package/dist/home/index.cjs +1 -1
  82. package/dist/home/index.js +1 -1
  83. package/dist/index.cjs +631 -535
  84. package/dist/index.js +8 -8
  85. package/dist/settings/index.cjs +1 -1
  86. package/dist/settings/index.js +1 -1
  87. package/dist/shell/index.cjs +1 -1
  88. package/dist/shell/index.js +1 -1
  89. package/dist/studio/index.cjs +4 -4
  90. package/dist/studio/index.js +3 -3
  91. package/dist/workflow-canvas/SignalsEditor.d.ts +41 -0
  92. package/dist/workflow-canvas/StepActionSettings.d.ts +132 -0
  93. package/dist/workflow-canvas/StepInspector.d.ts +28 -2
  94. package/dist/workflow-canvas/TriggerInspector.d.ts +11 -2
  95. package/dist/workflow-canvas/WorkflowBuilder.d.ts +17 -4
  96. package/dist/workflow-canvas/WorkflowCanvas.d.ts +27 -2
  97. package/dist/workflow-canvas/edit.d.ts +9 -1
  98. package/dist/workflow-canvas/index.cjs +1282 -208
  99. package/dist/workflow-canvas/index.cjs.map +1 -1
  100. package/dist/workflow-canvas/index.d.ts +2 -1
  101. package/dist/workflow-canvas/index.js +1255 -188
  102. package/dist/workflow-canvas/index.js.map +1 -1
  103. package/dist/workflow-canvas/trigger.d.ts +20 -1
  104. package/package.json +4 -4
  105. package/src/workflow-canvas/canvas.css +9 -0
  106. package/dist/chunk-5EBGRG3X.js.map +0 -1
  107. package/dist/chunk-F4LUD3YC.cjs.map +0 -1
  108. package/dist/chunk-IPGKTUF7.cjs.map +0 -1
  109. package/dist/chunk-LT2UORRG.js.map +0 -1
  110. package/dist/chunk-P2RBE3FD.cjs.map +0 -1
  111. package/dist/chunk-UIWLDSTF.js.map +0 -1
  112. package/dist/chunk-YWYVIQ7T.js.map +0 -1
  113. package/dist/chunk-ZWA7UUZL.cjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { useConnection } from '../chunk-OYMWV45N.js';
3
- import { describeRRule, RecurrenceBuilder, AgentSelect, useWorkflowPreview, workflowWhen, isoToLocalInput, localInputToIso } from '../chunk-LT2UORRG.js';
3
+ import { workflowWhen, isoToLocalInput, describeRRule, RecurrenceBuilder, AgentSelect, useWorkflowPreview, localInputToIso } from '../chunk-HEVVT6IT.js';
4
4
  import '../chunk-CKB64Z4R.js';
5
5
  import '../chunk-P6GHJSLR.js';
6
- import { workflowSteps, dependsOn, stepLevels, stepDependencies, runFields, validateWorkflowGraph, WorkflowRunner, fromPlanSteps, layoutFromPlanSteps, skillToWorkflow, orderSteps, toPlanSteps } from '../chunk-YWYVIQ7T.js';
6
+ import { workflowSteps, dependsOn, stepLevels, isIncompleteSignal, runFields, upstreamSteps, stepDependencies, canAssign, fromPlanSteps, layoutFromPlanSteps, validateWorkflowGraph, stepConfigProblems, WorkflowRunner, skillToWorkflow, assigneeName, orderSteps, toPlanSteps } from '../chunk-34UW6XUQ.js';
7
7
  import '../chunk-4WWM3GQ5.js';
8
8
  import '../chunk-RFXJYIDV.js';
9
9
  import '../chunk-DPLRHEJZ.js';
@@ -14,23 +14,33 @@ import '../chunk-ZPLG7QYF.js';
14
14
  import '../chunk-DDF5GPIJ.js';
15
15
  import '../chunk-XD2M6LIG.js';
16
16
  import '../chunk-S7PSMMRG.js';
17
+ import '../chunk-76JDDMSP.js';
17
18
  import '../chunk-HOXKR26S.js';
18
19
  import '../chunk-AA3PT6KR.js';
19
20
  import '../chunk-SLSBJRWW.js';
20
21
  import '../chunk-NPLYHR2E.js';
21
- import '../chunk-76JDDMSP.js';
22
22
  import '../chunk-OXF2IFXG.js';
23
23
  import '../chunk-TX2ZICS7.js';
24
24
  import '../chunk-7F6CBP3Z.js';
25
25
  import '../chunk-VUNV25KB.js';
26
26
  import { useMemo, useState, useEffect, useCallback, useRef } from 'react';
27
- import { useWorkflows, useSkills, useAgents, useConversations, useCreateWorkflow, useUpdateWorkflow, useRunWorkflow } from '@arbidocs/react';
28
- import { Input, Textarea, Checkbox, Button, cn, Label, Popover, PopoverTrigger, PopoverContent } from '@arbidocs/react/ui';
29
- import { X, Trash2, Plus, Maximize, ClipboardCheck, Bot, Upload, FileInput, PencilRuler, Eye, LayoutGrid, Settings2, Play, Loader2, Save, Zap, GitBranch, Check, AlertTriangle, MinusCircle } from 'lucide-react';
27
+ import { useWorkspaceUsers, useTags, useDocuments, useWorkflows, useSkills, useAgents, useConversations, useCreateWorkflow, useUpdateWorkflow, useRunWorkflow } from '@arbidocs/react';
28
+ import { Label, Input, cn, Button, Textarea, Checkbox, Popover, PopoverTrigger, PopoverContent } from '@arbidocs/react/ui';
29
+ import { X, Plus, Trash2, Maximize, Table2, Mail, PenLine, ClipboardCheck, Bot, Upload, FileInput, PencilRuler, Eye, LayoutGrid, Settings2, Play, Loader2, Save, Zap, GitBranch, FilePenLine, UserRound, Hourglass, Check, AlertTriangle, MinusCircle } from 'lucide-react';
30
30
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
31
31
  import { MarkerType, applyNodeChanges, ReactFlow, Background, BackgroundVariant, Controls, ControlButton, MiniMap, Handle, Position } from '@xyflow/react';
32
32
 
33
33
  // src/workflow-canvas/edit.ts
34
+ var WORKFLOW_STEP_KINDS = [
35
+ "form",
36
+ "upload",
37
+ "agent",
38
+ "review",
39
+ "sign",
40
+ "email_draft",
41
+ "tabular_review"
42
+ ];
43
+ var stepKindOf = (step) => step.kind === "action" ? step.action.type : step.kind;
34
44
  function newSteppedWorkflow(id, title) {
35
45
  return {
36
46
  id,
@@ -63,7 +73,10 @@ var DEFAULT_TITLES = {
63
73
  form: "Details",
64
74
  upload: "Upload files",
65
75
  agent: "Agent step",
66
- review: "Review"
76
+ review: "Review",
77
+ sign: "Sign",
78
+ email_draft: "Email draft",
79
+ tabular_review: "Tabular review"
67
80
  };
68
81
  function blankStep(kind, id, title) {
69
82
  switch (kind) {
@@ -75,6 +88,22 @@ function blankStep(kind, id, title) {
75
88
  return { id, kind, title };
76
89
  case "review":
77
90
  return { id, kind, title, instructions: "" };
91
+ case "sign":
92
+ return { id, kind: "action", title, action: { type: "sign", signers: [] } };
93
+ case "email_draft":
94
+ return {
95
+ id,
96
+ kind: "action",
97
+ title,
98
+ action: { type: "email_draft", to: [], subject: "", body: "" }
99
+ };
100
+ case "tabular_review":
101
+ return {
102
+ id,
103
+ kind: "action",
104
+ title,
105
+ action: { type: "tabular_review", tags: [], documents: "run_uploads" }
106
+ };
78
107
  }
79
108
  }
80
109
  function addStep(workflow, kind, options = {}) {
@@ -139,14 +168,49 @@ function renameInput(workflow, from, to) {
139
168
  return {
140
169
  ...s,
141
170
  with: s.with ? Object.fromEntries(Object.entries(s.with).map(([k, v]) => [k, renameIn(v, from, to)])) : s.with,
142
- run: s.run?.kind === "prompt" ? { ...s.run, promptTemplate: renameIn(s.run.promptTemplate, from, to) } : s.run
171
+ run: s.run?.kind === "prompt" ? { ...s.run, promptTemplate: renameIn(s.run.promptTemplate, from, to) } : s.run,
172
+ ...s.editDocument ? { editDocument: renameRef(s.editDocument, from, to) } : {}
143
173
  };
144
- if (s.kind === "review" && s.instructions)
145
- return { ...s, instructions: renameIn(s.instructions, from, to) };
146
- return s;
174
+ const assignee = s.assignee && renamePerson(s.assignee, from, to);
175
+ const base = assignee ? { ...s, assignee } : s;
176
+ if (base.kind === "review" && base.instructions)
177
+ return { ...base, instructions: renameIn(base.instructions, from, to) };
178
+ if (base.kind === "action") {
179
+ const a = base.action;
180
+ if (a.type === "sign")
181
+ return {
182
+ ...base,
183
+ action: {
184
+ ...a,
185
+ document: a.document && renameRef(a.document, from, to),
186
+ signers: a.signers.map((x) => renamePerson(x, from, to)),
187
+ ...a.message ? { message: renameIn(a.message, from, to) } : {}
188
+ }
189
+ };
190
+ if (a.type === "email_draft")
191
+ return {
192
+ ...base,
193
+ action: {
194
+ ...a,
195
+ to: a.to.map((t) => renameIn(t, from, to)),
196
+ ...a.cc ? { cc: a.cc.map((t) => renameIn(t, from, to)) } : {},
197
+ subject: renameIn(a.subject, from, to),
198
+ body: renameIn(a.body, from, to),
199
+ ...a.attachments ? { attachments: a.attachments.map((r) => renameRef(r, from, to)) } : {}
200
+ }
201
+ };
202
+ if (Array.isArray(a.documents))
203
+ return {
204
+ ...base,
205
+ action: { ...a, documents: a.documents.map((r) => renameRef(r, from, to)) }
206
+ };
207
+ }
208
+ return base;
147
209
  });
148
210
  return withSteps(workflow, steps);
149
211
  }
212
+ var renamePerson = (a, from, to) => "input" in a && a.input === from ? { input: to } : a;
213
+ var renameRef = (r, from, to) => "input" in r && r.input === from ? { input: to } : r;
150
214
  function moveStep(workflow, id, position) {
151
215
  return withSteps(workflow, workflowSteps(workflow), { ...layoutOf(workflow), [id]: position });
152
216
  }
@@ -165,6 +229,753 @@ function layoutWithDefaults(workflow) {
165
229
  const auto = autoLayout(workflowSteps(workflow));
166
230
  return { ...auto, ...layoutOf(workflow) };
167
231
  }
232
+ var DEFAULT_SIGNALS_EDITOR_LABELS = {
233
+ heading: "When done, signal\u2026",
234
+ hint: "Another workflow can start on a signal (\u201CWhen a step signals\u201D), as its own thread linked to this one.",
235
+ add: "Add signal",
236
+ name: "Signal",
237
+ namePlaceholder: "e.g. risk-high",
238
+ when: "When",
239
+ always: "Whenever it is done",
240
+ fieldEquals: "A field equals",
241
+ answerContains: "The answer contains",
242
+ answerMatches: "The answer matches (regex)",
243
+ approved: "It is approved",
244
+ field: "Field",
245
+ value: "Value",
246
+ phrase: "Phrase",
247
+ phrasePlaceholder: "e.g. Risk rating: High",
248
+ pattern: "Pattern",
249
+ remove: "Remove signal"
250
+ };
251
+ function signalConditions(kind) {
252
+ switch (kind) {
253
+ case "form":
254
+ return ["always", "field"];
255
+ case "agent":
256
+ return ["always", "contains", "matches"];
257
+ case "review":
258
+ return ["approved", "always"];
259
+ default:
260
+ return ["always"];
261
+ }
262
+ }
263
+ function conditionOf(when) {
264
+ if (!when) return "always";
265
+ if ("field" in when) return "field";
266
+ if ("contains" in when) return "contains";
267
+ if ("matches" in when) return "matches";
268
+ return "approved";
269
+ }
270
+ function signalSlug(text) {
271
+ return text.toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^[^a-z0-9]+/, "").slice(0, 64);
272
+ }
273
+ function startCondition(kind, step) {
274
+ switch (kind) {
275
+ case "field":
276
+ return { field: step.kind === "form" ? step.inputs[0]?.name ?? "" : "", equals: "" };
277
+ case "contains":
278
+ return { contains: "" };
279
+ case "matches":
280
+ return { matches: "" };
281
+ case "approved":
282
+ return { approved: true };
283
+ default:
284
+ return void 0;
285
+ }
286
+ }
287
+ function newSignal(step, taken) {
288
+ const base = signalSlug(step.id) || "signal";
289
+ let name = `${base}-done`;
290
+ let n = 2;
291
+ while (taken.includes(name)) name = `${base}-done-${n++}`;
292
+ const when = startCondition(signalConditions(step.kind)[0], step);
293
+ return when ? { name, when } : { name };
294
+ }
295
+ var selectClass = "flex h-8 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
296
+ function SignalsEditor({
297
+ step,
298
+ onChange,
299
+ labels,
300
+ testId = "signals-editor"
301
+ }) {
302
+ const l = { ...DEFAULT_SIGNALS_EDITOR_LABELS, ...labels };
303
+ const signals = step.signals ?? [];
304
+ const conditions = signalConditions(step.kind);
305
+ const conditionLabel = {
306
+ always: l.always,
307
+ field: l.fieldEquals,
308
+ contains: l.answerContains,
309
+ matches: l.answerMatches,
310
+ approved: l.approved
311
+ };
312
+ const emit = (next) => onChange(next.length ? next : void 0);
313
+ const set = (i, signal) => emit(signals.map((s, j) => j === i ? signal : s));
314
+ const fields = step.kind === "form" ? step.inputs : [];
315
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", "data-testid": testId, children: [
316
+ /* @__PURE__ */ jsx(Label, { className: "text-xs", children: l.heading }),
317
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
318
+ signals.map((signal, i) => {
319
+ const condition = conditionOf(signal.when);
320
+ const when = signal.when;
321
+ return /* @__PURE__ */ jsxs(
322
+ "div",
323
+ {
324
+ className: cn(
325
+ "space-y-1.5 rounded-md border p-2",
326
+ isIncompleteSignal(signal) ? "border-destructive/50" : "border-border"
327
+ ),
328
+ "data-incomplete": isIncompleteSignal(signal) || void 0,
329
+ "data-testid": `${testId}-${i}`,
330
+ children: [
331
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
332
+ /* @__PURE__ */ jsx(
333
+ Input,
334
+ {
335
+ value: signal.name,
336
+ "aria-label": l.name,
337
+ placeholder: l.namePlaceholder,
338
+ onChange: (e) => set(i, { ...signal, name: signalSlug(e.target.value) }),
339
+ className: "h-8 font-mono text-xs",
340
+ "data-testid": `${testId}-${i}-name`
341
+ }
342
+ ),
343
+ /* @__PURE__ */ jsx(
344
+ "button",
345
+ {
346
+ type: "button",
347
+ "aria-label": l.remove,
348
+ onClick: () => emit(signals.filter((_, j) => j !== i)),
349
+ "data-testid": `${testId}-${i}-remove`,
350
+ children: /* @__PURE__ */ jsx(X, { className: "size-4 text-muted-foreground" })
351
+ }
352
+ )
353
+ ] }),
354
+ /* @__PURE__ */ jsx(
355
+ "select",
356
+ {
357
+ "aria-label": l.when,
358
+ className: selectClass,
359
+ value: condition,
360
+ onChange: (e) => {
361
+ const nextWhen = startCondition(e.target.value, step);
362
+ set(i, nextWhen ? { name: signal.name, when: nextWhen } : { name: signal.name });
363
+ },
364
+ "data-testid": `${testId}-${i}-when`,
365
+ children: [...conditions, ...conditions.includes(condition) ? [] : [condition]].map(
366
+ (c) => /* @__PURE__ */ jsx("option", { value: c, children: conditionLabel[c] }, c)
367
+ )
368
+ }
369
+ ),
370
+ when && "field" in when && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
371
+ /* @__PURE__ */ jsxs(
372
+ "select",
373
+ {
374
+ "aria-label": l.field,
375
+ className: cn(selectClass, "flex-1"),
376
+ value: when.field,
377
+ onChange: (e) => set(i, { ...signal, when: { ...when, field: e.target.value } }),
378
+ "data-testid": `${testId}-${i}-field`,
379
+ children: [
380
+ fields.map((f) => /* @__PURE__ */ jsx("option", { value: f.name, children: f.label }, f.name)),
381
+ !fields.some((f) => f.name === when.field) && /* @__PURE__ */ jsx("option", { value: when.field, children: when.field || "\u2014" })
382
+ ]
383
+ }
384
+ ),
385
+ /* @__PURE__ */ jsx(
386
+ Input,
387
+ {
388
+ "aria-label": l.value,
389
+ placeholder: l.value,
390
+ value: String(when.equals),
391
+ onChange: (e) => set(i, { ...signal, when: { ...when, equals: e.target.value } }),
392
+ className: "h-8 flex-1",
393
+ "data-testid": `${testId}-${i}-equals`
394
+ }
395
+ )
396
+ ] }),
397
+ when && "contains" in when && /* @__PURE__ */ jsx(
398
+ Input,
399
+ {
400
+ "aria-label": l.phrase,
401
+ placeholder: l.phrasePlaceholder,
402
+ value: when.contains,
403
+ onChange: (e) => set(i, { ...signal, when: { contains: e.target.value } }),
404
+ className: "h-8",
405
+ "data-testid": `${testId}-${i}-contains`
406
+ }
407
+ ),
408
+ when && "matches" in when && /* @__PURE__ */ jsx(
409
+ Input,
410
+ {
411
+ "aria-label": l.pattern,
412
+ placeholder: "risk rating:\\s*high",
413
+ value: when.matches,
414
+ onChange: (e) => set(i, { ...signal, when: { matches: e.target.value } }),
415
+ className: "h-8 font-mono text-xs",
416
+ "data-testid": `${testId}-${i}-matches`
417
+ }
418
+ )
419
+ ]
420
+ },
421
+ i
422
+ );
423
+ }),
424
+ /* @__PURE__ */ jsxs(
425
+ Button,
426
+ {
427
+ variant: "outline",
428
+ size: "sm",
429
+ onClick: () => emit([
430
+ ...signals,
431
+ newSignal(
432
+ step,
433
+ signals.map((s) => s.name)
434
+ )
435
+ ]),
436
+ "data-testid": `${testId}-add`,
437
+ children: [
438
+ /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
439
+ " ",
440
+ l.add
441
+ ]
442
+ }
443
+ )
444
+ ] }),
445
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.hint })
446
+ ] });
447
+ }
448
+ var DEFAULT_STEP_ACTION_SETTINGS_LABELS = {
449
+ assignee: "Who does it",
450
+ assigneeAnyone: "Anyone on the run",
451
+ assigneeRunOwner: "Whoever started the run",
452
+ assigneeProjectLead: "The project lead",
453
+ assigneeFields: "The person in a form field",
454
+ assigneePeople: "A person",
455
+ remind: "Remind after (hours)",
456
+ remindHint: "Left that long, they are told again. Blank: no reminder.",
457
+ documentFrom: "Document",
458
+ docFromStep: "From an earlier step",
459
+ docFromInput: "From a run input",
460
+ docById: "A document",
461
+ chooseStep: "Choose a step\u2026",
462
+ chooseInput: "Choose an input\u2026",
463
+ chooseDocument: "Choose a document\u2026",
464
+ documentIdPlaceholder: "doc-\u2026",
465
+ signDocument: "Document to sign",
466
+ signers: "Signers",
467
+ addSigner: "Add signer",
468
+ signMessage: "Message to the signers",
469
+ expires: "Expires after (hours)",
470
+ expiresHint: "Unsigned by then, the step fails. Blank: no expiry.",
471
+ emailTo: "To",
472
+ emailCc: "Cc",
473
+ emailSubject: "Subject",
474
+ emailBody: "Body",
475
+ addressesHint: "Separate several with commas.",
476
+ variablesHint: "Variables (click to add to the body):",
477
+ attachments: "Attachments",
478
+ addAttachment: "Add attachment",
479
+ reviewColumns: "Columns (labels)",
480
+ noTags: "No labels in this workspace yet.",
481
+ reviewDocuments: "Documents",
482
+ reviewRunUploads: "The files this run collects",
483
+ reviewWorkspace: "Every document in the workspace",
484
+ reviewChosen: "Chosen documents",
485
+ addDocument: "Add document",
486
+ overwrite: "Fill cells that already have a value again",
487
+ editDocument: "Edit this document (tracked changes)",
488
+ editDocumentHint: "The instruction says what to change; the edited copy is saved as its next version, to accept or reject change by change."
489
+ };
490
+ var selectClass2 = "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
491
+ function Field({
492
+ label,
493
+ children,
494
+ hint
495
+ }) {
496
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
497
+ /* @__PURE__ */ jsx(Label, { className: "text-xs", children: label }),
498
+ children,
499
+ hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
500
+ ] });
501
+ }
502
+ var assigneeValue = (a) => !a ? "" : "user" in a ? `user:${a.user}` : "input" in a ? `input:${a.input}` : "runOwner" in a ? "owner" : "lead";
503
+ var parseAssignee = (v) => v === "owner" ? { runOwner: true } : v === "lead" ? { projectLead: true } : v.startsWith("user:") ? { user: v.slice(5) } : v.startsWith("input:") ? { input: v.slice(6) } : void 0;
504
+ function AssigneeSelect({
505
+ value,
506
+ onChange,
507
+ ctx,
508
+ l,
509
+ anyone,
510
+ testId,
511
+ ariaLabel
512
+ }) {
513
+ const personFields = ctx.fields.filter((f) => f.type === "person");
514
+ const v = assigneeValue(value);
515
+ const known = !v.startsWith("user:") || ctx.people.some((p) => `user:${p.value}` === v) ? null : v.slice(5);
516
+ return /* @__PURE__ */ jsxs(
517
+ "select",
518
+ {
519
+ className: selectClass2,
520
+ value: v,
521
+ "aria-label": ariaLabel,
522
+ onChange: (e) => onChange(parseAssignee(e.target.value)),
523
+ "data-testid": testId,
524
+ children: [
525
+ anyone !== void 0 ? /* @__PURE__ */ jsx("option", { value: "", children: anyone }) : /* @__PURE__ */ jsx("option", { value: "", disabled: true }),
526
+ /* @__PURE__ */ jsx("option", { value: "owner", children: l.assigneeRunOwner }),
527
+ /* @__PURE__ */ jsx("option", { value: "lead", children: l.assigneeProjectLead }),
528
+ personFields.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: l.assigneeFields, children: personFields.map((f) => /* @__PURE__ */ jsx("option", { value: `input:${f.name}`, children: f.label }, f.name)) }),
529
+ (ctx.people.length > 0 || known) && /* @__PURE__ */ jsxs("optgroup", { label: l.assigneePeople, children: [
530
+ ctx.people.map((p) => /* @__PURE__ */ jsx("option", { value: `user:${p.value}`, children: p.label }, p.value)),
531
+ known && /* @__PURE__ */ jsx("option", { value: v, children: known })
532
+ ] })
533
+ ]
534
+ }
535
+ );
536
+ }
537
+ function AssigneeSettings({
538
+ step,
539
+ patch,
540
+ ctx,
541
+ l,
542
+ testId
543
+ }) {
544
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
545
+ /* @__PURE__ */ jsx(Field, { label: l.assignee, children: /* @__PURE__ */ jsx(
546
+ AssigneeSelect,
547
+ {
548
+ value: step.assignee,
549
+ onChange: (assignee) => patch({ assignee }),
550
+ ctx,
551
+ l,
552
+ anyone: l.assigneeAnyone,
553
+ testId: `${testId}-assignee`
554
+ }
555
+ ) }),
556
+ /* @__PURE__ */ jsx(Field, { label: l.remind, hint: l.remindHint, children: /* @__PURE__ */ jsx(
557
+ Input,
558
+ {
559
+ type: "number",
560
+ min: 1,
561
+ value: step.remindAfterHours ?? "",
562
+ onChange: (e) => {
563
+ const n = Number(e.target.value);
564
+ patch({ remindAfterHours: e.target.value && n > 0 ? n : void 0 });
565
+ },
566
+ className: "w-28",
567
+ "data-testid": `${testId}-remind`
568
+ }
569
+ ) })
570
+ ] });
571
+ }
572
+ var modeOf = (ref) => !ref ? "step" : "step" in ref ? "step" : "input" in ref ? "input" : "id";
573
+ function DocumentRefPicker({
574
+ value,
575
+ onChange,
576
+ ctx,
577
+ l,
578
+ testId
579
+ }) {
580
+ const mode = modeOf(value);
581
+ const inputs = ctx.fields.filter((f) => f.type === "documents" || f.type === "text");
582
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", "data-testid": testId, children: [
583
+ /* @__PURE__ */ jsxs(
584
+ "select",
585
+ {
586
+ className: cn(selectClass2, "h-8"),
587
+ value: mode,
588
+ "aria-label": l.documentFrom,
589
+ onChange: (e) => {
590
+ const m = e.target.value;
591
+ onChange(m === "step" ? { step: "" } : m === "input" ? { input: "" } : { id: "" });
592
+ },
593
+ "data-testid": `${testId}-mode`,
594
+ children: [
595
+ /* @__PURE__ */ jsx("option", { value: "step", children: l.docFromStep }),
596
+ /* @__PURE__ */ jsx("option", { value: "input", children: l.docFromInput }),
597
+ /* @__PURE__ */ jsx("option", { value: "id", children: l.docById })
598
+ ]
599
+ }
600
+ ),
601
+ mode === "step" && /* @__PURE__ */ jsxs(
602
+ "select",
603
+ {
604
+ className: cn(selectClass2, "h-8"),
605
+ value: value && "step" in value ? value.step : "",
606
+ onChange: (e) => onChange({ step: e.target.value }),
607
+ "data-testid": `${testId}-step`,
608
+ children: [
609
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: l.chooseStep }),
610
+ ctx.earlier.map((s) => /* @__PURE__ */ jsx("option", { value: s.id, children: s.title }, s.id))
611
+ ]
612
+ }
613
+ ),
614
+ mode === "input" && /* @__PURE__ */ jsxs(
615
+ "select",
616
+ {
617
+ className: cn(selectClass2, "h-8"),
618
+ value: value && "input" in value ? value.input : "",
619
+ onChange: (e) => onChange({ input: e.target.value }),
620
+ "data-testid": `${testId}-input`,
621
+ children: [
622
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: l.chooseInput }),
623
+ inputs.map((f) => /* @__PURE__ */ jsx("option", { value: f.name, children: f.label }, f.name))
624
+ ]
625
+ }
626
+ ),
627
+ mode === "id" && (ctx.documents.length ? /* @__PURE__ */ jsxs(
628
+ "select",
629
+ {
630
+ className: cn(selectClass2, "h-8"),
631
+ value: value && "id" in value ? value.id : "",
632
+ onChange: (e) => onChange({ id: e.target.value }),
633
+ "data-testid": `${testId}-id`,
634
+ children: [
635
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: l.chooseDocument }),
636
+ ctx.documents.map((d) => /* @__PURE__ */ jsx("option", { value: d.value, children: d.label }, d.value))
637
+ ]
638
+ }
639
+ ) : /* @__PURE__ */ jsx(
640
+ Input,
641
+ {
642
+ className: "h-8",
643
+ value: value && "id" in value ? value.id : "",
644
+ placeholder: l.documentIdPlaceholder,
645
+ onChange: (e) => onChange({ id: e.target.value }),
646
+ "data-testid": `${testId}-id`
647
+ }
648
+ ))
649
+ ] });
650
+ }
651
+ function DocumentRefList({
652
+ value,
653
+ onChange,
654
+ ctx,
655
+ l,
656
+ addLabel,
657
+ testId
658
+ }) {
659
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
660
+ value.map((ref, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5", children: [
661
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
662
+ DocumentRefPicker,
663
+ {
664
+ value: ref,
665
+ onChange: (next) => onChange(value.map((r, j) => j === i ? next : r)),
666
+ ctx,
667
+ l,
668
+ testId: `${testId}-${i}`
669
+ }
670
+ ) }),
671
+ /* @__PURE__ */ jsx(
672
+ "button",
673
+ {
674
+ type: "button",
675
+ className: "mt-2",
676
+ "aria-label": `${addLabel} \xD7`,
677
+ onClick: () => onChange(value.filter((_, j) => j !== i)),
678
+ children: /* @__PURE__ */ jsx(X, { className: "size-4 text-muted-foreground" })
679
+ }
680
+ )
681
+ ] }, i)),
682
+ /* @__PURE__ */ jsxs(
683
+ Button,
684
+ {
685
+ variant: "outline",
686
+ size: "sm",
687
+ onClick: () => onChange([...value, { step: "" }]),
688
+ "data-testid": `${testId}-add`,
689
+ children: [
690
+ /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
691
+ " ",
692
+ addLabel
693
+ ]
694
+ }
695
+ )
696
+ ] });
697
+ }
698
+ var optionalNumber = (raw) => {
699
+ const n = Number(raw);
700
+ return raw && n > 0 ? n : void 0;
701
+ };
702
+ function SignSettings({
703
+ action,
704
+ onChange,
705
+ ctx,
706
+ l,
707
+ testId
708
+ }) {
709
+ const set = (p) => onChange({ ...action, ...p });
710
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
711
+ /* @__PURE__ */ jsx(Field, { label: l.signDocument, children: /* @__PURE__ */ jsx(
712
+ DocumentRefPicker,
713
+ {
714
+ value: action.document,
715
+ onChange: (document) => set({ document }),
716
+ ctx,
717
+ l,
718
+ testId: `${testId}-document`
719
+ }
720
+ ) }),
721
+ /* @__PURE__ */ jsx(Field, { label: l.signers, children: /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", "data-testid": `${testId}-signers`, children: [
722
+ action.signers.map((s, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
723
+ /* @__PURE__ */ jsx(
724
+ AssigneeSelect,
725
+ {
726
+ value: s,
727
+ onChange: (next) => set({
728
+ signers: next ? action.signers.map((x, j) => j === i ? next : x) : action.signers.filter((_, j) => j !== i)
729
+ }),
730
+ ctx,
731
+ l,
732
+ ariaLabel: `${l.signers} ${i + 1}`,
733
+ testId: `${testId}-signer-${i}`
734
+ }
735
+ ),
736
+ /* @__PURE__ */ jsx(
737
+ "button",
738
+ {
739
+ type: "button",
740
+ "aria-label": `${l.signers} ${i + 1} \xD7`,
741
+ onClick: () => set({ signers: action.signers.filter((_, j) => j !== i) }),
742
+ children: /* @__PURE__ */ jsx(X, { className: "size-4 text-muted-foreground" })
743
+ }
744
+ )
745
+ ] }, i)),
746
+ /* @__PURE__ */ jsxs(
747
+ Button,
748
+ {
749
+ variant: "outline",
750
+ size: "sm",
751
+ onClick: () => set({ signers: [...action.signers, { runOwner: true }] }),
752
+ "data-testid": `${testId}-add-signer`,
753
+ children: [
754
+ /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
755
+ " ",
756
+ l.addSigner
757
+ ]
758
+ }
759
+ )
760
+ ] }) }),
761
+ /* @__PURE__ */ jsx(Field, { label: l.signMessage, children: /* @__PURE__ */ jsx(
762
+ Textarea,
763
+ {
764
+ rows: 3,
765
+ value: action.message ?? "",
766
+ onChange: (e) => set({ message: e.target.value || void 0 }),
767
+ "data-testid": `${testId}-message`
768
+ }
769
+ ) }),
770
+ /* @__PURE__ */ jsx(Field, { label: l.expires, hint: l.expiresHint, children: /* @__PURE__ */ jsx(
771
+ Input,
772
+ {
773
+ type: "number",
774
+ min: 1,
775
+ className: "w-28",
776
+ value: action.expiresAfterHours ?? "",
777
+ onChange: (e) => set({ expiresAfterHours: optionalNumber(e.target.value) }),
778
+ "data-testid": `${testId}-expires`
779
+ }
780
+ ) })
781
+ ] });
782
+ }
783
+ var addresses = (list) => (list ?? []).join(", ");
784
+ var parseAddresses = (text) => text.split(",").map((t) => t.trim());
785
+ function templateVariables(ctx) {
786
+ return [
787
+ ...ctx.fields.map((f) => `{{${f.name}}}`),
788
+ ...ctx.earlier.filter((s) => s.kind === "agent").map((s) => `{{${s.id}.answer}}`)
789
+ ];
790
+ }
791
+ function EmailDraftSettings({
792
+ action,
793
+ onChange,
794
+ ctx,
795
+ l,
796
+ testId
797
+ }) {
798
+ const set = (p) => onChange({ ...action, ...p });
799
+ const vars = templateVariables(ctx);
800
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
801
+ /* @__PURE__ */ jsx(Field, { label: l.emailTo, hint: l.addressesHint, children: /* @__PURE__ */ jsx(
802
+ Input,
803
+ {
804
+ value: addresses(action.to),
805
+ onChange: (e) => set({ to: parseAddresses(e.target.value) }),
806
+ placeholder: "{{client_email}}",
807
+ "data-testid": `${testId}-to`
808
+ }
809
+ ) }),
810
+ /* @__PURE__ */ jsx(Field, { label: l.emailCc, children: /* @__PURE__ */ jsx(
811
+ Input,
812
+ {
813
+ value: addresses(action.cc),
814
+ onChange: (e) => {
815
+ const cc = parseAddresses(e.target.value);
816
+ set({ cc: cc.some(Boolean) ? cc : void 0 });
817
+ },
818
+ "data-testid": `${testId}-cc`
819
+ }
820
+ ) }),
821
+ /* @__PURE__ */ jsx(Field, { label: l.emailSubject, children: /* @__PURE__ */ jsx(
822
+ Input,
823
+ {
824
+ value: action.subject,
825
+ onChange: (e) => set({ subject: e.target.value }),
826
+ "data-testid": `${testId}-subject`
827
+ }
828
+ ) }),
829
+ /* @__PURE__ */ jsx(Field, { label: l.emailBody, children: /* @__PURE__ */ jsx(
830
+ Textarea,
831
+ {
832
+ rows: 6,
833
+ value: action.body,
834
+ onChange: (e) => set({ body: e.target.value }),
835
+ "data-testid": `${testId}-body`
836
+ }
837
+ ) }),
838
+ vars.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", "data-testid": `${testId}-variables`, children: [
839
+ /* @__PURE__ */ jsx("span", { className: "w-full text-xs text-muted-foreground", children: l.variablesHint }),
840
+ vars.map((v) => /* @__PURE__ */ jsx(
841
+ "button",
842
+ {
843
+ type: "button",
844
+ onClick: () => set({ body: `${action.body}${action.body ? " " : ""}${v}` }),
845
+ className: "rounded bg-muted px-1.5 py-0.5 font-mono text-[11px] text-muted-foreground hover:text-foreground",
846
+ title: v,
847
+ children: v
848
+ },
849
+ v
850
+ ))
851
+ ] }),
852
+ /* @__PURE__ */ jsx(Field, { label: l.attachments, children: /* @__PURE__ */ jsx(
853
+ DocumentRefList,
854
+ {
855
+ value: action.attachments ?? [],
856
+ onChange: (attachments) => set({ attachments: attachments.length ? attachments : void 0 }),
857
+ ctx,
858
+ l,
859
+ addLabel: l.addAttachment,
860
+ testId: `${testId}-attachments`
861
+ }
862
+ ) })
863
+ ] });
864
+ }
865
+ function TabularReviewSettings({
866
+ action,
867
+ onChange,
868
+ ctx,
869
+ l,
870
+ testId
871
+ }) {
872
+ const set = (p) => onChange({ ...action, ...p });
873
+ const mode = Array.isArray(action.documents) ? "chosen" : action.documents;
874
+ const toggle = (id) => set({
875
+ tags: action.tags.includes(id) ? action.tags.filter((t) => t !== id) : [...action.tags, id]
876
+ });
877
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
878
+ /* @__PURE__ */ jsx(Field, { label: l.reviewColumns, children: /* @__PURE__ */ jsxs(
879
+ "div",
880
+ {
881
+ className: "max-h-44 space-y-1 overflow-y-auto rounded-md border border-border p-2",
882
+ "data-testid": `${testId}-tags`,
883
+ children: [
884
+ ctx.tags.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.noTags }),
885
+ ctx.tags.map((t) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
886
+ /* @__PURE__ */ jsx(
887
+ Checkbox,
888
+ {
889
+ checked: action.tags.includes(t.value),
890
+ onCheckedChange: () => toggle(t.value),
891
+ "data-testid": `${testId}-tag-${t.value}`
892
+ }
893
+ ),
894
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: t.label })
895
+ ] }, t.value)),
896
+ action.tags.filter((t) => !ctx.tags.some((x) => x.value === t)).map((t) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
897
+ /* @__PURE__ */ jsx(Checkbox, { checked: true, onCheckedChange: () => toggle(t) }),
898
+ /* @__PURE__ */ jsx("code", { className: "text-xs", children: t })
899
+ ] }, t))
900
+ ]
901
+ }
902
+ ) }),
903
+ /* @__PURE__ */ jsx(Field, { label: l.reviewDocuments, children: /* @__PURE__ */ jsxs(
904
+ "select",
905
+ {
906
+ className: selectClass2,
907
+ value: mode,
908
+ onChange: (e) => {
909
+ const v = e.target.value;
910
+ set({ documents: v === "chosen" ? [] : v });
911
+ },
912
+ "data-testid": `${testId}-documents`,
913
+ children: [
914
+ /* @__PURE__ */ jsx("option", { value: "run_uploads", children: l.reviewRunUploads }),
915
+ /* @__PURE__ */ jsx("option", { value: "workspace", children: l.reviewWorkspace }),
916
+ /* @__PURE__ */ jsx("option", { value: "chosen", children: l.reviewChosen })
917
+ ]
918
+ }
919
+ ) }),
920
+ Array.isArray(action.documents) && /* @__PURE__ */ jsx(
921
+ DocumentRefList,
922
+ {
923
+ value: action.documents,
924
+ onChange: (documents) => set({ documents }),
925
+ ctx,
926
+ l,
927
+ addLabel: l.addDocument,
928
+ testId: `${testId}-chosen`
929
+ }
930
+ ),
931
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
932
+ /* @__PURE__ */ jsx(
933
+ Checkbox,
934
+ {
935
+ checked: !!action.overwrite,
936
+ onCheckedChange: (v) => set({ overwrite: v === true || void 0 })
937
+ }
938
+ ),
939
+ l.overwrite
940
+ ] })
941
+ ] });
942
+ }
943
+ function EditDocumentSettings({
944
+ step,
945
+ patch,
946
+ ctx,
947
+ l,
948
+ testId
949
+ }) {
950
+ const on = !!step.editDocument;
951
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
952
+ /* @__PURE__ */ jsxs("label", { className: "flex items-start gap-2 text-sm", children: [
953
+ /* @__PURE__ */ jsx(
954
+ Checkbox,
955
+ {
956
+ checked: on,
957
+ disabled: !!step.branch,
958
+ onCheckedChange: (v) => patch({ editDocument: v === true ? { step: "" } : void 0 }),
959
+ "data-testid": `${testId}-edit-document`
960
+ }
961
+ ),
962
+ /* @__PURE__ */ jsxs("span", { children: [
963
+ l.editDocument,
964
+ /* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground", children: l.editDocumentHint })
965
+ ] })
966
+ ] }),
967
+ on && /* @__PURE__ */ jsx(
968
+ DocumentRefPicker,
969
+ {
970
+ value: step.editDocument,
971
+ onChange: (editDocument) => patch({ editDocument }),
972
+ ctx,
973
+ l,
974
+ testId: `${testId}-edit-document-ref`
975
+ }
976
+ )
977
+ ] });
978
+ }
168
979
  var DEFAULT_STEP_INSPECTOR_LABELS = {
169
980
  workflow: "Workflow",
170
981
  title: "Title",
@@ -194,17 +1005,19 @@ var DEFAULT_STEP_INSPECTOR_LABELS = {
194
1005
  hint: "Hint",
195
1006
  instructions: "What to review",
196
1007
  instructionsHint: "Shown on the review task; {{field}} and {{steps.<id>}} work here.",
1008
+ reviewFields: "Filled in when approving",
1009
+ reviewFieldsHint: "E.g. a rating or a comment; the answers join the run\u2019s inputs.",
197
1010
  deleteStep: "Delete step"
198
1011
  };
199
- var FIELD_TYPES = ["text", "longtext", "boolean", "number", "date", "scope"];
200
- var selectClass = "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
201
- function Field({ label, children, hint }) {
202
- return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
203
- /* @__PURE__ */ jsx(Label, { className: "text-xs", children: label }),
204
- children,
205
- hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
206
- ] });
207
- }
1012
+ var FIELD_TYPES = [
1013
+ "text",
1014
+ "longtext",
1015
+ "boolean",
1016
+ "number",
1017
+ "date",
1018
+ "scope",
1019
+ "person"
1020
+ ];
208
1021
  var fieldName = (label, taken) => {
209
1022
  const base = label.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "").replace(/^[^a-z]+/, "") || "field";
210
1023
  let name = base;
@@ -218,7 +1031,12 @@ function StepInspector({
218
1031
  onChange,
219
1032
  onSelect,
220
1033
  workflows = [],
1034
+ people = [],
1035
+ tags = [],
1036
+ documents = [],
221
1037
  labels,
1038
+ actionLabels,
1039
+ signalLabels,
222
1040
  testId = "step-inspector"
223
1041
  }) {
224
1042
  const l = { ...DEFAULT_STEP_INSPECTOR_LABELS, ...labels };
@@ -247,6 +1065,30 @@ function StepInspector({
247
1065
  ] });
248
1066
  }
249
1067
  const patch = (p) => onChange(updateStep(workflow, step.id, p));
1068
+ const al = { ...DEFAULT_STEP_ACTION_SETTINGS_LABELS, ...actionLabels };
1069
+ const ctx = {
1070
+ earlier: upstreamSteps(steps, step.id),
1071
+ fields: runFields(workflow),
1072
+ people,
1073
+ tags,
1074
+ documents
1075
+ };
1076
+ const takenBy = (id) => steps.flatMap(
1077
+ (s) => s.id === id ? [] : s.kind === "form" ? s.inputs : s.kind === "review" ? s.fields ?? [] : []
1078
+ ).map((f) => f.name);
1079
+ const setFields = (before, after, key) => {
1080
+ const renamed = before.flatMap(
1081
+ (f, i) => after[i] && after[i].name !== f.name ? [[f.name, after[i].name]] : []
1082
+ );
1083
+ onChange(
1084
+ renamed.reduce(
1085
+ (w, [from, to]) => renameInput(w, from, to),
1086
+ updateStep(workflow, step.id, {
1087
+ [key]: key === "fields" && !after.length ? void 0 : after
1088
+ })
1089
+ )
1090
+ );
1091
+ };
250
1092
  const deps = stepDependencies(steps, step.id);
251
1093
  const titleOf = (id) => steps.find((s) => s.id === id)?.title ?? id;
252
1094
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", "data-testid": `${testId}-step`, children: [
@@ -296,18 +1138,8 @@ function StepInspector({
296
1138
  FormFields,
297
1139
  {
298
1140
  fields: step.inputs,
299
- taken: steps.flatMap((s) => s.kind === "form" && s.id !== step.id ? s.inputs : []).map((f) => f.name),
300
- onChange: (inputs) => {
301
- const renamed = step.inputs.flatMap(
302
- (f, i) => inputs[i] && inputs[i].name !== f.name ? [[f.name, inputs[i].name]] : []
303
- );
304
- onChange(
305
- renamed.reduce(
306
- (w, [from, to]) => renameInput(w, from, to),
307
- updateStep(workflow, step.id, { inputs })
308
- )
309
- );
310
- },
1141
+ taken: takenBy(step.id),
1142
+ onChange: (inputs) => setFields(step.inputs, inputs, "inputs"),
311
1143
  l,
312
1144
  testId
313
1145
  }
@@ -326,31 +1158,87 @@ function StepInspector({
326
1158
  /* @__PURE__ */ jsx(Field, { label: l.hint, children: /* @__PURE__ */ jsx(
327
1159
  Input,
328
1160
  {
329
- value: step.hint ?? "",
330
- onChange: (e) => patch({ hint: e.target.value || void 0 })
1161
+ value: step.hint ?? "",
1162
+ onChange: (e) => patch({ hint: e.target.value || void 0 })
1163
+ }
1164
+ ) })
1165
+ ] }),
1166
+ step.kind === "agent" && /* @__PURE__ */ jsxs(Fragment, { children: [
1167
+ /* @__PURE__ */ jsx(
1168
+ AgentSettings,
1169
+ {
1170
+ step,
1171
+ workflows,
1172
+ fields: runFields(workflow).map((f) => f.name),
1173
+ patch,
1174
+ l,
1175
+ testId
1176
+ }
1177
+ ),
1178
+ /* @__PURE__ */ jsx(EditDocumentSettings, { step, patch, ctx, l: al, testId })
1179
+ ] }),
1180
+ step.kind === "review" && /* @__PURE__ */ jsxs(Fragment, { children: [
1181
+ /* @__PURE__ */ jsx(Field, { label: l.instructions, hint: l.instructionsHint, children: /* @__PURE__ */ jsx(
1182
+ Textarea,
1183
+ {
1184
+ value: step.instructions ?? "",
1185
+ rows: 4,
1186
+ onChange: (e) => patch({ instructions: e.target.value || void 0 }),
1187
+ "data-testid": `${testId}-instructions`
1188
+ }
1189
+ ) }),
1190
+ /* @__PURE__ */ jsx(
1191
+ FormFields,
1192
+ {
1193
+ fields: step.fields ?? [],
1194
+ taken: takenBy(step.id),
1195
+ onChange: (fields) => setFields(step.fields ?? [], fields, "fields"),
1196
+ l: { ...l, fields: l.reviewFields },
1197
+ hint: l.reviewFieldsHint,
1198
+ testId: `${testId}-review`
331
1199
  }
332
- ) })
1200
+ )
333
1201
  ] }),
334
- step.kind === "agent" && /* @__PURE__ */ jsx(
335
- AgentSettings,
1202
+ step.kind === "action" && step.action.type === "sign" && /* @__PURE__ */ jsx(
1203
+ SignSettings,
336
1204
  {
337
- step,
338
- workflows,
339
- fields: runFields(workflow).map((f) => f.name),
340
- patch,
341
- l,
342
- testId
1205
+ action: step.action,
1206
+ onChange: (action) => patch({ action }),
1207
+ ctx,
1208
+ l: al,
1209
+ testId: `${testId}-sign`
343
1210
  }
344
1211
  ),
345
- step.kind === "review" && /* @__PURE__ */ jsx(Field, { label: l.instructions, hint: l.instructionsHint, children: /* @__PURE__ */ jsx(
346
- Textarea,
1212
+ step.kind === "action" && step.action.type === "email_draft" && /* @__PURE__ */ jsx(
1213
+ EmailDraftSettings,
347
1214
  {
348
- value: step.instructions ?? "",
349
- rows: 4,
350
- onChange: (e) => patch({ instructions: e.target.value || void 0 }),
351
- "data-testid": `${testId}-instructions`
1215
+ action: step.action,
1216
+ onChange: (action) => patch({ action }),
1217
+ ctx,
1218
+ l: al,
1219
+ testId: `${testId}-email`
352
1220
  }
353
- ) }),
1221
+ ),
1222
+ step.kind === "action" && step.action.type === "tabular_review" && /* @__PURE__ */ jsx(
1223
+ TabularReviewSettings,
1224
+ {
1225
+ action: step.action,
1226
+ onChange: (action) => patch({ action }),
1227
+ ctx,
1228
+ l: al,
1229
+ testId: `${testId}-review-grid`
1230
+ }
1231
+ ),
1232
+ canAssign(step) && /* @__PURE__ */ jsx(AssigneeSettings, { step, patch, ctx, l: al, testId }),
1233
+ /* @__PURE__ */ jsx(
1234
+ SignalsEditor,
1235
+ {
1236
+ step,
1237
+ onChange: (signals) => patch({ signals }),
1238
+ labels: signalLabels,
1239
+ testId: `${testId}-signals`
1240
+ }
1241
+ ),
354
1242
  /* @__PURE__ */ jsxs(
355
1243
  Button,
356
1244
  {
@@ -376,10 +1264,11 @@ function FormFields({
376
1264
  taken,
377
1265
  onChange,
378
1266
  l,
1267
+ hint,
379
1268
  testId
380
1269
  }) {
381
1270
  const set = (i, p) => onChange(fields.map((f, j) => j === i ? { ...f, ...p } : f));
382
- return /* @__PURE__ */ jsx(Field, { label: l.fields, children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": `${testId}-fields`, children: [
1271
+ return /* @__PURE__ */ jsx(Field, { label: l.fields, hint, children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", "data-testid": `${testId}-fields`, children: [
383
1272
  fields.map((f, i) => /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 rounded-md border border-border p-2", children: [
384
1273
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
385
1274
  /* @__PURE__ */ jsx(
@@ -412,10 +1301,12 @@ function FormFields({
412
1301
  "select",
413
1302
  {
414
1303
  "aria-label": l.fieldType,
415
- className: cn(selectClass, "h-8"),
1304
+ className: cn(selectClass2, "h-8"),
416
1305
  value: f.type,
417
1306
  onChange: (e) => set(i, { type: e.target.value }),
418
- children: FIELD_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: t }, t))
1307
+ children: (FIELD_TYPES.includes(f.type) ? FIELD_TYPES : [...FIELD_TYPES, f.type]).map(
1308
+ (t) => /* @__PURE__ */ jsx("option", { value: t, children: t }, t)
1309
+ )
419
1310
  }
420
1311
  ),
421
1312
  /* @__PURE__ */ jsxs("label", { className: "flex shrink-0 items-center gap-1.5 text-xs", children: [
@@ -479,7 +1370,7 @@ function AgentSettings({
479
1370
  /* @__PURE__ */ jsx(Field, { label: l.runs, children: /* @__PURE__ */ jsxs(
480
1371
  "select",
481
1372
  {
482
- className: selectClass,
1373
+ className: selectClass2,
483
1374
  value,
484
1375
  onChange: (e) => {
485
1376
  const id = e.target.value;
@@ -536,7 +1427,7 @@ function AgentSettings({
536
1427
  /* @__PURE__ */ jsx(Field, { label: l.thread, children: /* @__PURE__ */ jsxs(
537
1428
  "select",
538
1429
  {
539
- className: selectClass,
1430
+ className: selectClass2,
540
1431
  value: step.branch ? "branch" : "main",
541
1432
  onChange: (e) => patch({ branch: e.target.value === "branch" || void 0 }),
542
1433
  "data-testid": `${testId}-thread`,
@@ -549,7 +1440,7 @@ function AgentSettings({
549
1440
  /* @__PURE__ */ jsx(Field, { label: l.output, children: /* @__PURE__ */ jsxs(
550
1441
  "select",
551
1442
  {
552
- className: selectClass,
1443
+ className: selectClass2,
553
1444
  value: step.output ?? "answer",
554
1445
  onChange: (e) => patch({ output: e.target.value === "artifact" ? "artifact" : void 0 }),
555
1446
  children: [
@@ -560,6 +1451,138 @@ function AgentSettings({
560
1451
  ) })
561
1452
  ] });
562
1453
  }
1454
+
1455
+ // src/workflow-canvas/trigger.ts
1456
+ var WORKFLOW_SIGNAL_EVENT = "workflow_signal";
1457
+ var DEFAULT_WORKFLOW_TRIGGER = {
1458
+ start: "manual",
1459
+ runAt: "",
1460
+ rrule: "",
1461
+ timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : "UTC",
1462
+ eventKind: "",
1463
+ signal: "",
1464
+ afterTaskId: "",
1465
+ agentId: "",
1466
+ access: "ask_each_run"
1467
+ };
1468
+ function triggerProblem(trigger) {
1469
+ if (trigger.start === "once" && !trigger.runAt) return "runAt";
1470
+ if (trigger.start === "repeat" && !trigger.rrule.trim()) return "rrule";
1471
+ if (trigger.start === "event" && !trigger.eventKind.trim()) return "event";
1472
+ if (isSignalTrigger(trigger) && !trigger.signal.trim()) return "signal";
1473
+ if (trigger.start === "task" && !trigger.afterTaskId) return "task";
1474
+ return null;
1475
+ }
1476
+ var isSignalTrigger = (trigger) => trigger.start === "event" && trigger.eventKind.trim() === WORKFLOW_SIGNAL_EVENT;
1477
+ function eventFilter(trigger) {
1478
+ if (trigger.start !== "event") return null;
1479
+ if (isSignalTrigger(trigger)) return { signal: trigger.signal.trim() };
1480
+ return trigger.eventFilter && Object.keys(trigger.eventFilter).length ? trigger.eventFilter : null;
1481
+ }
1482
+ function triggerFields(trigger, clearOthers) {
1483
+ const none = clearOthers ? null : void 0;
1484
+ const filter = eventFilter(trigger);
1485
+ return {
1486
+ timezone: trigger.timezone,
1487
+ rrule: trigger.start === "repeat" ? trigger.rrule.trim() : none,
1488
+ run_at: trigger.start === "once" ? localInputToIso(trigger.runAt) : none,
1489
+ event_kind: trigger.start === "event" ? trigger.eventKind.trim() : none,
1490
+ // A step signal is `workflow_signal` narrowed to one signal name.
1491
+ event_filter: filter ?? none,
1492
+ after_conversation_ext_id: trigger.start === "task" ? trigger.afterTaskId : none,
1493
+ on_demand: trigger.start === "manual"
1494
+ };
1495
+ }
1496
+ var authMode = (trigger) => trigger.start === "manual" ? "run_now_temp" : trigger.access === "standing" ? "scheduled_permanent" : "scheduled_require_auth";
1497
+ var withoutUndefined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
1498
+ function plan(value, options) {
1499
+ return {
1500
+ goal: value.workflow.description,
1501
+ criteria: [],
1502
+ max_passes: 3,
1503
+ documents: [],
1504
+ steps: toPlanSteps(value.workflow, options)
1505
+ };
1506
+ }
1507
+ function builderToWorkflowRequest(value, workspaceId, options = {}) {
1508
+ return withoutUndefined({
1509
+ workspace_ext_id: workspaceId,
1510
+ name: value.workflow.title,
1511
+ description: value.workflow.description,
1512
+ active: true,
1513
+ shared: true,
1514
+ ...triggerFields(value.trigger, false),
1515
+ prompt: "",
1516
+ skill_ref: null,
1517
+ skill_inputs: null,
1518
+ agent_ext_id: value.trigger.agentId || null,
1519
+ auth_mode: authMode(value.trigger),
1520
+ plan: plan(value, options)
1521
+ });
1522
+ }
1523
+ function builderToWorkflowUpdate(value, options = {}) {
1524
+ return withoutUndefined({
1525
+ name: value.workflow.title,
1526
+ description: value.workflow.description,
1527
+ ...triggerFields(value.trigger, true),
1528
+ // The steps are what runs (a classic automation's single prompt or skill becomes its one step).
1529
+ prompt: "",
1530
+ skill_ref: null,
1531
+ skill_inputs: null,
1532
+ agent_ext_id: value.trigger.agentId || null,
1533
+ auth_mode: authMode(value.trigger),
1534
+ plan: plan(value, options)
1535
+ });
1536
+ }
1537
+ function workflowRecordToBuilder(record) {
1538
+ const planned = record.plan?.steps ?? [];
1539
+ const steps = planned.length ? fromPlanSteps(planned) : record.prompt || record.skill_ref ? [
1540
+ {
1541
+ id: "work",
1542
+ kind: "agent",
1543
+ title: record.name,
1544
+ ...record.skill_ref ? { workflow: record.skill_ref } : { run: { kind: "prompt", promptTemplate: record.prompt } }
1545
+ }
1546
+ ] : [];
1547
+ const when = workflowWhen(record);
1548
+ return {
1549
+ workflow: {
1550
+ id: record.external_id,
1551
+ title: record.name,
1552
+ description: record.description ?? "",
1553
+ inputs: [],
1554
+ landing: "chat",
1555
+ schedulable: false,
1556
+ run: { kind: "steps", steps, layout: layoutFromPlanSteps(planned ?? []) }
1557
+ },
1558
+ trigger: {
1559
+ ...DEFAULT_WORKFLOW_TRIGGER,
1560
+ start: when === "now" ? "manual" : when,
1561
+ runAt: isoToLocalInput(record.run_at),
1562
+ rrule: record.rrule ?? "",
1563
+ timezone: record.timezone || DEFAULT_WORKFLOW_TRIGGER.timezone,
1564
+ eventKind: record.event_kind ?? "",
1565
+ signal: record.event_kind === WORKFLOW_SIGNAL_EVENT && typeof record.event_filter?.signal === "string" ? record.event_filter.signal : "",
1566
+ eventFilter: record.event_kind && record.event_kind !== WORKFLOW_SIGNAL_EVENT && record.event_filter ? record.event_filter : void 0,
1567
+ afterTaskId: record.after_conversation_ext_id ?? "",
1568
+ agentId: record.agent_ext_id ?? "",
1569
+ access: record.auth_mode === "scheduled_permanent" ? "standing" : "ask_each_run"
1570
+ }
1571
+ };
1572
+ }
1573
+ function declaredSignals(records, current) {
1574
+ const out = /* @__PURE__ */ new Map();
1575
+ const add = (workflow, steps) => {
1576
+ for (const step of steps)
1577
+ for (const signal of step.signals ?? [])
1578
+ if (signal.name && !out.has(signal.name))
1579
+ out.set(signal.name, { value: signal.name, label: `${workflow} \u203A ${step.title}` });
1580
+ };
1581
+ for (const record of records)
1582
+ add(record.name, record.plan?.steps ?? []);
1583
+ if (current?.run.kind === "steps") add(current.title, current.run.steps);
1584
+ return [...out.values()];
1585
+ }
563
1586
  var DEFAULT_TRIGGER_INSPECTOR_LABELS = {
564
1587
  heading: "Start",
565
1588
  start: "Starts",
@@ -573,6 +1596,11 @@ var DEFAULT_TRIGGER_INSPECTOR_LABELS = {
573
1596
  runAt: "When",
574
1597
  event: "Event",
575
1598
  eventPlaceholder: "Pick an event",
1599
+ stepSignals: "When a step signals",
1600
+ signal: "Signal",
1601
+ signalPlaceholder: "e.g. risk-high",
1602
+ signalHint: "Starts as its own thread, linked to the thread whose step raised it, with that run\u2019s inputs.",
1603
+ signalSummary: "When a step signals \u201C{signal}\u201D",
576
1604
  afterTask: "After this task",
577
1605
  afterTaskPlaceholder: "Pick a task",
578
1606
  agent: "Runs as",
@@ -588,6 +1616,8 @@ function triggerSummary(trigger, options = {}) {
588
1616
  case "repeat":
589
1617
  return trigger.rrule ? describeRRule(trigger.rrule) : l.starts.repeat;
590
1618
  case "event":
1619
+ if (isSignalTrigger(trigger))
1620
+ return trigger.signal ? l.signalSummary.replace("{signal}", trigger.signal) : l.stepSignals;
591
1621
  return trigger.eventKind && options.eventLabel?.(trigger.eventKind) || trigger.eventKind || l.starts.event;
592
1622
  case "task":
593
1623
  return trigger.afterTaskId && options.taskLabel?.(trigger.afterTaskId) || l.starts.task;
@@ -595,7 +1625,7 @@ function triggerSummary(trigger, options = {}) {
595
1625
  return l.starts.manual;
596
1626
  }
597
1627
  }
598
- var selectClass2 = "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
1628
+ var selectClass3 = "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring";
599
1629
  var STARTS = ["manual", "once", "repeat", "event", "task"];
600
1630
  function TriggerInspector({
601
1631
  trigger,
@@ -603,11 +1633,13 @@ function TriggerInspector({
603
1633
  agents = [],
604
1634
  eventKinds = [],
605
1635
  tasks = [],
1636
+ signals = [],
606
1637
  labels,
607
1638
  testId = "trigger-inspector"
608
1639
  }) {
609
1640
  const l = { ...DEFAULT_TRIGGER_INSPECTOR_LABELS, ...labels };
610
1641
  const set = (patch) => onChange({ ...trigger, ...patch });
1642
+ const events = eventKinds.some((k) => k.value === WORKFLOW_SIGNAL_EVENT) ? eventKinds : [...eventKinds, { value: WORKFLOW_SIGNAL_EVENT, label: l.stepSignals }];
611
1643
  return /* @__PURE__ */ jsxs("div", { className: "space-y-4", "data-testid": testId, children: [
612
1644
  /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: l.heading }),
613
1645
  /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
@@ -647,23 +1679,39 @@ function TriggerInspector({
647
1679
  /* @__PURE__ */ jsxs(
648
1680
  "select",
649
1681
  {
650
- className: selectClass2,
1682
+ className: selectClass3,
651
1683
  value: trigger.eventKind,
652
- onChange: (e) => set({ eventKind: e.target.value }),
1684
+ onChange: (e) => set({ eventKind: e.target.value, eventFilter: void 0 }),
653
1685
  "data-testid": `${testId}-event`,
654
1686
  children: [
655
1687
  /* @__PURE__ */ jsx("option", { value: "", children: l.eventPlaceholder }),
656
- eventKinds.map((k) => /* @__PURE__ */ jsx("option", { value: k.value, children: k.label }, k.value))
1688
+ events.map((k) => /* @__PURE__ */ jsx("option", { value: k.value, children: k.label }, k.value))
657
1689
  ]
658
1690
  }
659
1691
  )
660
1692
  ] }),
1693
+ isSignalTrigger(trigger) && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
1694
+ /* @__PURE__ */ jsx(Label, { className: "text-xs", htmlFor: `${testId}-signal`, children: l.signal }),
1695
+ /* @__PURE__ */ jsx(
1696
+ Input,
1697
+ {
1698
+ id: `${testId}-signal`,
1699
+ list: `${testId}-signal-options`,
1700
+ value: trigger.signal,
1701
+ placeholder: l.signalPlaceholder,
1702
+ onChange: (e) => set({ signal: e.target.value.trim().toLowerCase() }),
1703
+ "data-testid": `${testId}-signal`
1704
+ }
1705
+ ),
1706
+ /* @__PURE__ */ jsx("datalist", { id: `${testId}-signal-options`, children: signals.map((s) => /* @__PURE__ */ jsx("option", { value: s.value, children: s.label }, s.value)) }),
1707
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.signalHint })
1708
+ ] }),
661
1709
  trigger.start === "task" && /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
662
1710
  /* @__PURE__ */ jsx(Label, { className: "text-xs", children: l.afterTask }),
663
1711
  /* @__PURE__ */ jsxs(
664
1712
  "select",
665
1713
  {
666
- className: selectClass2,
1714
+ className: selectClass3,
667
1715
  value: trigger.afterTaskId,
668
1716
  onChange: (e) => set({ afterTaskId: e.target.value }),
669
1717
  "data-testid": `${testId}-after-task`,
@@ -692,7 +1740,7 @@ function TriggerInspector({
692
1740
  /* @__PURE__ */ jsxs(
693
1741
  "select",
694
1742
  {
695
- className: selectClass2,
1743
+ className: selectClass3,
696
1744
  value: trigger.access,
697
1745
  onChange: (e) => set({ access: e.target.value === "standing" ? "standing" : "ask_each_run" }),
698
1746
  "data-testid": `${testId}-access`,
@@ -749,12 +1797,19 @@ var DEFAULT_WORKFLOW_CANVAS_LABELS = {
749
1797
  upload: "Upload",
750
1798
  agent: "AI step",
751
1799
  review: "Approval",
1800
+ sign: "Sign",
1801
+ email_draft: "Email draft",
1802
+ tabular_review: "Tabular review",
1803
+ redline: "Tracked changes",
752
1804
  branch: "Branch",
753
1805
  kindHints: {
754
1806
  form: "Ask for details",
755
1807
  upload: "Collect files",
756
1808
  agent: "Run a skill or an instruction",
757
- review: "A person approves"
1809
+ review: "A person approves",
1810
+ sign: "People e-sign a document",
1811
+ email_draft: "Prepare an email to send",
1812
+ tabular_review: "Review documents in a grid"
758
1813
  },
759
1814
  addNext: "Add the next step",
760
1815
  runs: "Runs \u201C{name}\u201D",
@@ -762,6 +1817,14 @@ var DEFAULT_WORKFLOW_CANVAS_LABELS = {
762
1817
  fields: "{count} fields",
763
1818
  noFields: "No fields yet",
764
1819
  approvedBy: "A person approves",
1820
+ signers: "{count} signers",
1821
+ chooseDocument: "Choose the document to sign",
1822
+ emailTo: "To {to}",
1823
+ noRecipients: "Add a recipient",
1824
+ reviewColumns: "{count} columns",
1825
+ noColumns: "Choose the columns",
1826
+ assignee: "{name}",
1827
+ remind: "Reminds after {hours}h",
765
1828
  emptyTitle: "Start your workflow",
766
1829
  emptyHint: "Add the first step: what should happen when it starts?",
767
1830
  fitView: "Fit view"
@@ -771,9 +1834,12 @@ var STEP_KIND_ICONS = {
771
1834
  form: FileInput,
772
1835
  upload: Upload,
773
1836
  agent: Bot,
774
- review: ClipboardCheck
1837
+ review: ClipboardCheck,
1838
+ sign: PenLine,
1839
+ email_draft: Mail,
1840
+ tabular_review: Table2
775
1841
  };
776
- var KINDS = ["form", "upload", "agent", "review"];
1842
+ var KINDS = WORKFLOW_STEP_KINDS;
777
1843
  function AddNext({
778
1844
  from,
779
1845
  onAdd,
@@ -826,20 +1892,23 @@ function AddNext({
826
1892
  }
827
1893
  function PhaseMark({ phase }) {
828
1894
  if (phase === "running") return /* @__PURE__ */ jsx(Loader2, { className: "wf-kind-text size-4 animate-spin" });
1895
+ if (phase === "waiting") return /* @__PURE__ */ jsx(Hourglass, { className: "wf-kind-text size-4" });
829
1896
  if (phase === "done") return /* @__PURE__ */ jsx(Check, { className: "wf-kind-text size-4" });
830
1897
  if (phase === "failed") return /* @__PURE__ */ jsx(AlertTriangle, { className: "size-4 text-destructive" });
831
1898
  if (phase === "skipped") return /* @__PURE__ */ jsx(MinusCircle, { className: "size-4 text-muted-foreground" });
832
1899
  return null;
833
1900
  }
834
1901
  function StepNode({ data }) {
835
- const { step, phase, summary, icon, l, onAdd, testId } = data;
836
- const KindIcon = STEP_KIND_ICONS[step.kind];
1902
+ const { step, phase, summary, assignee, icon, l, onAdd, testId } = data;
1903
+ const kind = stepKindOf(step);
1904
+ const KindIcon = STEP_KIND_ICONS[kind];
1905
+ const redline = step.kind === "agent" && !!step.editDocument;
837
1906
  return /* @__PURE__ */ jsxs(
838
1907
  "div",
839
1908
  {
840
1909
  className: cn(
841
1910
  "wf-node w-64 py-3 pl-4 pr-3 text-left",
842
- `wf-kind-${step.kind}`,
1911
+ `wf-kind-${kind}`,
843
1912
  phase && `wf-phase-${phase}`
844
1913
  ),
845
1914
  "data-testid": `${testId}-node-${step.id}`,
@@ -850,15 +1919,44 @@ function StepNode({ data }) {
850
1919
  /* @__PURE__ */ jsx("span", { className: "wf-badge flex size-8 shrink-0 items-center justify-center rounded-lg [&_svg]:size-4", children: icon ?? /* @__PURE__ */ jsx(KindIcon, {}) }),
851
1920
  /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
852
1921
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
853
- /* @__PURE__ */ jsx("span", { className: "wf-kind-text text-[10px] font-semibold uppercase tracking-wider", children: l[step.kind] }),
1922
+ /* @__PURE__ */ jsx("span", { className: "wf-kind-text text-[10px] font-semibold uppercase tracking-wider", children: l[kind] }),
854
1923
  /* @__PURE__ */ jsx(PhaseMark, { phase })
855
1924
  ] }),
856
1925
  /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-semibold leading-snug", children: step.title }),
857
1926
  summary && /* @__PURE__ */ jsx("p", { className: "mt-0.5 line-clamp-2 text-xs leading-snug text-muted-foreground", children: summary }),
858
- step.kind === "agent" && step.branch && /* @__PURE__ */ jsxs("span", { className: "mt-1.5 inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground", children: [
859
- /* @__PURE__ */ jsx(GitBranch, { className: "size-3" }),
860
- " ",
861
- l.branch
1927
+ (redline || step.kind === "agent" && step.branch || assignee) && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 flex flex-wrap gap-1", children: [
1928
+ step.kind === "agent" && step.branch && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground", children: [
1929
+ /* @__PURE__ */ jsx(GitBranch, { className: "size-3" }),
1930
+ " ",
1931
+ l.branch
1932
+ ] }),
1933
+ redline && /* @__PURE__ */ jsxs(
1934
+ "span",
1935
+ {
1936
+ className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
1937
+ "data-testid": `${testId}-node-${step.id}-redline`,
1938
+ children: [
1939
+ /* @__PURE__ */ jsx(FilePenLine, { className: "size-3" }),
1940
+ " ",
1941
+ l.redline
1942
+ ]
1943
+ }
1944
+ ),
1945
+ assignee && /* @__PURE__ */ jsxs(
1946
+ "span",
1947
+ {
1948
+ className: "inline-flex max-w-full items-center gap-1 truncate rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
1949
+ title: assignee,
1950
+ "data-testid": `${testId}-node-${step.id}-assignee`,
1951
+ children: [
1952
+ /* @__PURE__ */ jsx(UserRound, { className: "size-3 shrink-0" }),
1953
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: l.assignee.replace(
1954
+ "{name}",
1955
+ assignee.charAt(0).toUpperCase() + assignee.slice(1)
1956
+ ) })
1957
+ ]
1958
+ }
1959
+ )
862
1960
  ] })
863
1961
  ] })
864
1962
  ] }),
@@ -907,6 +2005,16 @@ function summaryOf(step, l, workflowTitle) {
907
2005
  return step.hint;
908
2006
  case "review":
909
2007
  return step.instructions ? firstWords(step.instructions) : l.approvedBy;
2008
+ case "action": {
2009
+ const a = step.action;
2010
+ if (a.type === "sign")
2011
+ return !a.document ? l.chooseDocument : a.signers.length ? l.signers.replace("{count}", String(a.signers.length)) : void 0;
2012
+ if (a.type === "email_draft") {
2013
+ const to = a.to.find((t) => t.trim());
2014
+ return to ? l.emailTo.replace("{to}", to) : l.noRecipients;
2015
+ }
2016
+ return a.tags.length ? l.reviewColumns.replace("{count}", String(a.tags.length)) : l.noColumns;
2017
+ }
910
2018
  }
911
2019
  }
912
2020
  function WorkflowCanvas({
@@ -918,6 +2026,7 @@ function WorkflowCanvas({
918
2026
  onAddAfter,
919
2027
  phases,
920
2028
  workflowTitle,
2029
+ assigneeOf,
921
2030
  trigger,
922
2031
  renderIcon,
923
2032
  labels,
@@ -956,6 +2065,7 @@ function WorkflowCanvas({
956
2065
  step,
957
2066
  phase: phases?.[step.id],
958
2067
  summary: summaryOf(step, l, workflowTitle),
2068
+ assignee: assigneeOf?.(step),
959
2069
  icon: step.icon && renderIcon ? renderIcon(step.icon) : void 0,
960
2070
  l,
961
2071
  onAdd: onAddAfter,
@@ -963,7 +2073,18 @@ function WorkflowCanvas({
963
2073
  }
964
2074
  }))
965
2075
  ];
966
- }, [workflow, selected, phases, workflowTitle, trigger, renderIcon, l, onAddAfter, testId]);
2076
+ }, [
2077
+ workflow,
2078
+ selected,
2079
+ phases,
2080
+ workflowTitle,
2081
+ assigneeOf,
2082
+ trigger,
2083
+ renderIcon,
2084
+ l,
2085
+ onAddAfter,
2086
+ testId
2087
+ ]);
967
2088
  const [nodes, setNodes] = useState(built);
968
2089
  useEffect(() => setNodes(built), [built]);
969
2090
  const edges = useMemo(
@@ -1177,10 +2298,17 @@ var DEFAULT_WORKFLOW_BUILDER_LABELS = {
1177
2298
  unknown: "\u201C{step}\u201D waits for a step that does not exist.",
1178
2299
  cycle: "\u201C{step}\u201D waits for itself (a loop).",
1179
2300
  order: "\u201C{step}\u201D is listed before a step it waits for."
2301
+ },
2302
+ missing: {
2303
+ document: "\u201C{step}\u201D needs a document.",
2304
+ signers: "\u201C{step}\u201D needs at least one signer.",
2305
+ recipients: "\u201C{step}\u201D needs a recipient.",
2306
+ tags: "\u201C{step}\u201D needs at least one column.",
2307
+ documents: "\u201C{step}\u201D needs documents to review."
1180
2308
  }
1181
2309
  };
1182
2310
  var PANEL_WIDTH = 344;
1183
- var KINDS2 = ["form", "upload", "agent", "review"];
2311
+ var KINDS2 = WORKFLOW_STEP_KINDS;
1184
2312
  function WorkflowBuilder({
1185
2313
  value,
1186
2314
  onChange,
@@ -1188,6 +2316,10 @@ function WorkflowBuilder({
1188
2316
  agents = [],
1189
2317
  eventKinds = [],
1190
2318
  tasks = [],
2319
+ signals = [],
2320
+ people = [],
2321
+ tags = [],
2322
+ documents = [],
1191
2323
  compose,
1192
2324
  renderIcon,
1193
2325
  actions,
@@ -1210,6 +2342,10 @@ function WorkflowBuilder({
1210
2342
  const { workflow, trigger } = value;
1211
2343
  const steps = workflowSteps(workflow);
1212
2344
  const problems = validateWorkflowGraph(steps);
2345
+ const missing = stepConfigProblems(steps);
2346
+ const nameOf = (id) => people.find((p) => p.value === id)?.label;
2347
+ const fields = runFields(workflow);
2348
+ const assigneeOf = (step) => canAssign(step) ? assigneeName(step.assignee, { nameOf, fields }) : void 0;
1213
2349
  const titles = useMemo(() => new Map(workflows.map((w) => [w.id, w.title])), [workflows]);
1214
2350
  const setWorkflow = (next) => onChange({ ...value, workflow: next });
1215
2351
  const addAfter = (from, kind) => {
@@ -1322,10 +2458,16 @@ function WorkflowBuilder({
1322
2458
  ] }),
1323
2459
  actions && /* @__PURE__ */ jsx("div", { className: "ml-auto flex flex-wrap items-center gap-2", children: actions })
1324
2460
  ] }),
1325
- problems.length > 0 && /* @__PURE__ */ jsx("ul", { className: "space-y-1 text-sm text-destructive", "data-testid": `${testId}-problems`, children: problems.map((p, i) => /* @__PURE__ */ jsx("li", { children: l.problems[p.code].replace(
1326
- "{step}",
1327
- steps.find((s) => s.id === p.step)?.title ?? p.step
1328
- ) }, i)) }),
2461
+ problems.length + missing.length > 0 && /* @__PURE__ */ jsxs("ul", { className: "space-y-1 text-sm text-destructive", "data-testid": `${testId}-problems`, children: [
2462
+ problems.map((p, i) => /* @__PURE__ */ jsx("li", { children: l.problems[p.code].replace(
2463
+ "{step}",
2464
+ steps.find((s) => s.id === p.step)?.title ?? p.step
2465
+ ) }, i)),
2466
+ missing.map((p, i) => /* @__PURE__ */ jsx("li", { "data-testid": `${testId}-missing-${p.step}-${p.missing}`, children: l.missing[p.missing].replace(
2467
+ "{step}",
2468
+ steps.find((s) => s.id === p.step)?.title ?? p.step
2469
+ ) }, `m${i}`))
2470
+ ] }),
1329
2471
  mode === "design" ? /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1330
2472
  /* @__PURE__ */ jsx(
1331
2473
  WorkflowCanvas,
@@ -1338,6 +2480,7 @@ function WorkflowBuilder({
1338
2480
  onAddAfter: addAfter,
1339
2481
  trigger: { title: l.start, summary },
1340
2482
  workflowTitle: (id) => titles.get(id),
2483
+ assigneeOf,
1341
2484
  renderIcon,
1342
2485
  labels: canvasLabels,
1343
2486
  reserveRight: panelOpen ? PANEL_WIDTH : 0,
@@ -1370,6 +2513,12 @@ function WorkflowBuilder({
1370
2513
  agents,
1371
2514
  eventKinds,
1372
2515
  tasks,
2516
+ signals: [
2517
+ ...signals,
2518
+ ...declaredSignals([], workflow).filter(
2519
+ (d) => !signals.some((s) => s.value === d.value)
2520
+ )
2521
+ ],
1373
2522
  labels: triggerLabels,
1374
2523
  testId: `${testId}-trigger`
1375
2524
  }
@@ -1381,6 +2530,9 @@ function WorkflowBuilder({
1381
2530
  onChange: setWorkflow,
1382
2531
  onSelect: setSelected,
1383
2532
  workflows,
2533
+ people,
2534
+ tags,
2535
+ documents,
1384
2536
  labels: inspectorLabels,
1385
2537
  testId: `${testId}-inspector`
1386
2538
  }
@@ -1447,111 +2599,6 @@ function WorkflowPreview({
1447
2599
  }
1448
2600
  );
1449
2601
  }
1450
-
1451
- // src/workflow-canvas/trigger.ts
1452
- var DEFAULT_WORKFLOW_TRIGGER = {
1453
- start: "manual",
1454
- runAt: "",
1455
- rrule: "",
1456
- timezone: typeof Intl !== "undefined" ? Intl.DateTimeFormat().resolvedOptions().timeZone : "UTC",
1457
- eventKind: "",
1458
- afterTaskId: "",
1459
- agentId: "",
1460
- access: "ask_each_run"
1461
- };
1462
- function triggerProblem(trigger) {
1463
- if (trigger.start === "once" && !trigger.runAt) return "runAt";
1464
- if (trigger.start === "repeat" && !trigger.rrule.trim()) return "rrule";
1465
- if (trigger.start === "event" && !trigger.eventKind.trim()) return "event";
1466
- if (trigger.start === "task" && !trigger.afterTaskId) return "task";
1467
- return null;
1468
- }
1469
- function triggerFields(trigger, clearOthers) {
1470
- const none = clearOthers ? null : void 0;
1471
- return {
1472
- timezone: trigger.timezone,
1473
- rrule: trigger.start === "repeat" ? trigger.rrule.trim() : none,
1474
- run_at: trigger.start === "once" ? localInputToIso(trigger.runAt) : none,
1475
- event_kind: trigger.start === "event" ? trigger.eventKind.trim() : none,
1476
- after_conversation_ext_id: trigger.start === "task" ? trigger.afterTaskId : none,
1477
- on_demand: trigger.start === "manual"
1478
- };
1479
- }
1480
- var authMode = (trigger) => trigger.start === "manual" ? "run_now_temp" : trigger.access === "standing" ? "scheduled_permanent" : "scheduled_require_auth";
1481
- var withoutUndefined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
1482
- function plan(value, options) {
1483
- return {
1484
- goal: value.workflow.description,
1485
- criteria: [],
1486
- max_passes: 3,
1487
- documents: [],
1488
- steps: toPlanSteps(value.workflow, options)
1489
- };
1490
- }
1491
- function builderToWorkflowRequest(value, workspaceId, options = {}) {
1492
- return withoutUndefined({
1493
- workspace_ext_id: workspaceId,
1494
- name: value.workflow.title,
1495
- description: value.workflow.description,
1496
- active: true,
1497
- shared: true,
1498
- ...triggerFields(value.trigger, false),
1499
- prompt: "",
1500
- skill_ref: null,
1501
- skill_inputs: null,
1502
- agent_ext_id: value.trigger.agentId || null,
1503
- auth_mode: authMode(value.trigger),
1504
- plan: plan(value, options)
1505
- });
1506
- }
1507
- function builderToWorkflowUpdate(value, options = {}) {
1508
- return withoutUndefined({
1509
- name: value.workflow.title,
1510
- description: value.workflow.description,
1511
- ...triggerFields(value.trigger, true),
1512
- // The steps are what runs (a classic automation's single prompt or skill becomes its one step).
1513
- prompt: "",
1514
- skill_ref: null,
1515
- skill_inputs: null,
1516
- agent_ext_id: value.trigger.agentId || null,
1517
- auth_mode: authMode(value.trigger),
1518
- plan: plan(value, options)
1519
- });
1520
- }
1521
- function workflowRecordToBuilder(record) {
1522
- const planned = record.plan?.steps ?? [];
1523
- const steps = planned.length ? fromPlanSteps(planned) : record.prompt || record.skill_ref ? [
1524
- {
1525
- id: "work",
1526
- kind: "agent",
1527
- title: record.name,
1528
- ...record.skill_ref ? { workflow: record.skill_ref } : { run: { kind: "prompt", promptTemplate: record.prompt } }
1529
- }
1530
- ] : [];
1531
- const when = workflowWhen(record);
1532
- return {
1533
- workflow: {
1534
- id: record.external_id,
1535
- title: record.name,
1536
- description: record.description ?? "",
1537
- inputs: [],
1538
- landing: "chat",
1539
- schedulable: false,
1540
- run: { kind: "steps", steps, layout: layoutFromPlanSteps(planned ?? []) }
1541
- },
1542
- trigger: {
1543
- ...DEFAULT_WORKFLOW_TRIGGER,
1544
- start: when === "now" ? "manual" : when,
1545
- runAt: isoToLocalInput(record.run_at),
1546
- rrule: record.rrule ?? "",
1547
- timezone: record.timezone || DEFAULT_WORKFLOW_TRIGGER.timezone,
1548
- eventKind: record.event_kind ?? "",
1549
- afterTaskId: record.after_conversation_ext_id ?? "",
1550
- agentId: record.agent_ext_id ?? "",
1551
- access: record.auth_mode === "scheduled_permanent" ? "standing" : "ask_each_run"
1552
- }
1553
- };
1554
- }
1555
2602
  var DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS = {
1556
2603
  save: "Save",
1557
2604
  saving: "Saving\u2026",
@@ -1564,7 +2611,8 @@ var DEFAULT_WORKFLOW_EVENT_KINDS = [
1564
2611
  { value: "conversation_ready", label: "Work is ready for me" },
1565
2612
  { value: "mention", label: "Someone mentions me" },
1566
2613
  { value: "workflow_completed", label: "Another workflow finishes" },
1567
- { value: "workflow_failed", label: "Another workflow fails" }
2614
+ { value: "workflow_failed", label: "Another workflow fails" },
2615
+ { value: "workflow_signal", label: "When a step signals" }
1568
2616
  ];
1569
2617
  function ConnectedWorkflowBuilder({
1570
2618
  workflowId,
@@ -1580,7 +2628,22 @@ function ConnectedWorkflowBuilder({
1580
2628
  ...builderProps
1581
2629
  }) {
1582
2630
  const l = { ...DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS, ...connectedLabels };
1583
- const { workspaceId } = useConnection();
2631
+ const { workspaceId, status, ensureWorkspaceOpen } = useConnection();
2632
+ const members = useWorkspaceUsers(workspaceId ?? void 0, {
2633
+ enabled: status === "authenticated" && !!workspaceId,
2634
+ beforeFetch: ensureWorkspaceOpen
2635
+ });
2636
+ const tagsQuery = useTags(workspaceId ?? void 0);
2637
+ const docsQuery = useDocuments(workspaceId ?? void 0);
2638
+ const people = (members.data ?? []).map((m) => ({
2639
+ value: m.user.external_id,
2640
+ label: [m.user.given_name, m.user.family_name].filter(Boolean).join(" ") || m.user.email
2641
+ }));
2642
+ const tagOptions = (tagsQuery.data ?? []).map((t) => ({ value: t.external_id, label: t.name }));
2643
+ const documentOptions = (docsQuery.data ?? []).map((d) => ({
2644
+ value: d.external_id,
2645
+ label: d.file_name ?? d.external_id
2646
+ }));
1584
2647
  const saved = useWorkflows();
1585
2648
  const skills = useSkills();
1586
2649
  const agentsQuery = useAgents();
@@ -1619,7 +2682,7 @@ function ConnectedWorkflowBuilder({
1619
2682
  }));
1620
2683
  const tasks = (conversations.data ?? []).filter((c) => c.status && c.status !== "done").map((c) => ({ value: c.external_id, label: c.title || c.external_id }));
1621
2684
  const options = { resolveWorkflow: (wid) => workflows.find((w) => w.id === wid), compose };
1622
- const problem = triggerProblem(value.trigger) ?? (validateWorkflowGraph(workflowSteps(value.workflow)).length ? "graph" : null);
2685
+ const problem = triggerProblem(value.trigger) ?? (validateWorkflowGraph(workflowSteps(value.workflow)).length || stepConfigProblems(workflowSteps(value.workflow)).length ? "graph" : null);
1623
2686
  const busy = create.isPending || update.isPending || run.isPending;
1624
2687
  const save = async () => {
1625
2688
  if (!workspaceId) return void 0;
@@ -1641,6 +2704,10 @@ function ConnectedWorkflowBuilder({
1641
2704
  agents,
1642
2705
  eventKinds,
1643
2706
  tasks,
2707
+ people,
2708
+ tags: tagOptions,
2709
+ documents: documentOptions,
2710
+ signals: declaredSignals(saved.data ?? []),
1644
2711
  compose,
1645
2712
  testId,
1646
2713
  actions: /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -1685,6 +2752,6 @@ function ConnectedWorkflowBuilder({
1685
2752
  );
1686
2753
  }
1687
2754
 
1688
- export { ConnectedWorkflowBuilder, DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS, DEFAULT_STEP_INSPECTOR_LABELS, DEFAULT_TRIGGER_INSPECTOR_LABELS, DEFAULT_WORKFLOW_BUILDER_LABELS, DEFAULT_WORKFLOW_CANVAS_LABELS, DEFAULT_WORKFLOW_EVENT_KINDS, DEFAULT_WORKFLOW_TRIGGER, StepInspector, TRIGGER_NODE, TriggerInspector, WorkflowBuilder, WorkflowCanvas, addStep, autoLayout, builderToWorkflowRequest, builderToWorkflowUpdate, connectSteps, disconnectSteps, layoutWithDefaults, moveStep, newSteppedWorkflow, removeStep, stepIdFor, triggerProblem, triggerSummary, updateStep, workflowRecordToBuilder, wouldCycle };
2755
+ export { ConnectedWorkflowBuilder, DEFAULT_CONNECTED_WORKFLOW_BUILDER_LABELS, DEFAULT_SIGNALS_EDITOR_LABELS, DEFAULT_STEP_INSPECTOR_LABELS, DEFAULT_TRIGGER_INSPECTOR_LABELS, DEFAULT_WORKFLOW_BUILDER_LABELS, DEFAULT_WORKFLOW_CANVAS_LABELS, DEFAULT_WORKFLOW_EVENT_KINDS, DEFAULT_WORKFLOW_TRIGGER, SignalsEditor, StepInspector, TRIGGER_NODE, TriggerInspector, WORKFLOW_SIGNAL_EVENT, WorkflowBuilder, WorkflowCanvas, addStep, autoLayout, builderToWorkflowRequest, builderToWorkflowUpdate, connectSteps, declaredSignals, disconnectSteps, isSignalTrigger, layoutWithDefaults, moveStep, newSteppedWorkflow, removeStep, signalConditions, signalSlug, stepIdFor, triggerProblem, triggerSummary, updateStep, workflowRecordToBuilder, wouldCycle };
1689
2756
  //# sourceMappingURL=index.js.map
1690
2757
  //# sourceMappingURL=index.js.map