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