@arbidocs/blocks 0.4.72 → 0.4.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/agents/index.cjs +401 -262
  2. package/dist/agents/index.js +7 -4
  3. package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
  4. package/dist/agents/tasks/WorkflowThreadStrip.d.ts +58 -0
  5. package/dist/agents/tasks/index.d.ts +1 -0
  6. package/dist/agents/workflows/WorkflowRunner.d.ts +86 -0
  7. package/dist/agents/workflows/WorkflowStepBar.d.ts +23 -0
  8. package/dist/agents/workflows/index.d.ts +7 -1
  9. package/dist/agents/workflows/planSteps.d.ts +28 -0
  10. package/dist/agents/workflows/run.d.ts +98 -0
  11. package/dist/agents/workflows/skillMarkdown.d.ts +15 -0
  12. package/dist/agents/workflows/types.d.ts +111 -0
  13. package/dist/agents/workflows/useWorkflowPreview.d.ts +14 -0
  14. package/dist/agents/workflows/useWorkflowView.d.ts +54 -0
  15. package/dist/agents/workflows/workflow.d.ts +3 -1
  16. package/dist/chat/index.cjs +124 -124
  17. package/dist/chat/index.js +3 -3
  18. package/dist/{chunk-DH7C2UJO.cjs → chunk-5LP54CWR.cjs} +299 -526
  19. package/dist/chunk-5LP54CWR.cjs.map +1 -0
  20. package/dist/{chunk-3SFFTSOI.cjs → chunk-7CVF3DK2.cjs} +5 -5
  21. package/dist/{chunk-3SFFTSOI.cjs.map → chunk-7CVF3DK2.cjs.map} +1 -1
  22. package/dist/chunk-7D737FLE.cjs +43 -0
  23. package/dist/chunk-7D737FLE.cjs.map +1 -0
  24. package/dist/{chunk-V3L5DONY.cjs → chunk-B4SRYJLM.cjs} +31 -2
  25. package/dist/chunk-B4SRYJLM.cjs.map +1 -0
  26. package/dist/{chunk-LFGJAZ5H.js → chunk-DDF5GPIJ.js} +6 -36
  27. package/dist/chunk-DDF5GPIJ.js.map +1 -0
  28. package/dist/chunk-DETZZBG2.cjs +91 -0
  29. package/dist/chunk-DETZZBG2.cjs.map +1 -0
  30. package/dist/chunk-EVUEIBNU.js +89 -0
  31. package/dist/chunk-EVUEIBNU.js.map +1 -0
  32. package/dist/{chunk-G5QTGKDJ.cjs → chunk-HITAN7JF.cjs} +8 -8
  33. package/dist/{chunk-G5QTGKDJ.cjs.map → chunk-HITAN7JF.cjs.map} +1 -1
  34. package/dist/{chunk-3VQYJBOI.js → chunk-HOXKR26S.js} +31 -4
  35. package/dist/chunk-HOXKR26S.js.map +1 -0
  36. package/dist/{chunk-KJ3QEKOJ.cjs → chunk-IPGKTUF7.cjs} +7 -33
  37. package/dist/chunk-IPGKTUF7.cjs.map +1 -0
  38. package/dist/{chunk-IMC2Z32C.js → chunk-KOSGX3UK.js} +269 -485
  39. package/dist/chunk-KOSGX3UK.js.map +1 -0
  40. package/dist/{chunk-KOXUBCLL.js → chunk-MK6NJQGF.js} +4 -4
  41. package/dist/{chunk-KOXUBCLL.js.map → chunk-MK6NJQGF.js.map} +1 -1
  42. package/dist/{chunk-THO7DZNN.cjs → chunk-MUMH3Z6K.cjs} +20 -15
  43. package/dist/chunk-MUMH3Z6K.cjs.map +1 -0
  44. package/dist/{chunk-5HOAOKZL.js → chunk-OYMWV45N.js} +21 -16
  45. package/dist/chunk-OYMWV45N.js.map +1 -0
  46. package/dist/chunk-P2RBE3FD.cjs +1448 -0
  47. package/dist/chunk-P2RBE3FD.cjs.map +1 -0
  48. package/dist/{chunk-G5DP27DU.js → chunk-UIWLDSTF.js} +3 -29
  49. package/dist/chunk-UIWLDSTF.js.map +1 -0
  50. package/dist/{chunk-VRPRAU3J.js → chunk-WJEKRSPH.js} +3 -3
  51. package/dist/{chunk-VRPRAU3J.js.map → chunk-WJEKRSPH.js.map} +1 -1
  52. package/dist/chunk-XD2M6LIG.js +41 -0
  53. package/dist/chunk-XD2M6LIG.js.map +1 -0
  54. package/dist/chunk-YWYVIQ7T.js +1402 -0
  55. package/dist/chunk-YWYVIQ7T.js.map +1 -0
  56. package/dist/{chunk-WBDK4PIA.cjs → chunk-Z5VUZ6YD.cjs} +6 -37
  57. package/dist/chunk-Z5VUZ6YD.cjs.map +1 -0
  58. package/dist/connect/docx.cjs +2 -2
  59. package/dist/connect/docx.js +1 -1
  60. package/dist/connect/index.cjs +379 -27
  61. package/dist/connect/index.cjs.map +1 -1
  62. package/dist/connect/index.d.ts +1 -0
  63. package/dist/connect/index.js +362 -11
  64. package/dist/connect/index.js.map +1 -1
  65. package/dist/connection/ConnectedWorkflowBuilder.d.ts +44 -0
  66. package/dist/connection/ConnectedWorkflowRunner.d.ts +31 -0
  67. package/dist/connection/useWorkflowThread.d.ts +38 -0
  68. package/dist/facts/index.cjs +1 -1
  69. package/dist/facts/index.js +1 -1
  70. package/dist/files/index.cjs +9 -83
  71. package/dist/files/index.cjs.map +1 -1
  72. package/dist/files/index.js +6 -83
  73. package/dist/files/index.js.map +1 -1
  74. package/dist/home/index.cjs +22 -21
  75. package/dist/home/index.cjs.map +1 -1
  76. package/dist/home/index.js +4 -3
  77. package/dist/home/index.js.map +1 -1
  78. package/dist/index.cjs +579 -440
  79. package/dist/index.cjs.map +1 -1
  80. package/dist/index.js +11 -8
  81. package/dist/index.js.map +1 -1
  82. package/dist/shell/index.cjs +1 -1
  83. package/dist/shell/index.js +1 -1
  84. package/dist/studio/index.cjs +7 -7
  85. package/dist/studio/index.js +5 -5
  86. package/dist/workflow-canvas/StepInspector.d.ts +57 -0
  87. package/dist/workflow-canvas/TriggerInspector.d.ts +46 -0
  88. package/dist/workflow-canvas/WorkflowBuilder.d.ts +55 -0
  89. package/dist/workflow-canvas/WorkflowCanvas.d.ts +69 -0
  90. package/dist/workflow-canvas/edit.d.ts +54 -0
  91. package/dist/workflow-canvas/index.cjs +1719 -0
  92. package/dist/workflow-canvas/index.cjs.map +1 -0
  93. package/dist/workflow-canvas/index.d.ts +13 -0
  94. package/dist/workflow-canvas/index.js +1689 -0
  95. package/dist/workflow-canvas/index.js.map +1 -0
  96. package/dist/workflow-canvas/trigger.d.ts +51 -0
  97. package/dist/workflow-canvas/viewport.d.ts +47 -0
  98. package/package.json +25 -14
  99. package/src/workflow-canvas/canvas.css +113 -0
  100. package/dist/chunk-3VQYJBOI.js.map +0 -1
  101. package/dist/chunk-5HOAOKZL.js.map +0 -1
  102. package/dist/chunk-DH7C2UJO.cjs.map +0 -1
  103. package/dist/chunk-G5DP27DU.js.map +0 -1
  104. package/dist/chunk-IMC2Z32C.js.map +0 -1
  105. package/dist/chunk-KJ3QEKOJ.cjs.map +0 -1
  106. package/dist/chunk-LFGJAZ5H.js.map +0 -1
  107. package/dist/chunk-THO7DZNN.cjs.map +0 -1
  108. package/dist/chunk-V3L5DONY.cjs.map +0 -1
  109. package/dist/chunk-WBDK4PIA.cjs.map +0 -1
@@ -0,0 +1,1402 @@
1
+ "use client";
2
+ import { UploadDropzone } from './chunk-EVUEIBNU.js';
3
+ import { FoldSection } from './chunk-XD2M6LIG.js';
4
+ import { useElementSize } from './chunk-HOXKR26S.js';
5
+ import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
6
+ import { useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect } from 'react';
7
+ import { cn, Card, Button, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Switch, Input, Textarea } from '@arbidocs/react/ui';
8
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+ import { CheckCircle2, ArrowLeft, Loader2, ArrowRight, RotateCw, GitBranch, FileText, Check, AlertTriangle, MinusCircle } from 'lucide-react';
10
+
11
+ // src/agents/workflows/types.ts
12
+ var EMPTY_WORKFLOW_SCOPE = { folders: [], labels: [] };
13
+
14
+ // src/agents/workflows/workflow.ts
15
+ var isWorkflowScope = (value) => typeof value === "object" && value !== null && Array.isArray(value.folders) && Array.isArray(value.labels);
16
+ var isEmptyWorkflowScope = (scope) => scope.folders.length === 0 && scope.labels.length === 0 && !scope.documents?.length;
17
+ var isFileField = (field) => field.type === "scope" || field.type === "documents";
18
+ function emptyValue(field) {
19
+ switch (field.type) {
20
+ case "boolean":
21
+ return false;
22
+ case "scope":
23
+ return { folders: [], labels: [] };
24
+ case "documents":
25
+ return { folders: [], labels: [], documents: [] };
26
+ default:
27
+ return "";
28
+ }
29
+ }
30
+ function defaultInputs(workflow) {
31
+ const inputs = {};
32
+ for (const field of workflow.inputs) {
33
+ const d = field.default;
34
+ inputs[field.name] = d === void 0 ? emptyValue(field) : isWorkflowScope(d) ? { ...d } : d;
35
+ }
36
+ return inputs;
37
+ }
38
+ function validateInputs(workflow, inputs) {
39
+ const errors = {};
40
+ for (const field of workflow.inputs) {
41
+ const value = inputs[field.name];
42
+ if (field.type === "number") {
43
+ const blank = value === "" || value === void 0;
44
+ if (blank) {
45
+ if (field.required) errors[field.name] = "required";
46
+ continue;
47
+ }
48
+ const n = Number(value);
49
+ if (Number.isNaN(n)) errors[field.name] = "number";
50
+ else if (field.min !== void 0 && n < field.min) errors[field.name] = "min";
51
+ else if (field.max !== void 0 && n > field.max) errors[field.name] = "max";
52
+ continue;
53
+ }
54
+ if (!field.required) continue;
55
+ if (field.type === "documents") {
56
+ if (!isWorkflowScope(value) || !value.documents?.length) errors[field.name] = "required";
57
+ continue;
58
+ }
59
+ if (field.type === "boolean" || field.type === "scope") continue;
60
+ if (typeof value !== "string" || value.trim() === "") errors[field.name] = "required";
61
+ }
62
+ return errors;
63
+ }
64
+ function promptFieldName(workflow) {
65
+ return workflow.inputs.find((f) => !f.advanced && (f.type === "text" || f.type === "longtext"))?.name;
66
+ }
67
+ var quoteList = (names) => {
68
+ const quoted = names.map((n) => `"${n}"`);
69
+ return quoted.length <= 1 ? quoted[0] ?? "" : `${quoted.slice(0, -1).join(", ")} and ${quoted[quoted.length - 1]}`;
70
+ };
71
+ function fragment(field, value, ctx) {
72
+ switch (field.type) {
73
+ case "documents": {
74
+ const ids = isWorkflowScope(value) ? value.documents ?? [] : [];
75
+ const names = ids.flatMap((id) => {
76
+ const title = ctx?.documentTitles?.[id];
77
+ return title ? [title] : [];
78
+ });
79
+ return quoteList(names);
80
+ }
81
+ case "boolean":
82
+ return value ? field.trueText ?? "yes" : field.falseText ?? "no";
83
+ case "select": {
84
+ const option = field.options?.find((o) => o.value === value);
85
+ return option ? option.text ?? option.label : String(value ?? "");
86
+ }
87
+ case "scope":
88
+ return "";
89
+ default:
90
+ return typeof value === "string" ? value.trim() : String(value ?? "");
91
+ }
92
+ }
93
+ function composeWorkflowPrompt(workflow, inputs, ctx) {
94
+ if (workflow.run.kind !== "prompt") return "";
95
+ const byName = new Map(workflow.inputs.map((f) => [f.name, f]));
96
+ const template = workflow.run.promptTemplate;
97
+ let out = "";
98
+ let last = 0;
99
+ const append = (text, isValue) => {
100
+ let t = text;
101
+ if (!isValue) {
102
+ t = t.replace(/[ \t]{2,}/g, " ");
103
+ if (/[ \t]$/.test(out)) t = t.replace(/^[ \t]+/, "");
104
+ }
105
+ out += t;
106
+ };
107
+ for (const m of template.matchAll(/\{\{\s*([a-z][a-z0-9_]*)\s*\}\}/gi)) {
108
+ append(template.slice(last, m.index), false);
109
+ const field = byName.get(m[1]);
110
+ append(field ? fragment(field, inputs[m[1]], ctx) : "", true);
111
+ last = m.index + m[0].length;
112
+ }
113
+ append(template.slice(last), false);
114
+ return out.trim();
115
+ }
116
+ function buildLaunch(workflow, inputs, agentId) {
117
+ const scopeField = workflow.inputs.find(isFileField);
118
+ const raw = scopeField ? inputs[scopeField.name] : void 0;
119
+ const scope = isWorkflowScope(raw) ? raw : { ...EMPTY_WORKFLOW_SCOPE };
120
+ return { workflow, inputs, scope, agentId: agentId || workflow.defaultAgentId || void 0 };
121
+ }
122
+ function workflowAccepts(workflow) {
123
+ const kinds = /* @__PURE__ */ new Set();
124
+ for (const field of workflow.inputs) if (field.context) kinds.add(field.context);
125
+ return [...kinds];
126
+ }
127
+ function workflowsAccepting(workflows, supplied) {
128
+ return workflows.filter((w) => workflowAccepts(w).some((k) => supplied.includes(k)));
129
+ }
130
+ function workflowsForHost(workflows, host) {
131
+ return workflows.filter((w) => !w.host || w.host === host);
132
+ }
133
+ function inputsFromContext(workflow, context) {
134
+ const inputs = {};
135
+ for (const field of workflow.inputs) {
136
+ if (!field.context) continue;
137
+ if (field.context === "selection") {
138
+ if (context.selection) inputs[field.name] = context.selection;
139
+ continue;
140
+ }
141
+ const ids = field.context === "image" ? context.image ? [context.image] : [] : context.documents;
142
+ if (ids?.length && isFileField(field)) {
143
+ inputs[field.name] = { folders: [], labels: [], documents: ids.slice(0, field.max ?? 1) };
144
+ }
145
+ }
146
+ return inputs;
147
+ }
148
+ var SKILL_PROMPT_LABEL = "What should it work on?";
149
+ var SKILL_PROMPT_FALLBACK_PLACEHOLDER = "Describe what you want";
150
+ var plainHint = (hint) => hint.replace(/^[<[]\s*|\s*[>\]]$/g, "").trim();
151
+ function skillToWorkflow(skill) {
152
+ const hint = plainHint((skill.arg_hint ?? "").trim());
153
+ const inputs = [
154
+ {
155
+ name: "args",
156
+ type: "longtext",
157
+ label: SKILL_PROMPT_LABEL,
158
+ placeholder: hint || SKILL_PROMPT_FALLBACK_PLACEHOLDER,
159
+ required: true
160
+ }
161
+ ];
162
+ return {
163
+ id: skill.slug,
164
+ skill: skill.slug,
165
+ title: skill.name || skill.slug,
166
+ description: skill.description ?? "",
167
+ inputs,
168
+ run: { kind: "prompt", promptTemplate: `/${skill.slug} {{args}}` },
169
+ landing: "chat",
170
+ schedulable: true
171
+ };
172
+ }
173
+ var FIELD_TYPES = [
174
+ "text",
175
+ "longtext",
176
+ "boolean",
177
+ "select",
178
+ "number",
179
+ "date",
180
+ "scope",
181
+ "documents"
182
+ ];
183
+ var str = (v) => typeof v === "string" ? v : void 0;
184
+ var num = (v) => typeof v === "number" ? v : void 0;
185
+ var bool = (v) => typeof v === "boolean" ? v : void 0;
186
+ function fieldFromFrontmatter(raw) {
187
+ if (typeof raw !== "object" || raw === null) return null;
188
+ const r = raw;
189
+ const name = str(r.name);
190
+ const type = FIELD_TYPES.find((t) => t === r.type);
191
+ if (!name || !/^[a-z][a-z0-9_]*$/.test(name) || !type) return null;
192
+ const options = Array.isArray(r.options) ? r.options.flatMap((o) => {
193
+ const ro = o;
194
+ const value = str(ro?.value);
195
+ const label = str(ro?.label);
196
+ return value && label ? [
197
+ {
198
+ value,
199
+ label,
200
+ description: str(ro.description),
201
+ text: str(ro.text),
202
+ icon: str(ro.icon)
203
+ }
204
+ ] : [];
205
+ }) : void 0;
206
+ return {
207
+ name,
208
+ type,
209
+ label: str(r.label) ?? name,
210
+ description: str(r.description),
211
+ placeholder: str(r.placeholder),
212
+ required: bool(r.required),
213
+ default: r.default,
214
+ options,
215
+ min: num(r.min),
216
+ max: num(r.max),
217
+ trueText: str(r.true_text),
218
+ falseText: str(r.false_text),
219
+ advanced: bool(r.advanced),
220
+ accept: r.accept === "image" ? "image" : void 0,
221
+ context: r.context === "documents" || r.context === "selection" || r.context === "image" ? r.context : void 0,
222
+ by: Array.isArray(r.by) ? r.by.filter((b) => b === "folders" || b === "labels") : void 0
223
+ };
224
+ }
225
+ function workflowFromFrontmatter(id, frontmatter, body) {
226
+ const inputs = Array.isArray(frontmatter.inputs) ? frontmatter.inputs.flatMap((f) => {
227
+ const field = fieldFromFrontmatter(f);
228
+ return field ? [field] : [];
229
+ }) : [];
230
+ return {
231
+ id,
232
+ title: str(frontmatter.name) ?? id,
233
+ description: str(frontmatter.description) ?? "",
234
+ icon: str(frontmatter.icon),
235
+ inputs,
236
+ run: { kind: "prompt", promptTemplate: body.trim() },
237
+ landing: frontmatter.landing === "files" ? "files" : "chat",
238
+ requiresFiles: bool(frontmatter.requires_files),
239
+ schedulable: bool(frontmatter.schedulable) ?? true
240
+ };
241
+ }
242
+ function fieldToFrontmatter(field) {
243
+ return compact({
244
+ name: field.name,
245
+ type: field.type,
246
+ label: field.label,
247
+ description: field.description,
248
+ placeholder: field.placeholder,
249
+ required: field.required,
250
+ default: field.default,
251
+ options: field.options?.map(
252
+ (o) => compact({
253
+ value: o.value,
254
+ label: o.label,
255
+ description: o.description,
256
+ text: o.text,
257
+ icon: o.icon
258
+ })
259
+ ),
260
+ min: field.min,
261
+ max: field.max,
262
+ true_text: field.trueText,
263
+ false_text: field.falseText,
264
+ advanced: field.advanced,
265
+ by: field.by,
266
+ accept: field.accept,
267
+ context: field.context
268
+ });
269
+ }
270
+ var compact = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
271
+ var DEFAULT_SCHEMA_FORM_LABELS = {
272
+ optional: "(optional)",
273
+ advanced: "More options",
274
+ errors: {
275
+ required: "This is needed to continue",
276
+ min: "Too small",
277
+ max: "Too large",
278
+ number: "Enter a number"
279
+ }
280
+ };
281
+ var TILE_MAX = 4;
282
+ function FieldControl({
283
+ field,
284
+ value,
285
+ error,
286
+ onChange,
287
+ l,
288
+ idFor,
289
+ renderScope,
290
+ renderDocuments,
291
+ renderIcon,
292
+ onEnterSubmit
293
+ }) {
294
+ const id = `${idFor()}-control`;
295
+ const testId = idFor();
296
+ switch (field.type) {
297
+ case "text":
298
+ return /* @__PURE__ */ jsx(
299
+ Input,
300
+ {
301
+ id,
302
+ "data-testid": testId,
303
+ value: String(value ?? ""),
304
+ placeholder: field.placeholder,
305
+ "aria-required": field.required || void 0,
306
+ "aria-invalid": error ? true : void 0,
307
+ "aria-describedby": error ? idFor("error") : void 0,
308
+ onChange: (e) => onChange(e.target.value)
309
+ }
310
+ );
311
+ case "longtext":
312
+ return /* @__PURE__ */ jsx(
313
+ Textarea,
314
+ {
315
+ id,
316
+ "data-testid": testId,
317
+ value: String(value ?? ""),
318
+ placeholder: field.placeholder,
319
+ "aria-required": field.required || void 0,
320
+ "aria-invalid": error ? true : void 0,
321
+ "aria-describedby": error ? idFor("error") : void 0,
322
+ className: "min-h-[96px]",
323
+ onChange: (e) => onChange(e.target.value),
324
+ onKeyDown: (e) => {
325
+ if (onEnterSubmit && e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
326
+ e.preventDefault();
327
+ onEnterSubmit();
328
+ }
329
+ }
330
+ }
331
+ );
332
+ case "number":
333
+ return /* @__PURE__ */ jsx(
334
+ Input,
335
+ {
336
+ id,
337
+ "data-testid": testId,
338
+ type: "number",
339
+ inputMode: "decimal",
340
+ min: field.min,
341
+ max: field.max,
342
+ value: value === void 0 ? "" : String(value),
343
+ placeholder: field.placeholder,
344
+ "aria-invalid": error ? true : void 0,
345
+ "aria-describedby": error ? idFor("error") : void 0,
346
+ onChange: (e) => onChange(e.target.value === "" ? "" : Number(e.target.value))
347
+ }
348
+ );
349
+ case "date":
350
+ return /* @__PURE__ */ jsx(
351
+ Input,
352
+ {
353
+ id,
354
+ "data-testid": testId,
355
+ type: "date",
356
+ value: String(value ?? ""),
357
+ "aria-invalid": error ? true : void 0,
358
+ "aria-describedby": error ? idFor("error") : void 0,
359
+ onChange: (e) => onChange(e.target.value)
360
+ }
361
+ );
362
+ case "boolean":
363
+ return /* @__PURE__ */ jsx(
364
+ Switch,
365
+ {
366
+ id,
367
+ "data-testid": testId,
368
+ checked: Boolean(value),
369
+ onCheckedChange: (checked) => onChange(checked)
370
+ }
371
+ );
372
+ case "select": {
373
+ const options = field.options ?? [];
374
+ if (options.length > 0 && options.length <= TILE_MAX) {
375
+ return /* @__PURE__ */ jsx(
376
+ "div",
377
+ {
378
+ role: "radiogroup",
379
+ "aria-label": field.label,
380
+ className: "grid grid-cols-2 gap-2 sm:grid-cols-4",
381
+ "data-testid": testId,
382
+ children: options.map((option) => {
383
+ const selected = value === option.value;
384
+ return /* @__PURE__ */ jsxs(
385
+ "button",
386
+ {
387
+ type: "button",
388
+ role: "radio",
389
+ "aria-checked": selected,
390
+ "data-testid": prefixedTestId(testId, option.value, {
391
+ testId: `workflow-field-${field.name}-${option.value}`
392
+ }),
393
+ onClick: () => {
394
+ onChange(option.value);
395
+ },
396
+ className: cn(
397
+ "flex min-h-24 flex-col items-center justify-center gap-1.5 rounded-lg border p-3 text-center transition-colors pointer-coarse:min-h-28 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
398
+ selected ? "border-primary bg-primary/10" : "border-border bg-card [&:hover]:border-primary [&:hover]:bg-muted"
399
+ ),
400
+ children: [
401
+ option.icon && renderIcon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: renderIcon(option.icon) }),
402
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: option.label }),
403
+ option.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: option.description })
404
+ ]
405
+ },
406
+ option.value
407
+ );
408
+ })
409
+ }
410
+ );
411
+ }
412
+ return /* @__PURE__ */ jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v), children: [
413
+ /* @__PURE__ */ jsx(SelectTrigger, { id, "data-testid": testId, className: "pointer-coarse:min-h-11", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: field.placeholder }) }),
414
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
415
+ ] });
416
+ }
417
+ case "scope": {
418
+ const scope = isWorkflowScope(value) ? value : { folders: [], labels: [] };
419
+ return /* @__PURE__ */ jsx("div", { "data-testid": testId, children: renderScope?.(field, scope, onChange) });
420
+ }
421
+ case "documents": {
422
+ const picked = isWorkflowScope(value) ? value : { folders: [], labels: [], documents: [] };
423
+ return /* @__PURE__ */ jsx("div", { "data-testid": testId, children: renderDocuments?.(field, picked, onChange) });
424
+ }
425
+ }
426
+ }
427
+ function FormField(props) {
428
+ const { field, error, l, idFor } = props;
429
+ const isBoolean = field.type === "boolean";
430
+ const showOptional = !field.required && field.type !== "boolean" && field.type !== "scope";
431
+ const label = /* @__PURE__ */ jsxs(
432
+ Label,
433
+ {
434
+ htmlFor: `${idFor()}-control`,
435
+ className: isBoolean ? "cursor-pointer font-normal" : void 0,
436
+ children: [
437
+ field.label,
438
+ showOptional && /* @__PURE__ */ jsxs(Fragment, { children: [
439
+ " ",
440
+ /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: l.optional })
441
+ ] })
442
+ ]
443
+ }
444
+ );
445
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", "data-slot": "schema-field", "data-field": field.name, children: [
446
+ isBoolean ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 pointer-coarse:min-h-11", children: [
447
+ /* @__PURE__ */ jsx(FieldControl, { ...props }),
448
+ label
449
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
450
+ field.type !== "scope" && label,
451
+ /* @__PURE__ */ jsx(FieldControl, { ...props })
452
+ ] }),
453
+ field.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: field.description }),
454
+ error && /* @__PURE__ */ jsx(
455
+ "p",
456
+ {
457
+ id: idFor("error"),
458
+ role: "alert",
459
+ className: "text-xs text-destructive",
460
+ "data-testid": idFor("error"),
461
+ children: l.errors[error]
462
+ }
463
+ )
464
+ ] });
465
+ }
466
+ function SchemaForm({
467
+ fields,
468
+ values,
469
+ onChange,
470
+ errors,
471
+ renderScope,
472
+ renderDocuments,
473
+ renderIcon,
474
+ onEnterSubmit,
475
+ testIdPrefix,
476
+ labels,
477
+ className
478
+ }) {
479
+ const l = {
480
+ ...DEFAULT_SCHEMA_FORM_LABELS,
481
+ ...labels,
482
+ errors: { ...DEFAULT_SCHEMA_FORM_LABELS.errors, ...labels?.errors }
483
+ };
484
+ const [advancedOpen, setAdvancedOpen] = useState(false);
485
+ const common = fields.filter((f) => !f.advanced);
486
+ const advanced = fields.filter((f) => f.advanced);
487
+ const render = (field) => /* @__PURE__ */ jsx(
488
+ FormField,
489
+ {
490
+ field,
491
+ value: values[field.name],
492
+ error: errors?.[field.name],
493
+ onChange: (v) => onChange(field.name, v),
494
+ l,
495
+ idFor: (suffix) => suffix ? `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}-${suffix}` : `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}`,
496
+ renderScope,
497
+ renderDocuments,
498
+ renderIcon,
499
+ onEnterSubmit
500
+ },
501
+ field.name
502
+ );
503
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", className), "data-slot": "schema-form", children: [
504
+ common.map(render),
505
+ advanced.length > 0 && /* @__PURE__ */ jsx(
506
+ FoldSection,
507
+ {
508
+ label: l.advanced,
509
+ open: advancedOpen,
510
+ onOpenChange: setAdvancedOpen,
511
+ testId: `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-advanced-toggle`,
512
+ children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: advanced.map(render) })
513
+ }
514
+ )
515
+ ] });
516
+ }
517
+
518
+ // src/agents/workflows/run.ts
519
+ function workflowSteps(workflow) {
520
+ return workflow.run.kind === "steps" ? workflow.run.steps : [];
521
+ }
522
+ var isSteppedWorkflow = (workflow) => workflow.run.kind === "steps";
523
+ function stepDependencies(steps, id) {
524
+ const i = steps.findIndex((s) => s.id === id);
525
+ if (i < 0) return [];
526
+ return steps[i].after ?? (i > 0 ? [steps[i - 1].id] : []);
527
+ }
528
+ function dependsOn(steps, a, b) {
529
+ const seen = /* @__PURE__ */ new Set();
530
+ const stack = [...stepDependencies(steps, a)];
531
+ while (stack.length) {
532
+ const id = stack.pop();
533
+ if (id === b) return true;
534
+ if (seen.has(id)) continue;
535
+ seen.add(id);
536
+ stack.push(...stepDependencies(steps, id));
537
+ }
538
+ return false;
539
+ }
540
+ function orderSteps(steps) {
541
+ const explicit = steps.map((s) => ({ ...s, after: stepDependencies(steps, s.id) }));
542
+ const known = new Set(explicit.map((s) => s.id));
543
+ const placed = /* @__PURE__ */ new Set();
544
+ const out = [];
545
+ let progress = true;
546
+ while (out.length < explicit.length && progress) {
547
+ progress = false;
548
+ for (const s of explicit) {
549
+ if (placed.has(s.id)) continue;
550
+ if (s.after.every((d) => placed.has(d) || !known.has(d))) {
551
+ out.push(s);
552
+ placed.add(s.id);
553
+ progress = true;
554
+ break;
555
+ }
556
+ }
557
+ }
558
+ return [...out, ...explicit.filter((s) => !placed.has(s.id))];
559
+ }
560
+ function validateWorkflowGraph(steps) {
561
+ const problems = [];
562
+ const ids = /* @__PURE__ */ new Set();
563
+ for (const s of steps) {
564
+ if (ids.has(s.id)) problems.push({ code: "duplicate", step: s.id });
565
+ ids.add(s.id);
566
+ }
567
+ steps.forEach((s, i) => {
568
+ for (const d of stepDependencies(steps, s.id)) {
569
+ if (!ids.has(d)) problems.push({ code: "unknown", step: s.id, dependency: d });
570
+ else if (d === s.id || dependsOn(steps, d, s.id)) problems.push({ code: "cycle", step: s.id });
571
+ else if (steps.findIndex((x) => x.id === d) > i)
572
+ problems.push({ code: "order", step: s.id, dependency: d });
573
+ }
574
+ });
575
+ return problems;
576
+ }
577
+ function stepLevels(steps) {
578
+ const depth = /* @__PURE__ */ new Map();
579
+ for (const s of steps) {
580
+ const deps = stepDependencies(steps, s.id).filter((d) => depth.has(d));
581
+ depth.set(s.id, deps.length ? Math.max(...deps.map((d) => depth.get(d))) + 1 : 0);
582
+ }
583
+ const levels = [];
584
+ for (const s of steps) (levels[depth.get(s.id)] ??= []).push(s);
585
+ return levels.filter(Boolean);
586
+ }
587
+ var STEP_EVENTS = {
588
+ step_started: "running",
589
+ step_done: "done",
590
+ step_skipped: "skipped",
591
+ step_failed: "failed"
592
+ };
593
+ function stepStatesFromActivity(events) {
594
+ const states = {};
595
+ for (const e of events) {
596
+ const status = STEP_EVENTS[e.kind];
597
+ const step = e.detail?.step;
598
+ if (!status || typeof step !== "string") continue;
599
+ const responseId = typeof e.detail?.response_id === "string" ? e.detail.response_id : void 0;
600
+ const error = typeof e.detail?.error === "string" ? e.detail.error : null;
601
+ const startedAt = status === "running" ? e.created_at : states[step]?.startedAt;
602
+ states[step] = {
603
+ status,
604
+ responseId: responseId ?? states[step]?.responseId ?? null,
605
+ error,
606
+ ...startedAt ? { startedAt } : {}
607
+ };
608
+ }
609
+ return states;
610
+ }
611
+ function runFields(workflow) {
612
+ return [
613
+ ...workflow.inputs,
614
+ ...workflowSteps(workflow).flatMap((s) => s.kind === "form" ? s.inputs : [])
615
+ ];
616
+ }
617
+ function initialRunInputs(workflow, inputs = {}) {
618
+ return { ...defaultInputs({ ...workflow, inputs: runFields(workflow) }), ...inputs };
619
+ }
620
+ var finished = (s) => s?.status === "done" || s?.status === "skipped";
621
+ function stepPhase(steps, states, id) {
622
+ const s = states[id];
623
+ if (s && s.status !== "pending") return s.status;
624
+ return stepDependencies(steps, id).every((d) => finished(states[d])) ? "ready" : "blocked";
625
+ }
626
+ var isRunFinished = (steps, states) => steps.length > 0 && steps.every((s) => finished(states[s.id]));
627
+ var isPersonStep = (step) => step.kind !== "agent";
628
+ function nextAction(steps, states, current) {
629
+ const i = steps.findIndex((s) => s.id === current);
630
+ const step = steps[i];
631
+ if (!step) return "wait";
632
+ const phase = stepPhase(steps, states, step.id);
633
+ if (phase === "blocked") return "wait";
634
+ const following = steps[i + 1];
635
+ const independentNext = !!following && !dependsOn(steps, following.id, step.id);
636
+ if (phase === "done" || phase === "skipped") {
637
+ if (following) return "move";
638
+ return isRunFinished(steps, states) ? "finish" : "wait";
639
+ }
640
+ if (isPersonStep(step)) return "complete";
641
+ if (phase !== "failed") return independentNext ? "move" : "wait";
642
+ const waitedFor = steps.slice(i + 1).some((s) => dependsOn(steps, s.id, step.id));
643
+ return waitedFor || !following ? "skip" : "move";
644
+ }
645
+ function validateStep(step, inputs) {
646
+ if (step.kind !== "form") return {};
647
+ return validateInputs(
648
+ {
649
+ id: step.id,
650
+ title: step.title,
651
+ inputs: step.inputs},
652
+ inputs
653
+ );
654
+ }
655
+ var asText = (value) => typeof value === "string" ? value.trim() : typeof value === "number" ? String(value) : "";
656
+ function fillStepInputs(templates, inputs) {
657
+ const out = {};
658
+ for (const [name, template] of Object.entries(templates ?? {})) {
659
+ const bare = /^\{\{\s*([a-z][a-z0-9_]*)\s*\}\}$/i.exec(template);
660
+ if (bare) {
661
+ out[name] = inputs[bare[1]] ?? "";
662
+ continue;
663
+ }
664
+ out[name] = fillRunText(template, inputs);
665
+ }
666
+ return out;
667
+ }
668
+ function fillRunText(template, inputs) {
669
+ return template.replace(/\{\{([^}]*)\}\}/g, (_, expr) => {
670
+ for (const ref of expr.split("||")) {
671
+ const text = asText(inputs[ref.trim()]);
672
+ if (text) return text;
673
+ }
674
+ return "";
675
+ }).trim();
676
+ }
677
+ function runThreadTitle(workflow, inputs) {
678
+ const template = workflow.run.kind === "steps" ? workflow.run.threadTitle : void 0;
679
+ return template && fillRunText(template, inputs) || workflow.title;
680
+ }
681
+ function reviewInstructions(step, inputs) {
682
+ return step.instructions && fillRunText(step.instructions, inputs) || step.title;
683
+ }
684
+ function composeStepPrompt(workflow, step, runInputs, { resolveWorkflow, compose } = {}) {
685
+ if (step.workflow) {
686
+ const target = resolveWorkflow?.(step.workflow);
687
+ if (!target) return "";
688
+ const inputs = { ...defaultInputs(target), ...fillStepInputs(step.with, runInputs) };
689
+ return target.run.kind === "prompt" ? composeWorkflowPrompt(target, inputs) : compose?.(target.id, inputs, runInputs) ?? "";
690
+ }
691
+ if (step.run?.kind === "prompt") {
692
+ return composeWorkflowPrompt(
693
+ { ...workflow, inputs: runFields(workflow), run: step.run },
694
+ runInputs
695
+ );
696
+ }
697
+ return compose?.(step.id, runInputs, runInputs) ?? "";
698
+ }
699
+
700
+ // src/agents/workflows/planSteps.ts
701
+ var compact2 = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0 && v !== ""));
702
+ function placeholders(workflow) {
703
+ return Object.fromEntries(runFields(workflow).map((f) => [f.name, `{{${f.name}}}`]));
704
+ }
705
+ function agentStep(workflow, step, options) {
706
+ const target = step.workflow ? options.resolveWorkflow?.(step.workflow) : void 0;
707
+ if (target?.skill) return { skill: target.skill, inputs: step.with ?? {}, prompt: null };
708
+ const given = Object.entries(options.inputs ?? {}).filter(
709
+ ([, v]) => v !== void 0 && v !== null && v !== ""
710
+ );
711
+ const inputs = { ...placeholders(workflow), ...Object.fromEntries(given) };
712
+ return { skill: null, inputs: null, prompt: composeStepPrompt(workflow, step, inputs, options) };
713
+ }
714
+ function toPlanSteps(workflow, options = {}) {
715
+ const layout = workflow.run.kind === "steps" ? workflow.run.layout : void 0;
716
+ return workflowSteps(workflow).map((step) => {
717
+ const ui = compact2({
718
+ description: step.description,
719
+ icon: step.icon,
720
+ commit: step.commit,
721
+ next_label: step.nextLabel,
722
+ position: layout?.[step.id],
723
+ ...step.kind === "form" ? { fields: step.inputs } : {},
724
+ ...step.kind === "upload" ? { required: step.required, accept: step.accept, hint: step.hint } : {},
725
+ ...step.kind === "review" ? { instructions: step.instructions } : {},
726
+ ...step.kind === "agent" ? {
727
+ output: step.output,
728
+ workflow: step.workflow,
729
+ with: step.with,
730
+ prompt_template: step.run?.kind === "prompt" ? step.run.promptTemplate : void 0
731
+ } : {}
732
+ });
733
+ return {
734
+ id: step.id,
735
+ title: step.title,
736
+ kind: step.kind,
737
+ after: step.after ?? null,
738
+ branch: step.kind === "agent" && !!step.branch,
739
+ requires_files: false,
740
+ ui,
741
+ ...step.kind === "agent" ? agentStep(workflow, step, options) : { skill: null, inputs: null, prompt: null }
742
+ };
743
+ });
744
+ }
745
+ function fromPlanSteps(steps) {
746
+ return (steps ?? []).map((p) => {
747
+ const ui = p.ui ?? {};
748
+ const base = {
749
+ id: p.id,
750
+ title: p.title,
751
+ description: ui.description,
752
+ icon: ui.icon,
753
+ commit: ui.commit,
754
+ nextLabel: ui.next_label,
755
+ ...p.after != null ? { after: p.after } : {}
756
+ };
757
+ switch (p.kind) {
758
+ case "form":
759
+ return { ...base, kind: "form", inputs: ui.fields ?? [] };
760
+ case "upload":
761
+ return { ...base, kind: "upload", required: ui.required, accept: ui.accept, hint: ui.hint };
762
+ case "review":
763
+ return { ...base, kind: "review", instructions: ui.instructions };
764
+ default: {
765
+ const promptTemplate = ui.prompt_template ?? p.prompt ?? void 0;
766
+ return {
767
+ ...base,
768
+ kind: "agent",
769
+ workflow: ui.workflow ?? p.skill ?? void 0,
770
+ with: ui.with ?? p.inputs ?? void 0,
771
+ run: !ui.workflow && !p.skill && promptTemplate ? { kind: "prompt", promptTemplate } : void 0,
772
+ output: ui.output,
773
+ branch: p.branch || void 0
774
+ };
775
+ }
776
+ }
777
+ });
778
+ }
779
+ function layoutFromPlanSteps(steps) {
780
+ const entries = (steps ?? []).flatMap((p) => {
781
+ const position = p.ui?.position;
782
+ return position ? [[p.id, position]] : [];
783
+ });
784
+ return entries.length ? Object.fromEntries(entries) : void 0;
785
+ }
786
+ var errorMessage = (e) => e instanceof Error ? e.message : typeof e === "string" ? e : "Something went wrong.";
787
+ function firstOpen(steps, states) {
788
+ const open = steps.find((s) => !["done", "skipped"].includes(states[s.id]?.status ?? "pending"));
789
+ return open?.id ?? (steps.length && isRunFinished(steps, states) ? null : steps[0]?.id ?? null);
790
+ }
791
+ function useWorkflowView(options) {
792
+ const { steps, states, inputs, setInput } = options;
793
+ const [current, setCurrent] = useState(() => firstOpen(steps, states));
794
+ const [showErrors, setShowErrors] = useState(false);
795
+ const [busy, setBusy] = useState(false);
796
+ const [actionError, setActionError] = useState(null);
797
+ const optionsRef = useRef(options);
798
+ optionsRef.current = options;
799
+ const placed = useRef(steps.length > 0);
800
+ useEffect(() => {
801
+ if (placed.current || steps.length === 0) return;
802
+ placed.current = true;
803
+ setCurrent(firstOpen(steps, states));
804
+ }, [steps, states]);
805
+ const step = steps.find((s) => s.id === current);
806
+ const following = useCallback(
807
+ (id) => {
808
+ const i = steps.findIndex((s) => s.id === id);
809
+ return steps[i + 1]?.id ?? null;
810
+ },
811
+ [steps]
812
+ );
813
+ const onward = useCallback(
814
+ (id) => {
815
+ const { steps: s, states: st } = optionsRef.current;
816
+ const i = s.findIndex((x) => x.id === id);
817
+ const open = s.slice(i + 1).find((x) => !["done", "skipped"].includes(st[x.id]?.status ?? "pending"));
818
+ return open?.id ?? following(id);
819
+ },
820
+ [following]
821
+ );
822
+ const action = busy ? "wait" : nextAction(steps, states, current);
823
+ const next = useCallback(async () => {
824
+ const { steps: s, states: st, inputs: values } = optionsRef.current;
825
+ const at = s.find((x) => x.id === current);
826
+ const act2 = nextAction(s, st, current);
827
+ if (!at || act2 === "wait" || busy) return;
828
+ setActionError(null);
829
+ if (act2 === "finish") return setCurrent(null);
830
+ if (act2 === "move") return setCurrent(following(current));
831
+ setBusy(true);
832
+ try {
833
+ if (act2 === "skip") {
834
+ await optionsRef.current.skip(at.id);
835
+ } else {
836
+ if (Object.keys(validateStep(at, values)).length > 0) {
837
+ setShowErrors(true);
838
+ return;
839
+ }
840
+ await optionsRef.current.complete(at);
841
+ }
842
+ setShowErrors(false);
843
+ setCurrent(onward(at.id) ?? current);
844
+ } catch (e) {
845
+ setActionError(errorMessage(e));
846
+ } finally {
847
+ setBusy(false);
848
+ }
849
+ }, [current, busy, following, onward]);
850
+ const goTo = useCallback((stepId) => {
851
+ setShowErrors(false);
852
+ setActionError(null);
853
+ setCurrent(stepId);
854
+ }, []);
855
+ const index = steps.findIndex((s) => s.id === current);
856
+ const back = useCallback(() => {
857
+ const i = steps.findIndex((s) => s.id === current);
858
+ const to = i < 0 ? steps[steps.length - 1] : steps[i - 1];
859
+ if (to) goTo(to.id);
860
+ }, [steps, current, goTo]);
861
+ const act = useCallback(
862
+ (fn) => fn && (async (stepId) => {
863
+ setBusy(true);
864
+ setActionError(null);
865
+ try {
866
+ await fn(stepId);
867
+ } catch (e) {
868
+ setActionError(errorMessage(e));
869
+ } finally {
870
+ setBusy(false);
871
+ }
872
+ }),
873
+ []
874
+ );
875
+ const currentRef = useRef(current);
876
+ currentRef.current = current;
877
+ const skip = useMemo(
878
+ () => act(async (id) => {
879
+ await optionsRef.current.skip(id);
880
+ if (currentRef.current !== id) return;
881
+ setShowErrors(false);
882
+ setCurrent(onward(id) ?? id);
883
+ }),
884
+ [act, onward]
885
+ );
886
+ const retry = useMemo(
887
+ () => options.retry ? act((id) => optionsRef.current.retry?.(id) ?? Promise.resolve()) : void 0,
888
+ // Only whether the host offers retry matters here.
889
+ // eslint-disable-next-line react-hooks/exhaustive-deps
890
+ [act, !!options.retry]
891
+ );
892
+ const isLocked = useCallback(
893
+ (stepId) => optionsRef.current.isLocked?.(stepId) ?? false,
894
+ []
895
+ );
896
+ return {
897
+ steps,
898
+ step,
899
+ current,
900
+ isComplete: current === null,
901
+ inputs,
902
+ setInput,
903
+ stateOf: (id) => states[id],
904
+ phaseOf: (id) => stepPhase(steps, states, id),
905
+ isLocked,
906
+ errors: showErrors && step && !isLocked(step.id) ? validateStep(step, inputs) : {},
907
+ busy,
908
+ actionError,
909
+ isRunning: Object.values(states).some((s) => s.status === "running"),
910
+ action,
911
+ canBack: (current === null || index > 0) && !busy,
912
+ next,
913
+ back,
914
+ goTo,
915
+ skip,
916
+ retry,
917
+ restart: () => {
918
+ setShowErrors(false);
919
+ setActionError(null);
920
+ setCurrent(steps[0]?.id ?? null);
921
+ }
922
+ };
923
+ }
924
+ function PhaseMark({ phase, icon }) {
925
+ if (phase === "done") return /* @__PURE__ */ jsx(Check, { className: "size-3.5 shrink-0" });
926
+ if (phase === "running") return /* @__PURE__ */ jsx(Loader2, { className: "size-3.5 shrink-0 animate-spin" });
927
+ if (phase === "failed") return /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5 shrink-0" });
928
+ if (phase === "skipped") return /* @__PURE__ */ jsx(MinusCircle, { className: "size-3.5 shrink-0" });
929
+ return icon ? /* @__PURE__ */ jsx("span", { className: "flex size-3.5 shrink-0 items-center justify-center [&_svg]:size-3.5", children: icon }) : null;
930
+ }
931
+ var PILL = "flex min-w-0 max-w-full shrink-0 items-center gap-2 whitespace-nowrap rounded-full border px-2.5 py-1.5 text-xs font-medium";
932
+ var LABEL = "min-w-0 max-w-[12rem] truncate";
933
+ function WorkflowStepBar({
934
+ run,
935
+ levels,
936
+ doneTitle,
937
+ doneIcon,
938
+ icon,
939
+ tid
940
+ }) {
941
+ const box = useRef(null);
942
+ const measure = useRef(null);
943
+ const row = useRef(null);
944
+ const { width } = useElementSize(box);
945
+ const [compact3, setCompact] = useState(false);
946
+ const titles = levels.map((l) => l.map((s) => s.title).join("\0")).join("") + doneTitle;
947
+ useLayoutEffect(() => {
948
+ const needed = measure.current?.scrollWidth ?? 0;
949
+ setCompact(width > 0 && needed > width);
950
+ }, [width, titles]);
951
+ useLayoutEffect(() => {
952
+ if (!compact3) return;
953
+ const el = row.current?.querySelector('[aria-current="step"]');
954
+ el?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
955
+ }, [compact3, run.current]);
956
+ const pill = (s) => {
957
+ const phase = run.phaseOf(s.id);
958
+ const current = s.id === run.current;
959
+ return /* @__PURE__ */ jsxs(
960
+ "button",
961
+ {
962
+ type: "button",
963
+ onClick: () => run.goTo(s.id),
964
+ disabled: run.busy,
965
+ className: cn(
966
+ PILL,
967
+ "transition-colors disabled:cursor-default",
968
+ current ? "border-primary bg-primary/10 text-primary" : phase === "failed" ? "border-destructive/40 text-destructive" : phase === "done" || phase === "skipped" || phase === "running" ? "border-primary/30 bg-primary/5 text-primary" : "border-border text-muted-foreground"
969
+ ),
970
+ "aria-current": current ? "step" : void 0,
971
+ "aria-label": s.title,
972
+ title: s.title,
973
+ "data-phase": phase,
974
+ "data-testid": tid(`step-${s.id}`),
975
+ children: [
976
+ /* @__PURE__ */ jsx(PhaseMark, { phase, icon: icon(s.icon) }),
977
+ (current || !compact3) && /* @__PURE__ */ jsx("span", { className: LABEL, "data-testid": tid(`step-${s.id}-label`), children: s.title })
978
+ ]
979
+ },
980
+ s.id
981
+ );
982
+ };
983
+ const done = run.isComplete;
984
+ return /* @__PURE__ */ jsxs("div", { ref: box, className: "relative min-w-0", children: [
985
+ /* @__PURE__ */ jsx(
986
+ "div",
987
+ {
988
+ ref: measure,
989
+ "aria-hidden": true,
990
+ className: "pointer-events-none invisible absolute left-0 top-0 flex w-max items-center gap-1.5",
991
+ children: [...levels, [{ id: "__done", title: doneTitle }]].map((level, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
992
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col items-start gap-1", children: level.map((s) => /* @__PURE__ */ jsxs("div", { className: PILL, children: [
993
+ /* @__PURE__ */ jsx("span", { className: "size-3.5 shrink-0" }),
994
+ /* @__PURE__ */ jsx(
995
+ "span",
996
+ {
997
+ className: cn(LABEL, "before:content-[attr(data-label)]"),
998
+ "data-label": s.title
999
+ }
1000
+ )
1001
+ ] }, s.id)) }),
1002
+ i < levels.length && /* @__PURE__ */ jsx("div", { className: "w-2" })
1003
+ ] }, i))
1004
+ }
1005
+ ),
1006
+ /* @__PURE__ */ jsx(
1007
+ "ol",
1008
+ {
1009
+ ref: row,
1010
+ className: cn("flex w-full items-center gap-1.5", compact3 && "overflow-x-auto pb-1"),
1011
+ "data-compact": compact3 || void 0,
1012
+ "data-testid": tid("steps"),
1013
+ children: [...levels, null].map((level, i) => /* @__PURE__ */ jsxs(
1014
+ "li",
1015
+ {
1016
+ className: cn(
1017
+ "flex min-w-0 items-center gap-1.5",
1018
+ i < levels.length && !compact3 && "flex-1",
1019
+ compact3 && "flex-none"
1020
+ ),
1021
+ children: [
1022
+ level ? /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-col items-start gap-1", children: level.map(pill) }) : /* @__PURE__ */ jsxs(
1023
+ "div",
1024
+ {
1025
+ className: cn(
1026
+ PILL,
1027
+ done ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground"
1028
+ ),
1029
+ "aria-current": done ? "step" : void 0,
1030
+ "aria-label": doneTitle,
1031
+ title: doneTitle,
1032
+ "data-testid": tid("step-done"),
1033
+ children: [
1034
+ /* @__PURE__ */ jsx(PhaseMark, { phase: "ready", icon: doneIcon }),
1035
+ (done || !compact3) && /* @__PURE__ */ jsx("span", { className: LABEL, children: doneTitle })
1036
+ ]
1037
+ }
1038
+ ),
1039
+ i < levels.length && /* @__PURE__ */ jsx(
1040
+ "div",
1041
+ {
1042
+ className: cn(
1043
+ "h-px",
1044
+ compact3 ? "w-3 flex-none" : "min-w-2 flex-1",
1045
+ level?.every((s) => ["done", "skipped"].includes(run.phaseOf(s.id))) ? "bg-primary/40" : "bg-border"
1046
+ )
1047
+ }
1048
+ )
1049
+ ]
1050
+ },
1051
+ level ? level.map((s) => s.id).join("+") : "done"
1052
+ ))
1053
+ }
1054
+ )
1055
+ ] });
1056
+ }
1057
+ var DEFAULT_WORKFLOW_RUNNER_LABELS = {
1058
+ back: "Back",
1059
+ next: "Continue",
1060
+ skip: "Skip",
1061
+ skipStep: "Skip this step",
1062
+ finish: "Finish",
1063
+ approve: "Approve",
1064
+ working: "Working\u2026",
1065
+ stepWorking: "{step}\u2026 {elapsed}",
1066
+ starting: "Starting\u2026",
1067
+ retry: "Retry",
1068
+ failed: "This step did not finish.",
1069
+ blocked: "Starts after {steps}.",
1070
+ awaitingReview: "Waiting for approval.",
1071
+ approved: "Approved.",
1072
+ skipped: "Skipped.",
1073
+ branch: "Runs alongside; its result joins the thread",
1074
+ complete: "Done",
1075
+ restart: "Start again",
1076
+ filesHeading: "Already in the workspace ({count})",
1077
+ addedHeading: "Added for this step ({count})",
1078
+ noFiles: "No files yet.",
1079
+ fileReading: "Reading\u2026",
1080
+ fileReady: "Ready",
1081
+ fileFailed: "Could not be read",
1082
+ readingFiles: "Reading {current} of {count} files\u2026"
1083
+ };
1084
+ function WorkflowRunner({
1085
+ workflow,
1086
+ run,
1087
+ renderAgentOutput,
1088
+ renderReview,
1089
+ onUpload,
1090
+ uploading = false,
1091
+ files,
1092
+ renderUpload,
1093
+ renderStepNote,
1094
+ renderComplete,
1095
+ renderScope,
1096
+ renderDocuments,
1097
+ renderIcon,
1098
+ labels,
1099
+ testIdPrefix = "workflow-run",
1100
+ className
1101
+ }) {
1102
+ const l = { ...DEFAULT_WORKFLOW_RUNNER_LABELS, ...labels };
1103
+ const { steps, step, isComplete, action } = run;
1104
+ const completion = workflow.run.kind === "steps" ? workflow.run.completion : void 0;
1105
+ const tid = (suffix) => `${testIdPrefix}-${suffix}`;
1106
+ const levels = stepLevels(steps);
1107
+ const icon = (key) => key && renderIcon ? renderIcon(key) : void 0;
1108
+ const added = step?.kind === "upload" ? (files ?? []).filter((f) => f.addedFor === step.id) : [];
1109
+ const unread = added.filter((f) => f.status === "processing").length;
1110
+ const reading = action === "complete" && unread > 0;
1111
+ const nextLabel = reading ? l.readingFiles.replace("{current}", String(Math.min(added.length - unread + 1, added.length))).replace("{count}", String(added.length)) : action === "skip" ? l.skip : action === "finish" ? l.finish : action === "complete" && step?.kind === "review" ? l.approve : action === "wait" && (run.isRunning || run.busy) ? l.working : (step && !run.isLocked(step.id) ? step.nextLabel : void 0) ?? l.next;
1112
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-6", className), "data-testid": testIdPrefix, children: [
1113
+ /* @__PURE__ */ jsx(
1114
+ WorkflowStepBar,
1115
+ {
1116
+ run,
1117
+ levels,
1118
+ doneTitle: completion?.title ?? l.complete,
1119
+ doneIcon: icon(completion?.icon),
1120
+ icon,
1121
+ tid
1122
+ }
1123
+ ),
1124
+ isComplete ? renderComplete?.(run) ?? /* @__PURE__ */ jsxs(Card, { className: "mx-auto max-w-lg p-8 text-center", "data-testid": tid("done"), children: [
1125
+ /* @__PURE__ */ jsx(CheckCircle2, { className: "mx-auto size-12 text-primary" }),
1126
+ /* @__PURE__ */ jsx("h2", { className: "mt-4 text-xl font-semibold", children: completion?.title ?? l.complete }),
1127
+ completion?.description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: completion.description }),
1128
+ /* @__PURE__ */ jsx(
1129
+ Button,
1130
+ {
1131
+ variant: "outline",
1132
+ className: "mt-6",
1133
+ onClick: run.restart,
1134
+ "data-testid": tid("restart"),
1135
+ children: l.restart
1136
+ }
1137
+ )
1138
+ ] }) : step ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: run.phaseOf(step.id) === "blocked" ? /* @__PURE__ */ jsx(Card, { className: "max-w-2xl p-6", "data-testid": tid(step.id), children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", "data-testid": tid(`${step.id}-blocked`), children: l.blocked.replace(
1139
+ "{steps}",
1140
+ stepDependencies(steps, step.id).map((d) => steps.find((s) => s.id === d)?.title ?? d).join(", ")
1141
+ ) }) }) : step.kind === "form" ? /* @__PURE__ */ jsxs(Card, { className: "max-w-2xl space-y-4 p-6", "data-testid": tid(step.id), children: [
1142
+ /* @__PURE__ */ jsx(StepHeading, { step, icon: icon(step.icon), testId: tid(`${step.id}-title`) }),
1143
+ /* @__PURE__ */ jsx("fieldset", { disabled: run.isLocked(step.id), className: "contents", children: /* @__PURE__ */ jsx(
1144
+ SchemaForm,
1145
+ {
1146
+ fields: step.inputs,
1147
+ values: run.inputs,
1148
+ onChange: run.setInput,
1149
+ errors: run.errors,
1150
+ renderScope,
1151
+ renderDocuments,
1152
+ renderIcon,
1153
+ onEnterSubmit: () => void run.next(),
1154
+ testIdPrefix: tid("field")
1155
+ }
1156
+ ) }),
1157
+ run.actionError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", "data-testid": tid("action-error"), children: run.actionError }),
1158
+ renderStepNote?.(step, run)
1159
+ ] }) : step.kind === "upload" ? /* @__PURE__ */ jsxs(Card, { className: "max-w-2xl space-y-4 p-6", "data-testid": tid(step.id), children: [
1160
+ renderUpload?.(step) ?? /* @__PURE__ */ jsxs(Fragment, { children: [
1161
+ /* @__PURE__ */ jsx(
1162
+ UploadDropzone,
1163
+ {
1164
+ onFiles: (picked) => void onUpload?.(picked, step),
1165
+ uploading,
1166
+ disabled: !onUpload,
1167
+ accept: step.accept,
1168
+ title: step.title,
1169
+ description: step.description,
1170
+ hint: step.hint,
1171
+ testId: tid(`${step.id}-drop`)
1172
+ }
1173
+ ),
1174
+ files && /* @__PURE__ */ jsx(
1175
+ UploadFiles,
1176
+ {
1177
+ added,
1178
+ others: files.filter((f) => f.addedFor !== step.id),
1179
+ l,
1180
+ testId: tid(`${step.id}-files`)
1181
+ }
1182
+ )
1183
+ ] }),
1184
+ run.actionError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: run.actionError }),
1185
+ renderStepNote?.(step, run)
1186
+ ] }) : step.kind === "review" ? /* @__PURE__ */ jsxs(Card, { className: "max-w-2xl space-y-4 p-6", "data-testid": tid(step.id), children: [
1187
+ /* @__PURE__ */ jsx(StepHeading, { step, icon: icon(step.icon) }),
1188
+ /* @__PURE__ */ jsx("p", { className: "whitespace-pre-line text-sm text-muted-foreground", children: reviewInstructions(step, run.inputs) }),
1189
+ /* @__PURE__ */ jsx("p", { className: "text-sm", "data-testid": tid(`${step.id}-status`), children: run.phaseOf(step.id) === "done" ? l.approved : run.phaseOf(step.id) === "skipped" ? l.skipped : l.awaitingReview }),
1190
+ run.phaseOf(step.id) === "ready" && renderReview?.(step),
1191
+ run.actionError && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: run.actionError }),
1192
+ renderStepNote?.(step, run)
1193
+ ] }) : /* @__PURE__ */ jsx(
1194
+ AgentStepBody,
1195
+ {
1196
+ step,
1197
+ run,
1198
+ renderAgentOutput,
1199
+ icon: icon(step.icon),
1200
+ renderStepNote,
1201
+ l,
1202
+ tid
1203
+ }
1204
+ ) }, step.id) : null,
1205
+ !isComplete && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-border pt-4", children: [
1206
+ /* @__PURE__ */ jsxs(
1207
+ Button,
1208
+ {
1209
+ variant: "ghost",
1210
+ onClick: run.back,
1211
+ disabled: !run.canBack,
1212
+ "data-testid": tid("back"),
1213
+ children: [
1214
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4" }),
1215
+ " ",
1216
+ l.back
1217
+ ]
1218
+ }
1219
+ ),
1220
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
1221
+ step && action !== "skip" && // A step that commits (creates the matter, starts the thread) is what the run stands on.
1222
+ !step.commit && ["ready", "blocked", "failed"].includes(run.phaseOf(step.id)) && /* @__PURE__ */ jsx(
1223
+ Button,
1224
+ {
1225
+ variant: "ghost",
1226
+ onClick: () => void run.skip(step.id),
1227
+ disabled: run.busy,
1228
+ "data-testid": tid("skip-step"),
1229
+ children: l.skipStep
1230
+ }
1231
+ ),
1232
+ /* @__PURE__ */ jsxs(
1233
+ Button,
1234
+ {
1235
+ onClick: () => void run.next(),
1236
+ disabled: action === "wait" || reading,
1237
+ "data-testid": tid("next"),
1238
+ children: [
1239
+ nextLabel,
1240
+ reading || action === "wait" && (run.isRunning || run.busy) ? /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx(ArrowRight, { className: "size-4" })
1241
+ ]
1242
+ }
1243
+ )
1244
+ ] })
1245
+ ] })
1246
+ ] });
1247
+ }
1248
+ function UploadFiles({
1249
+ added,
1250
+ others,
1251
+ l,
1252
+ testId
1253
+ }) {
1254
+ const heading = "text-xs font-semibold uppercase tracking-wide text-muted-foreground";
1255
+ const row = (f) => /* @__PURE__ */ jsxs(
1256
+ "div",
1257
+ {
1258
+ className: "flex items-center gap-2 text-sm text-muted-foreground",
1259
+ "data-status": f.status,
1260
+ "data-testid": `${testId}-file-${f.id}`,
1261
+ children: [
1262
+ /* @__PURE__ */ jsx(FileText, { className: "size-3.5 shrink-0 text-primary" }),
1263
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", title: f.name, children: f.name }),
1264
+ f.status === "processing" && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs", children: [
1265
+ /* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }),
1266
+ " ",
1267
+ l.fileReading
1268
+ ] }),
1269
+ f.status === "ready" && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-primary", children: [
1270
+ /* @__PURE__ */ jsx(Check, { className: "size-3" }),
1271
+ " ",
1272
+ l.fileReady
1273
+ ] }),
1274
+ f.status === "failed" && /* @__PURE__ */ jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
1275
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3" }),
1276
+ " ",
1277
+ l.fileFailed
1278
+ ] })
1279
+ ]
1280
+ },
1281
+ f.id
1282
+ );
1283
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-3", "data-testid": testId, children: [
1284
+ added.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1", "data-testid": `${testId}-added`, children: [
1285
+ /* @__PURE__ */ jsx("p", { className: heading, children: l.addedHeading.replace("{count}", String(added.length)) }),
1286
+ added.map(row)
1287
+ ] }),
1288
+ added.length === 0 && others.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.noFiles }),
1289
+ others.length > 0 && /* @__PURE__ */ jsxs("details", { className: "space-y-1", "data-testid": `${testId}-others`, children: [
1290
+ /* @__PURE__ */ jsx("summary", { className: cn(heading, "cursor-pointer select-none"), children: l.filesHeading.replace("{count}", String(others.length)) }),
1291
+ /* @__PURE__ */ jsx("div", { className: "mt-1 max-h-48 space-y-1 overflow-y-auto", children: others.map(row) })
1292
+ ] })
1293
+ ] });
1294
+ }
1295
+ function StepHeading({
1296
+ step,
1297
+ icon,
1298
+ testId
1299
+ }) {
1300
+ return /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1301
+ /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium", "data-testid": testId, children: [
1302
+ icon && /* @__PURE__ */ jsx("span", { className: "flex size-4 items-center justify-center text-primary [&_svg]:size-4", children: icon }),
1303
+ step.title
1304
+ ] }),
1305
+ step.description && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: step.description })
1306
+ ] });
1307
+ }
1308
+ function formatElapsed(ms) {
1309
+ const total = Math.max(0, Math.floor(ms / 1e3));
1310
+ const h = Math.floor(total / 3600);
1311
+ const m = Math.floor(total % 3600 / 60);
1312
+ const sec = String(total % 60).padStart(2, "0");
1313
+ return h ? `${h}:${String(m).padStart(2, "0")}:${sec}` : `${m}:${sec}`;
1314
+ }
1315
+ function StepWorking({ title, since, label }) {
1316
+ const seen = useRef(Date.now());
1317
+ const start = since && Date.parse(since) || seen.current;
1318
+ const [now, setNow] = useState(() => Date.now());
1319
+ useEffect(() => {
1320
+ const t = setInterval(() => setNow(Date.now()), 1e3);
1321
+ return () => clearInterval(t);
1322
+ }, []);
1323
+ return /* @__PURE__ */ jsx("span", { children: label.replace("{step}", title).replace("{elapsed}", formatElapsed(now - start)) });
1324
+ }
1325
+ function AgentStepBody({
1326
+ step,
1327
+ run,
1328
+ renderAgentOutput,
1329
+ icon,
1330
+ renderStepNote,
1331
+ l,
1332
+ tid
1333
+ }) {
1334
+ const state = run.stateOf(step.id);
1335
+ const phase = run.phaseOf(step.id);
1336
+ const header = /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
1337
+ /* @__PURE__ */ jsx(StepHeading, { step, icon }),
1338
+ phase === "failed" && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: run.retry && /* @__PURE__ */ jsxs(
1339
+ Button,
1340
+ {
1341
+ variant: "outline",
1342
+ size: "sm",
1343
+ onClick: () => void run.retry?.(step.id),
1344
+ disabled: run.busy,
1345
+ "data-testid": tid(`${step.id}-retry`),
1346
+ children: [
1347
+ /* @__PURE__ */ jsx(RotateCw, { className: "size-4" }),
1348
+ " ",
1349
+ l.retry
1350
+ ]
1351
+ }
1352
+ ) })
1353
+ ] });
1354
+ const status = /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
1355
+ step.branch && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
1356
+ /* @__PURE__ */ jsx(GitBranch, { className: "size-3.5" }),
1357
+ " ",
1358
+ l.branch
1359
+ ] }),
1360
+ (phase === "ready" || phase === "running") && !state?.text && /* @__PURE__ */ jsxs(
1361
+ "p",
1362
+ {
1363
+ className: "flex items-center gap-2 text-sm text-muted-foreground",
1364
+ "data-testid": tid(`${step.id}-working`),
1365
+ children: [
1366
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
1367
+ " ",
1368
+ phase === "ready" ? l.starting : /* @__PURE__ */ jsx(StepWorking, { title: step.title, since: state?.startedAt, label: l.stepWorking })
1369
+ ]
1370
+ }
1371
+ ),
1372
+ phase === "failed" && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", "data-testid": tid(`${step.id}-failed`), children: state?.error || l.failed }),
1373
+ phase === "skipped" && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.skipped })
1374
+ ] });
1375
+ if (step.output === "artifact") {
1376
+ return /* @__PURE__ */ jsxs(
1377
+ "div",
1378
+ {
1379
+ className: "grid gap-4 lg:grid-cols-[minmax(0,18rem)_minmax(0,1fr)]",
1380
+ "data-testid": tid(step.id),
1381
+ children: [
1382
+ /* @__PURE__ */ jsxs(Card, { className: "h-fit space-y-3 p-5", children: [
1383
+ header,
1384
+ status,
1385
+ renderStepNote?.(step, run)
1386
+ ] }),
1387
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: renderAgentOutput(step, state) })
1388
+ ]
1389
+ }
1390
+ );
1391
+ }
1392
+ return /* @__PURE__ */ jsxs(Card, { className: "space-y-3 p-6", "data-testid": tid(step.id), children: [
1393
+ header,
1394
+ status,
1395
+ renderAgentOutput(step, state),
1396
+ renderStepNote?.(step, run)
1397
+ ] });
1398
+ }
1399
+
1400
+ export { DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_WORKFLOW_RUNNER_LABELS, EMPTY_WORKFLOW_SCOPE, SKILL_PROMPT_FALLBACK_PLACEHOLDER, SKILL_PROMPT_LABEL, SchemaForm, WorkflowRunner, buildLaunch, composeStepPrompt, composeWorkflowPrompt, defaultInputs, dependsOn, fieldToFrontmatter, fillRunText, fillStepInputs, fromPlanSteps, initialRunInputs, inputsFromContext, isEmptyWorkflowScope, isPersonStep, isRunFinished, isSteppedWorkflow, isWorkflowScope, layoutFromPlanSteps, nextAction, orderSteps, promptFieldName, reviewInstructions, runFields, runThreadTitle, skillToWorkflow, stepDependencies, stepLevels, stepPhase, stepStatesFromActivity, toPlanSteps, useWorkflowView, validateInputs, validateStep, validateWorkflowGraph, workflowAccepts, workflowFromFrontmatter, workflowSteps, workflowsAccepting, workflowsForHost };
1401
+ //# sourceMappingURL=chunk-YWYVIQ7T.js.map
1402
+ //# sourceMappingURL=chunk-YWYVIQ7T.js.map