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