@arbidocs/blocks 0.4.72 → 0.4.73

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 (89) hide show
  1. package/dist/agents/index.cjs +400 -261
  2. package/dist/agents/index.js +6 -3
  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 +70 -0
  7. package/dist/agents/workflows/index.d.ts +7 -1
  8. package/dist/agents/workflows/planSteps.d.ts +28 -0
  9. package/dist/agents/workflows/run.d.ts +97 -0
  10. package/dist/agents/workflows/skillMarkdown.d.ts +15 -0
  11. package/dist/agents/workflows/types.d.ts +109 -0
  12. package/dist/agents/workflows/useWorkflowPreview.d.ts +14 -0
  13. package/dist/agents/workflows/useWorkflowView.d.ts +54 -0
  14. package/dist/agents/workflows/workflow.d.ts +3 -1
  15. package/dist/chunk-2P3T23C7.js +1250 -0
  16. package/dist/chunk-2P3T23C7.js.map +1 -0
  17. package/dist/chunk-7D737FLE.cjs +43 -0
  18. package/dist/chunk-7D737FLE.cjs.map +1 -0
  19. package/dist/{chunk-LFGJAZ5H.js → chunk-DDF5GPIJ.js} +6 -36
  20. package/dist/chunk-DDF5GPIJ.js.map +1 -0
  21. package/dist/chunk-DETZZBG2.cjs +91 -0
  22. package/dist/chunk-DETZZBG2.cjs.map +1 -0
  23. package/dist/chunk-EVUEIBNU.js +89 -0
  24. package/dist/chunk-EVUEIBNU.js.map +1 -0
  25. package/dist/chunk-GTNUQBXI.cjs +1296 -0
  26. package/dist/chunk-GTNUQBXI.cjs.map +1 -0
  27. package/dist/{chunk-DH7C2UJO.cjs → chunk-IUR565UW.cjs} +297 -524
  28. package/dist/chunk-IUR565UW.cjs.map +1 -0
  29. package/dist/{chunk-THO7DZNN.cjs → chunk-MUMH3Z6K.cjs} +20 -15
  30. package/dist/chunk-MUMH3Z6K.cjs.map +1 -0
  31. package/dist/{chunk-KOXUBCLL.js → chunk-ORA2XE7U.js} +3 -3
  32. package/dist/{chunk-KOXUBCLL.js.map → chunk-ORA2XE7U.js.map} +1 -1
  33. package/dist/{chunk-5HOAOKZL.js → chunk-OYMWV45N.js} +21 -16
  34. package/dist/chunk-OYMWV45N.js.map +1 -0
  35. package/dist/{chunk-IMC2Z32C.js → chunk-QDNXEB3T.js} +268 -484
  36. package/dist/chunk-QDNXEB3T.js.map +1 -0
  37. package/dist/{chunk-G5QTGKDJ.cjs → chunk-WOYUXVVQ.cjs} +6 -6
  38. package/dist/{chunk-G5QTGKDJ.cjs.map → chunk-WOYUXVVQ.cjs.map} +1 -1
  39. package/dist/chunk-XD2M6LIG.js +41 -0
  40. package/dist/chunk-XD2M6LIG.js.map +1 -0
  41. package/dist/{chunk-WBDK4PIA.cjs → chunk-Z5VUZ6YD.cjs} +6 -37
  42. package/dist/chunk-Z5VUZ6YD.cjs.map +1 -0
  43. package/dist/connect/docx.cjs +2 -2
  44. package/dist/connect/docx.js +1 -1
  45. package/dist/connect/index.cjs +316 -23
  46. package/dist/connect/index.cjs.map +1 -1
  47. package/dist/connect/index.d.ts +1 -0
  48. package/dist/connect/index.js +300 -8
  49. package/dist/connect/index.js.map +1 -1
  50. package/dist/connection/ConnectedWorkflowBuilder.d.ts +44 -0
  51. package/dist/connection/ConnectedWorkflowRunner.d.ts +27 -0
  52. package/dist/connection/useWorkflowThread.d.ts +34 -0
  53. package/dist/facts/index.cjs +1 -1
  54. package/dist/facts/index.js +1 -1
  55. package/dist/files/index.cjs +9 -83
  56. package/dist/files/index.cjs.map +1 -1
  57. package/dist/files/index.js +6 -83
  58. package/dist/files/index.js.map +1 -1
  59. package/dist/home/index.cjs +22 -21
  60. package/dist/home/index.cjs.map +1 -1
  61. package/dist/home/index.js +4 -3
  62. package/dist/home/index.js.map +1 -1
  63. package/dist/index.cjs +450 -311
  64. package/dist/index.cjs.map +1 -1
  65. package/dist/index.js +7 -4
  66. package/dist/index.js.map +1 -1
  67. package/dist/shell/index.cjs +1 -1
  68. package/dist/shell/index.js +1 -1
  69. package/dist/studio/index.cjs +5 -5
  70. package/dist/studio/index.js +3 -3
  71. package/dist/workflow-canvas/StepInspector.d.ts +46 -0
  72. package/dist/workflow-canvas/TriggerInspector.d.ts +46 -0
  73. package/dist/workflow-canvas/WorkflowBuilder.d.ts +55 -0
  74. package/dist/workflow-canvas/WorkflowCanvas.d.ts +65 -0
  75. package/dist/workflow-canvas/edit.d.ts +54 -0
  76. package/dist/workflow-canvas/index.cjs +1609 -0
  77. package/dist/workflow-canvas/index.cjs.map +1 -0
  78. package/dist/workflow-canvas/index.d.ts +13 -0
  79. package/dist/workflow-canvas/index.js +1579 -0
  80. package/dist/workflow-canvas/index.js.map +1 -0
  81. package/dist/workflow-canvas/trigger.d.ts +51 -0
  82. package/package.json +25 -14
  83. package/src/workflow-canvas/canvas.css +113 -0
  84. package/dist/chunk-5HOAOKZL.js.map +0 -1
  85. package/dist/chunk-DH7C2UJO.cjs.map +0 -1
  86. package/dist/chunk-IMC2Z32C.js.map +0 -1
  87. package/dist/chunk-LFGJAZ5H.js.map +0 -1
  88. package/dist/chunk-THO7DZNN.cjs.map +0 -1
  89. package/dist/chunk-WBDK4PIA.cjs.map +0 -1
@@ -3,17 +3,19 @@
3
3
 
4
4
  var chunkYJQVLVBJ_cjs = require('./chunk-YJQVLVBJ.cjs');
5
5
  var chunkZW6FPIFC_cjs = require('./chunk-ZW6FPIFC.cjs');
6
+ var chunkGTNUQBXI_cjs = require('./chunk-GTNUQBXI.cjs');
6
7
  var chunk7RGLTF76_cjs = require('./chunk-7RGLTF76.cjs');
7
8
  var chunk3AFWGEDJ_cjs = require('./chunk-3AFWGEDJ.cjs');
8
9
  var chunkVFUWWH52_cjs = require('./chunk-VFUWWH52.cjs');
9
10
  var chunkIA7RTPT3_cjs = require('./chunk-IA7RTPT3.cjs');
10
11
  var chunk2EI7NCUA_cjs = require('./chunk-2EI7NCUA.cjs');
11
- var chunkWBDK4PIA_cjs = require('./chunk-WBDK4PIA.cjs');
12
+ var chunkZ5VUZ6YD_cjs = require('./chunk-Z5VUZ6YD.cjs');
13
+ var chunk7D737FLE_cjs = require('./chunk-7D737FLE.cjs');
12
14
  var chunkOB5F4577_cjs = require('./chunk-OB5F4577.cjs');
13
- var chunkC54XEN5T_cjs = require('./chunk-C54XEN5T.cjs');
14
15
  var chunkV3L5DONY_cjs = require('./chunk-V3L5DONY.cjs');
15
16
  var chunk7UTB4PHM_cjs = require('./chunk-7UTB4PHM.cjs');
16
17
  var chunkFX3K6LNZ_cjs = require('./chunk-FX3K6LNZ.cjs');
18
+ var chunkC54XEN5T_cjs = require('./chunk-C54XEN5T.cjs');
17
19
  var chunkKDG6FER6_cjs = require('./chunk-KDG6FER6.cjs');
18
20
  var chunkULWRNGGE_cjs = require('./chunk-ULWRNGGE.cjs');
19
21
  var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
@@ -22,483 +24,6 @@ var ui = require('@arbidocs/react/ui');
22
24
  var jsxRuntime = require('react/jsx-runtime');
23
25
  var lucideReact = require('lucide-react');
24
26
 
25
- // src/agents/workflows/types.ts
26
- var EMPTY_WORKFLOW_SCOPE = { folders: [], labels: [] };
27
-
28
- // src/agents/workflows/workflow.ts
29
- var isWorkflowScope = (value) => typeof value === "object" && value !== null && Array.isArray(value.folders) && Array.isArray(value.labels);
30
- var isEmptyWorkflowScope = (scope) => scope.folders.length === 0 && scope.labels.length === 0 && !scope.documents?.length;
31
- var isFileField = (field) => field.type === "scope" || field.type === "documents";
32
- function emptyValue(field) {
33
- switch (field.type) {
34
- case "boolean":
35
- return false;
36
- case "scope":
37
- return { folders: [], labels: [] };
38
- case "documents":
39
- return { folders: [], labels: [], documents: [] };
40
- default:
41
- return "";
42
- }
43
- }
44
- function defaultInputs(workflow) {
45
- const inputs = {};
46
- for (const field of workflow.inputs) {
47
- const d = field.default;
48
- inputs[field.name] = d === void 0 ? emptyValue(field) : isWorkflowScope(d) ? { ...d } : d;
49
- }
50
- return inputs;
51
- }
52
- function validateInputs(workflow, inputs) {
53
- const errors = {};
54
- for (const field of workflow.inputs) {
55
- const value = inputs[field.name];
56
- if (field.type === "number") {
57
- const blank = value === "" || value === void 0;
58
- if (blank) {
59
- if (field.required) errors[field.name] = "required";
60
- continue;
61
- }
62
- const n = Number(value);
63
- if (Number.isNaN(n)) errors[field.name] = "number";
64
- else if (field.min !== void 0 && n < field.min) errors[field.name] = "min";
65
- else if (field.max !== void 0 && n > field.max) errors[field.name] = "max";
66
- continue;
67
- }
68
- if (!field.required) continue;
69
- if (field.type === "documents") {
70
- if (!isWorkflowScope(value) || !value.documents?.length) errors[field.name] = "required";
71
- continue;
72
- }
73
- if (field.type === "boolean" || field.type === "scope") continue;
74
- if (typeof value !== "string" || value.trim() === "") errors[field.name] = "required";
75
- }
76
- return errors;
77
- }
78
- function promptFieldName(workflow) {
79
- return workflow.inputs.find((f) => !f.advanced && (f.type === "text" || f.type === "longtext"))?.name;
80
- }
81
- var quoteList = (names) => {
82
- const quoted = names.map((n) => `"${n}"`);
83
- return quoted.length <= 1 ? quoted[0] ?? "" : `${quoted.slice(0, -1).join(", ")} and ${quoted[quoted.length - 1]}`;
84
- };
85
- function fragment(field, value, ctx) {
86
- switch (field.type) {
87
- case "documents": {
88
- const ids = isWorkflowScope(value) ? value.documents ?? [] : [];
89
- const names = ids.flatMap((id) => {
90
- const title = ctx?.documentTitles?.[id];
91
- return title ? [title] : [];
92
- });
93
- return quoteList(names);
94
- }
95
- case "boolean":
96
- return value ? field.trueText ?? "yes" : field.falseText ?? "no";
97
- case "select": {
98
- const option = field.options?.find((o) => o.value === value);
99
- return option ? option.text ?? option.label : String(value ?? "");
100
- }
101
- case "scope":
102
- return "";
103
- default:
104
- return typeof value === "string" ? value.trim() : String(value ?? "");
105
- }
106
- }
107
- function composeWorkflowPrompt(workflow, inputs, ctx) {
108
- if (workflow.run.kind !== "prompt") return "";
109
- const byName = new Map(workflow.inputs.map((f) => [f.name, f]));
110
- const template = workflow.run.promptTemplate;
111
- let out = "";
112
- let last = 0;
113
- const append = (text, isValue) => {
114
- let t = text;
115
- if (!isValue) {
116
- t = t.replace(/[ \t]{2,}/g, " ");
117
- if (/[ \t]$/.test(out)) t = t.replace(/^[ \t]+/, "");
118
- }
119
- out += t;
120
- };
121
- for (const m of template.matchAll(/\{\{\s*([a-z][a-z0-9_]*)\s*\}\}/gi)) {
122
- append(template.slice(last, m.index), false);
123
- const field = byName.get(m[1]);
124
- append(field ? fragment(field, inputs[m[1]], ctx) : "", true);
125
- last = m.index + m[0].length;
126
- }
127
- append(template.slice(last), false);
128
- return out.trim();
129
- }
130
- function buildLaunch(workflow, inputs, agentId) {
131
- const scopeField = workflow.inputs.find(isFileField);
132
- const raw = scopeField ? inputs[scopeField.name] : void 0;
133
- const scope = isWorkflowScope(raw) ? raw : { ...EMPTY_WORKFLOW_SCOPE };
134
- return { workflow, inputs, scope, agentId: agentId || workflow.defaultAgentId || void 0 };
135
- }
136
- function workflowAccepts(workflow) {
137
- const kinds = /* @__PURE__ */ new Set();
138
- for (const field of workflow.inputs) if (field.context) kinds.add(field.context);
139
- return [...kinds];
140
- }
141
- function workflowsAccepting(workflows, supplied) {
142
- return workflows.filter((w) => workflowAccepts(w).some((k) => supplied.includes(k)));
143
- }
144
- function workflowsForHost(workflows, host) {
145
- return workflows.filter((w) => !w.host || w.host === host);
146
- }
147
- function inputsFromContext(workflow, context) {
148
- const inputs = {};
149
- for (const field of workflow.inputs) {
150
- if (!field.context) continue;
151
- if (field.context === "selection") {
152
- if (context.selection) inputs[field.name] = context.selection;
153
- continue;
154
- }
155
- const ids = field.context === "image" ? context.image ? [context.image] : [] : context.documents;
156
- if (ids?.length && isFileField(field)) {
157
- inputs[field.name] = { folders: [], labels: [], documents: ids.slice(0, field.max ?? 1) };
158
- }
159
- }
160
- return inputs;
161
- }
162
- var SKILL_PROMPT_LABEL = "What should it work on?";
163
- var SKILL_PROMPT_FALLBACK_PLACEHOLDER = "Describe what you want";
164
- var plainHint = (hint) => hint.replace(/^[<[]\s*|\s*[>\]]$/g, "").trim();
165
- function skillToWorkflow(skill) {
166
- const hint = plainHint((skill.arg_hint ?? "").trim());
167
- const inputs = [
168
- {
169
- name: "args",
170
- type: "longtext",
171
- label: SKILL_PROMPT_LABEL,
172
- placeholder: hint || SKILL_PROMPT_FALLBACK_PLACEHOLDER,
173
- required: true
174
- }
175
- ];
176
- return {
177
- id: skill.slug,
178
- skill: skill.slug,
179
- title: skill.name || skill.slug,
180
- description: skill.description ?? "",
181
- inputs,
182
- run: { kind: "prompt", promptTemplate: `/${skill.slug} {{args}}` },
183
- landing: "chat",
184
- schedulable: true
185
- };
186
- }
187
- var FIELD_TYPES = [
188
- "text",
189
- "longtext",
190
- "boolean",
191
- "select",
192
- "number",
193
- "date",
194
- "scope",
195
- "documents"
196
- ];
197
- var str = (v) => typeof v === "string" ? v : void 0;
198
- var num = (v) => typeof v === "number" ? v : void 0;
199
- var bool = (v) => typeof v === "boolean" ? v : void 0;
200
- function fieldFromFrontmatter(raw) {
201
- if (typeof raw !== "object" || raw === null) return null;
202
- const r = raw;
203
- const name = str(r.name);
204
- const type = FIELD_TYPES.find((t) => t === r.type);
205
- if (!name || !/^[a-z][a-z0-9_]*$/.test(name) || !type) return null;
206
- const options = Array.isArray(r.options) ? r.options.flatMap((o) => {
207
- const ro = o;
208
- const value = str(ro?.value);
209
- const label = str(ro?.label);
210
- return value && label ? [
211
- {
212
- value,
213
- label,
214
- description: str(ro.description),
215
- text: str(ro.text),
216
- icon: str(ro.icon)
217
- }
218
- ] : [];
219
- }) : void 0;
220
- return {
221
- name,
222
- type,
223
- label: str(r.label) ?? name,
224
- description: str(r.description),
225
- placeholder: str(r.placeholder),
226
- required: bool(r.required),
227
- default: r.default,
228
- options,
229
- min: num(r.min),
230
- max: num(r.max),
231
- trueText: str(r.true_text),
232
- falseText: str(r.false_text),
233
- advanced: bool(r.advanced),
234
- accept: r.accept === "image" ? "image" : void 0,
235
- context: r.context === "documents" || r.context === "selection" || r.context === "image" ? r.context : void 0,
236
- by: Array.isArray(r.by) ? r.by.filter((b) => b === "folders" || b === "labels") : void 0
237
- };
238
- }
239
- function workflowFromFrontmatter(id, frontmatter, body) {
240
- const inputs = Array.isArray(frontmatter.inputs) ? frontmatter.inputs.flatMap((f) => {
241
- const field = fieldFromFrontmatter(f);
242
- return field ? [field] : [];
243
- }) : [];
244
- return {
245
- id,
246
- title: str(frontmatter.name) ?? id,
247
- description: str(frontmatter.description) ?? "",
248
- icon: str(frontmatter.icon),
249
- inputs,
250
- run: { kind: "prompt", promptTemplate: body.trim() },
251
- landing: frontmatter.landing === "files" ? "files" : "chat",
252
- requiresFiles: bool(frontmatter.requires_files),
253
- schedulable: bool(frontmatter.schedulable) ?? true
254
- };
255
- }
256
- var DEFAULT_SCHEMA_FORM_LABELS = {
257
- optional: "(optional)",
258
- advanced: "More options",
259
- errors: {
260
- required: "This is needed to continue",
261
- min: "Too small",
262
- max: "Too large",
263
- number: "Enter a number"
264
- }
265
- };
266
- var TILE_MAX = 4;
267
- function FieldControl({
268
- field,
269
- value,
270
- error,
271
- onChange,
272
- l,
273
- idFor,
274
- renderScope,
275
- renderDocuments,
276
- renderIcon,
277
- onEnterSubmit
278
- }) {
279
- const id = `${idFor()}-control`;
280
- const testId = idFor();
281
- switch (field.type) {
282
- case "text":
283
- return /* @__PURE__ */ jsxRuntime.jsx(
284
- ui.Input,
285
- {
286
- id,
287
- "data-testid": testId,
288
- value: String(value ?? ""),
289
- placeholder: field.placeholder,
290
- "aria-required": field.required || void 0,
291
- "aria-invalid": error ? true : void 0,
292
- "aria-describedby": error ? idFor("error") : void 0,
293
- onChange: (e) => onChange(e.target.value)
294
- }
295
- );
296
- case "longtext":
297
- return /* @__PURE__ */ jsxRuntime.jsx(
298
- ui.Textarea,
299
- {
300
- id,
301
- "data-testid": testId,
302
- value: String(value ?? ""),
303
- placeholder: field.placeholder,
304
- "aria-required": field.required || void 0,
305
- "aria-invalid": error ? true : void 0,
306
- "aria-describedby": error ? idFor("error") : void 0,
307
- className: "min-h-[96px]",
308
- onChange: (e) => onChange(e.target.value),
309
- onKeyDown: (e) => {
310
- if (onEnterSubmit && e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
311
- e.preventDefault();
312
- onEnterSubmit();
313
- }
314
- }
315
- }
316
- );
317
- case "number":
318
- return /* @__PURE__ */ jsxRuntime.jsx(
319
- ui.Input,
320
- {
321
- id,
322
- "data-testid": testId,
323
- type: "number",
324
- inputMode: "decimal",
325
- min: field.min,
326
- max: field.max,
327
- value: value === void 0 ? "" : String(value),
328
- placeholder: field.placeholder,
329
- "aria-invalid": error ? true : void 0,
330
- "aria-describedby": error ? idFor("error") : void 0,
331
- onChange: (e) => onChange(e.target.value === "" ? "" : Number(e.target.value))
332
- }
333
- );
334
- case "date":
335
- return /* @__PURE__ */ jsxRuntime.jsx(
336
- ui.Input,
337
- {
338
- id,
339
- "data-testid": testId,
340
- type: "date",
341
- value: String(value ?? ""),
342
- "aria-invalid": error ? true : void 0,
343
- "aria-describedby": error ? idFor("error") : void 0,
344
- onChange: (e) => onChange(e.target.value)
345
- }
346
- );
347
- case "boolean":
348
- return /* @__PURE__ */ jsxRuntime.jsx(
349
- ui.Switch,
350
- {
351
- id,
352
- "data-testid": testId,
353
- checked: Boolean(value),
354
- onCheckedChange: (checked) => onChange(checked)
355
- }
356
- );
357
- case "select": {
358
- const options = field.options ?? [];
359
- if (options.length > 0 && options.length <= TILE_MAX) {
360
- return /* @__PURE__ */ jsxRuntime.jsx(
361
- "div",
362
- {
363
- role: "radiogroup",
364
- "aria-label": field.label,
365
- className: "grid grid-cols-2 gap-2 sm:grid-cols-4",
366
- "data-testid": testId,
367
- children: options.map((option) => {
368
- const selected = value === option.value;
369
- return /* @__PURE__ */ jsxRuntime.jsxs(
370
- "button",
371
- {
372
- type: "button",
373
- role: "radio",
374
- "aria-checked": selected,
375
- "data-testid": chunkMHVNT4J3_cjs.prefixedTestId(testId, option.value, {
376
- testId: `workflow-field-${field.name}-${option.value}`
377
- }),
378
- onClick: () => {
379
- onChange(option.value);
380
- },
381
- className: ui.cn(
382
- "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",
383
- selected ? "border-primary bg-primary/10" : "border-border bg-card [&:hover]:border-primary [&:hover]:bg-muted"
384
- ),
385
- children: [
386
- option.icon && renderIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: renderIcon(option.icon) }),
387
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-foreground", children: option.label }),
388
- option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: option.description })
389
- ]
390
- },
391
- option.value
392
- );
393
- })
394
- }
395
- );
396
- }
397
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v), children: [
398
- /* @__PURE__ */ jsxRuntime.jsx(ui.SelectTrigger, { id, "data-testid": testId, className: "pointer-coarse:min-h-11", children: /* @__PURE__ */ jsxRuntime.jsx(ui.SelectValue, { placeholder: field.placeholder }) }),
399
- /* @__PURE__ */ jsxRuntime.jsx(ui.SelectContent, { children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(ui.SelectItem, { value: o.value, children: o.label }, o.value)) })
400
- ] });
401
- }
402
- case "scope": {
403
- const scope = isWorkflowScope(value) ? value : { folders: [], labels: [] };
404
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": testId, children: renderScope?.(field, scope, onChange) });
405
- }
406
- case "documents": {
407
- const picked = isWorkflowScope(value) ? value : { folders: [], labels: [], documents: [] };
408
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": testId, children: renderDocuments?.(field, picked, onChange) });
409
- }
410
- }
411
- }
412
- function FormField(props) {
413
- const { field, error, l, idFor } = props;
414
- const isBoolean = field.type === "boolean";
415
- const showOptional = !field.required && field.type !== "boolean" && field.type !== "scope";
416
- const label = /* @__PURE__ */ jsxRuntime.jsxs(
417
- ui.Label,
418
- {
419
- htmlFor: `${idFor()}-control`,
420
- className: isBoolean ? "cursor-pointer font-normal" : void 0,
421
- children: [
422
- field.label,
423
- showOptional && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
424
- " ",
425
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-normal text-muted-foreground", children: l.optional })
426
- ] })
427
- ]
428
- }
429
- );
430
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", "data-slot": "schema-field", "data-field": field.name, children: [
431
- isBoolean ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 pointer-coarse:min-h-11", children: [
432
- /* @__PURE__ */ jsxRuntime.jsx(FieldControl, { ...props }),
433
- label
434
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
435
- field.type !== "scope" && label,
436
- /* @__PURE__ */ jsxRuntime.jsx(FieldControl, { ...props })
437
- ] }),
438
- field.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: field.description }),
439
- error && /* @__PURE__ */ jsxRuntime.jsx(
440
- "p",
441
- {
442
- id: idFor("error"),
443
- role: "alert",
444
- className: "text-xs text-destructive",
445
- "data-testid": idFor("error"),
446
- children: l.errors[error]
447
- }
448
- )
449
- ] });
450
- }
451
- function SchemaForm({
452
- fields,
453
- values,
454
- onChange,
455
- errors,
456
- renderScope,
457
- renderDocuments,
458
- renderIcon,
459
- onEnterSubmit,
460
- testIdPrefix,
461
- labels,
462
- className
463
- }) {
464
- const l = {
465
- ...DEFAULT_SCHEMA_FORM_LABELS,
466
- ...labels,
467
- errors: { ...DEFAULT_SCHEMA_FORM_LABELS.errors, ...labels?.errors }
468
- };
469
- const [advancedOpen, setAdvancedOpen] = react.useState(false);
470
- const common = fields.filter((f) => !f.advanced);
471
- const advanced = fields.filter((f) => f.advanced);
472
- const render = (field) => /* @__PURE__ */ jsxRuntime.jsx(
473
- FormField,
474
- {
475
- field,
476
- value: values[field.name],
477
- error: errors?.[field.name],
478
- onChange: (v) => onChange(field.name, v),
479
- l,
480
- idFor: (suffix) => suffix ? `${chunkMHVNT4J3_cjs.testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}-${suffix}` : `${chunkMHVNT4J3_cjs.testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}`,
481
- renderScope,
482
- renderDocuments,
483
- renderIcon,
484
- onEnterSubmit
485
- },
486
- field.name
487
- );
488
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("flex flex-col gap-4", className), "data-slot": "schema-form", children: [
489
- common.map(render),
490
- advanced.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
491
- chunkWBDK4PIA_cjs.FoldSection,
492
- {
493
- label: l.advanced,
494
- open: advancedOpen,
495
- onOpenChange: setAdvancedOpen,
496
- testId: `${chunkMHVNT4J3_cjs.testIdOr(testIdPrefix, { testId: "workflow-field" })}-advanced-toggle`,
497
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: advanced.map(render) })
498
- }
499
- )
500
- ] });
501
- }
502
27
  function useControllableState(value, defaultValue, onChange) {
503
28
  const [inner, setInner] = react.useState(defaultValue);
504
29
  const isControlled = value !== void 0;
@@ -619,7 +144,7 @@ function WorkflowConfigDialog({
619
144
  }) {
620
145
  const l = { ...DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, ...labels };
621
146
  const initialKey = JSON.stringify(initialInputs ?? {});
622
- const seedKey = JSON.stringify({ ...defaultInputs(workflow), ...JSON.parse(initialKey) });
147
+ const seedKey = JSON.stringify({ ...chunkGTNUQBXI_cjs.defaultInputs(workflow), ...JSON.parse(initialKey) });
623
148
  const seed = react.useMemo(() => JSON.parse(seedKey), [seedKey]);
624
149
  const [inputs, setInputs] = useControllableState(inputsProp, seed, onInputsChange);
625
150
  const [agentId, setAgentId] = useControllableState(
@@ -631,7 +156,7 @@ function WorkflowConfigDialog({
631
156
  if (open && inputsProp === void 0) setInputs(seed);
632
157
  }, [open, seed]);
633
158
  const setField = (name, value) => setInputs({ ...inputs, [name]: value });
634
- const errors = validateInputs(workflow, inputs);
159
+ const errors = chunkGTNUQBXI_cjs.validateInputs(workflow, inputs);
635
160
  const valid = Object.keys(errors).length === 0;
636
161
  const visibleErrors = Object.fromEntries(
637
162
  Object.entries(errors).filter(([, e]) => e !== "required")
@@ -644,7 +169,7 @@ function WorkflowConfigDialog({
644
169
  const blockedByScope = matchedCount !== null && matchedCount === 0 && Boolean(workflow.requiresFiles);
645
170
  const showAgent = workflow.run.kind === "prompt" && workflow.options?.agent !== false && agents !== void 0 && agents.length > 0;
646
171
  const launch = (values) => {
647
- Promise.resolve(onLaunch(buildLaunch(workflow, values, agentId))).catch(() => {
172
+ Promise.resolve(onLaunch(chunkGTNUQBXI_cjs.buildLaunch(workflow, values, agentId))).catch(() => {
648
173
  });
649
174
  };
650
175
  const submit = () => {
@@ -663,7 +188,7 @@ function WorkflowConfigDialog({
663
188
  const firstField = workflow.inputs.find((f) => !f.advanced);
664
189
  const focusPromptFirst = firstField?.type === "text" || firstField?.type === "longtext";
665
190
  const defaultScopeRender = scopeSource ? (_field, value, onChange) => /* @__PURE__ */ jsxRuntime.jsx(
666
- chunkWBDK4PIA_cjs.ScopePicker,
191
+ chunkZ5VUZ6YD_cjs.ScopePicker,
667
192
  {
668
193
  folders: scopeSource.folders,
669
194
  unfiledCount: scopeSource.unfiledCount,
@@ -696,7 +221,7 @@ function WorkflowConfigDialog({
696
221
  },
697
222
  children: [
698
223
  /* @__PURE__ */ jsxRuntime.jsx(
699
- chunkWBDK4PIA_cjs.QuickActionDialogHeader,
224
+ chunkZ5VUZ6YD_cjs.QuickActionDialogHeader,
700
225
  {
701
226
  icon: workflow.icon && renderIcon ? renderIcon(workflow.icon) : null,
702
227
  title: workflow.title,
@@ -714,7 +239,7 @@ function WorkflowConfigDialog({
714
239
  submit();
715
240
  },
716
241
  children: noFiles ? /* @__PURE__ */ jsxRuntime.jsx(
717
- chunkWBDK4PIA_cjs.AddFilesFirst,
242
+ chunkZ5VUZ6YD_cjs.AddFilesFirst,
718
243
  {
719
244
  reason: l.addFilesReason,
720
245
  action: addFilesAction,
@@ -722,7 +247,7 @@ function WorkflowConfigDialog({
722
247
  }
723
248
  ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
724
249
  /* @__PURE__ */ jsxRuntime.jsx(
725
- SchemaForm,
250
+ chunkGTNUQBXI_cjs.SchemaForm,
726
251
  {
727
252
  fields,
728
253
  values: inputs,
@@ -781,7 +306,7 @@ function defaultScopeRenderer(scopeSource) {
781
306
  if (!scopeSource) return void 0;
782
307
  return function renderScope(_field, value, onChange) {
783
308
  return /* @__PURE__ */ jsxRuntime.jsx(
784
- chunkWBDK4PIA_cjs.ScopePicker,
309
+ chunkZ5VUZ6YD_cjs.ScopePicker,
785
310
  {
786
311
  folders: scopeSource.folders,
787
312
  unfiledCount: scopeSource.unfiledCount,
@@ -800,7 +325,7 @@ function resolveScopeInputs(workflow, inputs, scopeSource) {
800
325
  for (const field of workflow.inputs) {
801
326
  if (field.type !== "scope") continue;
802
327
  const raw = inputs[field.name];
803
- const scope = isWorkflowScope(raw) ? raw : { folders: [], labels: [] };
328
+ const scope = chunkGTNUQBXI_cjs.isWorkflowScope(raw) ? raw : { folders: [], labels: [] };
804
329
  next[field.name] = { ...scope, documents: scopeSource.resolveDocuments(scope) };
805
330
  }
806
331
  return next;
@@ -842,9 +367,9 @@ function WorkflowLauncher({
842
367
  };
843
368
  const select = (workflow) => {
844
369
  if (workflow.run.kind === "operation" && workflow.inputs.length === 0) {
845
- const inputs = defaultInputs(workflow);
846
- if (Object.keys(validateInputs(workflow, inputs)).length === 0) {
847
- Promise.resolve(onLaunch(buildLaunch(workflow, inputs, void 0))).catch(() => {
370
+ const inputs = chunkGTNUQBXI_cjs.defaultInputs(workflow);
371
+ if (Object.keys(chunkGTNUQBXI_cjs.validateInputs(workflow, inputs)).length === 0) {
372
+ Promise.resolve(onLaunch(chunkGTNUQBXI_cjs.buildLaunch(workflow, inputs, void 0))).catch(() => {
848
373
  });
849
374
  return;
850
375
  }
@@ -866,7 +391,7 @@ function WorkflowLauncher({
866
391
  });
867
392
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, "data-slot": "workflow-launcher", children: [
868
393
  showTiles && /* @__PURE__ */ jsxRuntime.jsx(
869
- chunkWBDK4PIA_cjs.StartTiles,
394
+ chunkZ5VUZ6YD_cjs.StartTiles,
870
395
  {
871
396
  items: [...tiles, ...extraTiles],
872
397
  caption,
@@ -977,6 +502,93 @@ function WorkflowDocumentsField({
977
502
  addFilesAction
978
503
  ] });
979
504
  }
505
+
506
+ // src/agents/workflows/skillMarkdown.ts
507
+ var JSON_KEYS = /* @__PURE__ */ new Set(["inputs"]);
508
+ var oneLine = (text) => text.replace(/\s*\n\s*/g, " ").trim();
509
+ var skillSlug = (raw) => raw.toLowerCase().replace(/[^a-z0-9-]/g, "");
510
+ function workflowToSkillMarkdown(workflow) {
511
+ const { run } = workflow;
512
+ if (run.kind !== "prompt") throw new Error("Only skills that start a chat can be copied");
513
+ const lines = [
514
+ "---",
515
+ `name: ${skillSlug(workflow.id)}`,
516
+ `description: ${oneLine(workflow.description)}`
517
+ ];
518
+ if (workflow.icon) lines.push(`icon: ${workflow.icon}`);
519
+ if (workflow.landing !== "chat") lines.push(`landing: ${workflow.landing}`);
520
+ if (workflow.requiresFiles) lines.push("requires_files: true");
521
+ if (workflow.inputs.length > 0) {
522
+ lines.push(`inputs: ${JSON.stringify(workflow.inputs.map(chunkGTNUQBXI_cjs.fieldToFrontmatter))}`);
523
+ }
524
+ lines.push("---", "", run.promptTemplate.trim(), "");
525
+ return lines.join("\n");
526
+ }
527
+ function workflowFromSkillMarkdown(id, text) {
528
+ const match = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/.exec(text);
529
+ const frontmatter = {};
530
+ const body = match ? match[2] : text;
531
+ for (const line of (match ? match[1] : "").split("\n")) {
532
+ const i = line.indexOf(":");
533
+ if (i < 1) continue;
534
+ const key = line.slice(0, i).trim();
535
+ const value = line.slice(i + 1).trim();
536
+ if (JSON_KEYS.has(key)) {
537
+ try {
538
+ frontmatter[key] = JSON.parse(value);
539
+ } catch {
540
+ }
541
+ } else if (value === "true" || value === "false") frontmatter[key] = value === "true";
542
+ else frontmatter[key] = value;
543
+ }
544
+ return chunkGTNUQBXI_cjs.workflowFromFrontmatter(id, frontmatter, body);
545
+ }
546
+ function useWorkflowPreview(workflow, { answer = "{prompt}", delayMs = 400, resolveWorkflow, compose } = {}) {
547
+ const steps = chunkGTNUQBXI_cjs.workflowSteps(workflow);
548
+ const [inputs, setInputs] = react.useState(() => chunkGTNUQBXI_cjs.initialRunInputs(workflow));
549
+ const [states, setStates] = react.useState({});
550
+ const set = (id, state) => setStates((s) => ({ ...s, [id]: state }));
551
+ const timers = react.useRef(/* @__PURE__ */ new Map());
552
+ react.useEffect(() => {
553
+ const pending = timers.current;
554
+ return () => {
555
+ for (const t of pending.values()) clearTimeout(t);
556
+ pending.clear();
557
+ setStates(
558
+ (s) => Object.fromEntries(
559
+ Object.entries(s).map(([id, v]) => [
560
+ id,
561
+ v.status === "running" ? { status: "pending" } : v
562
+ ])
563
+ )
564
+ );
565
+ };
566
+ }, []);
567
+ react.useEffect(() => {
568
+ if (Object.values(states).some((s) => s.status === "running")) return;
569
+ const next = steps.find((s) => s.kind === "agent" && chunkGTNUQBXI_cjs.stepPhase(steps, states, s.id) === "ready");
570
+ if (!next || next.kind !== "agent") return;
571
+ const prompt = chunkGTNUQBXI_cjs.composeStepPrompt(workflow, next, inputs, { resolveWorkflow, compose });
572
+ set(next.id, { status: "running" });
573
+ timers.current.set(
574
+ next.id,
575
+ setTimeout(() => {
576
+ timers.current.delete(next.id);
577
+ set(next.id, { status: "done", text: answer.replace("{prompt}", prompt) });
578
+ }, delayMs)
579
+ );
580
+ }, [states, steps, workflow]);
581
+ return chunkGTNUQBXI_cjs.useWorkflowView({
582
+ steps,
583
+ states,
584
+ inputs,
585
+ setInput: (name, value) => setInputs((i) => ({ ...i, [name]: value })),
586
+ complete: async (step) => set(step.id, { status: "done" }),
587
+ skip: async (id) => set(id, { status: "skipped" }),
588
+ retry: async (id) => set(id, { status: "pending" }),
589
+ isLocked: (id) => states[id]?.status === "done"
590
+ });
591
+ }
980
592
  var DEFAULT_AGENT_CARD_LABELS = {
981
593
  running: "Running",
982
594
  runningIndicator: "Running",
@@ -1582,7 +1194,7 @@ function AgentCreator({
1582
1194
  ] })
1583
1195
  ] }),
1584
1196
  /* @__PURE__ */ jsxRuntime.jsx(
1585
- chunkWBDK4PIA_cjs.FoldSection,
1197
+ chunk7D737FLE_cjs.FoldSection,
1586
1198
  {
1587
1199
  label: l.advanced,
1588
1200
  open: advancedOpen,
@@ -5379,7 +4991,7 @@ function workflowTaskFields(workflow, inputs, name, context) {
5379
4991
  }
5380
4992
  const typed = name?.trim();
5381
4993
  if (workflow.options?.agent === false) {
5382
- const message = composeWorkflowPrompt(workflow, inputs, context);
4994
+ const message = chunkGTNUQBXI_cjs.composeWorkflowPrompt(workflow, inputs, context);
5383
4995
  return { name: typed || message, prompt: "", skill_ref: null, skill_inputs: null };
5384
4996
  }
5385
4997
  const derived = typed || deriveWorkflowName(workflow, inputs);
@@ -5393,7 +5005,7 @@ function workflowTaskFields(workflow, inputs, name, context) {
5393
5005
  }
5394
5006
  return {
5395
5007
  name: derived,
5396
- prompt: composeWorkflowPrompt(workflow, inputs, context),
5008
+ prompt: chunkGTNUQBXI_cjs.composeWorkflowPrompt(workflow, inputs, context),
5397
5009
  skill_ref: null,
5398
5010
  // The files a run is bound to travel in the saved inputs, whatever the template: the server binds
5399
5011
  // the run to the ids listed under any input's `documents`.
@@ -6595,7 +6207,11 @@ var ICONS = {
6595
6207
  artifact_edited: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareReply, { className: "size-3.5", "aria-hidden": true }),
6596
6208
  document_added: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "size-3.5", "aria-hidden": true }),
6597
6209
  document_removed: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5", "aria-hidden": true }),
6598
- notified: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserRoundCog, { className: "size-3.5", "aria-hidden": true })
6210
+ notified: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserRoundCog, { className: "size-3.5", "aria-hidden": true }),
6211
+ step_started: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "size-3.5", "aria-hidden": true }),
6212
+ step_done: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "size-3.5", "aria-hidden": true }),
6213
+ step_skipped: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcw, { className: "size-3.5", "aria-hidden": true }),
6214
+ step_failed: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5", "aria-hidden": true })
6599
6215
  };
6600
6216
  var asString = (v) => typeof v === "string" && v.trim() ? v : null;
6601
6217
  function summarizeError(error) {
@@ -6634,6 +6250,17 @@ function TaskActivityTimeline({
6634
6250
  return { headline: "Removed a document" };
6635
6251
  case "notified":
6636
6252
  return { headline: "Sent a notification" };
6253
+ case "step_started":
6254
+ return { headline: "Step started" };
6255
+ case "step_done":
6256
+ return { headline: "Step done" };
6257
+ case "step_skipped":
6258
+ return { headline: "Step skipped" };
6259
+ case "step_failed":
6260
+ return {
6261
+ headline: "Step failed",
6262
+ extra: asString(detail.error) ? l.failureLine(summarizeError(String(detail.error))) : void 0
6263
+ };
6637
6264
  case "created":
6638
6265
  return { headline: detail.from_workflow ? l.createdFromWorkflow : l.created };
6639
6266
  case "run_started":
@@ -6833,8 +6460,163 @@ function ThreadActivity({ item, children }) {
6833
6460
  }
6834
6461
  ) });
6835
6462
  }
6463
+ var STEP_KINDS = /* @__PURE__ */ new Set(["step_started", "step_done", "step_skipped", "step_failed"]);
6464
+ function groupThreadActivity(steps, items) {
6465
+ const out = { before: [], byStep: {}, after: [] };
6466
+ const states = {};
6467
+ let current;
6468
+ for (const item of items) {
6469
+ if (item.kind && STEP_KINDS.has(item.kind) && item.step) {
6470
+ current = item.step;
6471
+ states[item.step] = {
6472
+ status: item.kind === "step_started" ? "running" : item.kind === "step_done" ? "done" : item.kind === "step_skipped" ? "skipped" : "failed"
6473
+ };
6474
+ continue;
6475
+ }
6476
+ if (current === void 0) out.before.push(item);
6477
+ else if (chunkGTNUQBXI_cjs.isRunFinished(steps, states)) out.after.push(item);
6478
+ else {
6479
+ const status = states[current]?.status;
6480
+ const at = status === "done" || status === "skipped" ? steps.find((s) => !["done", "skipped"].includes(states[s.id]?.status ?? ""))?.id ?? current : current;
6481
+ (out.byStep[at] ??= []).push(item);
6482
+ }
6483
+ }
6484
+ return out;
6485
+ }
6486
+ var DEFAULT_WORKFLOW_THREAD_STRIP_LABELS = {
6487
+ happened: "{count} in this step",
6488
+ nothingYet: "Nothing here yet.",
6489
+ skip: "Skip this step"
6490
+ };
6491
+ function Mark({ phase, icon }) {
6492
+ if (phase === "done") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5" });
6493
+ if (phase === "running") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3.5 animate-spin" });
6494
+ if (phase === "failed") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5" });
6495
+ if (phase === "skipped") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MinusCircle, { className: "size-3.5" });
6496
+ return icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-3.5 items-center justify-center [&_svg]:size-3.5", children: icon }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-current" });
6497
+ }
6498
+ function Entry({ item }) {
6499
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6500
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", children: item.avatar }),
6501
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 text-left", children: [
6502
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block max-w-40 truncate text-[11px] font-medium leading-tight", children: item.label }),
6503
+ /* @__PURE__ */ jsxRuntime.jsx(
6504
+ "span",
6505
+ {
6506
+ className: "block text-[10px] leading-tight text-muted-foreground",
6507
+ title: item.exactTime,
6508
+ children: item.time
6509
+ }
6510
+ )
6511
+ ] })
6512
+ ] });
6513
+ return item.onSelect ? /* @__PURE__ */ jsxRuntime.jsx(
6514
+ "button",
6515
+ {
6516
+ type: "button",
6517
+ onClick: item.onSelect,
6518
+ className: "flex w-full items-center gap-1.5 rounded-md px-1 py-0.5 hover:bg-accent",
6519
+ "data-testid": `thread-flow-${item.id}`,
6520
+ children: content
6521
+ }
6522
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex items-center gap-1.5 px-1 py-0.5", "data-testid": `thread-flow-${item.id}`, children: content });
6523
+ }
6524
+ function WorkflowThreadStrip({
6525
+ steps,
6526
+ states,
6527
+ items,
6528
+ renderIcon,
6529
+ onSkip,
6530
+ renderStepAction,
6531
+ labels,
6532
+ className
6533
+ }) {
6534
+ const l = { ...DEFAULT_WORKFLOW_THREAD_STRIP_LABELS, ...labels };
6535
+ const grouped = groupThreadActivity(steps, items);
6536
+ const chevron = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-3 shrink-0 text-muted-foreground" });
6537
+ return /* @__PURE__ */ jsxRuntime.jsx(
6538
+ "div",
6539
+ {
6540
+ className: ui.cn("min-w-0 flex-1 overflow-x-auto overscroll-x-contain", className),
6541
+ role: "region",
6542
+ "aria-label": "Workflow steps",
6543
+ "data-testid": "workflow-thread-strip",
6544
+ children: /* @__PURE__ */ jsxRuntime.jsxs("ol", { className: "flex w-max min-w-full items-center gap-1", children: [
6545
+ grouped.before.map((item) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6546
+ /* @__PURE__ */ jsxRuntime.jsx(Entry, { item }),
6547
+ chevron
6548
+ ] }, item.id)),
6549
+ steps.map((step, i) => {
6550
+ const phase = chunkGTNUQBXI_cjs.stepPhase(steps, states, step.id);
6551
+ const happened = grouped.byStep[step.id] ?? [];
6552
+ const chip = /* @__PURE__ */ jsxRuntime.jsxs(
6553
+ "span",
6554
+ {
6555
+ className: ui.cn(
6556
+ "flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-full border px-2 py-0.5 text-xs font-medium",
6557
+ phase === "running" || phase === "ready" ? "border-primary bg-primary/10 text-primary" : phase === "done" || phase === "skipped" ? "border-primary/30 text-primary" : phase === "failed" ? "border-destructive/40 text-destructive" : "border-dashed border-border text-muted-foreground"
6558
+ ),
6559
+ "data-phase": phase,
6560
+ "data-testid": `workflow-thread-step-${step.id}`,
6561
+ children: [
6562
+ /* @__PURE__ */ jsxRuntime.jsx(
6563
+ Mark,
6564
+ {
6565
+ phase,
6566
+ icon: step.icon && renderIcon ? renderIcon(step.icon) : void 0
6567
+ }
6568
+ ),
6569
+ step.title,
6570
+ happened.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-muted px-1.5 text-[10px] text-muted-foreground", children: happened.length })
6571
+ ]
6572
+ }
6573
+ );
6574
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6575
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Popover, { children: [
6576
+ /* @__PURE__ */ jsxRuntime.jsx(ui.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "rounded-full", children: chip }) }),
6577
+ /* @__PURE__ */ jsxRuntime.jsxs(
6578
+ ui.PopoverContent,
6579
+ {
6580
+ align: "start",
6581
+ className: "w-72 space-y-1 p-2",
6582
+ "data-testid": `workflow-thread-step-${step.id}-menu`,
6583
+ children: [
6584
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-1 text-xs font-medium text-muted-foreground", children: happened.length ? l.happened.replace("{count}", String(happened.length)) : l.nothingYet }),
6585
+ happened.map((item) => /* @__PURE__ */ jsxRuntime.jsx(Entry, { item }, item.id)),
6586
+ renderStepAction?.(step, phase),
6587
+ onSkip && ["ready", "blocked", "failed"].includes(phase) && /* @__PURE__ */ jsxRuntime.jsx(
6588
+ "button",
6589
+ {
6590
+ type: "button",
6591
+ onClick: () => onSkip(step.id),
6592
+ className: "w-full rounded-md px-1 py-1 text-left text-xs text-muted-foreground hover:bg-accent",
6593
+ "data-testid": `workflow-thread-step-${step.id}-skip`,
6594
+ children: l.skip
6595
+ }
6596
+ )
6597
+ ]
6598
+ }
6599
+ )
6600
+ ] }),
6601
+ (i < steps.length - 1 || grouped.after.length > 0) && chevron
6602
+ ] }, step.id);
6603
+ }),
6604
+ grouped.after.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6605
+ /* @__PURE__ */ jsxRuntime.jsx(Entry, { item }),
6606
+ i < grouped.after.length - 1 && chevron
6607
+ ] }, item.id))
6608
+ ] })
6609
+ }
6610
+ );
6611
+ }
6836
6612
 
6837
6613
  // src/agents/tasks/compact-thread-activity.ts
6614
+ var STEP_LABELS = {
6615
+ step_started: "Step started",
6616
+ step_done: "Step done",
6617
+ step_skipped: "Step skipped",
6618
+ step_failed: "Step failed"
6619
+ };
6838
6620
  function compactThreadActivity(events) {
6839
6621
  const result = [];
6840
6622
  const batches = /* @__PURE__ */ new Map();
@@ -6856,6 +6638,8 @@ function compactThreadActivity(events) {
6856
6638
  entry.recipients.push(event.to_ext_id);
6857
6639
  const count = Math.max(1, entry.recipients.length);
6858
6640
  entry.label = `Notified ${count} ${count === 1 ? "user" : "users"}`;
6641
+ } else if (STEP_LABELS[event.kind]) {
6642
+ result.push({ event, label: STEP_LABELS[event.kind], recipients: [] });
6859
6643
  } else if (["artifact_created", "artifact_edited", "document_added", "document_removed"].includes(
6860
6644
  event.kind
6861
6645
  )) {
@@ -7252,7 +7036,7 @@ function defaultTaskComposerValues(workflows, initial) {
7252
7036
  return {
7253
7037
  assignee: "me",
7254
7038
  workflowId,
7255
- inputs: workflow ? { ...defaultInputs(workflow), ...initial?.inputs } : { ...initial?.inputs },
7039
+ inputs: workflow ? { ...chunkGTNUQBXI_cjs.defaultInputs(workflow), ...initial?.inputs } : { ...initial?.inputs },
7256
7040
  when: "manual",
7257
7041
  runAt: "",
7258
7042
  rrule: "",
@@ -7361,7 +7145,7 @@ function WorkflowComposer({
7361
7145
  return !docs?.length;
7362
7146
  })
7363
7147
  );
7364
- const whatMissing = !workflow || Object.keys(validateInputs({ ...workflow, inputs: fields }, values.inputs)).length > 0;
7148
+ const whatMissing = !workflow || Object.keys(chunkGTNUQBXI_cjs.validateInputs({ ...workflow, inputs: fields }, values.inputs)).length > 0;
7365
7149
  const runAtPast = values.when === "once" && values.runAt !== "" && values.runAt !== initialValues?.runAt && new Date(values.runAt).getTime() <= Date.now();
7366
7150
  const whenMissing = missingWhen(values, runAtPast);
7367
7151
  const scheduled = values.when !== "now" && values.when !== "manual";
@@ -7373,7 +7157,7 @@ function WorkflowComposer({
7373
7157
  setValues({
7374
7158
  ...values,
7375
7159
  workflowId: next,
7376
- inputs: def ? defaultInputs(def) : {},
7160
+ inputs: def ? chunkGTNUQBXI_cjs.defaultInputs(def) : {},
7377
7161
  ...def?.documentAction ? { access: "standing" } : {}
7378
7162
  });
7379
7163
  };
@@ -7501,7 +7285,7 @@ function WorkflowComposer({
7501
7285
  },
7502
7286
  "data-testid": `${id}-dropzone`,
7503
7287
  children: /* @__PURE__ */ jsxRuntime.jsx(
7504
- chunkWBDK4PIA_cjs.AddFilesFirst,
7288
+ chunkZ5VUZ6YD_cjs.AddFilesFirst,
7505
7289
  {
7506
7290
  reason: l.addFilesReason,
7507
7291
  action: addFilesAction,
@@ -7511,7 +7295,7 @@ function WorkflowComposer({
7511
7295
  }
7512
7296
  ),
7513
7297
  !noFiles && workflow && fields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
7514
- SchemaForm,
7298
+ chunkGTNUQBXI_cjs.SchemaForm,
7515
7299
  {
7516
7300
  fields,
7517
7301
  values: values.inputs,
@@ -7950,7 +7734,7 @@ function WorkTaskComposer({
7950
7734
  }, [open]);
7951
7735
  const workflow = workflows.find((w) => w.id === values.workflowId);
7952
7736
  const fields = workflow?.inputs ?? [];
7953
- const errors = workflow ? validateInputs({ ...workflow, inputs: fields }, values.inputs) : {};
7737
+ const errors = workflow ? chunkGTNUQBXI_cjs.validateInputs({ ...workflow, inputs: fields }, values.inputs) : {};
7954
7738
  const hasWork = configOpen && Boolean(workflow) && Object.keys(errors).length === 0;
7955
7739
  const unattended = hasWork && values.when !== "now" && values.when !== "manual";
7956
7740
  const canConfigure = !isEdit || seed.assignee === "agent";
@@ -7958,7 +7742,7 @@ function WorkTaskComposer({
7958
7742
  const set = (key, value) => setValues({ ...values, [key]: value });
7959
7743
  const pickWorkflow = (id2) => {
7960
7744
  const next = workflows.find((w) => w.id === id2);
7961
- setValues({ ...values, workflowId: id2, inputs: next ? defaultInputs(next) : {} });
7745
+ setValues({ ...values, workflowId: id2, inputs: next ? chunkGTNUQBXI_cjs.defaultInputs(next) : {} });
7962
7746
  };
7963
7747
  const openConfigure = () => {
7964
7748
  setConfigOpen(true);
@@ -8144,7 +7928,7 @@ function WorkTaskComposer({
8144
7928
  )
8145
7929
  ] }),
8146
7930
  workflow && fields.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
8147
- SchemaForm,
7931
+ chunkGTNUQBXI_cjs.SchemaForm,
8148
7932
  {
8149
7933
  fields,
8150
7934
  values: values.inputs,
@@ -10172,7 +9956,6 @@ exports.DEFAULT_NEW_THREAD_DIALOG_LABELS = DEFAULT_NEW_THREAD_DIALOG_LABELS;
10172
9956
  exports.DEFAULT_PILL_SELECT_LABELS = DEFAULT_PILL_SELECT_LABELS;
10173
9957
  exports.DEFAULT_RECURRENCE = DEFAULT_RECURRENCE;
10174
9958
  exports.DEFAULT_RECURRENCE_BUILDER_LABELS = DEFAULT_RECURRENCE_BUILDER_LABELS;
10175
- exports.DEFAULT_SCHEMA_FORM_LABELS = DEFAULT_SCHEMA_FORM_LABELS;
10176
9959
  exports.DEFAULT_SKILL_CARD_LABELS = DEFAULT_SKILL_CARD_LABELS;
10177
9960
  exports.DEFAULT_SKILL_EDIT_FORM_LABELS = DEFAULT_SKILL_EDIT_FORM_LABELS;
10178
9961
  exports.DEFAULT_SKILL_GENERATE_FORM_LABELS = DEFAULT_SKILL_GENERATE_FORM_LABELS;
@@ -10196,9 +9979,9 @@ exports.DEFAULT_UPLOAD_TASK_LIST_LABELS = DEFAULT_UPLOAD_TASK_LIST_LABELS;
10196
9979
  exports.DEFAULT_WORKFLOWS_CHROME_LABELS = DEFAULT_WORKFLOWS_CHROME_LABELS;
10197
9980
  exports.DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS = DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS;
10198
9981
  exports.DEFAULT_WORKFLOW_LIST_LABELS = DEFAULT_WORKFLOW_LIST_LABELS;
9982
+ exports.DEFAULT_WORKFLOW_THREAD_STRIP_LABELS = DEFAULT_WORKFLOW_THREAD_STRIP_LABELS;
10199
9983
  exports.DERIVED_NAME_WORDS = DERIVED_NAME_WORDS;
10200
9984
  exports.EMPTY_NEW_THREAD = EMPTY_NEW_THREAD;
10201
- exports.EMPTY_WORKFLOW_SCOPE = EMPTY_WORKFLOW_SCOPE;
10202
9985
  exports.EntityChip = EntityChip;
10203
9986
  exports.GoalCriteria = GoalCriteria;
10204
9987
  exports.MAX_TASK_DEPTH = MAX_TASK_DEPTH;
@@ -10206,12 +9989,9 @@ exports.NewThreadDialog = NewThreadDialog;
10206
9989
  exports.PersonPill = PersonPill;
10207
9990
  exports.PillSelect = PillSelect;
10208
9991
  exports.RecurrenceBuilder = RecurrenceBuilder;
10209
- exports.SKILL_PROMPT_FALLBACK_PLACEHOLDER = SKILL_PROMPT_FALLBACK_PLACEHOLDER;
10210
- exports.SKILL_PROMPT_LABEL = SKILL_PROMPT_LABEL;
10211
9992
  exports.STATUS_LABELS = STATUS_LABELS;
10212
9993
  exports.STATUS_ORDER = STATUS_ORDER;
10213
9994
  exports.STATUS_TONE = STATUS_TONE;
10214
- exports.SchemaForm = SchemaForm;
10215
9995
  exports.SkillActionButton = SkillActionButton;
10216
9996
  exports.SkillCard = SkillCard;
10217
9997
  exports.SkillDetail = SkillDetail;
@@ -10262,19 +10042,18 @@ exports.WORKFLOW_COLUMN_ORDER = WORKFLOW_COLUMN_ORDER;
10262
10042
  exports.WorkflowConfigDialog = WorkflowConfigDialog;
10263
10043
  exports.WorkflowDocumentsField = WorkflowDocumentsField;
10264
10044
  exports.WorkflowLauncher = WorkflowLauncher;
10045
+ exports.WorkflowThreadStrip = WorkflowThreadStrip;
10265
10046
  exports.WorkflowsTable = WorkflowsTable;
10266
10047
  exports.WorkflowsToolbar = WorkflowsToolbar;
10267
10048
  exports.agentConfigSectionToValues = agentConfigSectionToValues;
10268
10049
  exports.agentCreatorToConfigSection = agentCreatorToConfigSection;
10269
10050
  exports.asTaskStatus = asTaskStatus;
10270
10051
  exports.authModeFor = authModeFor;
10271
- exports.buildLaunch = buildLaunch;
10272
10052
  exports.buildRRule = buildRRule;
10273
10053
  exports.buildTaskRows = buildTaskRows;
10274
10054
  exports.buildWorkflowScopeSource = buildWorkflowScopeSource;
10275
10055
  exports.compactThreadActivity = compactThreadActivity;
10276
10056
  exports.composePersona = composePersona;
10277
- exports.composeWorkflowPrompt = composeWorkflowPrompt;
10278
10057
  exports.composerToTaskQuery = composerToTaskQuery;
10279
10058
  exports.composerToWorkRequest = composerToWorkRequest;
10280
10059
  exports.composerToWorkflowRequest = composerToWorkflowRequest;
@@ -10282,7 +10061,6 @@ exports.composerToWorkflowUpdate = composerToWorkflowUpdate;
10282
10061
  exports.createTaskColumns = createTaskColumns;
10283
10062
  exports.createWorkflowColumns = createWorkflowColumns;
10284
10063
  exports.createsWork = createsWork;
10285
- exports.defaultInputs = defaultInputs;
10286
10064
  exports.defaultScopeRenderer = defaultScopeRenderer;
10287
10065
  exports.defaultTaskComposerValues = defaultTaskComposerValues;
10288
10066
  exports.deriveAgentName = deriveAgentName;
@@ -10293,20 +10071,18 @@ exports.filterConversationRows = filterConversationRows;
10293
10071
  exports.firstWords = firstWords;
10294
10072
  exports.formatElapsed = formatElapsed;
10295
10073
  exports.goalProgress = goalProgress;
10074
+ exports.groupThreadActivity = groupThreadActivity;
10296
10075
  exports.hasTaskFields = hasTaskFields;
10297
10076
  exports.hasTrigger = hasTrigger;
10298
10077
  exports.humanizeSection = humanizeSection;
10299
10078
  exports.indexTasks = indexTasks;
10300
10079
  exports.inferType = inferType;
10301
10080
  exports.inputDocumentIds = inputDocumentIds;
10302
- exports.inputsFromContext = inputsFromContext;
10303
10081
  exports.isAgenticWorkflow = isAgenticWorkflow;
10304
- exports.isEmptyWorkflowScope = isEmptyWorkflowScope;
10305
10082
  exports.isOutOfBounds = isOutOfBounds;
10306
10083
  exports.isPlainTodo = isPlainTodo;
10307
10084
  exports.isSkillRow = isSkillRow;
10308
10085
  exports.isValidAgentName = isValidAgentName;
10309
- exports.isWorkflowScope = isWorkflowScope;
10310
10086
  exports.isoToLocalInput = isoToLocalInput;
10311
10087
  exports.localInputToIso = localInputToIso;
10312
10088
  exports.matchWorkflowScope = matchWorkflowScope;
@@ -10316,9 +10092,8 @@ exports.nextCriterionId = nextCriterionId;
10316
10092
  exports.ownerExtId = ownerExtId;
10317
10093
  exports.parseRRule = parseRRule;
10318
10094
  exports.prettifyKey = prettifyKey;
10319
- exports.promptFieldName = promptFieldName;
10320
10095
  exports.resolveScopeInputs = resolveScopeInputs;
10321
- exports.skillToWorkflow = skillToWorkflow;
10096
+ exports.skillSlug = skillSlug;
10322
10097
  exports.stripPersonaPreamble = stripPersonaPreamble;
10323
10098
  exports.summarizeAgent = summarizeAgent;
10324
10099
  exports.summarizeCapabilities = summarizeCapabilities;
@@ -10326,15 +10101,13 @@ exports.taskComposerToCreateRequest = taskComposerToCreateRequest;
10326
10101
  exports.taskComposerToUpdateRequest = taskComposerToUpdateRequest;
10327
10102
  exports.taskNeedsAccess = taskNeedsAccess;
10328
10103
  exports.taskToComposerValues = taskToComposerValues;
10329
- exports.validateInputs = validateInputs;
10330
- exports.workflowAccepts = workflowAccepts;
10331
- exports.workflowFromFrontmatter = workflowFromFrontmatter;
10104
+ exports.useWorkflowPreview = useWorkflowPreview;
10105
+ exports.workflowFromSkillMarkdown = workflowFromSkillMarkdown;
10332
10106
  exports.workflowStatus = workflowStatus;
10333
10107
  exports.workflowTaskFields = workflowTaskFields;
10334
10108
  exports.workflowToComposerValues = workflowToComposerValues;
10109
+ exports.workflowToSkillMarkdown = workflowToSkillMarkdown;
10335
10110
  exports.workflowTriggerType = workflowTriggerType;
10336
10111
  exports.workflowWhen = workflowWhen;
10337
- exports.workflowsAccepting = workflowsAccepting;
10338
- exports.workflowsForHost = workflowsForHost;
10339
- //# sourceMappingURL=chunk-DH7C2UJO.cjs.map
10340
- //# sourceMappingURL=chunk-DH7C2UJO.cjs.map
10112
+ //# sourceMappingURL=chunk-IUR565UW.cjs.map
10113
+ //# sourceMappingURL=chunk-IUR565UW.cjs.map