@arbidocs/blocks 0.4.142 → 0.4.143

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 (209) hide show
  1. package/dist/agents/index.cjs +438 -435
  2. package/dist/agents/index.js +10 -7
  3. package/dist/chat/index.cjs +139 -138
  4. package/dist/chat/index.js +4 -3
  5. package/dist/{chunk-S24XEVPS.cjs → chunk-464YPRAE.cjs} +33 -2
  6. package/dist/chunk-464YPRAE.cjs.map +1 -0
  7. package/dist/{chunk-7YLJHTDC.cjs → chunk-5A2QQAF5.cjs} +11 -11
  8. package/dist/{chunk-7YLJHTDC.cjs.map → chunk-5A2QQAF5.cjs.map} +1 -1
  9. package/dist/{chunk-ON3TKY5Y.js → chunk-5YHEHEJT.js} +242 -4
  10. package/dist/chunk-5YHEHEJT.js.map +1 -0
  11. package/dist/chunk-76L6LOP3.cjs +308 -0
  12. package/dist/chunk-76L6LOP3.cjs.map +1 -0
  13. package/dist/chunk-AOSUHWIL.js +98 -0
  14. package/dist/chunk-AOSUHWIL.js.map +1 -0
  15. package/dist/{chunk-PROK33G6.js → chunk-C44TDH54.js} +13 -1598
  16. package/dist/chunk-C44TDH54.js.map +1 -0
  17. package/dist/{chunk-YFY3TQ6Q.cjs → chunk-COCGRJLA.cjs} +7 -7
  18. package/dist/{chunk-YFY3TQ6Q.cjs.map → chunk-COCGRJLA.cjs.map} +1 -1
  19. package/dist/chunk-CQCC7LE7.js +210 -0
  20. package/dist/chunk-CQCC7LE7.js.map +1 -0
  21. package/dist/{chunk-UGCKUXRV.js → chunk-CSI2B2H5.js} +3 -3
  22. package/dist/{chunk-UGCKUXRV.js.map → chunk-CSI2B2H5.js.map} +1 -1
  23. package/dist/{chunk-R26BK7YL.cjs → chunk-DTROMMDX.cjs} +4 -4
  24. package/dist/{chunk-R26BK7YL.cjs.map → chunk-DTROMMDX.cjs.map} +1 -1
  25. package/dist/{chunk-65THHQVB.cjs → chunk-ECW2R2KF.cjs} +27 -27
  26. package/dist/{chunk-65THHQVB.cjs.map → chunk-ECW2R2KF.cjs.map} +1 -1
  27. package/dist/{chunk-RI6DZA5X.js → chunk-EF4ZLKRM.js} +3 -3
  28. package/dist/{chunk-RI6DZA5X.js.map → chunk-EF4ZLKRM.js.map} +1 -1
  29. package/dist/{chunk-WS5EX7DN.cjs → chunk-EYKISBDO.cjs} +5 -5
  30. package/dist/{chunk-WS5EX7DN.cjs.map → chunk-EYKISBDO.cjs.map} +1 -1
  31. package/dist/chunk-FJETR2AS.js +561 -0
  32. package/dist/chunk-FJETR2AS.js.map +1 -0
  33. package/dist/{chunk-JO3EMZ4X.js → chunk-GWSGIZQ5.js} +3 -3
  34. package/dist/{chunk-JO3EMZ4X.js.map → chunk-GWSGIZQ5.js.map} +1 -1
  35. package/dist/{chunk-I7WG3JRD.js → chunk-H4D7WKDY.js} +3 -3
  36. package/dist/{chunk-I7WG3JRD.js.map → chunk-H4D7WKDY.js.map} +1 -1
  37. package/dist/{chunk-GBS6QVGS.cjs → chunk-HAOKT4LC.cjs} +5 -5
  38. package/dist/{chunk-GBS6QVGS.cjs.map → chunk-HAOKT4LC.cjs.map} +1 -1
  39. package/dist/{chunk-N5X37J3D.js → chunk-IJST4EBM.js} +11 -8
  40. package/dist/chunk-IJST4EBM.js.map +1 -0
  41. package/dist/{chunk-3RJN2VTL.js → chunk-IXWJGOM2.js} +3 -3
  42. package/dist/{chunk-3RJN2VTL.js.map → chunk-IXWJGOM2.js.map} +1 -1
  43. package/dist/{chunk-CYNF5PZI.js → chunk-J5CWKFSC.js} +3 -3
  44. package/dist/{chunk-CYNF5PZI.js.map → chunk-J5CWKFSC.js.map} +1 -1
  45. package/dist/{chunk-OWCEQKAR.cjs → chunk-JSTKEZBS.cjs} +21 -318
  46. package/dist/chunk-JSTKEZBS.cjs.map +1 -0
  47. package/dist/{chunk-TP6PLDNM.cjs → chunk-KMZWKSKO.cjs} +8 -8
  48. package/dist/{chunk-TP6PLDNM.cjs.map → chunk-KMZWKSKO.cjs.map} +1 -1
  49. package/dist/{chunk-C4WSHRR6.cjs → chunk-KPZZ5FHE.cjs} +32 -12
  50. package/dist/chunk-KPZZ5FHE.cjs.map +1 -0
  51. package/dist/{chunk-CKCBBYTA.js → chunk-KSHKTOY2.js} +5 -205
  52. package/dist/chunk-KSHKTOY2.js.map +1 -0
  53. package/dist/chunk-LJJJ6CYH.cjs +62 -0
  54. package/dist/chunk-LJJJ6CYH.cjs.map +1 -0
  55. package/dist/chunk-LPYEUD2D.cjs +1627 -0
  56. package/dist/chunk-LPYEUD2D.cjs.map +1 -0
  57. package/dist/chunk-MHFF5N65.cjs +101 -0
  58. package/dist/chunk-MHFF5N65.cjs.map +1 -0
  59. package/dist/{chunk-GYAUJ4KT.js → chunk-MTSKK3BN.js} +32 -3
  60. package/dist/chunk-MTSKK3BN.js.map +1 -0
  61. package/dist/chunk-NHZK64TQ.js +75 -0
  62. package/dist/chunk-NHZK64TQ.js.map +1 -0
  63. package/dist/{chunk-BPBSSMRB.js → chunk-NRFAWUVD.js} +3 -3
  64. package/dist/{chunk-BPBSSMRB.js.map → chunk-NRFAWUVD.js.map} +1 -1
  65. package/dist/chunk-NWNVWO6L.cjs +80 -0
  66. package/dist/chunk-NWNVWO6L.cjs.map +1 -0
  67. package/dist/{chunk-HIJUXAWS.cjs → chunk-O2GW5IY6.cjs} +86 -83
  68. package/dist/chunk-O2GW5IY6.cjs.map +1 -0
  69. package/dist/{chunk-3BFGL2JL.cjs → chunk-ODRHHWHY.cjs} +4 -4
  70. package/dist/{chunk-3BFGL2JL.cjs.map → chunk-ODRHHWHY.cjs.map} +1 -1
  71. package/dist/{chunk-Y3KA6X7B.js → chunk-OVR3XMYL.js} +4 -4
  72. package/dist/{chunk-Y3KA6X7B.js.map → chunk-OVR3XMYL.js.map} +1 -1
  73. package/dist/{chunk-Y5KTM3V5.js → chunk-PDKM27DF.js} +17 -295
  74. package/dist/chunk-PDKM27DF.js.map +1 -0
  75. package/dist/{chunk-OAL3B2ZU.cjs → chunk-PLJ7PHWU.cjs} +5 -5
  76. package/dist/{chunk-OAL3B2ZU.cjs.map → chunk-PLJ7PHWU.cjs.map} +1 -1
  77. package/dist/{chunk-DPGFEMVT.cjs → chunk-RB7GX2VT.cjs} +57 -1665
  78. package/dist/chunk-RB7GX2VT.cjs.map +1 -0
  79. package/dist/chunk-RFIBUWLF.cjs +232 -0
  80. package/dist/chunk-RFIBUWLF.cjs.map +1 -0
  81. package/dist/{chunk-MIDXCYZB.cjs → chunk-RQ2Y7USX.cjs} +15 -235
  82. package/dist/chunk-RQ2Y7USX.cjs.map +1 -0
  83. package/dist/chunk-SV65E4QW.js +58 -0
  84. package/dist/chunk-SV65E4QW.js.map +1 -0
  85. package/dist/{chunk-LYUO3E6V.js → chunk-SZOFGU7W.js} +3 -3
  86. package/dist/{chunk-LYUO3E6V.js.map → chunk-SZOFGU7W.js.map} +1 -1
  87. package/dist/chunk-T5B7FM7S.js +1602 -0
  88. package/dist/chunk-T5B7FM7S.js.map +1 -0
  89. package/dist/{chunk-YNIBUKV5.js → chunk-TBEVGWY3.js} +32 -14
  90. package/dist/chunk-TBEVGWY3.js.map +1 -0
  91. package/dist/{chunk-MJCCBMM5.cjs → chunk-TC3RQNEX.cjs} +6 -80
  92. package/dist/chunk-TC3RQNEX.cjs.map +1 -0
  93. package/dist/chunk-TZGBRLPK.js +288 -0
  94. package/dist/chunk-TZGBRLPK.js.map +1 -0
  95. package/dist/chunk-U6YVZDOV.cjs +574 -0
  96. package/dist/chunk-U6YVZDOV.cjs.map +1 -0
  97. package/dist/{chunk-QIMVTGKS.cjs → chunk-U73KPFYH.cjs} +255 -2
  98. package/dist/chunk-U73KPFYH.cjs.map +1 -0
  99. package/dist/{chunk-HFGXA5CL.cjs → chunk-UTTTJSQU.cjs} +4 -4
  100. package/dist/{chunk-HFGXA5CL.cjs.map → chunk-UTTTJSQU.cjs.map} +1 -1
  101. package/dist/{chunk-DLBUFHLY.js → chunk-VTTZZ4FN.js} +4 -74
  102. package/dist/chunk-VTTZZ4FN.js.map +1 -0
  103. package/dist/{chunk-5FTIHRZH.cjs → chunk-XVUOMWMD.cjs} +4 -4
  104. package/dist/{chunk-5FTIHRZH.cjs.map → chunk-XVUOMWMD.cjs.map} +1 -1
  105. package/dist/{chunk-FXG7TFAG.js → chunk-Y4ATWQGV.js} +3 -3
  106. package/dist/{chunk-FXG7TFAG.js.map → chunk-Y4ATWQGV.js.map} +1 -1
  107. package/dist/{chunk-444XKG46.js → chunk-YKQ2DPIP.js} +3 -3
  108. package/dist/{chunk-444XKG46.js.map → chunk-YKQ2DPIP.js.map} +1 -1
  109. package/dist/{chunk-HEMU73OP.cjs → chunk-YSHIC4NJ.cjs} +4 -4
  110. package/dist/{chunk-HEMU73OP.cjs.map → chunk-YSHIC4NJ.cjs.map} +1 -1
  111. package/dist/{chunk-5BXEYYH6.js → chunk-ZM26YEOT.js} +3 -3
  112. package/dist/{chunk-5BXEYYH6.js.map → chunk-ZM26YEOT.js.map} +1 -1
  113. package/dist/citations/index.cjs +12 -12
  114. package/dist/citations/index.js +3 -3
  115. package/dist/connect/docx.cjs +36 -7
  116. package/dist/connect/docx.cjs.map +1 -1
  117. package/dist/connect/docx.d.ts +9 -2
  118. package/dist/connect/docx.js +30 -6
  119. package/dist/connect/docx.js.map +1 -1
  120. package/dist/connect/index.cjs +802 -628
  121. package/dist/connect/index.cjs.map +1 -1
  122. package/dist/connect/index.d.ts +2 -0
  123. package/dist/connect/index.js +636 -507
  124. package/dist/connect/index.js.map +1 -1
  125. package/dist/connection/ConnectedSettings.d.ts +3 -2
  126. package/dist/connection/docx/ConnectedNativeDocxComparison.d.ts +5 -0
  127. package/dist/connection/docx/ConnectedNativeDocxEditor.d.ts +16 -0
  128. package/dist/connection/{ConnectedStreamedWordArtifact.d.ts → docx/ConnectedStreamedWordArtifact.d.ts} +1 -1
  129. package/dist/connection/docx/support.d.ts +27 -0
  130. package/dist/connection/docx/useConnectedDocxReferences.d.ts +2 -0
  131. package/dist/connection/docx/useConnectedHouseTemplate.d.ts +2 -0
  132. package/dist/connection/settings-page/ConnectedAccountSettings.d.ts +35 -0
  133. package/dist/connection/settings-page/ConnectedMailSettings.d.ts +13 -0
  134. package/dist/connection/settings-page/ConnectedPremiumModels.d.ts +1 -0
  135. package/dist/connection/settings-page/ConnectedPrivacySettings.d.ts +12 -0
  136. package/dist/connection/settings-page/ConnectedSettingsPage.d.ts +29 -0
  137. package/dist/connection/settings-page/SessionStatusIcon.d.ts +7 -0
  138. package/dist/connection/settings-page/index.d.ts +6 -0
  139. package/dist/docx/index.cjs +17 -63
  140. package/dist/docx/index.cjs.map +1 -1
  141. package/dist/docx/index.d.ts +1 -0
  142. package/dist/docx/index.js +2 -64
  143. package/dist/docx/index.js.map +1 -1
  144. package/dist/docx/template/candidates.d.ts +16 -0
  145. package/dist/facts/index.cjs +3 -3
  146. package/dist/facts/index.js +2 -2
  147. package/dist/files/index.cjs +3 -3
  148. package/dist/files/index.js +2 -2
  149. package/dist/home/index.cjs +20 -20
  150. package/dist/home/index.js +4 -4
  151. package/dist/index.cjs +766 -741
  152. package/dist/index.cjs.map +1 -1
  153. package/dist/index.d.ts +2 -0
  154. package/dist/index.js +23 -18
  155. package/dist/index.js.map +1 -1
  156. package/dist/lib/deep-link.d.ts +46 -0
  157. package/dist/provider/BlocksProvider.d.ts +5 -1
  158. package/dist/provider/settings-section.d.ts +9 -0
  159. package/dist/retrieval/index.cjs +4 -4
  160. package/dist/retrieval/index.js +2 -2
  161. package/dist/settings/AppearanceSettings.d.ts +18 -0
  162. package/dist/settings/ServerConnectionControls.d.ts +16 -0
  163. package/dist/settings/SettingsPage.d.ts +31 -0
  164. package/dist/settings/index.cjs +188 -250
  165. package/dist/settings/index.cjs.map +1 -1
  166. package/dist/settings/index.d.ts +3 -1
  167. package/dist/settings/index.js +88 -199
  168. package/dist/settings/index.js.map +1 -1
  169. package/dist/shell/index.cjs +44 -44
  170. package/dist/shell/index.js +3 -3
  171. package/dist/site/index.cjs +74 -73
  172. package/dist/site/index.js +3 -2
  173. package/dist/studio/index.cjs +80 -78
  174. package/dist/studio/index.cjs.map +1 -1
  175. package/dist/studio/index.js +10 -8
  176. package/dist/studio/index.js.map +1 -1
  177. package/dist/workflow-canvas/index.cjs +62 -59
  178. package/dist/workflow-canvas/index.cjs.map +1 -1
  179. package/dist/workflow-canvas/index.js +10 -7
  180. package/dist/workflow-canvas/index.js.map +1 -1
  181. package/dist/workspaces/index.cjs +3 -3
  182. package/dist/workspaces/index.js +2 -2
  183. package/node_modules/@arbidocs/coedit/package.json +1 -1
  184. package/package.json +4 -4
  185. package/dist/chunk-4TR5QCCX.cjs +0 -43
  186. package/dist/chunk-4TR5QCCX.cjs.map +0 -1
  187. package/dist/chunk-7NDW4KF4.cjs +0 -112
  188. package/dist/chunk-7NDW4KF4.cjs.map +0 -1
  189. package/dist/chunk-C4WSHRR6.cjs.map +0 -1
  190. package/dist/chunk-CKCBBYTA.js.map +0 -1
  191. package/dist/chunk-DLBUFHLY.js.map +0 -1
  192. package/dist/chunk-DPGFEMVT.cjs.map +0 -1
  193. package/dist/chunk-ETXYVO6E.js +0 -109
  194. package/dist/chunk-ETXYVO6E.js.map +0 -1
  195. package/dist/chunk-GYAUJ4KT.js.map +0 -1
  196. package/dist/chunk-HIJUXAWS.cjs.map +0 -1
  197. package/dist/chunk-MCKOZACC.js +0 -41
  198. package/dist/chunk-MCKOZACC.js.map +0 -1
  199. package/dist/chunk-MIDXCYZB.cjs.map +0 -1
  200. package/dist/chunk-MJCCBMM5.cjs.map +0 -1
  201. package/dist/chunk-N5X37J3D.js.map +0 -1
  202. package/dist/chunk-ON3TKY5Y.js.map +0 -1
  203. package/dist/chunk-OWCEQKAR.cjs.map +0 -1
  204. package/dist/chunk-PROK33G6.js.map +0 -1
  205. package/dist/chunk-QIMVTGKS.cjs.map +0 -1
  206. package/dist/chunk-S24XEVPS.cjs.map +0 -1
  207. package/dist/chunk-Y5KTM3V5.js.map +0 -1
  208. package/dist/chunk-YNIBUKV5.js.map +0 -1
  209. package/dist/connection/ConnectedNativeDocxEditor.d.ts +0 -6
@@ -1,924 +1,21 @@
1
1
  "use client";
2
- import { FoldSection, QuickActionDialogHeader, AddFilesFirst, StartTiles, ScopePicker } from './chunk-3RJN2VTL.js';
2
+ import { SchemaForm, workflowRunStatusLabel } from './chunk-T5B7FM7S.js';
3
+ import { FoldSection } from './chunk-IXWJGOM2.js';
3
4
  import { useControllableState } from './chunk-RLWIUUQ5.js';
4
- import { DocumentPicker, TriStateFilterMenu } from './chunk-CKCBBYTA.js';
5
- import { EmptyState } from './chunk-P6GHJSLR.js';
6
5
  import { UploadDropzone } from './chunk-EVUEIBNU.js';
7
- import { ActionLink } from './chunk-444XKG46.js';
8
- import { SelectionBar, SelectionBarAction } from './chunk-NUNKSZKU.js';
9
- import { FilterInput } from './chunk-YU2KUMGE.js';
6
+ import { ActionLink } from './chunk-YKQ2DPIP.js';
10
7
  import { GridView } from './chunk-N5YEF3LC.js';
11
8
  import { TabHeader } from './chunk-4WWM3GQ5.js';
12
- import { defaultInputs, validateInputs, workflowSteps, canAssign, fieldToFrontmatter, workflowFromFrontmatter, nextAction, validateStep, assigneeName, runFieldsOf, failedUpstream, stepPhase, useElementSize, sendBackTargets, formatDate, shownValue, stepKindOf, stepLevels, waitingDocuments, stepDependencies, reviewInstructions, splitDocRef, isPersonStep, mergeSkillWorkflows, eventWaitingDocuments, waitingForDocumentsText, StepBadgeMark, StepChip, buildLaunch, STEP_KIND_ICONS, DEFAULT_STEP_KIND_LABELS, composeStepPrompt, isRunFinished, runFields, isWorkflowScope } from './chunk-Y5KTM3V5.js';
13
- import { TONE_DOT, TONE_SURFACE, TONE_SOLID_BORDER, TONE_BORDER } from './chunk-AUS3KBHJ.js';
14
- import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
15
- import { useBlocksEnvironment } from './chunk-YNIBUKV5.js';
16
- import { initials } from './chunk-OXF2IFXG.js';
17
- import { useState, useId, useMemo, useEffect, useRef, useCallback } from 'react';
18
- import { Globe, Terminal, Telescope, ListChecks, FileText, ImageIcon, Brain, Wand2, Loader2, Play, FolderPlus, X, UserRound, CornerUpLeft, ShieldCheck, MessageSquare, Check, Hourglass, Clock, PenLine, ExternalLink, Mail, Table2, CheckCircle2, ArrowLeft, ArrowRight, RotateCw, GitBranch, AlertTriangle, Bot, Sparkles, Copy, Pencil, Lock, Download, Trash2, MoreHorizontal, History, Workflow, Eye, LayoutGrid, List, ChevronLeft, ChevronRight, Link2, Bell, MousePointerClick, ArrowUpRight, BellRing, Flag, RotateCcw, Disc, Phone, UserRoundCog, MessageSquareReply, Square, KeyRound } from 'lucide-react';
19
- import { cn, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Dialog, DialogContent, Button, getEntityColor, Popover, PopoverTrigger, PopoverContent, Textarea, Card, DialogHeader, DialogTitle, DialogDescription, Input, Tooltip, TooltipTrigger, TooltipContent, UserEntity, getEntityColorStyles, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, badgeVariants, VisibilityToggle, Switch } from '@arbidocs/react/ui';
9
+ import { workflowSteps, canAssign, nextAction, validateStep, assigneeName, runFieldsOf, failedUpstream, stepPhase, useElementSize, sendBackTargets, formatDate, shownValue, stepKindOf, stepLevels, waitingDocuments, stepDependencies, reviewInstructions, splitDocRef, isPersonStep, eventWaitingDocuments, waitingForDocumentsText, StepBadgeMark, StepChip, STEP_KIND_ICONS, DEFAULT_STEP_KIND_LABELS, composeStepPrompt, isRunFinished, runFields } from './chunk-PDKM27DF.js';
10
+ import { fieldToFrontmatter, workflowFromFrontmatter, mergeSkillWorkflows } from './chunk-TZGBRLPK.js';
11
+ import { testIdOr } from './chunk-7F6CBP3Z.js';
12
+ import { useBlocksEnvironment } from './chunk-TBEVGWY3.js';
13
+ import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
14
+ import { Globe, Terminal, Telescope, ListChecks, FileText, ImageIcon, Brain, Wand2, Loader2, UserRound, CornerUpLeft, ShieldCheck, MessageSquare, Check, Hourglass, Clock, PenLine, X, ExternalLink, Mail, Table2, CheckCircle2, ArrowLeft, ArrowRight, RotateCw, GitBranch, AlertTriangle, Bot, Sparkles, Copy, Play, Pencil, Lock, Download, Trash2, Eye, History, LayoutGrid, List, ChevronLeft, ChevronRight, ArrowUpRight, BellRing, Flag, RotateCcw, Disc, Phone, UserRoundCog, MessageSquareReply, Square, KeyRound } from 'lucide-react';
15
+ import { cn, Popover, PopoverTrigger, PopoverContent, Button, Textarea, Card, Label, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Input, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Tooltip, TooltipTrigger, TooltipContent } from '@arbidocs/react/ui';
20
16
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
21
17
  import { unzip, strFromU8 } from 'fflate';
22
18
 
23
- var DEFAULT_SCHEMA_FORM_LABELS = {
24
- optional: "(optional)",
25
- advanced: "More options",
26
- errors: {
27
- required: "This is needed to continue",
28
- min: "Too small",
29
- max: "Too large",
30
- number: "Enter a number"
31
- }
32
- };
33
- var TILE_MAX = 4;
34
- function FieldControl({
35
- field,
36
- value,
37
- error,
38
- onChange,
39
- l,
40
- idFor,
41
- renderScope,
42
- renderDocuments,
43
- renderIcon,
44
- onEnterSubmit,
45
- people
46
- }) {
47
- const id = `${idFor()}-control`;
48
- const testId = idFor();
49
- switch (field.type) {
50
- case "text":
51
- return /* @__PURE__ */ jsx(
52
- Input,
53
- {
54
- id,
55
- "data-testid": testId,
56
- value: String(value ?? ""),
57
- placeholder: field.placeholder,
58
- "aria-required": field.required || void 0,
59
- "aria-invalid": error ? true : void 0,
60
- "aria-describedby": error ? idFor("error") : void 0,
61
- onChange: (e) => onChange(e.target.value)
62
- }
63
- );
64
- case "longtext":
65
- return /* @__PURE__ */ jsx(
66
- Textarea,
67
- {
68
- id,
69
- "data-testid": testId,
70
- value: String(value ?? ""),
71
- placeholder: field.placeholder,
72
- "aria-required": field.required || void 0,
73
- "aria-invalid": error ? true : void 0,
74
- "aria-describedby": error ? idFor("error") : void 0,
75
- className: "min-h-[96px]",
76
- onChange: (e) => onChange(e.target.value),
77
- onKeyDown: (e) => {
78
- if (onEnterSubmit && e.key === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
79
- e.preventDefault();
80
- onEnterSubmit();
81
- }
82
- }
83
- }
84
- );
85
- case "number":
86
- return /* @__PURE__ */ jsx(
87
- Input,
88
- {
89
- id,
90
- "data-testid": testId,
91
- type: "number",
92
- inputMode: "decimal",
93
- min: field.min,
94
- max: field.max,
95
- value: value === void 0 ? "" : String(value),
96
- placeholder: field.placeholder,
97
- "aria-invalid": error ? true : void 0,
98
- "aria-describedby": error ? idFor("error") : void 0,
99
- onChange: (e) => onChange(e.target.value === "" ? "" : Number(e.target.value))
100
- }
101
- );
102
- case "date":
103
- return /* @__PURE__ */ jsx(
104
- Input,
105
- {
106
- id,
107
- "data-testid": testId,
108
- type: "date",
109
- value: String(value ?? ""),
110
- "aria-invalid": error ? true : void 0,
111
- "aria-describedby": error ? idFor("error") : void 0,
112
- onChange: (e) => onChange(e.target.value)
113
- }
114
- );
115
- case "boolean":
116
- return /* @__PURE__ */ jsx(
117
- Switch,
118
- {
119
- id,
120
- "data-testid": testId,
121
- checked: Boolean(value),
122
- onCheckedChange: (checked) => onChange(checked)
123
- }
124
- );
125
- case "select": {
126
- const options = field.options ?? [];
127
- if (options.length > 0 && options.length <= TILE_MAX) {
128
- const compact2 = options.every((o) => !o.icon && !o.description);
129
- return /* @__PURE__ */ jsx(
130
- "div",
131
- {
132
- role: "radiogroup",
133
- "aria-label": field.label,
134
- className: "flex flex-wrap gap-2",
135
- "data-testid": testId,
136
- children: options.map((option) => /* @__PURE__ */ jsx(
137
- ChoiceTile,
138
- {
139
- option,
140
- selected: value === option.value,
141
- compact: compact2,
142
- renderIcon,
143
- testId: prefixedTestId(testId, option.value, {
144
- testId: `workflow-field-${field.name}-${option.value}`
145
- }),
146
- onSelect: () => onChange(option.value)
147
- },
148
- option.value
149
- ))
150
- }
151
- );
152
- }
153
- return /* @__PURE__ */ jsxs(Select, { value: String(value ?? ""), onValueChange: (v) => onChange(v), children: [
154
- /* @__PURE__ */ jsx(SelectTrigger, { id, "data-testid": testId, className: "pointer-coarse:min-h-11", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: field.placeholder }) }),
155
- /* @__PURE__ */ jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
156
- ] });
157
- }
158
- case "scope": {
159
- const scope = isWorkflowScope(value) ? value : { folders: [], labels: [] };
160
- return /* @__PURE__ */ jsx("div", { "data-testid": testId, children: renderScope?.(field, scope, onChange) });
161
- }
162
- case "documents": {
163
- const picked = isWorkflowScope(value) ? value : { folders: [], labels: [], documents: [] };
164
- return /* @__PURE__ */ jsx("div", { "data-testid": testId, children: renderDocuments?.(field, picked, onChange) });
165
- }
166
- case "person":
167
- return people?.length ? /* @__PURE__ */ jsxs(
168
- "select",
169
- {
170
- id,
171
- "data-testid": testId,
172
- value: String(value ?? ""),
173
- "aria-required": field.required || void 0,
174
- "aria-invalid": error ? true : void 0,
175
- onChange: (e) => onChange(e.target.value),
176
- className: "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm shadow-sm",
177
- children: [
178
- /* @__PURE__ */ jsx("option", { value: "", children: field.placeholder ?? "" }),
179
- people.map((p) => /* @__PURE__ */ jsx("option", { value: p.value, children: p.label }, p.value))
180
- ]
181
- }
182
- ) : /* @__PURE__ */ jsx(
183
- Input,
184
- {
185
- id,
186
- "data-testid": testId,
187
- value: String(value ?? ""),
188
- placeholder: field.placeholder ?? "usr-\u2026",
189
- "aria-required": field.required || void 0,
190
- "aria-invalid": error ? true : void 0,
191
- onChange: (e) => onChange(e.target.value)
192
- }
193
- );
194
- }
195
- }
196
- function ChoiceTile({
197
- option,
198
- selected,
199
- compact: compact2,
200
- renderIcon,
201
- testId,
202
- onSelect
203
- }) {
204
- const tone = option.tone;
205
- return /* @__PURE__ */ jsxs(
206
- "button",
207
- {
208
- type: "button",
209
- role: "radio",
210
- "aria-checked": selected,
211
- "data-testid": testId,
212
- "data-tone": tone,
213
- onClick: onSelect,
214
- className: cn(
215
- // Sized to its label (flex-basis auto), growing to share the row, never wider than it.
216
- "flex max-w-full min-w-[min(4rem,100%)] flex-auto flex-col items-center justify-center gap-1.5 rounded-lg border text-center transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
217
- compact2 ? "min-h-9 px-3 py-1.5 pointer-coarse:min-h-11" : "min-h-24 p-3 pointer-coarse:min-h-28",
218
- tone ? selected ? cn(TONE_SURFACE[tone], TONE_SOLID_BORDER[tone]) : cn(TONE_BORDER[tone], "bg-card [&:hover]:bg-muted") : selected ? "border-primary bg-primary/10" : "border-border bg-card [&:hover]:border-primary [&:hover]:bg-muted"
219
- ),
220
- children: [
221
- option.icon && renderIcon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: renderIcon(option.icon) }),
222
- /* @__PURE__ */ jsxs(
223
- "span",
224
- {
225
- className: cn(
226
- "flex max-w-full items-center gap-1.5 text-sm font-medium",
227
- tone && selected ? void 0 : "text-foreground"
228
- ),
229
- children: [
230
- selected ? /* @__PURE__ */ jsx(Check, { className: "size-3.5 shrink-0", "aria-hidden": true }) : tone && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("size-2 shrink-0 rounded-full", TONE_DOT[tone]) }),
231
- /* @__PURE__ */ jsx("span", { className: "min-w-0 break-words", children: option.label })
232
- ]
233
- }
234
- ),
235
- option.description && /* @__PURE__ */ jsx("span", { className: "max-w-full text-xs break-words text-muted-foreground", children: option.description })
236
- ]
237
- }
238
- );
239
- }
240
- function FormField(props) {
241
- const { field, error, l, idFor } = props;
242
- const isBoolean = field.type === "boolean";
243
- const showOptional = !field.required && field.type !== "boolean" && field.type !== "scope";
244
- const label = /* @__PURE__ */ jsxs(
245
- Label,
246
- {
247
- htmlFor: `${idFor()}-control`,
248
- className: isBoolean ? "cursor-pointer font-normal" : void 0,
249
- children: [
250
- field.label,
251
- showOptional && /* @__PURE__ */ jsxs(Fragment, { children: [
252
- " ",
253
- /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: l.optional })
254
- ] })
255
- ]
256
- }
257
- );
258
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", "data-slot": "schema-field", "data-field": field.name, children: [
259
- isBoolean ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 pointer-coarse:min-h-11", children: [
260
- /* @__PURE__ */ jsx(FieldControl, { ...props }),
261
- label
262
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
263
- field.type !== "scope" && label,
264
- /* @__PURE__ */ jsx(FieldControl, { ...props })
265
- ] }),
266
- field.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: field.description }),
267
- error && /* @__PURE__ */ jsx(
268
- "p",
269
- {
270
- id: idFor("error"),
271
- role: "alert",
272
- className: "text-xs text-destructive",
273
- "data-testid": idFor("error"),
274
- children: l.errors[error]
275
- }
276
- )
277
- ] });
278
- }
279
- function SchemaForm({
280
- fields,
281
- values,
282
- onChange,
283
- errors,
284
- renderScope,
285
- renderDocuments,
286
- renderIcon,
287
- onEnterSubmit,
288
- people,
289
- testIdPrefix,
290
- labels,
291
- className
292
- }) {
293
- const l = {
294
- ...DEFAULT_SCHEMA_FORM_LABELS,
295
- ...labels,
296
- errors: { ...DEFAULT_SCHEMA_FORM_LABELS.errors, ...labels?.errors }
297
- };
298
- const [advancedOpen, setAdvancedOpen] = useState(false);
299
- const common = fields.filter((f) => !f.advanced);
300
- const advanced = fields.filter((f) => f.advanced);
301
- const render = (field) => /* @__PURE__ */ jsx(
302
- FormField,
303
- {
304
- field,
305
- value: values[field.name],
306
- error: errors?.[field.name],
307
- onChange: (v) => onChange(field.name, v),
308
- l,
309
- idFor: (suffix) => suffix ? `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}-${suffix}` : `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-${field.name}`,
310
- renderScope,
311
- renderDocuments,
312
- renderIcon,
313
- onEnterSubmit,
314
- people
315
- },
316
- field.name
317
- );
318
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", className), "data-slot": "schema-form", children: [
319
- common.map(render),
320
- advanced.length > 0 && /* @__PURE__ */ jsx(
321
- FoldSection,
322
- {
323
- label: l.advanced,
324
- open: advancedOpen,
325
- onOpenChange: setAdvancedOpen,
326
- testId: `${testIdOr(testIdPrefix, { testId: "workflow-field" })}-advanced-toggle`,
327
- children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: advanced.map(render) })
328
- }
329
- )
330
- ] });
331
- }
332
- var DEFAULT_AGENT_SELECT_LABELS = {
333
- label: "Run as",
334
- myAssistant: "My assistant"
335
- };
336
- var ME = "__me__";
337
- function AgentSelect({
338
- agents,
339
- value,
340
- defaultValue = "",
341
- onValueChange,
342
- hideLabel,
343
- disabled,
344
- className,
345
- labels,
346
- testId,
347
- optionTestId
348
- }) {
349
- const l = { ...DEFAULT_AGENT_SELECT_LABELS, ...labels };
350
- const triggerId = useId();
351
- const [current, setCurrent] = useControllableState(value, defaultValue, onValueChange);
352
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), "data-slot": "agent-select", children: [
353
- /* @__PURE__ */ jsx(Label, { htmlFor: triggerId, className: hideLabel ? "sr-only" : void 0, children: l.label }),
354
- /* @__PURE__ */ jsxs(
355
- Select,
356
- {
357
- value: current === "" ? ME : current,
358
- onValueChange: (v) => setCurrent(v === ME ? "" : v),
359
- disabled,
360
- children: [
361
- /* @__PURE__ */ jsx(
362
- SelectTrigger,
363
- {
364
- id: triggerId,
365
- "data-testid": testIdOr(testId, { testId: "agent-select" }),
366
- className: "pointer-coarse:min-h-11",
367
- children: /* @__PURE__ */ jsx(SelectValue, {})
368
- }
369
- ),
370
- /* @__PURE__ */ jsxs(SelectContent, { children: [
371
- /* @__PURE__ */ jsx(
372
- SelectItem,
373
- {
374
- value: ME,
375
- "data-testid": prefixedTestId(optionTestId, "me", {
376
- testId: "agent-select-option-me"
377
- }),
378
- children: l.myAssistant
379
- }
380
- ),
381
- agents.map((agent) => /* @__PURE__ */ jsx(
382
- SelectItem,
383
- {
384
- value: agent.id,
385
- "data-testid": prefixedTestId(optionTestId, agent.id, {
386
- testId: `agent-select-option-${agent.id}`
387
- }),
388
- children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
389
- agent.avatar,
390
- /* @__PURE__ */ jsx("span", { children: agent.label }),
391
- agent.description && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: agent.description })
392
- ] })
393
- },
394
- agent.id
395
- ))
396
- ] })
397
- ]
398
- }
399
- )
400
- ] });
401
- }
402
- var DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS = {
403
- start: "Start",
404
- starting: "Starting\u2026",
405
- addFilesReason: "This reads your files, and there is nothing to read yet.",
406
- agentLabel: "Run as"
407
- };
408
- function WorkflowConfigDialog({
409
- workflow,
410
- open,
411
- onOpenChange,
412
- onLaunch,
413
- initialInputs,
414
- inputs: inputsProp,
415
- onInputsChange,
416
- scopeSource,
417
- renderScope,
418
- renderDocuments,
419
- renderIcon,
420
- addFilesAction,
421
- agents,
422
- agentId: agentIdProp,
423
- onAgentChange,
424
- isLaunching,
425
- submitLabel,
426
- fieldPlaceholder,
427
- renderNotice,
428
- labels,
429
- formLabels,
430
- agentLabels,
431
- testId,
432
- startTestId,
433
- className
434
- }) {
435
- const l = { ...DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, ...labels };
436
- const initialKey = JSON.stringify(initialInputs ?? {});
437
- const seedKey = JSON.stringify({ ...defaultInputs(workflow), ...JSON.parse(initialKey) });
438
- const seed = useMemo(() => JSON.parse(seedKey), [seedKey]);
439
- const [inputs, setInputs] = useControllableState(inputsProp, seed, onInputsChange);
440
- const [agentId, setAgentId] = useControllableState(
441
- agentIdProp,
442
- workflow.defaultAgentId ?? "",
443
- onAgentChange
444
- );
445
- useEffect(() => {
446
- if (open && inputsProp === void 0) setInputs(seed);
447
- }, [open, seed]);
448
- const setField = (name, value) => setInputs({ ...inputs, [name]: value });
449
- const errors = validateInputs(workflow, inputs);
450
- const valid = Object.keys(errors).length === 0;
451
- const visibleErrors = Object.fromEntries(
452
- Object.entries(errors).filter(([, e]) => e !== "required")
453
- );
454
- const scopeField = workflow.inputs.find((f) => f.type === "scope");
455
- const rawScope = scopeField ? inputs[scopeField.name] : void 0;
456
- const scopeValue = rawScope && typeof rawScope === "object" ? rawScope : { folders: [], labels: [] };
457
- const matchedCount = scopeSource && scopeField ? scopeSource.countMatching(scopeValue) : null;
458
- const noFiles = Boolean(workflow.requiresFiles && scopeSource && scopeSource.totalCount === 0);
459
- const blockedByScope = matchedCount !== null && matchedCount === 0 && Boolean(workflow.requiresFiles);
460
- const showAgent = workflow.run.kind === "prompt" && workflow.options?.agent !== false && agents !== void 0 && agents.length > 0;
461
- const launch = (values) => {
462
- Promise.resolve(onLaunch(buildLaunch(workflow, values, agentId))).catch(() => {
463
- });
464
- };
465
- const submit = () => {
466
- if (!valid || noFiles || blockedByScope || isLaunching) return;
467
- launch(inputs);
468
- };
469
- const fields = useMemo(
470
- () => workflow.inputs.map((f) => {
471
- const placeholder = fieldPlaceholder?.(f, inputs, workflow);
472
- return placeholder === void 0 ? f : { ...f, placeholder };
473
- }),
474
- [workflow, fieldPlaceholder, inputs]
475
- );
476
- const id = testIdOr(testId, { testId: "workflow-dialog" });
477
- const formRef = useRef(null);
478
- const firstField = workflow.inputs.find((f) => !f.advanced);
479
- const focusPromptFirst = firstField?.type === "text" || firstField?.type === "longtext";
480
- const defaultScopeRender = scopeSource ? (_field, value, onChange) => /* @__PURE__ */ jsx(
481
- ScopePicker,
482
- {
483
- folders: scopeSource.folders,
484
- unfiledCount: scopeSource.unfiledCount,
485
- labels: scopeSource.labels,
486
- totalCount: scopeSource.totalCount,
487
- matchedCount: scopeSource.countMatching(value),
488
- scope: value,
489
- onScopeChange: onChange
490
- }
491
- ) : void 0;
492
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
493
- DialogContent,
494
- {
495
- presentation: "sheet",
496
- className: `max-h-[calc(100dvh-2rem)] overflow-y-auto sm:max-w-xl ${className ?? ""}`,
497
- "data-testid": id,
498
- "data-workflow": workflow.id,
499
- onOpenAutoFocus: (event) => {
500
- if (!focusPromptFirst || !firstField) return;
501
- const control = formRef.current?.querySelector(
502
- `[data-testid="${id}-field-${firstField.name}"]`
503
- );
504
- if (!control) return;
505
- event.preventDefault();
506
- control.focus();
507
- if (control instanceof HTMLInputElement || control instanceof HTMLTextAreaElement) {
508
- const end = control.value.length;
509
- control.setSelectionRange(end, end);
510
- }
511
- },
512
- children: [
513
- /* @__PURE__ */ jsx(
514
- QuickActionDialogHeader,
515
- {
516
- icon: workflow.icon && renderIcon ? renderIcon(workflow.icon) : null,
517
- title: workflow.title,
518
- description: workflow.details ?? workflow.description,
519
- descriptionTestId: `${id}-description`
520
- }
521
- ),
522
- /* @__PURE__ */ jsx(
523
- "form",
524
- {
525
- ref: formRef,
526
- className: "mt-2 flex flex-col gap-4",
527
- onSubmit: (event) => {
528
- event.preventDefault();
529
- submit();
530
- },
531
- children: noFiles ? /* @__PURE__ */ jsx(
532
- AddFilesFirst,
533
- {
534
- reason: l.addFilesReason,
535
- action: addFilesAction,
536
- testId: `${id}-empty-state`
537
- }
538
- ) : /* @__PURE__ */ jsxs(Fragment, { children: [
539
- /* @__PURE__ */ jsx(
540
- SchemaForm,
541
- {
542
- fields,
543
- values: inputs,
544
- onChange: setField,
545
- errors: visibleErrors,
546
- renderScope: renderScope ?? defaultScopeRender,
547
- renderDocuments,
548
- renderIcon,
549
- labels: formLabels,
550
- onEnterSubmit: submit,
551
- testIdPrefix: `${id}-field`
552
- }
553
- ),
554
- renderNotice?.({ workflow, inputs }),
555
- /* @__PURE__ */ jsxs(
556
- "div",
557
- {
558
- className: "flex flex-col gap-3 border-t border-border pt-3 sm:flex-row sm:items-end sm:justify-between",
559
- "data-slot": "workflow-footer",
560
- children: [
561
- showAgent ? /* @__PURE__ */ jsx(
562
- AgentSelect,
563
- {
564
- agents: agents ?? [],
565
- value: agentId,
566
- onValueChange: setAgentId,
567
- labels: { label: l.agentLabel, ...agentLabels },
568
- testId: `${id}-agent`,
569
- className: "sm:w-56"
570
- }
571
- ) : /* @__PURE__ */ jsx("span", {}),
572
- /* @__PURE__ */ jsxs(
573
- Button,
574
- {
575
- type: "submit",
576
- className: "gap-1.5 px-5 pointer-coarse:min-h-11",
577
- disabled: !valid || blockedByScope || isLaunching,
578
- "data-testid": testIdOr(startTestId, { testId: "workflow-start-button" }),
579
- children: [
580
- isLaunching ? /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx(Play, { className: "size-4" }),
581
- isLaunching ? l.starting : submitLabel?.({ workflow, inputs, matchedCount }) ?? workflow.startLabel ?? l.start
582
- ]
583
- }
584
- )
585
- ]
586
- }
587
- )
588
- ] })
589
- }
590
- )
591
- ]
592
- }
593
- ) });
594
- }
595
- function WorkflowLauncher({
596
- workflows,
597
- tileWorkflows,
598
- onLaunch,
599
- showTiles = true,
600
- caption,
601
- captionTestId,
602
- tileTestId,
603
- disabledReason,
604
- activeId: activeIdProp,
605
- onActiveIdChange,
606
- initialInputsFor,
607
- testId,
608
- extraTiles = [],
609
- className,
610
- children,
611
- renderIcon,
612
- ...dialog
613
- }) {
614
- const [activeId, setActiveId] = useControllableState(
615
- activeIdProp,
616
- null,
617
- onActiveIdChange
618
- );
619
- const [isLaunching, setIsLaunching] = useState(false);
620
- const active = workflows.find((w) => w.id === activeId) ?? null;
621
- const run = async (launch) => {
622
- setIsLaunching(true);
623
- try {
624
- await onLaunch(launch);
625
- setActiveId(null);
626
- } finally {
627
- setIsLaunching(false);
628
- }
629
- };
630
- const select = (workflow) => {
631
- if (workflow.run.kind === "operation" && workflow.inputs.length === 0) {
632
- const inputs = defaultInputs(workflow);
633
- if (Object.keys(validateInputs(workflow, inputs)).length === 0) {
634
- Promise.resolve(onLaunch(buildLaunch(workflow, inputs, void 0))).catch(() => {
635
- });
636
- return;
637
- }
638
- }
639
- setActiveId(workflow.id);
640
- };
641
- const tiles = (tileWorkflows ?? workflows).map((workflow) => {
642
- const reason = disabledReason?.(workflow);
643
- return {
644
- id: workflow.id,
645
- iconNode: workflow.icon && renderIcon ? renderIcon(workflow.icon) : void 0,
646
- title: workflow.title,
647
- description: workflow.description,
648
- onSelect: () => select(workflow),
649
- disabled: reason !== void 0,
650
- disabledReason: reason,
651
- testId: tileTestId?.(workflow) ?? `workflow-tile-${workflow.id}`
652
- };
653
- });
654
- return /* @__PURE__ */ jsxs("div", { className, "data-slot": "workflow-launcher", children: [
655
- showTiles && /* @__PURE__ */ jsx(
656
- StartTiles,
657
- {
658
- items: [...tiles, ...extraTiles],
659
- caption,
660
- captionTestId,
661
- testId
662
- }
663
- ),
664
- children,
665
- active && /* @__PURE__ */ jsx(
666
- WorkflowConfigDialog,
667
- {
668
- ...dialog,
669
- renderIcon,
670
- workflow: active,
671
- open: true,
672
- onOpenChange: (open) => !open && setActiveId(null),
673
- onLaunch: run,
674
- isLaunching,
675
- initialInputs: initialInputsFor?.(active)
676
- }
677
- )
678
- ] });
679
- }
680
- function documentScopeLabels(tags) {
681
- return tags.filter((tag) => {
682
- if (tag.kind === "search") return false;
683
- const onDocs = (tag.doctag_count ?? 0) > 0;
684
- const onFacts = (tag.facttag_count ?? 0) > 0;
685
- return onDocs || !onFacts;
686
- });
687
- }
688
- var canonical = (path) => (path ?? "").split("/").map((part) => part.trim()).filter(Boolean).join("/");
689
- function matchWorkflowScope(docs, scope) {
690
- if (scope.documents?.length) {
691
- const ids = new Set(scope.documents);
692
- return docs.filter((doc) => ids.has(doc.external_id));
693
- }
694
- if (!scope.folders.length && !scope.labels.length) return docs;
695
- const folders = scope.folders.map(canonical);
696
- const labels = new Set(scope.labels);
697
- return docs.filter((doc) => {
698
- const folder = canonical(doc.folder);
699
- return folders.some(
700
- (path) => path === "" ? folder === "" : folder === path || folder.startsWith(`${path}/`)
701
- ) || doc.doctags?.some((tag) => labels.has(tag.tag_ext_id));
702
- });
703
- }
704
- function buildWorkflowScopeSource(docs, labels = []) {
705
- const counts = /* @__PURE__ */ new Map();
706
- for (const doc of docs) {
707
- const parts = canonical(doc.folder).split("/").filter(Boolean);
708
- for (let i = 1; i <= parts.length; i++) {
709
- const path = parts.slice(0, i).join("/");
710
- counts.set(path, (counts.get(path) ?? 0) + 1);
711
- }
712
- }
713
- return {
714
- folders: [...counts].sort(([a], [b]) => a.localeCompare(b)).map(([path, count]) => ({
715
- path,
716
- count,
717
- label: path.split("/").at(-1),
718
- depth: path.split("/").length - 1
719
- })),
720
- unfiledCount: docs.filter((doc) => !canonical(doc.folder)).length,
721
- labels: labels.map((label) => ({
722
- id: label.external_id,
723
- name: label.name,
724
- color: label.color ?? getEntityColor(label.external_id, "medium"),
725
- count: docs.filter((doc) => doc.doctags?.some((tag) => tag.tag_ext_id === label.external_id)).length
726
- })),
727
- totalCount: docs.length,
728
- countMatching: (scope) => matchWorkflowScope(docs, scope).length,
729
- resolveDocuments: (scope) => matchWorkflowScope(docs, scope).map((doc) => doc.external_id)
730
- };
731
- }
732
- var DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS = {
733
- pickOne: "Pick a file",
734
- pickMany: "Pick files",
735
- allDocuments: "All documents",
736
- addFiles: "Add files",
737
- adding: "Adding\u2026",
738
- empty: "No files in this workspace yet. Drop one here, or add it.",
739
- remove: (name) => `Remove ${name}`,
740
- pending: (name, status) => `${name}: ${status}. You can still pick it.`,
741
- status: {
742
- queued: "Queued",
743
- uploading: "Uploading",
744
- encrypting: "Encrypting",
745
- processing: "Processing",
746
- parsing: "Processing",
747
- indexing: "Indexing",
748
- analysing: "Analysing"
749
- }
750
- };
751
- var isReady = (status) => !status || ["completed", "done", "ready", "success"].includes(status.toLowerCase());
752
- var byTitle = (a, b) => a.title.toLowerCase().localeCompare(b.title.toLowerCase());
753
- function WorkflowDocumentsField({
754
- field,
755
- value,
756
- onChange,
757
- documents,
758
- loaded = true,
759
- thumbnailOf,
760
- onAddFiles,
761
- adding,
762
- labels
763
- }) {
764
- const l = { ...DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS, ...labels };
765
- const ids = value.documents ?? [];
766
- const max = field.max ?? 1;
767
- const multiple = max > 1;
768
- const [isOver, setIsOver] = useState(false);
769
- const docOf = (id) => documents.find((d) => d.id === id);
770
- const nameOf = (id) => docOf(id)?.title || id;
771
- const set = (next) => onChange({ ...value, documents: next });
772
- const toggle = (id) => set(ids.includes(id) ? ids.filter((d) => d !== id) : [...ids, id].slice(-max));
773
- const offered = useMemo(
774
- () => field.accept === "image" ? documents.filter((d) => d.isImage) : documents,
775
- [documents, field.accept]
776
- );
777
- const awaitingAdd = useRef(false);
778
- const known = useRef(null);
779
- const latest = useRef({ ids, set });
780
- latest.current = { ids, set };
781
- useEffect(() => {
782
- if (!loaded) return;
783
- const current = new Set(documents.map((d) => d.id));
784
- const before = known.current;
785
- known.current = current;
786
- if (!before || !awaitingAdd.current) return;
787
- const fresh = [...current].filter((id) => !before.has(id));
788
- if (fresh.length === 0) return;
789
- awaitingAdd.current = false;
790
- latest.current.set([...latest.current.ids, ...fresh].slice(-max));
791
- }, [documents, loaded, max]);
792
- const addFiles = (files) => {
793
- if (!onAddFiles) return;
794
- awaitingAdd.current = true;
795
- onAddFiles(files?.length ? files : void 0);
796
- };
797
- const dropProps = onAddFiles ? {
798
- onDragOver: (e) => {
799
- e.preventDefault();
800
- setIsOver(true);
801
- },
802
- onDragLeave: () => setIsOver(false),
803
- onDrop: (e) => {
804
- e.preventDefault();
805
- setIsOver(false);
806
- const files = Array.from(e.dataTransfer?.files ?? []);
807
- if (files.length) addFiles(files);
808
- }
809
- } : {};
810
- const dropClass = isOver ? "ring-2 ring-primary" : "";
811
- const addButton = (className, variant = "outline") => onAddFiles && /* @__PURE__ */ jsx(
812
- Button,
813
- {
814
- type: "button",
815
- size: "sm",
816
- variant,
817
- className,
818
- disabled: adding,
819
- onClick: () => addFiles(),
820
- "data-testid": "workflow-add-files",
821
- children: adding ? l.adding : l.addFiles
822
- }
823
- );
824
- if (loaded && documents.length === 0) {
825
- return /* @__PURE__ */ jsxs(
826
- "div",
827
- {
828
- className: cn(
829
- "flex flex-col items-center gap-2 rounded-lg border border-dashed border-border bg-muted/40 px-4 py-6 text-center",
830
- dropClass
831
- ),
832
- "data-testid": "workflow-documents-empty",
833
- ...dropProps,
834
- children: [
835
- /* @__PURE__ */ jsx(FolderPlus, { className: "size-5 text-muted-foreground", "aria-hidden": true }),
836
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.empty }),
837
- addButton(void 0, "default")
838
- ]
839
- }
840
- );
841
- }
842
- const pending = ids.flatMap((id) => {
843
- const status = docOf(id)?.status;
844
- return isReady(status) ? [] : [{ id, label: l.status[String(status).toLowerCase()] ?? String(status) }];
845
- });
846
- const selected = multiple ? void 0 : docOf(ids[0] ?? "");
847
- return /* @__PURE__ */ jsxs(
848
- "div",
849
- {
850
- className: cn("flex flex-col gap-3 rounded-lg", dropClass),
851
- "data-testid": `workflow-documents-${field.name}`,
852
- ...dropProps,
853
- children: [
854
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
855
- /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx(
856
- DocumentPicker,
857
- {
858
- groups: [{ id: "all", heading: l.allDocuments, docs: [...offered].sort(byTitle) }],
859
- value: multiple ? "" : ids[0] ?? "",
860
- onValueChange: (id) => multiple ? toggle(id) : set([id]),
861
- selected,
862
- selectedIds: multiple ? ids : void 0,
863
- labels: { placeholder: field.placeholder ?? (multiple ? l.pickMany : l.pickOne) }
864
- }
865
- ) }),
866
- addButton("shrink-0 pointer-coarse:h-11")
867
- ] }),
868
- pending.map((p) => /* @__PURE__ */ jsx(
869
- "p",
870
- {
871
- className: "text-xs text-muted-foreground",
872
- "data-testid": `workflow-document-status-${p.id}`,
873
- children: l.pending(nameOf(p.id), p.label)
874
- },
875
- p.id
876
- )),
877
- multiple && ids.length > 0 && /* @__PURE__ */ jsx(
878
- "div",
879
- {
880
- className: "grid grid-cols-2 gap-3 sm:grid-cols-3",
881
- "data-testid": "workflow-documents-gallery",
882
- children: ids.map((id) => {
883
- const thumbnail = thumbnailOf?.(id);
884
- return /* @__PURE__ */ jsxs(
885
- "figure",
886
- {
887
- className: "relative overflow-hidden rounded-lg border border-border bg-muted/40",
888
- "data-testid": `workflow-document-${id}`,
889
- children: [
890
- thumbnail ? /* @__PURE__ */ jsx(
891
- "img",
892
- {
893
- src: thumbnail,
894
- alt: nameOf(id),
895
- className: "aspect-square w-full object-cover"
896
- }
897
- ) : /* @__PURE__ */ jsx("div", { className: "flex aspect-square w-full items-center justify-center text-muted-foreground/50", children: /* @__PURE__ */ jsx(ImageIcon, { className: "size-8" }) }),
898
- /* @__PURE__ */ jsx("figcaption", { className: "truncate bg-background/90 px-2 py-1 text-xs text-muted-foreground", children: nameOf(id) }),
899
- /* @__PURE__ */ jsx(
900
- "button",
901
- {
902
- type: "button",
903
- onClick: () => toggle(id),
904
- "aria-label": l.remove(nameOf(id)),
905
- className: "absolute right-1 top-1 flex size-6 items-center justify-center rounded-full bg-background/80 text-muted-foreground hover:text-foreground pointer-coarse:size-11",
906
- "data-testid": `workflow-document-remove-${id}`,
907
- children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
908
- }
909
- )
910
- ]
911
- },
912
- id
913
- );
914
- })
915
- }
916
- )
917
- ]
918
- }
919
- );
920
- }
921
-
922
19
  // src/agents/workflows/planSteps.ts
923
20
  function toPlanAssignee(a) {
924
21
  if ("user" in a) return { user: a.user };
@@ -4429,688 +3526,6 @@ function SkillLibraryDetail({
4429
3526
  }
4430
3527
  );
4431
3528
  }
4432
- function PersonPill({ person, size = "sm", testId }) {
4433
- return /* @__PURE__ */ jsx("span", { "data-testid": testId, className: "inline-flex min-w-0", children: /* @__PURE__ */ jsx(
4434
- UserEntity,
4435
- {
4436
- variant: "pill",
4437
- size,
4438
- interactive: false,
4439
- showTooltip: false,
4440
- initials: initials(person.label),
4441
- displayName: person.label,
4442
- avatarStyle: person.id ? getEntityColorStyles(person.id) : void 0,
4443
- isAgent: person.isAgent,
4444
- isMe: person.isMe
4445
- }
4446
- ) });
4447
- }
4448
- var DEFAULT_TASK_TRIGGER_CHIP_LABELS = {
4449
- after: (name) => `After \u201C${name}\u201D is done`,
4450
- afterUnknown: "After another task is done",
4451
- onDemand: "Manual"
4452
- };
4453
- function TriggerIcon({ type, chained }) {
4454
- const cls = "size-3.5 shrink-0 text-muted-foreground";
4455
- if (chained) return /* @__PURE__ */ jsx(Link2, { className: cls, "aria-hidden": true });
4456
- switch (type) {
4457
- case "on_demand":
4458
- return /* @__PURE__ */ jsx(MousePointerClick, { className: cls, "aria-hidden": true });
4459
- case "recurring":
4460
- return /* @__PURE__ */ jsx(Clock, { className: cls, "aria-hidden": true });
4461
- case "event":
4462
- return /* @__PURE__ */ jsx(Bell, { className: cls, "aria-hidden": true });
4463
- default:
4464
- return /* @__PURE__ */ jsx(Clock, { className: cls, "aria-hidden": true });
4465
- }
4466
- }
4467
- function TaskTriggerChip({
4468
- id,
4469
- triggerType,
4470
- summary,
4471
- afterTaskId,
4472
- afterTaskName,
4473
- testId,
4474
- labels
4475
- }) {
4476
- const l = { ...DEFAULT_TASK_TRIGGER_CHIP_LABELS, ...labels };
4477
- const chained = Boolean(afterTaskId);
4478
- const text = chained ? afterTaskName ? l.after(afterTaskName) : l.afterUnknown : triggerType === "on_demand" ? l.onDemand : summary;
4479
- return /* @__PURE__ */ jsxs(
4480
- "span",
4481
- {
4482
- className: "inline-flex min-w-0 max-w-full items-center gap-1.5 text-sm font-normal text-foreground",
4483
- "data-testid": testIdOr(testId, { testId: `task-trigger-${id}` }),
4484
- "data-trigger": chained ? "task" : triggerType,
4485
- children: [
4486
- /* @__PURE__ */ jsx(TriggerIcon, { type: triggerType, chained }),
4487
- /* @__PURE__ */ jsx("span", { className: "truncate", children: text })
4488
- ]
4489
- }
4490
- );
4491
- }
4492
-
4493
- // src/agents/tasks/workflowRows.ts
4494
- var isSkillRow = (row) => row.kind === "skill";
4495
- var hasTrigger = (row) => !row.on_demand && Boolean(row.rrule || row.run_at || row.event_kind || row.after_conversation_ext_id);
4496
- function workflowStatus(row) {
4497
- if (isSkillRow(row) || !hasTrigger(row)) return "on_demand";
4498
- return row.active ? "active" : "paused";
4499
- }
4500
- function workflowTriggerType(workflow) {
4501
- if (workflow.on_demand) return "on_demand";
4502
- if (workflow.after_conversation_ext_id) return "after";
4503
- if (workflow.event_kind) return "event";
4504
- if (workflow.rrule) return "recurring";
4505
- if (workflow.run_at) return "one_time";
4506
- return "on_demand";
4507
- }
4508
- function workflowRunStatusLabel(status) {
4509
- if (!status) return "None";
4510
- const labels = {
4511
- completed: "Success",
4512
- success: "Success",
4513
- failed: "Failed",
4514
- running: "In progress",
4515
- awaiting_authorization: "Awaiting access"
4516
- };
4517
- return labels[status] ?? status.replaceAll("_", " ");
4518
- }
4519
- function listedRunStatus(status, threadStatus) {
4520
- if (threadStatus === "done" && status === "running") return "completed";
4521
- return status;
4522
- }
4523
-
4524
- // src/agents/tasks/workflowColumns.tsx
4525
- var WORKFLOW_COLUMN_ORDER = [
4526
- "name",
4527
- "trigger",
4528
- "last_run",
4529
- "result",
4530
- "status",
4531
- "shared",
4532
- "actions"
4533
- ];
4534
- function cell(render) {
4535
- return (params) => params.data ? render(params.data) : null;
4536
- }
4537
- var time = (iso) => iso ? Date.parse(iso) : Number.POSITIVE_INFINITY;
4538
- function createWorkflowColumns(o) {
4539
- const l = o.labels;
4540
- const base = {
4541
- sortable: false,
4542
- cellStyle: { display: "flex", alignItems: "center" }
4543
- };
4544
- return [
4545
- {
4546
- ...base,
4547
- colId: "name",
4548
- sortable: true,
4549
- headerName: l.colName,
4550
- flex: 3,
4551
- minWidth: 210,
4552
- valueGetter: (p) => p.data?.name.toLowerCase() ?? "",
4553
- cellRenderer: cell(o.renderName)
4554
- },
4555
- {
4556
- ...base,
4557
- colId: "trigger",
4558
- headerName: l.colTrigger,
4559
- flex: 2.4,
4560
- minWidth: 185,
4561
- valueGetter: (p) => p.data ? o.getTriggerText(p.data) : "",
4562
- cellRenderer: cell(o.renderTrigger)
4563
- },
4564
- {
4565
- ...base,
4566
- colId: "last_run",
4567
- sortable: true,
4568
- headerName: l.colLastRun,
4569
- flex: 1.4,
4570
- minWidth: 140,
4571
- cellStyle: { display: "flex", alignItems: "center", padding: 0 },
4572
- valueGetter: (p) => time(p.data?.last_fired_at),
4573
- cellRenderer: cell(o.renderLastRun)
4574
- },
4575
- {
4576
- ...base,
4577
- colId: "result",
4578
- headerName: "Result",
4579
- width: 130,
4580
- valueGetter: (p) => p.data?.last_run_status ?? "",
4581
- cellStyle: { display: "flex", alignItems: "center", padding: 0 },
4582
- cellRenderer: cell(o.renderResult)
4583
- },
4584
- {
4585
- ...base,
4586
- colId: "status",
4587
- sortable: true,
4588
- headerName: l.colStatus,
4589
- width: 120,
4590
- valueGetter: (p) => p.data ? workflowStatus(p.data) : "",
4591
- cellRenderer: cell(o.renderStatus)
4592
- },
4593
- {
4594
- ...base,
4595
- colId: "shared",
4596
- headerName: l.colShared,
4597
- headerTooltip: l.shared,
4598
- width: 96,
4599
- cellStyle: { display: "flex", alignItems: "center", justifyContent: "center" },
4600
- valueGetter: (p) => p.data?.shared ?? false,
4601
- cellRenderer: cell(o.renderShared)
4602
- },
4603
- {
4604
- ...base,
4605
- colId: "actions",
4606
- headerName: "",
4607
- width: 180,
4608
- minWidth: 180,
4609
- cellStyle: { display: "flex", alignItems: "center", justifyContent: "flex-end" },
4610
- cellRenderer: cell(o.renderActions)
4611
- }
4612
- ];
4613
- }
4614
-
4615
- // src/agents/tasks/workflowTableLabels.ts
4616
- var DEFAULT_WORKFLOW_LIST_LABELS = {
4617
- colName: "Name",
4618
- colType: "Type",
4619
- colTrigger: "When",
4620
- colAction: "What it does",
4621
- colAgent: "Agent",
4622
- colStatus: "Active",
4623
- colShared: "Shared",
4624
- colLastRun: "Last run",
4625
- colNextRun: "Next run",
4626
- shared: "Shared with the workspace",
4627
- sharedOwnerOnly: "Only the creator can change who can see this",
4628
- deleteOwnerOnly: "Only the creator or workspace owner can delete this",
4629
- typeSkill: "Skill",
4630
- typeWorkflow: "Workflow",
4631
- statusActive: "Active",
4632
- statusPaused: "Inactive",
4633
- statusOnDemand: "On demand",
4634
- activeSwitch: (name) => `Active: \u201C${name}\u201D`,
4635
- agent: "Agent",
4636
- myAssistant: "My assistant",
4637
- me: "Me",
4638
- someone: "Someone",
4639
- never: "Never",
4640
- none: "\u2014",
4641
- reminder: "Reminder",
4642
- failed: "Failed",
4643
- lastRunFailed: "Last run failed",
4644
- openLastRun: "Open the task this run created",
4645
- editWorkflow: "Edit",
4646
- run: "Run",
4647
- runLater: "Run later",
4648
- runNow: "Run now",
4649
- runs: "Runs",
4650
- delete: "Delete",
4651
- moreActions: "More actions",
4652
- searchLabel: "Search workflows",
4653
- searchPlaceholder: "Search workflows and skills\u2026",
4654
- emptyTitle: "Nothing to run yet",
4655
- emptyMessage: "Skills and workflows you can run will appear here.",
4656
- firstRun: "Run a skill now, or choose Run later to save it as a workflow that runs on its own.",
4657
- noMatches: "Nothing in this view.",
4658
- filterAll: "All",
4659
- filterSkills: "Skills",
4660
- filterWorkflows: "Workflows",
4661
- filterActive: "Active",
4662
- filterPaused: "Inactive",
4663
- makeActive: "Make active",
4664
- makePaused: "Deactivate",
4665
- selectAll: "Select all",
4666
- selectWorkflow: (name) => `Select ${name}`
4667
- };
4668
- var ROW_HEIGHT = 40;
4669
- function WorkflowsTable(props) {
4670
- const { workflows, isLoading, busyId, header, testId } = props;
4671
- const l = { ...DEFAULT_WORKFLOW_LIST_LABELS, ...props.labels };
4672
- const [filterStates, setFilterStates] = useState(/* @__PURE__ */ new Map());
4673
- const [filterOpen, setFilterOpen] = useState(false);
4674
- const [query, setQuery] = useState("");
4675
- const [selected, setSelected] = useState([]);
4676
- const apiRef = useRef(null);
4677
- const q = query.trim().toLowerCase();
4678
- const matches = (w) => !q || `${w.name} ${w.description ?? ""} ${w.prompt ?? ""} ${w.skill_ref ?? ""}`.toLowerCase().includes(q);
4679
- const inFilter = (w, f) => f === "all" || f === "skills" && isSkillRow(w) || f === "workflows" && !isSkillRow(w) || f === "active" && workflowStatus(w) === "active" || f === "paused" && workflowStatus(w) === "paused";
4680
- const counts = useMemo(() => {
4681
- const out = { all: 0, skills: 0, workflows: 0, active: 0, paused: 0 };
4682
- for (const w of workflows) {
4683
- if (!matches(w)) continue;
4684
- for (const f of Object.keys(out)) if (inFilter(w, f)) out[f] += 1;
4685
- }
4686
- return out;
4687
- }, [workflows, q]);
4688
- const shown = useMemo(
4689
- () => workflows.filter((w) => {
4690
- if (!matches(w)) return false;
4691
- for (const group of [
4692
- ["skills", "workflows"],
4693
- ["active", "paused"]
4694
- ]) {
4695
- const included = group.filter((f) => filterStates.get(f) === "include");
4696
- if (included.length && !included.some((f) => inFilter(w, f))) return false;
4697
- if (group.some((f) => filterStates.get(f) === "exclude" && inFilter(w, f))) return false;
4698
- }
4699
- return true;
4700
- }),
4701
- [workflows, filterStates, q]
4702
- );
4703
- const renderPerson = props.renderPerson ?? ((p) => /* @__PURE__ */ jsx(PersonPill, { person: p }));
4704
- const actionText = (w) => {
4705
- if (w.action)
4706
- return w.action.type === "email_documents" ? "Email latest documents" : "AI Review";
4707
- if (isSkillRow(w))
4708
- return w.description || w.skill_ref && props.skillNames?.[w.skill_ref] || w.name;
4709
- return w.skill_ref ? props.skillNames?.[w.skill_ref] ?? w.skill_ref : w.prompt?.trim() || l.reminder;
4710
- };
4711
- const latest = useRef({ props, l, renderPerson, actionText });
4712
- latest.current = { props, l, renderPerson, actionText };
4713
- const columnDefs = useMemo(
4714
- () => createWorkflowColumns({
4715
- labels: l,
4716
- getTriggerText: (w) => isSkillRow(w) ? l.statusOnDemand : latest.current.props.describeTrigger(w),
4717
- renderName: (w) => {
4718
- const { l: lb } = latest.current;
4719
- const skill = isSkillRow(w);
4720
- const text = skill ? latest.current.actionText(w) : w.description || latest.current.actionText(w);
4721
- const stem = w.name.replace(/…$/, "").trim();
4722
- const about = text && text.trim() !== w.name.trim() && text.trim() !== stem ? text : "";
4723
- return /* @__PURE__ */ jsxs("div", { className: "min-w-0 leading-tight", children: [
4724
- /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
4725
- /* @__PURE__ */ jsx(
4726
- "span",
4727
- {
4728
- className: cn(
4729
- "truncate text-sm font-normal",
4730
- workflowStatus(w) === "paused" && "text-muted-foreground"
4731
- ),
4732
- "data-testid": `workflow-name-${w.external_id}`,
4733
- children: w.name
4734
- }
4735
- ),
4736
- skill && /* @__PURE__ */ jsx(
4737
- "span",
4738
- {
4739
- className: "shrink-0 rounded-full border border-border px-1.5 text-[11px] text-muted-foreground",
4740
- "data-testid": `workflow-type-${w.external_id}`,
4741
- children: lb.typeSkill
4742
- }
4743
- )
4744
- ] }),
4745
- about && !latest.current.props.automationsOnly && /* @__PURE__ */ jsx(
4746
- "p",
4747
- {
4748
- className: "truncate text-xs text-muted-foreground",
4749
- "data-testid": `workflow-action-${w.external_id}`,
4750
- children: about
4751
- }
4752
- )
4753
- ] });
4754
- },
4755
- renderTrigger: (w) => {
4756
- const { props: p } = latest.current;
4757
- const after = w.after_conversation_ext_id;
4758
- const skill = isSkillRow(w);
4759
- return /* @__PURE__ */ jsx("div", { className: "min-w-0 leading-tight", children: /* @__PURE__ */ jsx(
4760
- TaskTriggerChip,
4761
- {
4762
- id: w.external_id,
4763
- testId: `workflow-trigger-${w.external_id}`,
4764
- triggerType: workflowTriggerType(w),
4765
- summary: skill ? "" : p.describeTrigger(w),
4766
- afterTaskId: after,
4767
- afterTaskName: after ? p.taskNames?.[after] : void 0,
4768
- labels: p.triggerChipLabels
4769
- }
4770
- ) });
4771
- },
4772
- renderStatus: (w) => {
4773
- const { props: p, l: lb } = latest.current;
4774
- const canEdit = w.is_owner !== false || Boolean(p.canEditShared);
4775
- return /* @__PURE__ */ jsx(
4776
- Switch,
4777
- {
4778
- checked: hasTrigger(w) && !isSkillRow(w) && Boolean(w.active),
4779
- disabled: !hasTrigger(w) || isSkillRow(w) || !canEdit || p.busyId === w.external_id,
4780
- onCheckedChange: (next) => p.onToggleActive(w, next),
4781
- className: "disabled:data-[state=unchecked]:bg-muted dark:disabled:data-[state=unchecked]:bg-muted",
4782
- "aria-label": lb.activeSwitch(w.name),
4783
- "data-testid": `workflow-active-${w.external_id}`
4784
- }
4785
- );
4786
- },
4787
- renderShared: (w) => {
4788
- const { props: p, l: lb } = latest.current;
4789
- if (!p.onToggleShared || isSkillRow(w)) return null;
4790
- const isCreator = w.is_owner !== false;
4791
- return /* @__PURE__ */ jsx(
4792
- VisibilityToggle,
4793
- {
4794
- items: { shared: w.shared ?? false },
4795
- onToggle: (share) => latest.current.props.onToggleShared?.(w, share),
4796
- disabled: !isCreator || p.busyId === w.external_id,
4797
- disabledTooltip: lb.sharedOwnerOnly,
4798
- showLabel: false,
4799
- "data-testid": `workflow-shared-${w.external_id}`
4800
- }
4801
- );
4802
- },
4803
- renderLastRun: (w) => {
4804
- const { props: p, l: lb } = latest.current;
4805
- const at = w.last_fired_at ?? p.lastRuns?.[w.external_id]?.at;
4806
- return /* @__PURE__ */ jsx(
4807
- "button",
4808
- {
4809
- type: "button",
4810
- className: "h-full w-full truncate px-4 text-left text-sm hover:text-primary",
4811
- onClick: () => p.onViewRuns?.(w),
4812
- title: "View run history",
4813
- "data-testid": `workflow-last-run-${w.external_id}`,
4814
- children: at ? p.formatDate(at) : lb.never
4815
- }
4816
- );
4817
- },
4818
- renderResult: (w) => {
4819
- const status = listedRunStatus(
4820
- w.last_run_status,
4821
- latest.current.props.lastRuns?.[w.external_id]?.threadStatus
4822
- );
4823
- const label = workflowRunStatusLabel(status);
4824
- return /* @__PURE__ */ jsx(
4825
- "button",
4826
- {
4827
- type: "button",
4828
- onClick: () => latest.current.props.onViewRuns?.(w),
4829
- title: "View run history",
4830
- className: cn(
4831
- badgeVariants({ variant: "outline" }),
4832
- "mx-4 cursor-pointer text-xs font-medium",
4833
- status === "failed" ? "border-red-border bg-red-bg text-red-text hover:bg-red-bg/80" : status === "completed" || status === "success" ? "border-green-border bg-green-bg text-green-text hover:bg-green-bg/80" : status ? "border-primary/20 bg-primary/10 text-primary hover:bg-primary/15" : "border-border bg-muted text-muted-foreground hover:bg-muted/80"
4834
- ),
4835
- "data-testid": `workflow-result-${w.external_id}`,
4836
- children: label
4837
- }
4838
- );
4839
- },
4840
- renderActions: (w) => {
4841
- const { props: p, l: lb } = latest.current;
4842
- const id = w.external_id;
4843
- const skill = isSkillRow(w);
4844
- const busy = p.busyId === id;
4845
- const isOwner = w.is_owner !== false;
4846
- const canEdit = isOwner || Boolean(p.canEditShared);
4847
- const canAdmin = isOwner || Boolean(p.isWorkspaceOwner);
4848
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1", children: [
4849
- (skill || canEdit) && /* @__PURE__ */ jsxs(
4850
- Button,
4851
- {
4852
- size: "sm",
4853
- variant: "outline",
4854
- className: "h-8 gap-1.5 pointer-coarse:h-11",
4855
- disabled: busy,
4856
- onClick: () => p.onRun(w),
4857
- "data-testid": `workflow-run-btn-${id}`,
4858
- children: [
4859
- /* @__PURE__ */ jsx(Play, { className: "size-3.5", "aria-hidden": true }),
4860
- lb.run
4861
- ]
4862
- }
4863
- ),
4864
- /* @__PURE__ */ jsxs(DropdownMenu, { children: [
4865
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
4866
- Button,
4867
- {
4868
- variant: "ghost",
4869
- size: "icon",
4870
- className: "size-8 pointer-coarse:size-11",
4871
- "aria-label": lb.moreActions,
4872
- "data-testid": `workflow-menu-${id}`,
4873
- children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4", "aria-hidden": true })
4874
- }
4875
- ) }),
4876
- /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
4877
- skill && p.onRunLater && /* @__PURE__ */ jsxs(
4878
- DropdownMenuItem,
4879
- {
4880
- onSelect: () => p.onRunLater?.(w),
4881
- "data-testid": `workflow-run-later-${id}`,
4882
- children: [
4883
- /* @__PURE__ */ jsx(History, { className: "mr-2 size-4", "aria-hidden": true }),
4884
- lb.runLater
4885
- ]
4886
- }
4887
- ),
4888
- !skill && canEdit && /* @__PURE__ */ jsxs(
4889
- DropdownMenuItem,
4890
- {
4891
- onSelect: () => p.onEdit(w),
4892
- "data-testid": `workflow-edit-${id}`,
4893
- children: [
4894
- /* @__PURE__ */ jsx(Pencil, { className: "mr-2 size-4", "aria-hidden": true }),
4895
- lb.editWorkflow
4896
- ]
4897
- }
4898
- ),
4899
- !skill && p.onViewRuns && /* @__PURE__ */ jsxs(
4900
- DropdownMenuItem,
4901
- {
4902
- onSelect: () => p.onViewRuns?.(w),
4903
- "data-testid": `workflow-runs-${id}`,
4904
- children: [
4905
- /* @__PURE__ */ jsx(History, { className: "mr-2 size-4", "aria-hidden": true }),
4906
- lb.runs
4907
- ]
4908
- }
4909
- ),
4910
- !skill && canEdit && /* @__PURE__ */ jsxs(Fragment, { children: [
4911
- /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
4912
- /* @__PURE__ */ jsxs(
4913
- DropdownMenuItem,
4914
- {
4915
- disabled: busy || !canAdmin,
4916
- onSelect: () => p.onDelete(w),
4917
- title: canAdmin ? void 0 : lb.deleteOwnerOnly,
4918
- className: "text-destructive focus:text-destructive",
4919
- "data-testid": `workflow-delete-${id}`,
4920
- children: [
4921
- /* @__PURE__ */ jsx(Trash2, { className: "mr-2 size-4", "aria-hidden": true }),
4922
- lb.delete
4923
- ]
4924
- }
4925
- )
4926
- ] })
4927
- ] })
4928
- ] })
4929
- ] });
4930
- }
4931
- }),
4932
- // Stable on purpose: only the header texts rebuild the columns (see `latest`).
4933
- // eslint-disable-next-line react-hooks/exhaustive-deps
4934
- [
4935
- l.colName,
4936
- l.colType,
4937
- l.colTrigger,
4938
- l.colAction,
4939
- l.colAgent,
4940
- l.colStatus,
4941
- l.colShared,
4942
- l.shared,
4943
- l.colLastRun,
4944
- l.colNextRun
4945
- ]
4946
- );
4947
- useEffect(() => {
4948
- apiRef.current?.refreshCells({ force: true });
4949
- }, [
4950
- busyId,
4951
- props.agentNames,
4952
- props.skillNames,
4953
- props.taskNames,
4954
- props.lastRuns,
4955
- props.renderPerson,
4956
- props.labels,
4957
- props.canEditShared,
4958
- props.isWorkspaceOwner
4959
- ]);
4960
- const mine = selected.filter((w) => !isSkillRow(w));
4961
- const adminSelected = mine.filter((w) => w.is_owner !== false || props.isWorkspaceOwner);
4962
- const editableSelected = mine.filter(
4963
- (w) => hasTrigger(w) && (w.is_owner !== false || props.canEditShared)
4964
- );
4965
- const clearSelection = () => setSelected([]);
4966
- return /* @__PURE__ */ jsxs(
4967
- "div",
4968
- {
4969
- className: "flex min-h-0 flex-1 flex-col",
4970
- "data-testid": testIdOr(testId, { testId: "workflow-list" }),
4971
- children: [
4972
- /* @__PURE__ */ jsx(
4973
- TabHeader,
4974
- {
4975
- testId: "automations-tab-header",
4976
- tabs: [
4977
- {
4978
- id: "automations",
4979
- label: "",
4980
- count: shown.length,
4981
- countIcon: /* @__PURE__ */ jsx(Workflow, { className: "size-3.5" }),
4982
- countPlacement: "leading",
4983
- presentation: "count",
4984
- hasActiveFilters: !!q || [...filterStates.values()].some(Boolean)
4985
- },
4986
- ...props.tabs ?? []
4987
- ],
4988
- activeTabId: props.activeTabId ?? "automations",
4989
- onTabChange: props.onTabChange ?? (() => {
4990
- }),
4991
- firstTabContent: /* @__PURE__ */ jsx(
4992
- FilterInput,
4993
- {
4994
- value: query,
4995
- onChange: setQuery,
4996
- fields: ["text"],
4997
- onFieldsChange: () => {
4998
- },
4999
- hideFieldPicker: true,
5000
- ariaLabel: l.searchLabel,
5001
- testIds: { input: "workflow-search" },
5002
- filter: /* @__PURE__ */ jsx(
5003
- TriStateFilterMenu,
5004
- {
5005
- testId: "automations-filter-button",
5006
- open: filterOpen,
5007
- onOpenChange: setFilterOpen,
5008
- filterStates,
5009
- onFiltersChange: setFilterStates,
5010
- triggerClassName: "flex h-5 items-center gap-0.5 rounded px-1 text-muted-foreground hover:text-foreground pointer-coarse:h-11! pointer-coarse:min-w-11 pointer-coarse:justify-center",
5011
- renderChevron: true,
5012
- disableHoverOpen: true,
5013
- options: [
5014
- ...!props.automationsOnly ? [
5015
- { id: "skills", label: l.filterSkills, count: counts.skills },
5016
- {
5017
- id: "workflows",
5018
- label: l.filterWorkflows,
5019
- count: counts.workflows
5020
- }
5021
- ] : [],
5022
- { id: "active", label: l.filterActive, count: counts.active },
5023
- { id: "paused", label: l.filterPaused, count: counts.paused }
5024
- ]
5025
- }
5026
- )
5027
- }
5028
- ),
5029
- rightContent: header
5030
- }
5031
- ),
5032
- props.content ? props.content : workflows.length === 0 && !isLoading ? /* @__PURE__ */ jsx(
5033
- EmptyState,
5034
- {
5035
- icon: Workflow,
5036
- title: l.emptyTitle,
5037
- description: l.emptyMessage,
5038
- testId: "workflow-list-empty"
5039
- }
5040
- ) : /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
5041
- GridView,
5042
- {
5043
- testId: "workflow-grid",
5044
- gridId: props.gridId ?? "workflows-grid-v2",
5045
- items: shown,
5046
- columnDefs,
5047
- getItemId: (w) => w.external_id,
5048
- getRowTestId: (w) => `workflow-row-${w.external_id}`,
5049
- isLoading,
5050
- showEmpty: shown.length === 0,
5051
- emptyState: { title: l.noMatches },
5052
- rowHeight: ROW_HEIGHT,
5053
- height: "100%",
5054
- onGridReady: ({ api }) => {
5055
- apiRef.current = api;
5056
- },
5057
- onRowClick: (row) => props.onOpenRow?.(row),
5058
- selection: { mode: "multiple", selected, onSelectionChange: setSelected },
5059
- gridOptions: GRID_OPTIONS
5060
- }
5061
- ) }),
5062
- !props.content && /* @__PURE__ */ jsx(SelectionBar, { count: selected.length, onClear: clearSelection, children: (isCompact) => /* @__PURE__ */ jsxs(Fragment, { children: [
5063
- props.onToggleActiveMany && /* @__PURE__ */ jsxs(Fragment, { children: [
5064
- /* @__PURE__ */ jsx(
5065
- SelectionBarAction,
5066
- {
5067
- icon: Play,
5068
- label: l.makeActive,
5069
- onClick: () => {
5070
- props.onToggleActiveMany?.(editableSelected, true);
5071
- clearSelection();
5072
- },
5073
- disabled: editableSelected.length === 0,
5074
- isCompact,
5075
- testId: "workflow-bulk-activate"
5076
- }
5077
- ),
5078
- /* @__PURE__ */ jsx(
5079
- SelectionBarAction,
5080
- {
5081
- icon: Workflow,
5082
- label: l.makePaused,
5083
- onClick: () => {
5084
- props.onToggleActiveMany?.(editableSelected, false);
5085
- clearSelection();
5086
- },
5087
- disabled: editableSelected.length === 0,
5088
- isCompact,
5089
- testId: "workflow-bulk-pause"
5090
- }
5091
- )
5092
- ] }),
5093
- props.onDeleteMany && /* @__PURE__ */ jsx(
5094
- SelectionBarAction,
5095
- {
5096
- icon: Trash2,
5097
- label: l.delete,
5098
- onClick: () => {
5099
- props.onDeleteMany?.(adminSelected);
5100
- clearSelection();
5101
- },
5102
- disabled: adminSelected.length === 0,
5103
- isCompact,
5104
- className: "border-red-border text-red-text hover:bg-red-bg hover:text-red-text",
5105
- testId: "workflow-bulk-delete"
5106
- }
5107
- )
5108
- ] }) })
5109
- ]
5110
- }
5111
- );
5112
- }
5113
- var GRID_OPTIONS = { suppressClickEdit: true };
5114
3529
  var DEFAULT_TASK_ACTIVITY_LABELS = {
5115
3530
  title: "Activity",
5116
3531
  empty: "Nothing has happened yet.",
@@ -5468,6 +3883,6 @@ function TaskRunsDialog({
5468
3883
  ) });
5469
3884
  }
5470
3885
 
5471
- export { ActionStepBody, AgentAvatarField, AgentConnectInstructions, AgentCreator, AgentSelect, AgentTypeSelector, ApprovalEvidence, AssigneeLine, CapabilityGrid, CapabilityTile, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_CAPABILITIES, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_SELECT_LABELS, DEFAULT_AGENT_TEMPLATES, DEFAULT_AGENT_TYPES, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_STEP_BAR_LABELS, DEFAULT_TASK_ACTIVITY_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TASK_TRIGGER_CHIP_LABELS, DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, DEFAULT_WORKFLOW_DOCUMENTS_FIELD_LABELS, DEFAULT_WORKFLOW_LIST_LABELS, DEFAULT_WORKFLOW_RUNNER_LABELS, DEFAULT_WORKFLOW_STEP_PARTS_LABELS, PersonPill, SKILL_FIELD_TYPE_LABELS, SKILL_MAIN_FILENAME, SKILL_SOURCE_LABELS, SKILL_TYPES, SKILL_TYPE_LABELS, STEP_LABEL, STEP_LABEL_CURRENT, STEP_LABEL_MAX, SchemaForm, SendBackControl, SkillActionButton, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillLibraryDetail, SkillTile, SkillTypeBadge, SkillViewToggle, StepBarFrame, TaskActivityDialog, TaskActivityTimeline, TaskRunsDialog, TaskTriggerChip, WORKFLOW_COLUMN_ORDER, WorkflowConfigDialog, WorkflowDocumentsField, WorkflowLauncher, WorkflowRunner, WorkflowStepBar, WorkflowsTable, activateOnKey, activeStepId, agentConfigSectionToValues, agentCreatorToConfigSection, buildLibrarySkills, buildWorkflowScopeSource, buildZipSkillImport, composePersona, createWorkflowColumns, deriveAgentName, documentScopeLabels, filterLibrarySkills, fromPlanAssignee, fromPlanDocumentRef, fromPlanSteps, hasTrigger, importMarkdownSkill, importSkillFile, importSkillFromUrl, isIncompleteSignal, isMainSkillFile, isSkillRow, isValidAgentName, layoutFromPlanSteps, matchWorkflowScope, parseSkillFrontmatter, readSkillArchive, serializeSkill, skillSlug, stepWindow, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskActivityHeadline, toPlanAssignee, toPlanDocumentRef, toPlanSteps, useWorkflowView, workflowFromSkillMarkdown, workflowStatus, workflowToSkillMarkdown, workflowTriggerType };
5472
- //# sourceMappingURL=chunk-PROK33G6.js.map
5473
- //# sourceMappingURL=chunk-PROK33G6.js.map
3886
+ export { ActionStepBody, AgentAvatarField, AgentConnectInstructions, AgentCreator, AgentTypeSelector, ApprovalEvidence, AssigneeLine, CapabilityGrid, CapabilityTile, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_CAPABILITIES, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_TEMPLATES, DEFAULT_AGENT_TYPES, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_STEP_BAR_LABELS, DEFAULT_TASK_ACTIVITY_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_WORKFLOW_RUNNER_LABELS, DEFAULT_WORKFLOW_STEP_PARTS_LABELS, SKILL_FIELD_TYPE_LABELS, SKILL_MAIN_FILENAME, SKILL_SOURCE_LABELS, SKILL_TYPES, SKILL_TYPE_LABELS, STEP_LABEL, STEP_LABEL_CURRENT, STEP_LABEL_MAX, SendBackControl, SkillActionButton, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillLibraryDetail, SkillTile, SkillTypeBadge, SkillViewToggle, StepBarFrame, TaskActivityDialog, TaskActivityTimeline, TaskRunsDialog, WorkflowRunner, WorkflowStepBar, activateOnKey, activeStepId, agentConfigSectionToValues, agentCreatorToConfigSection, buildLibrarySkills, buildZipSkillImport, composePersona, deriveAgentName, filterLibrarySkills, fromPlanAssignee, fromPlanDocumentRef, fromPlanSteps, importMarkdownSkill, importSkillFile, importSkillFromUrl, isIncompleteSignal, isMainSkillFile, isValidAgentName, layoutFromPlanSteps, parseSkillFrontmatter, readSkillArchive, serializeSkill, skillSlug, stepWindow, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskActivityHeadline, toPlanAssignee, toPlanDocumentRef, toPlanSteps, useWorkflowView, workflowFromSkillMarkdown, workflowToSkillMarkdown };
3887
+ //# sourceMappingURL=chunk-C44TDH54.js.map
3888
+ //# sourceMappingURL=chunk-C44TDH54.js.map