@arbidocs/blocks 0.4.31 → 0.4.33

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 (179) hide show
  1. package/dist/agents/index.cjs +256 -214
  2. package/dist/agents/index.js +7 -5
  3. package/dist/agents/tasks/ConversationListView.d.ts +58 -0
  4. package/dist/agents/tasks/ConversationTurnSpeaker.d.ts +16 -0
  5. package/dist/agents/tasks/NewThreadDialog.d.ts +1 -1
  6. package/dist/agents/tasks/TaskActivityTimeline.d.ts +1 -1
  7. package/dist/agents/tasks/TaskFlow.d.ts +22 -0
  8. package/dist/agents/tasks/TaskInbox.d.ts +26 -0
  9. package/dist/agents/tasks/TaskReviewDialog.d.ts +22 -0
  10. package/dist/agents/tasks/TaskRowMenu.d.ts +10 -2
  11. package/dist/agents/tasks/TaskRunsDialog.d.ts +8 -3
  12. package/dist/agents/tasks/TaskStartDialog.d.ts +24 -0
  13. package/dist/agents/tasks/TaskTable.d.ts +1 -1
  14. package/dist/agents/tasks/ThreadNotifyDialog.d.ts +11 -0
  15. package/dist/agents/tasks/WorkflowComposer.d.ts +1 -1
  16. package/dist/agents/tasks/WorkflowsTable.d.ts +7 -0
  17. package/dist/agents/tasks/compact-thread-activity.d.ts +8 -0
  18. package/dist/agents/tasks/index.d.ts +10 -0
  19. package/dist/agents/tasks/taskComposerTypes.d.ts +16 -1
  20. package/dist/agents/tasks/taskRequest.d.ts +1 -0
  21. package/dist/agents/tasks/testGrid.d.ts +24 -0
  22. package/dist/agents/tasks/workflowColumns.d.ts +2 -1
  23. package/dist/agents/tasks/workflowRows.d.ts +6 -0
  24. package/dist/agents/workflows/types.d.ts +2 -0
  25. package/dist/auth/index.cjs +27 -27
  26. package/dist/auth/index.js +1 -1
  27. package/dist/chat/Message.d.ts +8 -2
  28. package/dist/chat/index.cjs +132 -120
  29. package/dist/chat/index.d.ts +2 -0
  30. package/dist/chat/index.js +2 -2
  31. package/dist/chat/participant-tints.d.ts +1 -0
  32. package/dist/chat/useRecipientDraft.d.ts +14 -0
  33. package/dist/{chunk-KF4EC5XU.js → chunk-24KQJYSB.js} +3 -3
  34. package/dist/{chunk-KF4EC5XU.js.map → chunk-24KQJYSB.js.map} +1 -1
  35. package/dist/{chunk-GVQOBJKR.cjs → chunk-2EAE5JP6.cjs} +7 -4
  36. package/dist/chunk-2EAE5JP6.cjs.map +1 -0
  37. package/dist/{chunk-S5HZBXZA.cjs → chunk-2QTT2RZE.cjs} +242 -2
  38. package/dist/chunk-2QTT2RZE.cjs.map +1 -0
  39. package/dist/chunk-3AFWGEDJ.cjs +53 -0
  40. package/dist/chunk-3AFWGEDJ.cjs.map +1 -0
  41. package/dist/{chunk-4XJZ6AAY.js → chunk-4AWS54US.js} +244 -6
  42. package/dist/chunk-4AWS54US.js.map +1 -0
  43. package/dist/{chunk-56BUD74K.cjs → chunk-65THHQVB.cjs} +27 -27
  44. package/dist/{chunk-56BUD74K.cjs.map → chunk-65THHQVB.cjs.map} +1 -1
  45. package/dist/{chunk-5B4PXAKI.cjs → chunk-6DNYPLCD.cjs} +21 -7
  46. package/dist/chunk-6DNYPLCD.cjs.map +1 -0
  47. package/dist/{chunk-Y2LWA4ZO.js → chunk-6RXUMBTK.js} +1855 -501
  48. package/dist/chunk-6RXUMBTK.js.map +1 -0
  49. package/dist/{chunk-UTYQPVIW.cjs → chunk-7QDX2CO4.cjs} +6 -6
  50. package/dist/{chunk-UTYQPVIW.cjs.map → chunk-7QDX2CO4.cjs.map} +1 -1
  51. package/dist/{chunk-FRRDPYBR.cjs → chunk-AZ75JUIH.cjs} +74 -5
  52. package/dist/chunk-AZ75JUIH.cjs.map +1 -0
  53. package/dist/{chunk-NUPVHEJW.js → chunk-BUHKUKKB.js} +7 -4
  54. package/dist/chunk-BUHKUKKB.js.map +1 -0
  55. package/dist/chunk-C7FGONCM.js +124 -0
  56. package/dist/chunk-C7FGONCM.js.map +1 -0
  57. package/dist/{chunk-KXMDOTGW.js → chunk-DLBUFHLY.js} +10 -2
  58. package/dist/chunk-DLBUFHLY.js.map +1 -0
  59. package/dist/{chunk-ZHLMDJCO.cjs → chunk-DLVX6R6B.cjs} +62 -26
  60. package/dist/chunk-DLVX6R6B.cjs.map +1 -0
  61. package/dist/{chunk-JGZTRLKL.cjs → chunk-IA7RTPT3.cjs} +7 -4
  62. package/dist/chunk-IA7RTPT3.cjs.map +1 -0
  63. package/dist/{chunk-NJL4LIXX.js → chunk-LFGJAZ5H.js} +11 -8
  64. package/dist/chunk-LFGJAZ5H.js.map +1 -0
  65. package/dist/{chunk-IAKUTBPX.js → chunk-LYUO3E6V.js} +3 -3
  66. package/dist/{chunk-IAKUTBPX.js.map → chunk-LYUO3E6V.js.map} +1 -1
  67. package/dist/{chunk-EYPPB5CY.cjs → chunk-M2YGPC5N.cjs} +4 -4
  68. package/dist/{chunk-EYPPB5CY.cjs.map → chunk-M2YGPC5N.cjs.map} +1 -1
  69. package/dist/{chunk-5ZBP7TCD.cjs → chunk-MJCCBMM5.cjs} +10 -2
  70. package/dist/chunk-MJCCBMM5.cjs.map +1 -0
  71. package/dist/chunk-MZL67U2E.cjs +128 -0
  72. package/dist/chunk-MZL67U2E.cjs.map +1 -0
  73. package/dist/{chunk-OJSWQM4G.js → chunk-OZJ5PXA6.js} +29 -4
  74. package/dist/chunk-OZJ5PXA6.js.map +1 -0
  75. package/dist/{chunk-UBNVIIBT.js → chunk-PXFJDX2C.js} +21 -7
  76. package/dist/chunk-PXFJDX2C.js.map +1 -0
  77. package/dist/{chunk-RGHQFJOL.cjs → chunk-QFUF4A4J.cjs} +28 -2
  78. package/dist/chunk-QFUF4A4J.cjs.map +1 -0
  79. package/dist/chunk-RFXJYIDV.js +50 -0
  80. package/dist/chunk-RFXJYIDV.js.map +1 -0
  81. package/dist/{chunk-CQWRVIJC.cjs → chunk-SEQWI6E4.cjs} +1882 -517
  82. package/dist/chunk-SEQWI6E4.cjs.map +1 -0
  83. package/dist/{chunk-QN42OA5J.js → chunk-SFXVNFES.js} +4 -4
  84. package/dist/chunk-SFXVNFES.js.map +1 -0
  85. package/dist/{chunk-3NZR6PAG.js → chunk-V6U5KVAR.js} +70 -4
  86. package/dist/chunk-V6U5KVAR.js.map +1 -0
  87. package/dist/{chunk-YVIOCITQ.cjs → chunk-VUEZARW5.cjs} +3 -3
  88. package/dist/chunk-VUEZARW5.cjs.map +1 -0
  89. package/dist/{chunk-JLOYWXRB.js → chunk-VZGBCBYB.js} +3 -3
  90. package/dist/chunk-VZGBCBYB.js.map +1 -0
  91. package/dist/{chunk-ZVPTFTGV.cjs → chunk-WBDK4PIA.cjs} +11 -8
  92. package/dist/chunk-WBDK4PIA.cjs.map +1 -0
  93. package/dist/{chunk-ZORQ5M3W.cjs → chunk-WQFGG2BV.cjs} +4 -4
  94. package/dist/chunk-WQFGG2BV.cjs.map +1 -0
  95. package/dist/{chunk-C75S6USL.js → chunk-WYVCXY7R.js} +7 -4
  96. package/dist/chunk-WYVCXY7R.js.map +1 -0
  97. package/dist/{chunk-WSJVHSGN.js → chunk-XWEJ5LV2.js} +63 -27
  98. package/dist/chunk-XWEJ5LV2.js.map +1 -0
  99. package/dist/{chunk-YMHGF6R5.js → chunk-ZCF2JJFA.js} +3 -3
  100. package/dist/{chunk-YMHGF6R5.js.map → chunk-ZCF2JJFA.js.map} +1 -1
  101. package/dist/collaboration/index.cjs +45 -41
  102. package/dist/collaboration/index.js +1 -1
  103. package/dist/collaboration/mail/MailMessagePreview.d.ts +11 -0
  104. package/dist/collaboration/mail/index.d.ts +1 -0
  105. package/dist/connect/index.cjs +33 -33
  106. package/dist/connect/index.js +4 -4
  107. package/dist/facts/FactsFilterInput.d.ts +2 -46
  108. package/dist/facts/FactsToolbar.d.ts +5 -5
  109. package/dist/facts/index.cjs +27 -124
  110. package/dist/facts/index.cjs.map +1 -1
  111. package/dist/facts/index.js +13 -118
  112. package/dist/facts/index.js.map +1 -1
  113. package/dist/files/FilesPage.d.ts +1 -1
  114. package/dist/files/FilesToolbar.d.ts +1 -1
  115. package/dist/files/FolderPicker.d.ts +2 -1
  116. package/dist/files/ViewerChrome.d.ts +1 -1
  117. package/dist/files/bulk/FolderFilterButton.d.ts +3 -2
  118. package/dist/files/cells/BulkLabelSelect.d.ts +11 -0
  119. package/dist/files/cells/LabelMultiSelect.d.ts +2 -1
  120. package/dist/files/cells/index.d.ts +1 -0
  121. package/dist/files/index.cjs +108 -165
  122. package/dist/files/index.cjs.map +1 -1
  123. package/dist/files/index.js +94 -157
  124. package/dist/files/index.js.map +1 -1
  125. package/dist/home/index.cjs +19 -19
  126. package/dist/home/index.cjs.map +1 -1
  127. package/dist/home/index.js +4 -4
  128. package/dist/home/index.js.map +1 -1
  129. package/dist/index.cjs +790 -767
  130. package/dist/index.cjs.map +1 -1
  131. package/dist/index.d.ts +1 -0
  132. package/dist/index.js +20 -68
  133. package/dist/index.js.map +1 -1
  134. package/dist/settings/SettingsPanel.d.ts +1 -1
  135. package/dist/settings/index.cjs +55 -280
  136. package/dist/settings/index.cjs.map +1 -1
  137. package/dist/settings/index.js +17 -248
  138. package/dist/settings/index.js.map +1 -1
  139. package/dist/shell/FilterInput.d.ts +46 -0
  140. package/dist/shell/TabHeader.d.ts +5 -1
  141. package/dist/shell/index.cjs +61 -48
  142. package/dist/shell/index.d.ts +1 -0
  143. package/dist/shell/index.js +3 -2
  144. package/dist/site/index.cjs +62 -62
  145. package/dist/site/index.js +2 -2
  146. package/dist/studio/index.cjs +74 -74
  147. package/dist/studio/index.js +5 -5
  148. package/dist/workspaces/WorkspaceCard.d.ts +2 -2
  149. package/dist/workspaces/index.cjs +9 -2
  150. package/dist/workspaces/index.cjs.map +1 -1
  151. package/dist/workspaces/index.js +9 -2
  152. package/dist/workspaces/index.js.map +1 -1
  153. package/package.json +3 -3
  154. package/src/blocks.css +4 -0
  155. package/src/components/grid.css +10 -0
  156. package/dist/chunk-3NZR6PAG.js.map +0 -1
  157. package/dist/chunk-4XJZ6AAY.js.map +0 -1
  158. package/dist/chunk-5B4PXAKI.cjs.map +0 -1
  159. package/dist/chunk-5ZBP7TCD.cjs.map +0 -1
  160. package/dist/chunk-C75S6USL.js.map +0 -1
  161. package/dist/chunk-CQWRVIJC.cjs.map +0 -1
  162. package/dist/chunk-FRRDPYBR.cjs.map +0 -1
  163. package/dist/chunk-GVQOBJKR.cjs.map +0 -1
  164. package/dist/chunk-JGZTRLKL.cjs.map +0 -1
  165. package/dist/chunk-JLOYWXRB.js.map +0 -1
  166. package/dist/chunk-KXMDOTGW.js.map +0 -1
  167. package/dist/chunk-NJL4LIXX.js.map +0 -1
  168. package/dist/chunk-NUPVHEJW.js.map +0 -1
  169. package/dist/chunk-OJSWQM4G.js.map +0 -1
  170. package/dist/chunk-QN42OA5J.js.map +0 -1
  171. package/dist/chunk-RGHQFJOL.cjs.map +0 -1
  172. package/dist/chunk-S5HZBXZA.cjs.map +0 -1
  173. package/dist/chunk-UBNVIIBT.js.map +0 -1
  174. package/dist/chunk-WSJVHSGN.js.map +0 -1
  175. package/dist/chunk-Y2LWA4ZO.js.map +0 -1
  176. package/dist/chunk-YVIOCITQ.cjs.map +0 -1
  177. package/dist/chunk-ZHLMDJCO.cjs.map +0 -1
  178. package/dist/chunk-ZORQ5M3W.cjs.map +0 -1
  179. package/dist/chunk-ZVPTFTGV.cjs.map +0 -1
@@ -1,19 +1,21 @@
1
1
  "use client";
2
2
  import { EmptyState } from './chunk-P6GHJSLR.js';
3
- import { GridView, SelectionBar, SelectionBarAction } from './chunk-NUPVHEJW.js';
4
- import { FoldSection, QuickActionDialogHeader, AddFilesFirst, ScopePicker, StartTiles } from './chunk-NJL4LIXX.js';
3
+ import { FoldSection, QuickActionDialogHeader, AddFilesFirst, ScopePicker, StartTiles } from './chunk-LFGJAZ5H.js';
4
+ import { CellHoverIcon } from './chunk-RFXJYIDV.js';
5
+ import { GridView, SelectionBar, SelectionBarAction } from './chunk-BUHKUKKB.js';
6
+ import { FilterInput } from './chunk-C7FGONCM.js';
5
7
  import { ActionLink } from './chunk-S7PSMMRG.js';
6
- import { DocumentPicker, MultiSelect } from './chunk-4XJZ6AAY.js';
8
+ import { DocumentPicker, TriStateFilterMenu, MultiSelect } from './chunk-4AWS54US.js';
9
+ import { TabHeader } from './chunk-PXFJDX2C.js';
7
10
  import { ToneBadge } from './chunk-DPLRHEJZ.js';
8
- import { TabHeader } from './chunk-UBNVIIBT.js';
9
11
  import { useBlocksEnvironment } from './chunk-76JDDMSP.js';
10
12
  import { formatCount, initials } from './chunk-OXF2IFXG.js';
11
13
  import { ModalHeader } from './chunk-CPMNAJLF.js';
12
14
  import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
13
- import { memo, forwardRef, useState, useMemo, useId, useEffect, useRef, useCallback } from 'react';
14
- import { cn, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea, Input, Switch, Button, Collapsible, CollapsibleTrigger, CollapsibleContent, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Tooltip, TooltipTrigger, TooltipContent, Badge, Slider, UserEntity, getEntityColorStyles, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, Popover, PopoverTrigger, PopoverContent, Command, CommandInput, CommandList, CommandEmpty, CommandItem, VisibilityToggle, EntityPill, DropdownMenuSeparator } from '@arbidocs/react/ui';
15
+ import { memo, forwardRef, useState, useMemo, useId, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
16
+ import { cn, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Textarea, Input, Switch, Button, Collapsible, CollapsibleTrigger, CollapsibleContent, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Tooltip, TooltipTrigger, TooltipContent, Badge, Slider, UserEntity, getEntityColorStyles, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, Popover, PopoverTrigger, PopoverContent, Command, CommandInput, CommandList, CommandEmpty, CommandItem, VisibilityToggle, EntityPill, ThreadVisibilityIcon, DialogClose, DropdownMenuSeparator, badgeVariants, Checkbox } from '@arbidocs/react/ui';
15
17
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
- import { ChevronDown, ChevronRight, Plus, Trash2, Loader2, Play, MessageSquare, Eye, ClipboardList, Pencil, Copy, Bot, Sparkles, Wand2, X, Globe, Download, Lock, ListChecks, AlertTriangle, FileX, SkipForward, Check, FileText, CornerDownRight, MessageSquareReply, UserCheck, AlertCircle, KeyRound, Workflow, ChevronsUpDown, ChevronsDownUp, ListTodo, CheckCheck, CalendarClock, MoreHorizontal, History, Search, ArrowRight, ChevronUp, Pause, Activity, Hourglass, MoreVertical, TriangleAlert, CheckSquare, Square, CheckCircle2, ArrowLeft, LayoutGrid, List, CircleDashed, RotateCcw, ListPlus, UserRoundCog, Link2, Clock, Zap, Repeat, MousePointerClick, CircleDot } from 'lucide-react';
18
+ import { ChevronDown, ChevronRight, Plus, Trash2, Loader2, Play, MessageSquare, Eye, ClipboardList, Pencil, Copy, Bot, Sparkles, Wand2, X, Globe, Download, Lock, ListChecks, AlertTriangle, FileX, SkipForward, Check, FileText, CornerDownRight, MessageSquareReply, UserCheck, AlertCircle, KeyRound, Workflow, ChevronsUpDown, ChevronsDownUp, ListTodo, CheckCheck, MoreHorizontal, CalendarClock, History, ArrowRight, ChevronUp, Pause, Activity, Hourglass, MoreVertical, TriangleAlert, CheckSquare, Square, CheckCircle2, ArrowLeft, LayoutGrid, List, CircleDashed, RotateCcw, ListPlus, UserRoundCog, Link2, Clock, Bell, MousePointerClick, CircleDot, Zap } from 'lucide-react';
17
19
 
18
20
  // src/agents/workflows/types.ts
19
21
  var EMPTY_WORKFLOW_SCOPE = { folders: [], labels: [] };
@@ -3411,144 +3413,6 @@ function TaskReviewActions({
3411
3413
  ] })
3412
3414
  ] });
3413
3415
  }
3414
-
3415
- // src/agents/tasks/taskRows.ts
3416
- var MAX_TASK_DEPTH = 5;
3417
- var ownerExtId = (task) => task.signoff_ext_id || task.owner_ext_id || task.created_by_ext_id || null;
3418
- var isPlainTodo = (task) => !task.agent_ext_id && !task.has_agent_action && !task.skill_ref;
3419
- function indexTasks(tasks) {
3420
- const byId = new Map(tasks.map((t) => [t.external_id, t]));
3421
- const kids = /* @__PURE__ */ new Map();
3422
- const parentOf = /* @__PURE__ */ new Map();
3423
- for (const task of tasks) {
3424
- const parent = task.parent_conversation_ext_id;
3425
- if (parent && parent !== task.external_id && byId.has(parent)) {
3426
- parentOf.set(task.external_id, parent);
3427
- const list = kids.get(parent);
3428
- if (list) list.push(task);
3429
- else kids.set(parent, [task]);
3430
- }
3431
- }
3432
- return { byId, kids, parentOf };
3433
- }
3434
- function descendantIds(tree, id) {
3435
- const out = [];
3436
- const seen = /* @__PURE__ */ new Set([id]);
3437
- const stack = [id];
3438
- while (stack.length) {
3439
- for (const child of tree.kids.get(stack.pop()) ?? []) {
3440
- if (seen.has(child.external_id)) continue;
3441
- seen.add(child.external_id);
3442
- out.push(child.external_id);
3443
- stack.push(child.external_id);
3444
- }
3445
- }
3446
- return out;
3447
- }
3448
- function subtreeLevels(tree, id, seen = /* @__PURE__ */ new Set()) {
3449
- if (seen.has(id)) return 0;
3450
- const next = new Set(seen).add(id);
3451
- let deepest = 0;
3452
- for (const child of tree.kids.get(id) ?? []) {
3453
- deepest = Math.max(deepest, subtreeLevels(tree, child.external_id, next));
3454
- }
3455
- return 1 + deepest;
3456
- }
3457
- function levelOf(tree, id) {
3458
- let level = 1;
3459
- const seen = /* @__PURE__ */ new Set([id]);
3460
- for (let at = tree.parentOf.get(id); at && !seen.has(at); at = tree.parentOf.get(at)) {
3461
- seen.add(at);
3462
- level += 1;
3463
- }
3464
- return level;
3465
- }
3466
- function moveTargets(tasks, task) {
3467
- const tree = indexTasks(tasks);
3468
- const banned = /* @__PURE__ */ new Set([task.external_id, ...descendantIds(tree, task.external_id)]);
3469
- const height = subtreeLevels(tree, task.external_id);
3470
- return tasks.filter(
3471
- (t) => !banned.has(t.external_id) && levelOf(tree, t.external_id) + height <= MAX_TASK_DEPTH
3472
- );
3473
- }
3474
- var sameStats = (a, b) => a === b || a !== void 0 && b !== void 0 && a.done === b.done && a.total === b.total;
3475
- function buildTaskRows(tasks, filter, collapsed, compare, options = {}) {
3476
- const tree = indexTasks(tasks);
3477
- const { kids, parentOf } = tree;
3478
- const sorted = (list) => compare ? [...list].sort(compare) : list;
3479
- const query = options.query?.trim().toLowerCase() ?? "";
3480
- const titleOf = options.titleOf ?? ((t) => t.title ?? "");
3481
- let included = null;
3482
- let matched = null;
3483
- if (filter !== "all" || query) {
3484
- matched = /* @__PURE__ */ new Set();
3485
- included = /* @__PURE__ */ new Set();
3486
- for (const task of tasks) {
3487
- const statusOk = filter === "all" || asTaskStatus(task.status) === filter;
3488
- const textOk = !query || `${titleOf(task)} ${task.description ?? ""}`.toLowerCase().includes(query);
3489
- if (!statusOk || !textOk) continue;
3490
- matched.add(task.external_id);
3491
- for (let at = task.external_id; at && !included.has(at); at = parentOf.get(at)) {
3492
- included.add(at);
3493
- }
3494
- }
3495
- }
3496
- const shown = (list) => included ? list.filter((t) => included.has(t.external_id)) : list;
3497
- const build = (task, depth, seen) => {
3498
- const nextSeen = new Set(seen).add(task.external_id);
3499
- return {
3500
- task,
3501
- depth,
3502
- context: matched ? !matched.has(task.external_id) : false,
3503
- children: sorted(shown(kids.get(task.external_id) ?? [])).filter((child) => !nextSeen.has(child.external_id)).map((child) => build(child, depth + 1, nextSeen))
3504
- };
3505
- };
3506
- const sections = new Map([
3507
- ...STATUS_ORDER.map((s) => [s, []]),
3508
- ["sorted", []]
3509
- ]);
3510
- const sectionOf = (task) => compare ? "sorted" : asTaskStatus(task.status);
3511
- const roots = tasks.filter((t) => !parentOf.has(t.external_id));
3512
- for (const task of sorted(shown(roots))) {
3513
- sections.get(sectionOf(task))?.push(build(task, 0, /* @__PURE__ */ new Set()));
3514
- }
3515
- const cache = options.cache;
3516
- const used = /* @__PURE__ */ new Set();
3517
- const rows = [];
3518
- const walk = (node, parentId, setSize, posInSet) => {
3519
- const id = node.task.external_id;
3520
- const expanded = !collapsed.has(id);
3521
- const all = kids.get(id);
3522
- const childStats = all ? { done: all.filter((c) => asTaskStatus(c.status) === "done").length, total: all.length } : void 0;
3523
- let row = {
3524
- external_id: id,
3525
- task: node.task,
3526
- depth: node.depth,
3527
- childStats,
3528
- expanded,
3529
- parentId,
3530
- setSize,
3531
- posInSet,
3532
- context: node.context
3533
- };
3534
- const prev = cache?.get(id);
3535
- if (prev && prev.task === row.task && prev.depth === row.depth && prev.expanded === row.expanded && prev.parentId === row.parentId && prev.setSize === row.setSize && prev.posInSet === row.posInSet && prev.context === row.context && sameStats(prev.childStats, row.childStats)) {
3536
- row = prev;
3537
- }
3538
- used.add(id);
3539
- cache?.set(id, row);
3540
- rows.push(row);
3541
- if (expanded) {
3542
- node.children.forEach((child, i) => walk(child, id, node.children.length, i + 1));
3543
- }
3544
- };
3545
- const ordered = [...STATUS_ORDER, "sorted"].flatMap((s) => sections.get(s) ?? []);
3546
- ordered.forEach((node, i) => walk(node, null, ordered.length, i + 1));
3547
- if (cache) {
3548
- for (const id of [...cache.keys()]) if (!used.has(id)) cache.delete(id);
3549
- }
3550
- return rows;
3551
- }
3552
3416
  function TaskRowMenu({
3553
3417
  task,
3554
3418
  status,
@@ -3557,6 +3421,10 @@ function TaskRowMenu({
3557
3421
  canAdmin,
3558
3422
  canEdit,
3559
3423
  labels,
3424
+ canMarkDone = canEdit,
3425
+ canReopen = canEdit,
3426
+ selected = false,
3427
+ onToggleSelected,
3560
3428
  onMarkDone,
3561
3429
  onReopen,
3562
3430
  onAddSubtask,
@@ -3565,6 +3433,7 @@ function TaskRowMenu({
3565
3433
  onMoveTo,
3566
3434
  onChangeOwner,
3567
3435
  onOpenActivity,
3436
+ onToggleShared,
3568
3437
  onGrantAccess,
3569
3438
  reviewActions
3570
3439
  }) {
@@ -3585,6 +3454,7 @@ function TaskRowMenu({
3585
3454
  }
3586
3455
  ) }),
3587
3456
  /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
3457
+ onToggleSelected && /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: onToggleSelected, "data-testid": `task-select-${id}`, children: selected ? "Deselect task" : "Select task" }),
3588
3458
  reviewActions && /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5", children: typeof reviewActions === "function" ? reviewActions(() => setOpen(false)) : reviewActions }),
3589
3459
  isOwner && onGrantAccess && task.pending_auth_request_id && /* @__PURE__ */ jsxs(
3590
3460
  DropdownMenuItem,
@@ -3598,10 +3468,18 @@ function TaskRowMenu({
3598
3468
  ]
3599
3469
  }
3600
3470
  ),
3601
- isChat || !canEdit ? null : done ? /* @__PURE__ */ jsxs(DropdownMenuItem, { disabled: busy, onSelect: onReopen, "data-testid": `task-reopen-${id}`, children: [
3602
- /* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 size-4", "aria-hidden": true }),
3603
- labels.reopen
3604
- ] }) : isPlainTodo(task) && /* @__PURE__ */ jsxs(
3471
+ isChat || !canEdit ? null : done ? canReopen && /* @__PURE__ */ jsxs(
3472
+ DropdownMenuItem,
3473
+ {
3474
+ disabled: busy,
3475
+ onSelect: onReopen,
3476
+ "data-testid": `task-reopen-${id}`,
3477
+ children: [
3478
+ /* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 size-4", "aria-hidden": true }),
3479
+ labels.reopen
3480
+ ]
3481
+ }
3482
+ ) : canMarkDone && /* @__PURE__ */ jsxs(
3605
3483
  DropdownMenuItem,
3606
3484
  {
3607
3485
  disabled: busy,
@@ -3617,6 +3495,7 @@ function TaskRowMenu({
3617
3495
  /* @__PURE__ */ jsx(History, { className: "mr-2 size-4", "aria-hidden": true }),
3618
3496
  labels.activity
3619
3497
  ] }),
3498
+ isOwner && onToggleShared && /* @__PURE__ */ jsx(DropdownMenuItem, { disabled: busy, onSelect: onToggleShared, children: task.is_shared ? "Make private" : "Share with workspace" }),
3620
3499
  canEdit && onAddSubtask && /* @__PURE__ */ jsxs(DropdownMenuItem, { onSelect: onAddSubtask, "data-testid": `task-add-subtask-${id}`, children: [
3621
3500
  /* @__PURE__ */ jsx(ListPlus, { className: "mr-2 size-4", "aria-hidden": true }),
3622
3501
  labels.addSubtask
@@ -3633,7 +3512,7 @@ function TaskRowMenu({
3633
3512
  /* @__PURE__ */ jsx(Pencil, { className: "mr-2 size-4", "aria-hidden": true }),
3634
3513
  isChat ? labels.rename : labels.edit
3635
3514
  ] }),
3636
- canEdit && /* @__PURE__ */ jsxs(Fragment, { children: [
3515
+ canEdit && onDelete && /* @__PURE__ */ jsxs(Fragment, { children: [
3637
3516
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
3638
3517
  /* @__PURE__ */ jsxs(
3639
3518
  DropdownMenuItem,
@@ -3856,6 +3735,144 @@ function applyColumnWidthRules(api, gridWidth, rules) {
3856
3735
  }
3857
3736
  }
3858
3737
 
3738
+ // src/agents/tasks/taskRows.ts
3739
+ var MAX_TASK_DEPTH = 5;
3740
+ var ownerExtId = (task) => task.signoff_ext_id || task.owner_ext_id || task.created_by_ext_id || null;
3741
+ var isPlainTodo = (task) => !task.agent_ext_id && !task.has_agent_action && !task.skill_ref;
3742
+ function indexTasks(tasks) {
3743
+ const byId = new Map(tasks.map((t) => [t.external_id, t]));
3744
+ const kids = /* @__PURE__ */ new Map();
3745
+ const parentOf = /* @__PURE__ */ new Map();
3746
+ for (const task of tasks) {
3747
+ const parent = task.parent_conversation_ext_id;
3748
+ if (parent && parent !== task.external_id && byId.has(parent)) {
3749
+ parentOf.set(task.external_id, parent);
3750
+ const list = kids.get(parent);
3751
+ if (list) list.push(task);
3752
+ else kids.set(parent, [task]);
3753
+ }
3754
+ }
3755
+ return { byId, kids, parentOf };
3756
+ }
3757
+ function descendantIds(tree, id) {
3758
+ const out = [];
3759
+ const seen = /* @__PURE__ */ new Set([id]);
3760
+ const stack = [id];
3761
+ while (stack.length) {
3762
+ for (const child of tree.kids.get(stack.pop()) ?? []) {
3763
+ if (seen.has(child.external_id)) continue;
3764
+ seen.add(child.external_id);
3765
+ out.push(child.external_id);
3766
+ stack.push(child.external_id);
3767
+ }
3768
+ }
3769
+ return out;
3770
+ }
3771
+ function subtreeLevels(tree, id, seen = /* @__PURE__ */ new Set()) {
3772
+ if (seen.has(id)) return 0;
3773
+ const next = new Set(seen).add(id);
3774
+ let deepest = 0;
3775
+ for (const child of tree.kids.get(id) ?? []) {
3776
+ deepest = Math.max(deepest, subtreeLevels(tree, child.external_id, next));
3777
+ }
3778
+ return 1 + deepest;
3779
+ }
3780
+ function levelOf(tree, id) {
3781
+ let level = 1;
3782
+ const seen = /* @__PURE__ */ new Set([id]);
3783
+ for (let at = tree.parentOf.get(id); at && !seen.has(at); at = tree.parentOf.get(at)) {
3784
+ seen.add(at);
3785
+ level += 1;
3786
+ }
3787
+ return level;
3788
+ }
3789
+ function moveTargets(tasks, task) {
3790
+ const tree = indexTasks(tasks);
3791
+ const banned = /* @__PURE__ */ new Set([task.external_id, ...descendantIds(tree, task.external_id)]);
3792
+ const height = subtreeLevels(tree, task.external_id);
3793
+ return tasks.filter(
3794
+ (t) => !banned.has(t.external_id) && levelOf(tree, t.external_id) + height <= MAX_TASK_DEPTH
3795
+ );
3796
+ }
3797
+ var sameStats = (a, b) => a === b || a !== void 0 && b !== void 0 && a.done === b.done && a.total === b.total;
3798
+ function buildTaskRows(tasks, filter, collapsed, compare, options = {}) {
3799
+ const tree = indexTasks(tasks);
3800
+ const { kids, parentOf } = tree;
3801
+ const sorted = (list) => compare ? [...list].sort(compare) : list;
3802
+ const query = options.query?.trim().toLowerCase() ?? "";
3803
+ const titleOf = options.titleOf ?? ((t) => t.title ?? "");
3804
+ let included = null;
3805
+ let matched = null;
3806
+ if (filter !== "all" || query) {
3807
+ matched = /* @__PURE__ */ new Set();
3808
+ included = /* @__PURE__ */ new Set();
3809
+ for (const task of tasks) {
3810
+ const statusOk = filter === "all" || asTaskStatus(task.status) === filter;
3811
+ const textOk = !query || `${titleOf(task)} ${task.description ?? ""}`.toLowerCase().includes(query);
3812
+ if (!statusOk || !textOk) continue;
3813
+ matched.add(task.external_id);
3814
+ for (let at = task.external_id; at && !included.has(at); at = parentOf.get(at)) {
3815
+ included.add(at);
3816
+ }
3817
+ }
3818
+ }
3819
+ const shown = (list) => included ? list.filter((t) => included.has(t.external_id)) : list;
3820
+ const build = (task, depth, seen) => {
3821
+ const nextSeen = new Set(seen).add(task.external_id);
3822
+ return {
3823
+ task,
3824
+ depth,
3825
+ context: matched ? !matched.has(task.external_id) : false,
3826
+ children: sorted(shown(kids.get(task.external_id) ?? [])).filter((child) => !nextSeen.has(child.external_id)).map((child) => build(child, depth + 1, nextSeen))
3827
+ };
3828
+ };
3829
+ const sections = new Map([
3830
+ ...STATUS_ORDER.map((s) => [s, []]),
3831
+ ["sorted", []]
3832
+ ]);
3833
+ const sectionOf = (task) => compare ? "sorted" : asTaskStatus(task.status);
3834
+ const roots = tasks.filter((t) => !parentOf.has(t.external_id));
3835
+ for (const task of sorted(shown(roots))) {
3836
+ sections.get(sectionOf(task))?.push(build(task, 0, /* @__PURE__ */ new Set()));
3837
+ }
3838
+ const cache = options.cache;
3839
+ const used = /* @__PURE__ */ new Set();
3840
+ const rows = [];
3841
+ const walk = (node, parentId, setSize, posInSet) => {
3842
+ const id = node.task.external_id;
3843
+ const expanded = !collapsed.has(id);
3844
+ const all = kids.get(id);
3845
+ const childStats = all ? { done: all.filter((c) => asTaskStatus(c.status) === "done").length, total: all.length } : void 0;
3846
+ let row = {
3847
+ external_id: id,
3848
+ task: node.task,
3849
+ depth: node.depth,
3850
+ childStats,
3851
+ expanded,
3852
+ parentId,
3853
+ setSize,
3854
+ posInSet,
3855
+ context: node.context
3856
+ };
3857
+ const prev = cache?.get(id);
3858
+ if (prev && prev.task === row.task && prev.depth === row.depth && prev.expanded === row.expanded && prev.parentId === row.parentId && prev.setSize === row.setSize && prev.posInSet === row.posInSet && prev.context === row.context && sameStats(prev.childStats, row.childStats)) {
3859
+ row = prev;
3860
+ }
3861
+ used.add(id);
3862
+ cache?.set(id, row);
3863
+ rows.push(row);
3864
+ if (expanded) {
3865
+ node.children.forEach((child, i) => walk(child, id, node.children.length, i + 1));
3866
+ }
3867
+ };
3868
+ const ordered = [...STATUS_ORDER, "sorted"].flatMap((s) => sections.get(s) ?? []);
3869
+ ordered.forEach((node, i) => walk(node, null, ordered.length, i + 1));
3870
+ if (cache) {
3871
+ for (const id of [...cache.keys()]) if (!used.has(id)) cache.delete(id);
3872
+ }
3873
+ return rows;
3874
+ }
3875
+
3859
3876
  // src/agents/tasks/taskTableLabels.ts
3860
3877
  var DEFAULT_TASK_LIST_LABELS = {
3861
3878
  filterAll: "All",
@@ -4584,29 +4601,819 @@ function TaskTable(props) {
4584
4601
  empty: l.moveToEmpty,
4585
4602
  cancel: l.moveToCancel
4586
4603
  },
4587
- testId: "task-owner"
4604
+ testId: "task-owner"
4605
+ }
4606
+ ),
4607
+ moving && props.onMove && /* @__PURE__ */ jsx(
4608
+ TaskMoveDialog,
4609
+ {
4610
+ open: true,
4611
+ onOpenChange: (open) => !open && setMoving(null),
4612
+ options: moveTargets(tasks, moving).map((t) => ({ id: t.external_id, label: nameOf(t) })),
4613
+ currentParentId: moving.parent_conversation_ext_id,
4614
+ onPick: (parentId) => props.onMove?.(moving, parentId),
4615
+ labels: {
4616
+ title: l.moveToTitle(nameOf(moving)),
4617
+ none: l.moveToNone,
4618
+ search: l.moveToSearch,
4619
+ empty: l.moveToEmpty,
4620
+ cancel: l.moveToCancel
4621
+ }
4622
+ }
4623
+ )
4624
+ ]
4625
+ }
4626
+ );
4627
+ }
4628
+ function TaskInbox(p) {
4629
+ const [filterOpen, setFilterOpen] = useState(false);
4630
+ const [statusFilters, setStatusFilters] = useState(
4631
+ () => /* @__PURE__ */ new Map([["done", "exclude"]])
4632
+ );
4633
+ const [localQuery, setLocalQuery] = useState("");
4634
+ const [searchFields, setSearchFields] = useState(["text", "labels"]);
4635
+ const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
4636
+ const [collapsed, setCollapsed] = useState(/* @__PURE__ */ new Set());
4637
+ const [moving, setMoving] = useState(null);
4638
+ const [handingOff, setHandingOff] = useState(null);
4639
+ const l = { ...DEFAULT_TASK_LIST_LABELS, ...p.labels };
4640
+ const nameOf = (t) => t.title?.trim() || t.workflow_ext_id && p.workflowNames?.[t.workflow_ext_id] || l.untitled;
4641
+ const all = p.tasks.filter((t) => t.status != null);
4642
+ const filterText = p.filterText ?? localQuery;
4643
+ const q = filterText.trim().toLowerCase();
4644
+ const included = [...statusFilters].filter(([, state]) => state === "include").map(([id]) => id);
4645
+ const statusMatches = (t) => statusFilters.get(asTaskStatus(t.status)) !== "exclude" && (!included.length || included.includes(asTaskStatus(t.status)));
4646
+ const rows = all.filter(
4647
+ (t) => statusMatches(t) && (!q || [
4648
+ searchFields.includes("text") ? `${nameOf(t)} ${t.description ?? ""}` : "",
4649
+ searchFields.includes("labels") && t.workflow_ext_id ? p.workflowNames?.[t.workflow_ext_id] ?? "" : ""
4650
+ ].join(" ").toLowerCase().includes(q))
4651
+ );
4652
+ const hasActiveFilters = !!q || [...statusFilters.values()].some((state) => state != null);
4653
+ const selectedTasks = all.filter((t) => selected.has(t.external_id));
4654
+ const canEdit = (t) => t.is_owner !== false || Boolean(p.canEditShared);
4655
+ const markable = (t) => t.status !== "done" && t.status !== "generating" && canEdit(t) && !t.in_progress;
4656
+ const markableTasks = selectedTasks.filter(markable);
4657
+ const deletableTasks = selectedTasks.filter((t) => t.is_owner !== false || p.isWorkspaceOwner);
4658
+ const clearSelection = () => setSelected(/* @__PURE__ */ new Set());
4659
+ const toggle = (set, id) => set((old) => {
4660
+ const next = new Set(old);
4661
+ if (next.has(id)) next.delete(id);
4662
+ else next.add(id);
4663
+ return next;
4664
+ });
4665
+ p.renderPerson ?? ((value) => /* @__PURE__ */ jsx(PersonPill, { person: value }));
4666
+ const taskById = new Map(all.map((t) => [t.external_id, t]));
4667
+ const visible = new Set(rows.map((t) => t.external_id));
4668
+ for (const task of rows) {
4669
+ let id = task.parent_conversation_ext_id;
4670
+ const seen = /* @__PURE__ */ new Set();
4671
+ while (id && taskById.has(id) && !seen.has(id)) {
4672
+ seen.add(id);
4673
+ visible.add(id);
4674
+ id = taskById.get(id)?.parent_conversation_ext_id;
4675
+ }
4676
+ }
4677
+ const listed = all.filter((t) => visible.has(t.external_id));
4678
+ const roots = listed.filter(
4679
+ (t) => !t.parent_conversation_ext_id || !visible.has(t.parent_conversation_ext_id)
4680
+ );
4681
+ const workflows = (p.workflows ?? []).filter((w) => {
4682
+ const runs = roots.filter((t) => t.workflow_ext_id === w.external_id);
4683
+ return runs.length > 0 || !included.length && (!q || w.name.toLowerCase().includes(q));
4684
+ });
4685
+ const workflowIds = new Set(workflows.map((w) => w.external_id));
4686
+ const order = (a, b) => {
4687
+ const weight = (t) => t.pending_auth_request_id || t.last_error ? 0 : t.status === "ready_for_review" ? 1 : t.status === "todo" ? 2 : t.status === "generating" ? 3 : 4;
4688
+ return weight(a) - weight(b) || (b.updated_at ?? "").localeCompare(a.updated_at ?? "");
4689
+ };
4690
+ const renderTask = (task, depth = 0) => {
4691
+ const id = task.external_id;
4692
+ const status = asTaskStatus(task.status);
4693
+ const busy = p.busyId === id;
4694
+ const children = listed.filter((t) => t.parent_conversation_ext_id === id).sort(order);
4695
+ const outputs = p.outputsByTask?.[id] ?? [];
4696
+ return /* @__PURE__ */ jsxs("li", { "data-testid": `task-inbox-row-${id}`, children: [
4697
+ /* @__PURE__ */ jsxs(
4698
+ "div",
4699
+ {
4700
+ className: cn(
4701
+ "relative flex cursor-pointer items-start gap-2 border-b py-3 hover:bg-muted/40",
4702
+ selected.has(id) && "bg-muted/60"
4703
+ ),
4704
+ onClick: (event) => {
4705
+ if (!event.target.closest(
4706
+ 'button, a, input, select, textarea, [role="menuitem"], [role="checkbox"], [role="combobox"]'
4707
+ )) {
4708
+ p.onOpenThread(id, task);
4709
+ }
4710
+ },
4711
+ style: { paddingLeft: `${Math.min(depth, 5) * 20}px` },
4712
+ children: [
4713
+ children.length > 0 && /* @__PURE__ */ jsx(
4714
+ Button,
4715
+ {
4716
+ variant: "ghost",
4717
+ size: "icon",
4718
+ className: "size-7 shrink-0",
4719
+ "aria-label": `${collapsed.has(id) ? "Expand" : "Collapse"} ${nameOf(task)}`,
4720
+ onClick: () => toggle(setCollapsed, id),
4721
+ children: collapsed.has(id) ? /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
4722
+ }
4723
+ ),
4724
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
4725
+ /* @__PURE__ */ jsx(
4726
+ "button",
4727
+ {
4728
+ className: cn(
4729
+ "block w-full text-left text-sm font-medium hover:underline",
4730
+ status === "done" && "text-muted-foreground"
4731
+ ),
4732
+ "data-testid": `task-open-${id}`,
4733
+ onClick: () => p.onOpenThread(id, task),
4734
+ children: nameOf(task)
4735
+ }
4736
+ ),
4737
+ /* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground", children: [
4738
+ status !== "todo" && status !== "ready_for_review" && /* @__PURE__ */ jsx(
4739
+ TaskStatusPill,
4740
+ {
4741
+ id,
4742
+ status: task.status,
4743
+ runStartedAt: task.run_started_at,
4744
+ lastError: task.last_error,
4745
+ awaitingAccess: Boolean(task.pending_auth_request_id)
4746
+ }
4747
+ ),
4748
+ task.due_at && /* @__PURE__ */ jsxs("span", { children: [
4749
+ "Due ",
4750
+ p.formatDate(task.due_at)
4751
+ ] }),
4752
+ children.length > 0 && /* @__PURE__ */ jsxs("span", { children: [
4753
+ all.filter((t) => t.parent_conversation_ext_id === id && t.status === "done").length,
4754
+ "/",
4755
+ all.filter((t) => t.parent_conversation_ext_id === id).length,
4756
+ " steps complete"
4757
+ ] })
4758
+ ] }),
4759
+ outputs.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap gap-2", "aria-label": "Outputs", children: outputs.map((output) => /* @__PURE__ */ jsxs(
4760
+ Button,
4761
+ {
4762
+ variant: "link",
4763
+ size: "sm",
4764
+ className: "h-auto max-w-full gap-1 px-0 py-1 text-xs",
4765
+ disabled: !p.onOpenOutput,
4766
+ onClick: () => p.onOpenOutput?.(output.id, task),
4767
+ "data-testid": `task-output-${id}-${output.id}`,
4768
+ children: [
4769
+ /* @__PURE__ */ jsx(FileText, { className: "size-3.5 shrink-0" }),
4770
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: output.name })
4771
+ ]
4772
+ },
4773
+ output.id
4774
+ )) })
4775
+ ] }),
4776
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
4777
+ task.pending_auth_request_id && task.is_owner !== false && p.onGrantAccess && /* @__PURE__ */ jsx(
4778
+ Button,
4779
+ {
4780
+ size: "sm",
4781
+ variant: "outline",
4782
+ disabled: busy,
4783
+ onClick: () => p.onGrantAccess?.(task),
4784
+ children: "Allow access"
4785
+ }
4786
+ ),
4787
+ /* @__PURE__ */ jsx(
4788
+ TaskRowMenu,
4789
+ {
4790
+ task,
4791
+ status,
4792
+ busy,
4793
+ isOwner: task.is_owner !== false,
4794
+ canAdmin: task.is_owner !== false || Boolean(p.isWorkspaceOwner),
4795
+ canEdit: canEdit(task),
4796
+ canMarkDone: markable(task),
4797
+ canReopen: canEdit(task),
4798
+ selected: selected.has(id),
4799
+ onToggleSelected: p.selectionActions || p.onMarkDoneMany || p.onDeleteMany ? () => toggle(setSelected, id) : void 0,
4800
+ labels: l,
4801
+ onMarkDone: () => p.onMarkDone(task),
4802
+ onNotify: p.onNotify ? () => p.onNotify?.(task) : void 0,
4803
+ onReopen: () => p.onReopen(task),
4804
+ onEdit: () => p.onEdit(task),
4805
+ onAddSubtask: p.onAddSubtask ? () => p.onAddSubtask?.(task) : void 0,
4806
+ onMoveTo: p.onMove ? () => setMoving(task) : void 0,
4807
+ onChangeOwner: status !== "ready_for_review" && p.onChangeOwner && p.people?.length ? () => setHandingOff(task) : void 0,
4808
+ onOpenActivity: p.onOpenActivity ? () => p.onOpenActivity?.(task) : void 0,
4809
+ onToggleShared: p.onToggleShared ? () => p.onToggleShared?.(task, !task.is_shared) : void 0
4810
+ }
4811
+ )
4812
+ ] })
4813
+ ]
4814
+ }
4815
+ ),
4816
+ children.length > 0 && !collapsed.has(id) && /* @__PURE__ */ jsx("ul", { children: children.map((child) => renderTask(child, depth + 1)) })
4817
+ ] }, id);
4818
+ };
4819
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", "data-testid": p.testId ?? "task-inbox", children: [
4820
+ /* @__PURE__ */ jsx(
4821
+ TabHeader,
4822
+ {
4823
+ testId: "tasks-tab-header",
4824
+ tabs: [
4825
+ {
4826
+ id: "tasks",
4827
+ label: "",
4828
+ count: rows.length,
4829
+ countPlacement: "leading",
4830
+ countIcon: /* @__PURE__ */ jsx(ListTodo, { className: "size-3.5" }),
4831
+ hasActiveFilters,
4832
+ testId: "tasks-tab",
4833
+ presentation: "count"
4834
+ }
4835
+ ],
4836
+ activeTabId: "tasks",
4837
+ onTabChange: () => {
4838
+ },
4839
+ firstTabContent: /* @__PURE__ */ jsx(
4840
+ FilterInput,
4841
+ {
4842
+ value: filterText,
4843
+ onChange: p.onFilterTextChange ?? setLocalQuery,
4844
+ fields: searchFields,
4845
+ onFieldsChange: setSearchFields,
4846
+ labels: { fieldNames: { text: "Task", labels: "Workflow" } },
4847
+ className: "w-44 max-w-[40vw]",
4848
+ testIds: {
4849
+ root: "tasks-filter",
4850
+ input: "tasks-filter-input",
4851
+ fieldsButton: "tasks-filter-fields"
4852
+ },
4853
+ filter: /* @__PURE__ */ jsx(
4854
+ TriStateFilterMenu,
4855
+ {
4856
+ testId: "tasks-status-filter",
4857
+ open: filterOpen,
4858
+ onOpenChange: setFilterOpen,
4859
+ filterStates: statusFilters,
4860
+ onFiltersChange: setStatusFilters,
4861
+ options: [
4862
+ {
4863
+ id: "todo",
4864
+ label: "To do",
4865
+ count: all.filter((t) => t.status === "todo").length
4866
+ },
4867
+ {
4868
+ id: "generating",
4869
+ label: "Generating",
4870
+ count: all.filter((t) => t.status === "generating").length
4871
+ },
4872
+ {
4873
+ id: "ready_for_review",
4874
+ label: "Ready for review",
4875
+ count: all.filter((t) => t.status === "ready_for_review").length
4876
+ },
4877
+ {
4878
+ id: "done",
4879
+ label: "Completed",
4880
+ count: all.filter((t) => t.status === "done").length
4881
+ }
4882
+ ],
4883
+ groups: [
4884
+ { label: "Status", options: ["todo", "generating", "ready_for_review", "done"] }
4885
+ ],
4886
+ 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",
4887
+ renderChevron: true,
4888
+ disableHoverOpen: true
4889
+ }
4890
+ )
4891
+ }
4892
+ ),
4893
+ rightContent: p.onCreate ? /* @__PURE__ */ jsxs(DropdownMenu, { children: [
4894
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { "data-testid": "new-task-button", children: [
4895
+ /* @__PURE__ */ jsx(Plus, { className: "mr-1 size-4" }),
4896
+ "New",
4897
+ /* @__PURE__ */ jsx(ChevronDown, { className: "ml-1 size-3" })
4898
+ ] }) }),
4899
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
4900
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: p.onCreate, children: "Task" }),
4901
+ p.onCreateWorkflow && /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: p.onCreateWorkflow, children: "Saved workflow" })
4902
+ ] })
4903
+ ] }) : p.header
4904
+ }
4905
+ ),
4906
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto", "aria-busy": p.isLoading, children: p.isLoading ? /* @__PURE__ */ jsx("p", { className: "py-12 text-center text-sm text-muted-foreground", children: "Loading work\u2026" }) : !listed.length && !workflows.length ? /* @__PURE__ */ jsx(
4907
+ EmptyState,
4908
+ {
4909
+ title: q ? "No matches" : all.length ? "You\u2019re all caught up" : "No work here yet",
4910
+ description: "Create a task from a prompt or a saved workflow. Keep its drafts, reviews and handoffs together."
4911
+ }
4912
+ ) : /* @__PURE__ */ jsxs("ul", { children: [
4913
+ workflows.map((w) => {
4914
+ const runs = roots.filter((t) => t.workflow_ext_id === w.external_id).sort(order);
4915
+ const editable = w.is_owner !== false || p.canEditShared;
4916
+ return /* @__PURE__ */ jsxs("li", { "data-testid": `task-workflow-${w.external_id}`, children: [
4917
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 border-b py-3", children: [
4918
+ runs.length > 0 ? /* @__PURE__ */ jsx(
4919
+ Button,
4920
+ {
4921
+ variant: "ghost",
4922
+ size: "icon",
4923
+ className: "size-7",
4924
+ "aria-label": `${collapsed.has(w.external_id) ? "Expand" : "Collapse"} ${w.name}`,
4925
+ onClick: () => toggle(setCollapsed, w.external_id),
4926
+ children: collapsed.has(w.external_id) ? /* @__PURE__ */ jsx(ChevronRight, { className: "size-4" }) : /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
4927
+ }
4928
+ ) : /* @__PURE__ */ jsx(Workflow, { className: "mx-1 mt-1 size-4 shrink-0 text-muted-foreground" }),
4929
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
4930
+ /* @__PURE__ */ jsx(
4931
+ "button",
4932
+ {
4933
+ className: "block text-left text-sm font-medium hover:underline",
4934
+ disabled: !editable,
4935
+ onClick: () => p.onEditWorkflow?.(w.external_id),
4936
+ children: w.name
4937
+ }
4938
+ ),
4939
+ /* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
4940
+ "Saved workflow \xB7 ",
4941
+ w.summary ?? "Run when needed",
4942
+ !w.active ? " \xB7 Paused" : "",
4943
+ runs.length ? ` \xB7 ${runs.length} ${runs.length === 1 ? "task" : "tasks"}` : ""
4944
+ ] }),
4945
+ w.last_error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive", children: w.last_error })
4946
+ ] }),
4947
+ /* @__PURE__ */ jsxs(DropdownMenu, { children: [
4948
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
4949
+ Button,
4950
+ {
4951
+ variant: "ghost",
4952
+ size: "icon",
4953
+ className: "size-8",
4954
+ "aria-label": `Actions for ${w.name}`,
4955
+ children: /* @__PURE__ */ jsx(MoreHorizontal, { className: "size-4" })
4956
+ }
4957
+ ) }),
4958
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", children: [
4959
+ p.onWorkflowHistory && /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => p.onWorkflowHistory?.(w.external_id), children: "Run history" }),
4960
+ editable && p.onToggleWorkflow && /* @__PURE__ */ jsx(
4961
+ DropdownMenuItem,
4962
+ {
4963
+ onSelect: () => p.onToggleWorkflow?.(w.external_id, !w.active),
4964
+ children: w.active ? "Pause" : "Resume"
4965
+ }
4966
+ ),
4967
+ (w.is_owner !== false || p.isWorkspaceOwner) && p.onDeleteWorkflow && /* @__PURE__ */ jsx(DropdownMenuItem, { onSelect: () => p.onDeleteWorkflow?.(w.external_id), children: "Delete workflow" })
4968
+ ] })
4969
+ ] })
4970
+ ] }),
4971
+ !collapsed.has(w.external_id) && runs.length > 0 && /* @__PURE__ */ jsx("ul", { children: runs.map((t) => renderTask(t, 1)) })
4972
+ ] }, w.external_id);
4973
+ }),
4974
+ roots.filter((t) => !t.workflow_ext_id || !workflowIds.has(t.workflow_ext_id)).sort(order).map((t) => renderTask(t))
4975
+ ] }) }),
4976
+ /* @__PURE__ */ jsx(SelectionBar, { count: selectedTasks.length, onClear: clearSelection, children: (isCompact) => /* @__PURE__ */ jsxs(Fragment, { children: [
4977
+ p.selectionActions?.(selectedTasks, isCompact, clearSelection),
4978
+ p.onMarkDoneMany && /* @__PURE__ */ jsx(
4979
+ SelectionBarAction,
4980
+ {
4981
+ icon: CheckCheck,
4982
+ label: l.markDoneMany,
4983
+ isCompact,
4984
+ disabled: !markableTasks.length,
4985
+ onClick: () => {
4986
+ p.onMarkDoneMany?.(markableTasks);
4987
+ clearSelection();
4988
+ },
4989
+ testId: "task-bulk-done"
4990
+ }
4991
+ ),
4992
+ p.onDeleteMany && /* @__PURE__ */ jsx(
4993
+ SelectionBarAction,
4994
+ {
4995
+ icon: Trash2,
4996
+ label: l.deleteMany,
4997
+ isCompact,
4998
+ disabled: !deletableTasks.length,
4999
+ onClick: () => {
5000
+ p.onDeleteMany?.(deletableTasks);
5001
+ clearSelection();
5002
+ },
5003
+ className: "text-red-text hover:bg-red-bg hover:text-red-text",
5004
+ testId: "task-bulk-delete"
5005
+ }
5006
+ )
5007
+ ] }) }),
5008
+ moving && p.onMove && /* @__PURE__ */ jsx(
5009
+ TaskMoveDialog,
5010
+ {
5011
+ open: true,
5012
+ onOpenChange: (open) => !open && setMoving(null),
5013
+ options: moveTargets(all, moving).map((t) => ({ id: t.external_id, label: nameOf(t) })),
5014
+ currentParentId: moving.parent_conversation_ext_id,
5015
+ onPick: (id) => p.onMove?.(moving, id),
5016
+ labels: {
5017
+ title: l.moveToTitle(nameOf(moving)),
5018
+ none: l.moveToNone,
5019
+ search: l.moveToSearch,
5020
+ empty: l.moveToEmpty,
5021
+ cancel: l.moveToCancel
5022
+ }
5023
+ }
5024
+ ),
5025
+ handingOff && p.onChangeOwner && /* @__PURE__ */ jsx(
5026
+ TaskMoveDialog,
5027
+ {
5028
+ open: true,
5029
+ onOpenChange: (open) => !open && setHandingOff(null),
5030
+ options: p.people ?? [],
5031
+ currentParentId: handingOff.signoff_ext_id,
5032
+ onPick: (id) => p.onChangeOwner?.(handingOff, id),
5033
+ labels: {
5034
+ title: l.changeOwnerTitle(nameOf(handingOff)),
5035
+ none: l.changeOwnerMe,
5036
+ search: l.moveToSearch,
5037
+ empty: l.moveToEmpty,
5038
+ cancel: l.moveToCancel
5039
+ },
5040
+ testId: "task-owner"
5041
+ }
5042
+ )
5043
+ ] });
5044
+ }
5045
+ function EntityChip({
5046
+ variant = "pill",
5047
+ icon,
5048
+ label,
5049
+ detail,
5050
+ pillTooltip,
5051
+ showTooltip = true,
5052
+ href,
5053
+ onClick,
5054
+ size = "sm",
5055
+ labelMaxWidth,
5056
+ className,
5057
+ testId
5058
+ }) {
5059
+ if (variant === "icon") {
5060
+ const glyph = /* @__PURE__ */ jsx(
5061
+ "span",
5062
+ {
5063
+ "data-slot": "entity-chip",
5064
+ className: cn("inline-flex items-center", (onClick || href) && "cursor-pointer", className),
5065
+ onClick,
5066
+ "data-testid": testId,
5067
+ children: href ? /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children: icon }) : icon
5068
+ }
5069
+ );
5070
+ if (!showTooltip) return glyph;
5071
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
5072
+ /* @__PURE__ */ jsx(TooltipTrigger, { className: "inline-flex", children: glyph }),
5073
+ /* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5", children: [
5074
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: label }),
5075
+ detail && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: detail })
5076
+ ] }) })
5077
+ ] });
5078
+ }
5079
+ return /* @__PURE__ */ jsx(
5080
+ EntityPill,
5081
+ {
5082
+ icon,
5083
+ label,
5084
+ size,
5085
+ shape: "rounded",
5086
+ href,
5087
+ onClick,
5088
+ tooltipContent: pillTooltip,
5089
+ labelMaxWidth,
5090
+ className,
5091
+ "data-testid": testId
5092
+ }
5093
+ );
5094
+ }
5095
+ function filterConversationRows(conversations, query, labelText, doneFilter = "exclude", visibilityFilters) {
5096
+ const q = query.trim().toLowerCase();
5097
+ return [...conversations].sort(
5098
+ (a, b) => (Date.parse(b.last_message_updated_at || b.updated_at || b.created_at || "") || 0) - (Date.parse(a.last_message_updated_at || a.updated_at || a.created_at || "") || 0)
5099
+ ).filter(
5100
+ (row) => doneFilter === "exclude" ? row.status !== "done" : doneFilter === "include" ? row.status === "done" : true
5101
+ ).filter((row) => {
5102
+ const state = row.is_shared ? visibilityFilters?.workspace : visibilityFilters?.me;
5103
+ const hasIncluded = visibilityFilters?.me === "include" || visibilityFilters?.workspace === "include";
5104
+ return state !== "exclude" && (!hasIncluded || state === "include");
5105
+ }).filter((row) => !q || `${row.title ?? ""} ${labelText?.(row) ?? ""}`.toLowerCase().includes(q));
5106
+ }
5107
+ function ConversationListView(p) {
5108
+ const liveProps = useRef(p);
5109
+ liveProps.current = p;
5110
+ const [query, setQuery] = useState("");
5111
+ const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
5112
+ const q = `${query} ${p.filterText ?? ""}`.trim().toLowerCase();
5113
+ const rows = useMemo(
5114
+ () => filterConversationRows(p.conversations, q, p.labelText, p.doneFilter, p.visibilityFilters),
5115
+ [p.conversations, q, p.labelText, p.doneFilter, p.visibilityFilters]
5116
+ );
5117
+ const selectedRows = p.conversations.filter((c) => selected.has(c.external_id));
5118
+ const columns = useMemo(
5119
+ () => [
5120
+ {
5121
+ colId: "name",
5122
+ headerName: "Thread",
5123
+ flex: 1,
5124
+ minWidth: 180,
5125
+ valueGetter: ({ data }) => data?.title?.trim() || "Untitled thread",
5126
+ cellRenderer: ({ data }) => data && /* @__PURE__ */ jsxs("div", { className: "group flex h-full min-w-0 items-center gap-2", children: [
5127
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children: liveProps.current.renderThread ? liveProps.current.renderThread(data) : /* @__PURE__ */ jsx(
5128
+ EntityChip,
5129
+ {
5130
+ icon: /* @__PURE__ */ jsx(ThreadVisibilityIcon, { shared: data.is_shared ?? false, className: "size-4" }),
5131
+ label: data.title?.trim() || "Untitled thread",
5132
+ pillTooltip: "Open conversation",
5133
+ labelMaxWidth: "max-w-full",
5134
+ onClick: () => liveProps.current.onOpen(data),
5135
+ testId: `thread-open-${data.external_id}`
5136
+ }
5137
+ ) }),
5138
+ (data.is_owner !== false || liveProps.current.canEditShared) && /* @__PURE__ */ jsx(
5139
+ "button",
5140
+ {
5141
+ type: "button",
5142
+ "aria-label": `Rename ${data.title?.trim() || "Untitled thread"}`,
5143
+ onClick: () => liveProps.current.onRename(data),
5144
+ "data-testid": `thread-rename-${data.external_id}`,
5145
+ className: "shrink-0 pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center",
5146
+ children: /* @__PURE__ */ jsx(CellHoverIcon, {})
5147
+ }
5148
+ )
5149
+ ] })
5150
+ },
5151
+ ...liveProps.current.renderLabels ? [
5152
+ {
5153
+ colId: "labels",
5154
+ headerName: "Labels",
5155
+ flex: 0.5,
5156
+ minWidth: 160,
5157
+ valueGetter: ({ data }) => data ? liveProps.current.labelText?.(data) ?? "" : "",
5158
+ cellRenderer: ({ data }) => data && liveProps.current.renderLabels?.(data)
5159
+ }
5160
+ ] : [],
5161
+ ...liveProps.current.renderBy || liveProps.current.renderOwner ? [
5162
+ {
5163
+ colId: liveProps.current.renderBy ? "by" : "owner",
5164
+ headerName: liveProps.current.renderBy ? "By" : "Owner",
5165
+ width: 160,
5166
+ cellRenderer: ({ data }) => data && (liveProps.current.renderBy || liveProps.current.renderOwner)?.(data)
5167
+ }
5168
+ ] : [],
5169
+ {
5170
+ colId: "status",
5171
+ headerName: "Status",
5172
+ width: 150,
5173
+ valueGetter: ({ data }) => data?.status,
5174
+ cellRenderer: ({ data }) => data && (liveProps.current.renderStatus ? liveProps.current.renderStatus(data) : /* @__PURE__ */ jsx(TaskStatusPill, { id: data.external_id, status: data.status }))
5175
+ },
5176
+ {
5177
+ valueGetter: ({ data }) => data?.message_count,
5178
+ colId: "messages",
5179
+ headerName: "Messages",
5180
+ width: 110,
5181
+ valueFormatter: ({ value }) => value == null ? "\u2014" : String(value),
5182
+ cellClass: "text-muted-foreground"
5183
+ },
5184
+ ...liveProps.current.onToggleShared ? [
5185
+ {
5186
+ colId: "visibility",
5187
+ headerName: "Visibility",
5188
+ width: 100,
5189
+ cellClass: "cell-hcenter",
5190
+ sortable: false,
5191
+ resizable: false,
5192
+ cellRenderer: ({ data }) => data && /* @__PURE__ */ jsx(
5193
+ VisibilityToggle,
5194
+ {
5195
+ items: [data],
5196
+ showLabel: false,
5197
+ disabled: data.is_owner === false,
5198
+ onToggle: () => liveProps.current.onToggleShared?.(data, !data.is_shared)
5199
+ }
5200
+ )
5201
+ }
5202
+ ] : [],
5203
+ {
5204
+ colId: "activity",
5205
+ initialSort: "desc",
5206
+ headerName: "Activity",
5207
+ width: 160,
5208
+ valueGetter: ({ data }) => data?.last_message_updated_at || data?.updated_at || data?.created_at || "",
5209
+ valueFormatter: ({ value }) => value ? liveProps.current.formatDate(value) : "\u2014",
5210
+ cellClass: "text-muted-foreground"
5211
+ }
5212
+ ],
5213
+ [
5214
+ Boolean(p.renderThread),
5215
+ Boolean(p.renderLabels),
5216
+ Boolean(p.renderOwner),
5217
+ Boolean(p.renderBy),
5218
+ Boolean(p.renderStatus),
5219
+ Boolean(p.onToggleShared)
5220
+ ]
5221
+ );
5222
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", "data-testid": "conversation-list-view", children: [
5223
+ p.showHeader !== false && /* @__PURE__ */ jsx(
5224
+ TabHeader,
5225
+ {
5226
+ testId: "threads-tab-header",
5227
+ tabs: [
5228
+ {
5229
+ id: "threads",
5230
+ label: "",
5231
+ count: rows.length,
5232
+ countIcon: /* @__PURE__ */ jsx(MessageSquare, { className: "size-3.5" }),
5233
+ countPlacement: "leading",
5234
+ presentation: "count",
5235
+ hasActiveFilters: !!q
5236
+ }
5237
+ ],
5238
+ activeTabId: "threads",
5239
+ onTabChange: () => {
5240
+ },
5241
+ firstTabContent: /* @__PURE__ */ jsx(
5242
+ FilterInput,
5243
+ {
5244
+ value: query,
5245
+ hideFieldPicker: true,
5246
+ ariaLabel: "Search threads",
5247
+ onChange: setQuery,
5248
+ fields: ["text"],
5249
+ onFieldsChange: () => {
5250
+ },
5251
+ labels: {
5252
+ placeholder: "Find a thread\u2026",
5253
+ fieldNames: { text: "Thread" }
5254
+ },
5255
+ className: "w-44 max-w-[40vw]"
5256
+ }
5257
+ ),
5258
+ rightContent: p.header
5259
+ }
5260
+ ),
5261
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
5262
+ GridView,
5263
+ {
5264
+ testId: "threads-grid",
5265
+ items: rows,
5266
+ columnDefs: columns,
5267
+ getItemId: (row) => row.external_id,
5268
+ getRowTestId: (row) => `thread-row-${row.external_id}`,
5269
+ onRowClick: p.onOpen,
5270
+ height: "100%",
5271
+ isLoading: p.isLoading,
5272
+ loadingMessage: "Loading threads\u2026",
5273
+ emptyState: {
5274
+ title: q ? "No threads match" : "No conversations yet",
5275
+ message: "Start a conversation with people, ARBI, or both."
5276
+ },
5277
+ selection: p.selectionActions ? {
5278
+ mode: "multiple",
5279
+ controlled: true,
5280
+ selected: selectedRows,
5281
+ onSelectionChange: (items) => setSelected(new Set(items.map((item) => item.external_id)))
5282
+ } : void 0,
5283
+ gridOptions: {
5284
+ suppressClickEdit: true,
5285
+ onCellKeyDown: (event) => {
5286
+ if (event.event?.key === "Enter" && "column" in event && event.column.getColId() === "name" && event.data)
5287
+ p.onOpen(event.data);
5288
+ }
5289
+ }
5290
+ }
5291
+ ) }),
5292
+ p.selectionActions && /* @__PURE__ */ jsx(SelectionBar, { count: selectedRows.length, onClear: () => setSelected(/* @__PURE__ */ new Set()), children: (compact) => p.selectionActions?.(selectedRows, compact, () => setSelected(/* @__PURE__ */ new Set())) })
5293
+ ] });
5294
+ }
5295
+ function TaskStartDialog({
5296
+ open,
5297
+ onOpenChange,
5298
+ workflows,
5299
+ isPending,
5300
+ error,
5301
+ onStart,
5302
+ onLater
5303
+ }) {
5304
+ const [prompt, setPrompt] = useState("");
5305
+ const [choice, setChoice] = useState("prompt");
5306
+ const [shared, setShared] = useState(false);
5307
+ const todo = choice === "todo";
5308
+ const workflowId = choice === "prompt" || todo ? null : choice;
5309
+ const valid = workflowId ? workflows.some((w) => w.external_id === workflowId) : Boolean(prompt.trim());
5310
+ const values = {
5311
+ prompt: prompt.trim(),
5312
+ workflowId,
5313
+ todo,
5314
+ shared
5315
+ };
5316
+ return /* @__PURE__ */ jsx(Dialog, { modal: false, open, onOpenChange: (next) => !isPending && onOpenChange(next), children: /* @__PURE__ */ jsxs(
5317
+ DialogContent,
5318
+ {
5319
+ presentation: "right",
5320
+ hideCloseButton: true,
5321
+ onInteractOutside: (event) => event.preventDefault(),
5322
+ className: "flex flex-col gap-0 overflow-hidden p-0 shadow-lg",
5323
+ "data-testid": "task-start-dialog",
5324
+ children: [
5325
+ /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: "New task" }),
5326
+ /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: "Describe the task, then start it now or schedule it." }),
5327
+ /* @__PURE__ */ jsx(
5328
+ TabHeader,
5329
+ {
5330
+ tabs: [{ id: "new-task", label: "New task", presentation: "count" }],
5331
+ activeTabId: "new-task",
5332
+ onTabChange: () => {
5333
+ },
5334
+ rightContent: /* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", "aria-label": "Close", disabled: isPending, children: /* @__PURE__ */ jsx(X, { className: "size-4" }) }) })
4588
5335
  }
4589
5336
  ),
4590
- moving && props.onMove && /* @__PURE__ */ jsx(
4591
- TaskMoveDialog,
4592
- {
4593
- open: true,
4594
- onOpenChange: (open) => !open && setMoving(null),
4595
- options: moveTargets(tasks, moving).map((t) => ({ id: t.external_id, label: nameOf(t) })),
4596
- currentParentId: moving.parent_conversation_ext_id,
4597
- onPick: (parentId) => props.onMove?.(moving, parentId),
4598
- labels: {
4599
- title: l.moveToTitle(nameOf(moving)),
4600
- none: l.moveToNone,
4601
- search: l.moveToSearch,
4602
- empty: l.moveToEmpty,
4603
- cancel: l.moveToCancel
5337
+ /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto px-3 py-3", children: [
5338
+ !workflowId ? /* @__PURE__ */ jsxs(Fragment, { children: [
5339
+ /* @__PURE__ */ jsx(Label, { className: "sr-only", htmlFor: "task-start-prompt", children: todo ? "What needs doing?" : "What should ARBI do?" }),
5340
+ /* @__PURE__ */ jsx(
5341
+ Textarea,
5342
+ {
5343
+ id: "task-start-prompt",
5344
+ autoFocus: true,
5345
+ value: prompt,
5346
+ onChange: (event) => setPrompt(event.target.value),
5347
+ disabled: isPending,
5348
+ placeholder: "What needs doing?",
5349
+ className: "min-h-44 resize-y shadow-none"
5350
+ }
5351
+ )
5352
+ ] }) : /* @__PURE__ */ jsx("p", { className: "text-sm", children: workflows.find((workflow) => workflow.external_id === workflowId)?.name }),
5353
+ /* @__PURE__ */ jsxs(Select, { value: choice, onValueChange: setChoice, disabled: isPending, children: [
5354
+ /* @__PURE__ */ jsx(
5355
+ SelectTrigger,
5356
+ {
5357
+ id: "task-start-source",
5358
+ "aria-label": "Who does the work",
5359
+ className: "mt-3 h-7 w-auto max-w-full border-0 bg-transparent px-1 text-xs font-normal text-muted-foreground shadow-none hover:bg-muted",
5360
+ children: /* @__PURE__ */ jsx(SelectValue, {})
5361
+ }
5362
+ ),
5363
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
5364
+ /* @__PURE__ */ jsx(SelectItem, { value: "prompt", children: "With ARBI" }),
5365
+ /* @__PURE__ */ jsx(SelectItem, { value: "todo", children: "People only" }),
5366
+ workflows.map((workflow) => /* @__PURE__ */ jsx(SelectItem, { value: workflow.external_id, children: workflow.name }, workflow.external_id))
5367
+ ] })
5368
+ ] }),
5369
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "mt-3 text-sm text-destructive", children: error })
5370
+ ] }),
5371
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 border-t px-3 py-2", children: [
5372
+ /* @__PURE__ */ jsx(
5373
+ Button,
5374
+ {
5375
+ variant: "ghost",
5376
+ disabled: !valid || isPending,
5377
+ onClick: () => onLater(values),
5378
+ "data-testid": "task-start-later",
5379
+ className: "h-8 px-2 text-sm font-medium",
5380
+ children: "Schedule"
4604
5381
  }
4605
- }
4606
- )
5382
+ ),
5383
+ /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-3", children: [
5384
+ /* @__PURE__ */ jsx(
5385
+ VisibilityToggle,
5386
+ {
5387
+ items: { shared },
5388
+ onToggle: setShared,
5389
+ label: shared ? "Workspace" : "Only Me",
5390
+ disabled: isPending,
5391
+ "data-testid": "task-start-visibility"
5392
+ }
5393
+ ),
5394
+ /* @__PURE__ */ jsx(
5395
+ Button,
5396
+ {
5397
+ disabled: !valid || isPending,
5398
+ "data-testid": "task-start-now",
5399
+ className: "h-8 px-3 text-sm font-medium",
5400
+ onClick: async () => {
5401
+ try {
5402
+ await onStart(values);
5403
+ setPrompt("");
5404
+ setChoice("prompt");
5405
+ setShared(false);
5406
+ } catch {
5407
+ }
5408
+ },
5409
+ children: isPending ? "Starting\u2026" : "Start now"
5410
+ }
5411
+ )
5412
+ ] })
5413
+ ] })
4607
5414
  ]
4608
5415
  }
4609
- );
5416
+ ) });
4610
5417
  }
4611
5418
  var DEFAULT_DUE_DATE_MENU_LABELS = {
4612
5419
  today: "Today",
@@ -4780,6 +5587,25 @@ var hasDocumentInputs = (inputs) => Object.values(inputs).some(
4780
5587
  (v) => v !== null && typeof v === "object" && Array.isArray(v.documents) && (v.documents.length ?? 0) > 0
4781
5588
  );
4782
5589
  function workflowTaskFields(workflow, inputs, name, context) {
5590
+ if (workflow.documentAction) {
5591
+ const scope = inputs.scope && typeof inputs.scope === "object" ? inputs.scope : { labels: []};
5592
+ return {
5593
+ name: name?.trim() || workflow.title,
5594
+ prompt: "",
5595
+ skill_ref: null,
5596
+ skill_inputs: inputs,
5597
+ action: {
5598
+ type: workflow.documentAction,
5599
+ documents: {
5600
+ doc_ext_ids: scope.documents ?? [],
5601
+ label_ext_ids: scope.labels ?? [],
5602
+ latest: inputs.latest === true
5603
+ },
5604
+ tag_ext_ids: typeof inputs.output === "string" && inputs.output ? [inputs.output] : [],
5605
+ overwrite: inputs.overwrite === true
5606
+ }
5607
+ };
5608
+ }
4783
5609
  for (const value of Object.values(inputs)) {
4784
5610
  if (!value || typeof value !== "object") continue;
4785
5611
  const scope = value;
@@ -4892,6 +5718,7 @@ function composerToWorkflowRequest({ workflow, values, plan, documentTitles }, w
4892
5718
  shared: values.shared,
4893
5719
  timezone: values.timezone,
4894
5720
  ...workflowTrigger(values, false),
5721
+ ...fields.action ? { action: fields.action } : {},
4895
5722
  prompt: fields.prompt,
4896
5723
  skill_ref: fields.skill_ref,
4897
5724
  skill_inputs: fields.skill_inputs,
@@ -4904,7 +5731,7 @@ function composerToWorkflowRequest({ workflow, values, plan, documentTitles }, w
4904
5731
  });
4905
5732
  }
4906
5733
  function taskComposerToCreateRequest(ctx, workspaceId, forceWorkflow = false) {
4907
- if (forceWorkflow || !createsWork(ctx.values)) {
5734
+ if (forceWorkflow || ctx.workflow.documentAction || !createsWork(ctx.values)) {
4908
5735
  return { kind: "workflow", body: composerToWorkflowRequest(ctx, workspaceId) };
4909
5736
  }
4910
5737
  return ctx.values.assignee === "me" || !isAgenticWorkflow(ctx.workflow) ? { kind: "work", body: composerToWorkRequest(ctx, workspaceId) } : { kind: "query", query: composerToTaskQuery(ctx, workspaceId) };
@@ -4936,6 +5763,7 @@ function composerToWorkflowUpdate({
4936
5763
  shared: values.shared,
4937
5764
  timezone: values.timezone,
4938
5765
  ...workflowTrigger(values, true),
5766
+ action: fields.action ?? null,
4939
5767
  prompt: fields.prompt,
4940
5768
  skill_ref: fields.skill_ref,
4941
5769
  skill_inputs: fields.skill_inputs,
@@ -4964,10 +5792,11 @@ function taskToComposerValues(task, workflows) {
4964
5792
  };
4965
5793
  }
4966
5794
  function workflowWhen(workflow) {
5795
+ if (workflow.on_demand) return "now";
4967
5796
  if (workflow.after_conversation_ext_id) return "task";
4968
5797
  if (workflow.event_kind) return "event";
4969
5798
  if (workflow.rrule) return "repeat";
4970
- return "once";
5799
+ return workflow.run_at ? "once" : "now";
4971
5800
  }
4972
5801
  function workflowToComposerValues(workflow, workflows) {
4973
5802
  const reminder = !workflow.prompt && !workflow.skill_ref;
@@ -4988,6 +5817,25 @@ function workflowToComposerValues(workflow, workflows) {
4988
5817
  name: workflow.name,
4989
5818
  access: workflow.auth_mode === "scheduled_permanent" ? "standing" : "ask_each_run"
4990
5819
  };
5820
+ if (workflow.action) {
5821
+ const definition = workflows.definitions?.find(
5822
+ (d) => d.documentAction === workflow.action?.type
5823
+ );
5824
+ return {
5825
+ ...base,
5826
+ workflowId: definition?.id ?? workflows.customWorkflowId,
5827
+ inputs: {
5828
+ scope: {
5829
+ folders: [],
5830
+ labels: workflow.action.documents?.label_ext_ids ?? [],
5831
+ documents: workflow.action.documents?.doc_ext_ids ?? []
5832
+ },
5833
+ output: workflow.action.tag_ext_ids?.[0] ?? "",
5834
+ overwrite: workflow.action.overwrite ?? false,
5835
+ latest: workflow.action.documents?.latest ?? false
5836
+ }
5837
+ };
5838
+ }
4991
5839
  if (skill) {
4992
5840
  return {
4993
5841
  ...base,
@@ -5011,7 +5859,7 @@ function workflowToComposerValues(workflow, workflows) {
5011
5859
  var EMPTY_NEW_THREAD = {
5012
5860
  prompt: "",
5013
5861
  title: "",
5014
- shared: true,
5862
+ shared: false,
5015
5863
  ownerId: "",
5016
5864
  dueAt: "",
5017
5865
  parentId: "",
@@ -5104,12 +5952,7 @@ function NewThreadDialog({
5104
5952
  );
5105
5953
  const [values, setValues] = useState(seed);
5106
5954
  const [detailsOpen, setDetailsOpen] = useState(hasTaskFields(seed));
5107
- useEffect(() => {
5108
- if (open) {
5109
- setValues(seed);
5110
- setDetailsOpen(hasTaskFields(seed));
5111
- }
5112
- }, [open, seed]);
5955
+ const [submitError, setSubmitError] = useState(null);
5113
5956
  const id = testIdOr(testId, { testId: "new-thread" });
5114
5957
  const set = (key, value) => setValues((v) => ({ ...v, [key]: value }));
5115
5958
  const canSubmit = values.prompt.trim() !== "" && !isPending;
@@ -5125,11 +5968,12 @@ function NewThreadDialog({
5125
5968
  label: t.name,
5126
5969
  icon: /* @__PURE__ */ jsx(CornerDownRight, { className: GLYPH, "aria-hidden": true })
5127
5970
  }));
5128
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
5971
+ return /* @__PURE__ */ jsx(Dialog, { modal: false, open, onOpenChange, children: /* @__PURE__ */ jsxs(
5129
5972
  DialogContent,
5130
5973
  {
5131
- presentation: "sheet",
5132
- className: "flex max-h-[calc(100dvh-2rem)] flex-col overflow-hidden p-0 sm:max-w-xl",
5974
+ presentation: "right",
5975
+ onInteractOutside: (event) => event.preventDefault(),
5976
+ className: "flex flex-col overflow-hidden p-0",
5133
5977
  "data-testid": id,
5134
5978
  children: [
5135
5979
  /* @__PURE__ */ jsxs(ModalHeader, { children: [
@@ -5140,9 +5984,17 @@ function NewThreadDialog({
5140
5984
  "form",
5141
5985
  {
5142
5986
  className: "flex min-h-0 flex-1 flex-col",
5143
- onSubmit: (event) => {
5987
+ onSubmit: async (event) => {
5144
5988
  event.preventDefault();
5145
- if (canSubmit) onSubmit(values);
5989
+ if (!canSubmit) return;
5990
+ setSubmitError(null);
5991
+ try {
5992
+ await onSubmit(values);
5993
+ setValues(EMPTY_NEW_THREAD);
5994
+ setDetailsOpen(false);
5995
+ } catch (error) {
5996
+ setSubmitError(error instanceof Error ? error.message : "Could not create the thread");
5997
+ }
5146
5998
  },
5147
5999
  children: [
5148
6000
  /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-6 pb-4", children: [
@@ -5184,6 +6036,7 @@ function NewThreadDialog({
5184
6036
  items: { shared: values.shared },
5185
6037
  onToggle: (share) => set("shared", share),
5186
6038
  label: l.visibility,
6039
+ presentation: "select",
5187
6040
  "data-testid": `${id}-visibility`
5188
6041
  }
5189
6042
  ) }),
@@ -5279,6 +6132,7 @@ function NewThreadDialog({
5279
6132
  ] })
5280
6133
  ] })
5281
6134
  ] }),
6135
+ submitError && /* @__PURE__ */ jsx("p", { role: "alert", className: "px-6 pb-2 text-sm text-destructive", children: submitError }),
5282
6136
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col-reverse gap-2 border-t border-border px-6 py-3 sm:flex-row sm:justify-end", children: [
5283
6137
  /* @__PURE__ */ jsx(
5284
6138
  Button,
@@ -5315,18 +6169,18 @@ function NewThreadDialog({
5315
6169
  var DEFAULT_TASK_TRIGGER_CHIP_LABELS = {
5316
6170
  after: (name) => `After \u201C${name}\u201D is done`,
5317
6171
  afterUnknown: "After another task is done",
5318
- onDemand: "On demand"
6172
+ onDemand: "Manual"
5319
6173
  };
5320
6174
  function TriggerIcon({ type, chained }) {
5321
- const cls = "size-3.5 shrink-0";
6175
+ const cls = "size-3.5 shrink-0 text-muted-foreground";
5322
6176
  if (chained) return /* @__PURE__ */ jsx(Link2, { className: cls, "aria-hidden": true });
5323
6177
  switch (type) {
5324
6178
  case "on_demand":
5325
6179
  return /* @__PURE__ */ jsx(MousePointerClick, { className: cls, "aria-hidden": true });
5326
6180
  case "recurring":
5327
- return /* @__PURE__ */ jsx(Repeat, { className: cls, "aria-hidden": true });
6181
+ return /* @__PURE__ */ jsx(Clock, { className: cls, "aria-hidden": true });
5328
6182
  case "event":
5329
- return /* @__PURE__ */ jsx(Zap, { className: cls, "aria-hidden": true });
6183
+ return /* @__PURE__ */ jsx(Bell, { className: cls, "aria-hidden": true });
5330
6184
  default:
5331
6185
  return /* @__PURE__ */ jsx(Clock, { className: cls, "aria-hidden": true });
5332
6186
  }
@@ -5346,7 +6200,7 @@ function TaskTriggerChip({
5346
6200
  return /* @__PURE__ */ jsxs(
5347
6201
  "span",
5348
6202
  {
5349
- className: "inline-flex min-w-0 items-center gap-1.5 text-xs text-muted-foreground",
6203
+ className: "inline-flex min-w-0 max-w-full items-center gap-1.5 text-sm font-normal text-foreground",
5350
6204
  "data-testid": testIdOr(testId, { testId: `task-trigger-${id}` }),
5351
6205
  "data-trigger": chained ? "task" : triggerType,
5352
6206
  children: [
@@ -5372,12 +6226,24 @@ function workflowTriggerType(workflow) {
5372
6226
  if (workflow.run_at) return "one_time";
5373
6227
  return "on_demand";
5374
6228
  }
6229
+ function workflowRunStatusLabel(status) {
6230
+ if (!status) return "None";
6231
+ const labels = {
6232
+ completed: "Success",
6233
+ success: "Success",
6234
+ failed: "Failed",
6235
+ running: "In progress",
6236
+ awaiting_authorization: "Awaiting access"
6237
+ };
6238
+ return labels[status] ?? status.replaceAll("_", " ");
6239
+ }
5375
6240
 
5376
6241
  // src/agents/tasks/workflowColumns.tsx
5377
6242
  var WORKFLOW_COLUMN_ORDER = [
5378
6243
  "name",
5379
6244
  "trigger",
5380
6245
  "last_run",
6246
+ "result",
5381
6247
  "status",
5382
6248
  "shared",
5383
6249
  "actions"
@@ -5390,7 +6256,6 @@ function createWorkflowColumns(o) {
5390
6256
  const l = o.labels;
5391
6257
  const base = {
5392
6258
  sortable: false,
5393
- suppressMovable: true,
5394
6259
  cellStyle: { display: "flex", alignItems: "center" }
5395
6260
  };
5396
6261
  return [
@@ -5400,7 +6265,7 @@ function createWorkflowColumns(o) {
5400
6265
  sortable: true,
5401
6266
  headerName: l.colName,
5402
6267
  flex: 3,
5403
- minWidth: 250,
6268
+ minWidth: 210,
5404
6269
  valueGetter: (p) => p.data?.name.toLowerCase() ?? "",
5405
6270
  cellRenderer: cell2(o.renderName)
5406
6271
  },
@@ -5409,7 +6274,7 @@ function createWorkflowColumns(o) {
5409
6274
  colId: "trigger",
5410
6275
  headerName: l.colTrigger,
5411
6276
  flex: 2.4,
5412
- minWidth: 220,
6277
+ minWidth: 185,
5413
6278
  valueGetter: (p) => p.data ? o.getTriggerText(p.data) : "",
5414
6279
  cellRenderer: cell2(o.renderTrigger)
5415
6280
  },
@@ -5419,16 +6284,26 @@ function createWorkflowColumns(o) {
5419
6284
  sortable: true,
5420
6285
  headerName: l.colLastRun,
5421
6286
  flex: 1.4,
5422
- minWidth: 190,
6287
+ minWidth: 140,
6288
+ cellStyle: { display: "flex", alignItems: "center", padding: 0 },
5423
6289
  valueGetter: (p) => time(p.data?.last_fired_at),
5424
6290
  cellRenderer: cell2(o.renderLastRun)
5425
6291
  },
6292
+ {
6293
+ ...base,
6294
+ colId: "result",
6295
+ headerName: "Result",
6296
+ width: 130,
6297
+ valueGetter: (p) => p.data?.last_run_status ?? "",
6298
+ cellStyle: { display: "flex", alignItems: "center", padding: 0 },
6299
+ cellRenderer: cell2(o.renderResult)
6300
+ },
5426
6301
  {
5427
6302
  ...base,
5428
6303
  colId: "status",
5429
6304
  sortable: true,
5430
6305
  headerName: l.colStatus,
5431
- width: 140,
6306
+ width: 120,
5432
6307
  valueGetter: (p) => p.data ? workflowStatus(p.data) : "",
5433
6308
  cellRenderer: cell2(o.renderStatus)
5434
6309
  },
@@ -5446,10 +6321,8 @@ function createWorkflowColumns(o) {
5446
6321
  ...base,
5447
6322
  colId: "actions",
5448
6323
  headerName: "",
5449
- // Always in view, even if the rest has to scroll.
5450
- pinned: "right",
5451
- lockPinned: true,
5452
- width: 140,
6324
+ width: 180,
6325
+ minWidth: 180,
5453
6326
  cellStyle: { display: "flex", alignItems: "center", justifyContent: "flex-end" },
5454
6327
  cellRenderer: cell2(o.renderActions)
5455
6328
  }
@@ -5463,7 +6336,7 @@ var DEFAULT_WORKFLOW_LIST_LABELS = {
5463
6336
  colTrigger: "When",
5464
6337
  colAction: "What it does",
5465
6338
  colAgent: "Agent",
5466
- colStatus: "Status",
6339
+ colStatus: "Active",
5467
6340
  colShared: "Shared",
5468
6341
  colLastRun: "Last run",
5469
6342
  colNextRun: "Next run",
@@ -5473,7 +6346,7 @@ var DEFAULT_WORKFLOW_LIST_LABELS = {
5473
6346
  typeSkill: "Skill",
5474
6347
  typeWorkflow: "Workflow",
5475
6348
  statusActive: "Active",
5476
- statusPaused: "Paused",
6349
+ statusPaused: "Inactive",
5477
6350
  statusOnDemand: "On demand",
5478
6351
  activeSwitch: (name) => `Active: \u201C${name}\u201D`,
5479
6352
  agent: "Agent",
@@ -5503,17 +6376,18 @@ var DEFAULT_WORKFLOW_LIST_LABELS = {
5503
6376
  filterSkills: "Skills",
5504
6377
  filterWorkflows: "Workflows",
5505
6378
  filterActive: "Active",
5506
- filterPaused: "Paused",
6379
+ filterPaused: "Inactive",
5507
6380
  makeActive: "Make active",
5508
- makePaused: "Pause",
6381
+ makePaused: "Deactivate",
5509
6382
  selectAll: "Select all",
5510
6383
  selectWorkflow: (name) => `Select ${name}`
5511
6384
  };
5512
- var ROW_HEIGHT2 = 56;
6385
+ var ROW_HEIGHT2 = 40;
5513
6386
  function WorkflowsTable(props) {
5514
6387
  const { workflows, isLoading, busyId, header, testId } = props;
5515
6388
  const l = { ...DEFAULT_WORKFLOW_LIST_LABELS, ...props.labels };
5516
- const [filter, setFilter] = useState("all");
6389
+ const [filterStates, setFilterStates] = useState(/* @__PURE__ */ new Map());
6390
+ const [filterOpen, setFilterOpen] = useState(false);
5517
6391
  const [query, setQuery] = useState("");
5518
6392
  const [selected, setSelected] = useState([]);
5519
6393
  const apiRef = useRef(null);
@@ -5529,12 +6403,24 @@ function WorkflowsTable(props) {
5529
6403
  return out;
5530
6404
  }, [workflows, q]);
5531
6405
  const shown = useMemo(
5532
- () => workflows.filter((w) => matches(w) && inFilter(w, filter)),
5533
- // eslint-disable-next-line react-hooks/exhaustive-deps
5534
- [workflows, filter, q]
6406
+ () => workflows.filter((w) => {
6407
+ if (!matches(w)) return false;
6408
+ for (const group of [
6409
+ ["skills", "workflows"],
6410
+ ["active", "paused"]
6411
+ ]) {
6412
+ const included = group.filter((f) => filterStates.get(f) === "include");
6413
+ if (included.length && !included.some((f) => inFilter(w, f))) return false;
6414
+ if (group.some((f) => filterStates.get(f) === "exclude" && inFilter(w, f))) return false;
6415
+ }
6416
+ return true;
6417
+ }),
6418
+ [workflows, filterStates, q]
5535
6419
  );
5536
6420
  const renderPerson = props.renderPerson ?? ((p) => /* @__PURE__ */ jsx(PersonPill, { person: p }));
5537
6421
  const actionText = (w) => {
6422
+ if (w.action)
6423
+ return w.action.type === "email_documents" ? "Email latest documents" : "AI Review";
5538
6424
  if (isSkillRow(w))
5539
6425
  return w.description || w.skill_ref && props.skillNames?.[w.skill_ref] || w.name;
5540
6426
  return w.skill_ref ? props.skillNames?.[w.skill_ref] ?? w.skill_ref : w.prompt?.trim() || l.reminder;
@@ -5557,7 +6443,7 @@ function WorkflowsTable(props) {
5557
6443
  "span",
5558
6444
  {
5559
6445
  className: cn(
5560
- "truncate text-sm font-medium",
6446
+ "truncate text-sm font-normal",
5561
6447
  workflowStatus(w) === "paused" && "text-muted-foreground"
5562
6448
  ),
5563
6449
  "data-testid": `workflow-name-${w.external_id}`,
@@ -5573,7 +6459,7 @@ function WorkflowsTable(props) {
5573
6459
  }
5574
6460
  )
5575
6461
  ] }),
5576
- about && /* @__PURE__ */ jsx(
6462
+ about && !latest.current.props.automationsOnly && /* @__PURE__ */ jsx(
5577
6463
  "p",
5578
6464
  {
5579
6465
  className: "truncate text-xs text-muted-foreground",
@@ -5584,62 +6470,36 @@ function WorkflowsTable(props) {
5584
6470
  ] });
5585
6471
  },
5586
6472
  renderTrigger: (w) => {
5587
- const { props: p, l: lb } = latest.current;
6473
+ const { props: p } = latest.current;
5588
6474
  const after = w.after_conversation_ext_id;
5589
6475
  const skill = isSkillRow(w);
5590
- const next = !skill && w.active && hasTrigger(w) && !w.run_at && w.next_fire_at ? p.formatDate(w.next_fire_at) : "";
5591
- const agentId = w.agent_ext_id;
5592
- const agent = skill ? "" : agentId ? p.agentNames?.[agentId] || lb.agent : lb.myAssistant;
5593
- const detail = [next && `${lb.colNextRun}: ${next}`, agent].filter(Boolean).join(" \xB7 ");
5594
- return /* @__PURE__ */ jsxs("div", { className: "min-w-0 leading-tight", children: [
5595
- /* @__PURE__ */ jsx(
5596
- TaskTriggerChip,
5597
- {
5598
- id: w.external_id,
5599
- testId: `workflow-trigger-${w.external_id}`,
5600
- triggerType: workflowTriggerType(w),
5601
- summary: skill ? "" : p.describeTrigger(w),
5602
- afterTaskId: after,
5603
- afterTaskName: after ? p.taskNames?.[after] : void 0,
5604
- labels: p.triggerChipLabels
5605
- }
5606
- ),
5607
- detail && /* @__PURE__ */ jsx(
5608
- "p",
5609
- {
5610
- className: "truncate text-xs text-muted-foreground",
5611
- "data-testid": `workflow-next-run-${w.external_id}`,
5612
- children: detail
5613
- }
5614
- )
5615
- ] });
6476
+ return /* @__PURE__ */ jsx("div", { className: "min-w-0 leading-tight", children: /* @__PURE__ */ jsx(
6477
+ TaskTriggerChip,
6478
+ {
6479
+ id: w.external_id,
6480
+ testId: `workflow-trigger-${w.external_id}`,
6481
+ triggerType: workflowTriggerType(w),
6482
+ summary: skill ? "" : p.describeTrigger(w),
6483
+ afterTaskId: after,
6484
+ afterTaskName: after ? p.taskNames?.[after] : void 0,
6485
+ labels: p.triggerChipLabels
6486
+ }
6487
+ ) });
5616
6488
  },
5617
6489
  renderStatus: (w) => {
5618
6490
  const { props: p, l: lb } = latest.current;
5619
- const status = workflowStatus(w);
5620
- if (status === "on_demand") return null;
5621
6491
  const canEdit = w.is_owner !== false || Boolean(p.canEditShared);
5622
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-2", children: [
5623
- /* @__PURE__ */ jsx(
5624
- Switch,
5625
- {
5626
- checked: status === "active",
5627
- disabled: !canEdit || p.busyId === w.external_id,
5628
- onCheckedChange: (next) => p.onToggleActive(w, next),
5629
- "aria-label": lb.activeSwitch(w.name),
5630
- "data-testid": `workflow-active-${w.external_id}`
5631
- }
5632
- ),
5633
- /* @__PURE__ */ jsx(
5634
- "span",
5635
- {
5636
- className: "text-sm text-muted-foreground",
5637
- "data-testid": `workflow-status-${w.external_id}`,
5638
- "data-status": status,
5639
- children: status === "active" ? lb.statusActive : lb.statusPaused
5640
- }
5641
- )
5642
- ] });
6492
+ return /* @__PURE__ */ jsx(
6493
+ Switch,
6494
+ {
6495
+ checked: hasTrigger(w) && !isSkillRow(w) && Boolean(w.active),
6496
+ disabled: !hasTrigger(w) || isSkillRow(w) || !canEdit || p.busyId === w.external_id,
6497
+ onCheckedChange: (next) => p.onToggleActive(w, next),
6498
+ className: "disabled:data-[state=unchecked]:bg-muted dark:disabled:data-[state=unchecked]:bg-muted",
6499
+ "aria-label": lb.activeSwitch(w.name),
6500
+ "data-testid": `workflow-active-${w.external_id}`
6501
+ }
6502
+ );
5643
6503
  },
5644
6504
  renderShared: (w) => {
5645
6505
  const { props: p, l: lb } = latest.current;
@@ -5659,41 +6519,37 @@ function WorkflowsTable(props) {
5659
6519
  },
5660
6520
  renderLastRun: (w) => {
5661
6521
  const { props: p, l: lb } = latest.current;
5662
- if (isSkillRow(w)) return /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: lb.none });
5663
- const last = p.lastRuns?.[w.external_id];
5664
- const at = w.last_fired_at ?? last?.at;
5665
- return /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
5666
- last && at ? /* @__PURE__ */ jsx(
5667
- "button",
5668
- {
5669
- type: "button",
5670
- onClick: () => p.onOpenThread?.(last.conversationId),
5671
- title: lb.openLastRun,
5672
- className: "truncate text-sm text-primary hover:underline focus-visible:underline focus-visible:outline-none",
5673
- "data-testid": `workflow-last-run-${w.external_id}`,
5674
- children: p.formatDate(at)
5675
- }
5676
- ) : /* @__PURE__ */ jsx(
5677
- "span",
5678
- {
5679
- className: "truncate text-sm text-muted-foreground",
5680
- "data-testid": `workflow-last-run-${w.external_id}`,
5681
- children: at ? p.formatDate(at) : lb.never
5682
- }
5683
- ),
5684
- w.last_error && /* @__PURE__ */ jsxs(
5685
- "span",
5686
- {
5687
- className: "inline-flex shrink-0 items-center gap-1 text-xs text-red-text",
5688
- title: `${lb.lastRunFailed}: ${w.last_error}`,
5689
- "data-testid": `workflow-error-${w.external_id}`,
5690
- children: [
5691
- /* @__PURE__ */ jsx(AlertCircle, { className: "size-3.5", "aria-hidden": true }),
5692
- lb.failed
5693
- ]
5694
- }
5695
- )
5696
- ] });
6522
+ const at = w.last_fired_at ?? p.lastRuns?.[w.external_id]?.at;
6523
+ return /* @__PURE__ */ jsx(
6524
+ "button",
6525
+ {
6526
+ type: "button",
6527
+ className: "h-full w-full truncate px-4 text-left text-sm hover:text-primary",
6528
+ onClick: () => p.onViewRuns?.(w),
6529
+ title: "View run history",
6530
+ "data-testid": `workflow-last-run-${w.external_id}`,
6531
+ children: at ? p.formatDate(at) : lb.never
6532
+ }
6533
+ );
6534
+ },
6535
+ renderResult: (w) => {
6536
+ const status = w.last_run_status;
6537
+ const label = workflowRunStatusLabel(status);
6538
+ return /* @__PURE__ */ jsx(
6539
+ "button",
6540
+ {
6541
+ type: "button",
6542
+ onClick: () => latest.current.props.onViewRuns?.(w),
6543
+ title: "View run history",
6544
+ className: cn(
6545
+ badgeVariants({ variant: "outline" }),
6546
+ "mx-4 cursor-pointer text-xs font-medium",
6547
+ 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"
6548
+ ),
6549
+ "data-testid": `workflow-result-${w.external_id}`,
6550
+ children: label
6551
+ }
6552
+ );
5697
6553
  },
5698
6554
  renderActions: (w) => {
5699
6555
  const { props: p, l: lb } = latest.current;
@@ -5821,61 +6677,73 @@ function WorkflowsTable(props) {
5821
6677
  (w) => hasTrigger(w) && (w.is_owner !== false || props.canEditShared)
5822
6678
  );
5823
6679
  const clearSelection = () => setSelected([]);
5824
- const hasSavedWorkflow = workflows.some((w) => !isSkillRow(w));
5825
6680
  return /* @__PURE__ */ jsxs(
5826
6681
  "div",
5827
6682
  {
5828
- className: "flex min-h-0 flex-1 flex-col gap-3",
6683
+ className: "flex min-h-0 flex-1 flex-col",
5829
6684
  "data-testid": testIdOr(testId, { testId: "workflow-list" }),
5830
6685
  children: [
5831
- header,
5832
- !isLoading && !hasSavedWorkflow && workflows.length > 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", "data-testid": "workflow-first-run", children: l.firstRun }),
5833
- /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
5834
- /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Filter workflows", className: "flex flex-wrap gap-1.5", children: [
5835
- ["all", l.filterAll],
5836
- ["skills", l.filterSkills],
5837
- ["workflows", l.filterWorkflows],
5838
- ["active", l.filterActive],
5839
- ["paused", l.filterPaused]
5840
- ].map(([key, label]) => {
5841
- const isSelected = filter === key;
5842
- return /* @__PURE__ */ jsxs(
5843
- "button",
6686
+ /* @__PURE__ */ jsx(
6687
+ TabHeader,
6688
+ {
6689
+ testId: "automations-tab-header",
6690
+ tabs: [
5844
6691
  {
5845
- type: "button",
5846
- role: "tab",
5847
- "aria-selected": isSelected,
5848
- onClick: () => setFilter(key),
5849
- className: cn(
5850
- "inline-flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
5851
- isSelected ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground hover:bg-accent"
5852
- ),
5853
- "data-testid": `workflow-filter-${key}`,
5854
- children: [
5855
- label,
5856
- /* @__PURE__ */ jsx("span", { className: "tabular-nums opacity-70", children: counts[key] })
5857
- ]
6692
+ id: "automations",
6693
+ label: "",
6694
+ count: shown.length,
6695
+ countIcon: /* @__PURE__ */ jsx(Workflow, { className: "size-3.5" }),
6696
+ countPlacement: "leading",
6697
+ presentation: "count",
6698
+ hasActiveFilters: !!q || [...filterStates.values()].some(Boolean)
5858
6699
  },
5859
- key
5860
- );
5861
- }) }),
5862
- /* @__PURE__ */ jsxs("div", { className: "relative", children: [
5863
- /* @__PURE__ */ jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }),
5864
- /* @__PURE__ */ jsx(
5865
- Input,
6700
+ ...props.tabs ?? []
6701
+ ],
6702
+ activeTabId: props.activeTabId ?? "automations",
6703
+ onTabChange: props.onTabChange ?? (() => {
6704
+ }),
6705
+ firstTabContent: /* @__PURE__ */ jsx(
6706
+ FilterInput,
5866
6707
  {
5867
- type: "search",
5868
6708
  value: query,
5869
- onChange: (e) => setQuery(e.target.value),
5870
- placeholder: l.searchPlaceholder,
5871
- "aria-label": l.searchLabel,
5872
- className: "h-8 w-56 pl-8 text-xs pointer-coarse:h-11",
5873
- "data-testid": "workflow-search"
6709
+ onChange: setQuery,
6710
+ fields: ["text"],
6711
+ onFieldsChange: () => {
6712
+ },
6713
+ hideFieldPicker: true,
6714
+ ariaLabel: l.searchLabel,
6715
+ testIds: { input: "workflow-search" },
6716
+ filter: /* @__PURE__ */ jsx(
6717
+ TriStateFilterMenu,
6718
+ {
6719
+ testId: "automations-filter-button",
6720
+ open: filterOpen,
6721
+ onOpenChange: setFilterOpen,
6722
+ filterStates,
6723
+ onFiltersChange: setFilterStates,
6724
+ 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",
6725
+ renderChevron: true,
6726
+ disableHoverOpen: true,
6727
+ options: [
6728
+ ...!props.automationsOnly ? [
6729
+ { id: "skills", label: l.filterSkills, count: counts.skills },
6730
+ {
6731
+ id: "workflows",
6732
+ label: l.filterWorkflows,
6733
+ count: counts.workflows
6734
+ }
6735
+ ] : [],
6736
+ { id: "active", label: l.filterActive, count: counts.active },
6737
+ { id: "paused", label: l.filterPaused, count: counts.paused }
6738
+ ]
6739
+ }
6740
+ )
5874
6741
  }
5875
- )
5876
- ] })
5877
- ] }),
5878
- workflows.length === 0 && !isLoading ? /* @__PURE__ */ jsx(
6742
+ ),
6743
+ rightContent: header
6744
+ }
6745
+ ),
6746
+ props.content ? props.content : workflows.length === 0 && !isLoading ? /* @__PURE__ */ jsx(
5879
6747
  EmptyState,
5880
6748
  {
5881
6749
  icon: Workflow,
@@ -5905,7 +6773,7 @@ function WorkflowsTable(props) {
5905
6773
  gridOptions: GRID_OPTIONS
5906
6774
  }
5907
6775
  ) }),
5908
- /* @__PURE__ */ jsx(SelectionBar, { count: selected.length, onClear: clearSelection, children: (isCompact) => /* @__PURE__ */ jsxs(Fragment, { children: [
6776
+ !props.content && /* @__PURE__ */ jsx(SelectionBar, { count: selected.length, onClear: clearSelection, children: (isCompact) => /* @__PURE__ */ jsxs(Fragment, { children: [
5909
6777
  props.onToggleActiveMany && /* @__PURE__ */ jsxs(Fragment, { children: [
5910
6778
  /* @__PURE__ */ jsx(
5911
6779
  SelectionBarAction,
@@ -5956,16 +6824,7 @@ function WorkflowsTable(props) {
5956
6824
  }
5957
6825
  );
5958
6826
  }
5959
- var WIDTH_RULES2 = [
5960
- { colId: "shared", minWidth: 1060 },
5961
- { colId: "last_run", minWidth: 880 }
5962
- ];
5963
- var GRID_OPTIONS = {
5964
- suppressClickEdit: true,
5965
- suppressCellFocus: true,
5966
- suppressColumnVirtualisation: true,
5967
- onGridSizeChanged: (event) => applyColumnWidthRules(event.api, event.clientWidth, WIDTH_RULES2)
5968
- };
6827
+ var GRID_OPTIONS = { suppressClickEdit: true };
5969
6828
  var DEFAULT_TASK_ACTIVITY_LABELS = {
5970
6829
  title: "Activity",
5971
6830
  empty: "Nothing has happened yet.",
@@ -5995,11 +6854,19 @@ var ICONS = {
5995
6854
  awaiting_access: /* @__PURE__ */ jsx(Lock, { className: "size-3.5", "aria-hidden": true }),
5996
6855
  access_granted: /* @__PURE__ */ jsx(KeyRound, { className: "size-3.5", "aria-hidden": true }),
5997
6856
  ready_for_review: /* @__PURE__ */ jsx(CircleDot, { className: "size-3.5", "aria-hidden": true }),
6857
+ reviewed: /* @__PURE__ */ jsx(CheckCircle2, { className: "size-3.5", "aria-hidden": true }),
5998
6858
  handed_off: /* @__PURE__ */ jsx(UserRoundCog, { className: "size-3.5", "aria-hidden": true }),
5999
6859
  changes_requested: /* @__PURE__ */ jsx(MessageSquareReply, { className: "size-3.5", "aria-hidden": true }),
6000
6860
  done: /* @__PURE__ */ jsx(CheckCircle2, { className: "size-3.5", "aria-hidden": true }),
6001
6861
  reopened: /* @__PURE__ */ jsx(RotateCcw, { className: "size-3.5", "aria-hidden": true }),
6002
- failed: /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5", "aria-hidden": true })
6862
+ failed: /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5", "aria-hidden": true }),
6863
+ participant_joined: /* @__PURE__ */ jsx(UserRoundCog, { className: "size-3.5", "aria-hidden": true }),
6864
+ assistant_responded: /* @__PURE__ */ jsx(Sparkles, { className: "size-3.5", "aria-hidden": true }),
6865
+ artifact_created: /* @__PURE__ */ jsx(Sparkles, { className: "size-3.5", "aria-hidden": true }),
6866
+ artifact_edited: /* @__PURE__ */ jsx(MessageSquareReply, { className: "size-3.5", "aria-hidden": true }),
6867
+ document_added: /* @__PURE__ */ jsx(Sparkles, { className: "size-3.5", "aria-hidden": true }),
6868
+ document_removed: /* @__PURE__ */ jsx(AlertTriangle, { className: "size-3.5", "aria-hidden": true }),
6869
+ notified: /* @__PURE__ */ jsx(UserRoundCog, { className: "size-3.5", "aria-hidden": true })
6003
6870
  };
6004
6871
  var asString = (v) => typeof v === "string" && v.trim() ? v : null;
6005
6872
  function summarizeError(error) {
@@ -6023,6 +6890,20 @@ function TaskActivityTimeline({
6023
6890
  const agentId = asString(detail.agent_ext_id);
6024
6891
  const agent = agentId ? agentName?.(agentId) : void 0;
6025
6892
  switch (e.kind) {
6893
+ case "participant_joined":
6894
+ return { headline: "Joined the conversation" };
6895
+ case "assistant_responded":
6896
+ return { headline: "Responded" };
6897
+ case "artifact_created":
6898
+ return { headline: "Created a document" };
6899
+ case "artifact_edited":
6900
+ return { headline: "Edited a document" };
6901
+ case "document_added":
6902
+ return { headline: "Added a document" };
6903
+ case "document_removed":
6904
+ return { headline: "Removed a document" };
6905
+ case "notified":
6906
+ return { headline: "Sent a notification" };
6026
6907
  case "created":
6027
6908
  return { headline: detail.from_workflow ? l.createdFromWorkflow : l.created };
6028
6909
  case "run_started":
@@ -6033,6 +6914,8 @@ function TaskActivityTimeline({
6033
6914
  return { headline: l.accessGranted };
6034
6915
  case "ready_for_review":
6035
6916
  return { headline: l.readyForReview };
6917
+ case "reviewed":
6918
+ return { headline: "Approved this review stage" };
6036
6919
  case "handed_off":
6037
6920
  return {
6038
6921
  headline: l.handedOff,
@@ -6044,7 +6927,7 @@ function TaskActivityTimeline({
6044
6927
  extra: note ? /* @__PURE__ */ jsx(Quote, { text: l.sentBackNote(note) }) : void 0
6045
6928
  };
6046
6929
  case "done":
6047
- return { headline: l.done };
6930
+ return { headline: l.done, extra: note ? /* @__PURE__ */ jsx(Quote, { text: note }) : void 0 };
6048
6931
  case "reopened":
6049
6932
  return { headline: l.reopened };
6050
6933
  case "failed": {
@@ -6112,39 +6995,189 @@ function TaskActivityTimeline({
6112
6995
  );
6113
6996
  }) });
6114
6997
  }
6115
- function Quote({ text }) {
6116
- return /* @__PURE__ */ jsx("blockquote", { className: "border-l-2 pl-2 text-xs text-muted-foreground whitespace-pre-wrap", children: text });
6998
+ function Quote({ text }) {
6999
+ return /* @__PURE__ */ jsx("blockquote", { className: "border-l-2 pl-2 text-xs text-muted-foreground whitespace-pre-wrap", children: text });
7000
+ }
7001
+ function TaskActivityDialog({
7002
+ open,
7003
+ onOpenChange,
7004
+ taskName,
7005
+ events,
7006
+ isLoading,
7007
+ isError,
7008
+ labels,
7009
+ testId,
7010
+ ...timeline
7011
+ }) {
7012
+ const l = { ...DEFAULT_TASK_ACTIVITY_LABELS, ...labels };
7013
+ const id = testIdOr(testId, { testId: "task-activity" });
7014
+ const count = events?.length ?? 0;
7015
+ const scrollToEnd = useCallback(
7016
+ (el) => {
7017
+ if (count >= 0) el?.scrollIntoView?.({ block: "end" });
7018
+ },
7019
+ [count]
7020
+ );
7021
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { presentation: "sheet", className: "max-h-[80dvh] sm:max-w-lg", "data-testid": id, children: [
7022
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
7023
+ /* @__PURE__ */ jsx(DialogTitle, { children: l.title }),
7024
+ /* @__PURE__ */ jsx(DialogDescription, { className: "truncate", children: taskName })
7025
+ ] }),
7026
+ /* @__PURE__ */ jsxs("div", { className: "max-h-[55dvh] overflow-y-auto pr-1", "data-testid": `${id}-scroll`, children: [
7027
+ isLoading && !events ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.loading }) : isError && !events ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: l.error }) : count === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.empty }) : /* @__PURE__ */ jsx(TaskActivityTimeline, { events: events ?? [], labels, testId: id, ...timeline }),
7028
+ /* @__PURE__ */ jsx("div", { ref: scrollToEnd })
7029
+ ] })
7030
+ ] }) });
7031
+ }
7032
+ function TaskFlow({
7033
+ items,
7034
+ className
7035
+ }) {
7036
+ const scroll = useRef(null);
7037
+ const following = useRef(true);
7038
+ const latest = items.at(-1)?.id;
7039
+ useLayoutEffect(() => {
7040
+ const el = scroll.current;
7041
+ if (!el) return;
7042
+ const follow = () => {
7043
+ if (following.current) el.scrollLeft = el.scrollWidth;
7044
+ };
7045
+ follow();
7046
+ const resize = new ResizeObserver(follow);
7047
+ resize.observe(el);
7048
+ return () => resize.disconnect();
7049
+ }, [latest]);
7050
+ return /* @__PURE__ */ jsx(
7051
+ "div",
7052
+ {
7053
+ ref: scroll,
7054
+ className: cn("min-w-0 flex-1 overflow-x-auto overscroll-x-contain", className),
7055
+ "data-testid": "thread-flow",
7056
+ role: "region",
7057
+ "aria-label": "Thread activity",
7058
+ tabIndex: 0,
7059
+ onScroll: (e) => {
7060
+ const el = e.currentTarget;
7061
+ following.current = el.scrollWidth - el.scrollLeft - el.clientWidth < 24;
7062
+ },
7063
+ children: /* @__PURE__ */ jsx("ol", { className: "flex w-max min-w-full items-center gap-1", children: items.map((item, i) => {
7064
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
7065
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: item.avatar }),
7066
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 text-left", children: [
7067
+ /* @__PURE__ */ jsx("span", { className: "block max-w-32 truncate text-[11px] leading-tight font-medium", children: item.label }),
7068
+ /* @__PURE__ */ jsx(
7069
+ "span",
7070
+ {
7071
+ className: "block text-[10px] leading-tight text-muted-foreground",
7072
+ title: item.exactTime,
7073
+ children: item.time
7074
+ }
7075
+ )
7076
+ ] })
7077
+ ] });
7078
+ const cls = cn(
7079
+ "flex shrink-0 items-center gap-1.5 rounded-md px-1 py-0.5",
7080
+ item.current && "bg-accent text-accent-foreground"
7081
+ );
7082
+ return /* @__PURE__ */ jsxs(
7083
+ "li",
7084
+ {
7085
+ className: "flex shrink-0 items-center gap-1",
7086
+ "data-testid": `thread-flow-${item.id}`,
7087
+ children: [
7088
+ i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3 shrink-0 text-muted-foreground", "aria-hidden": true }),
7089
+ item.onSelect ? /* @__PURE__ */ jsx(
7090
+ "button",
7091
+ {
7092
+ className: cn(cls, "hover:bg-muted"),
7093
+ onClick: item.onSelect,
7094
+ title: item.description ?? item.label,
7095
+ children: content
7096
+ }
7097
+ ) : item.detail ? /* @__PURE__ */ jsxs(Popover, { children: [
7098
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
7099
+ "button",
7100
+ {
7101
+ className: cn(cls, "hover:bg-muted"),
7102
+ title: item.description ?? item.label,
7103
+ children: content
7104
+ }
7105
+ ) }),
7106
+ /* @__PURE__ */ jsx(PopoverContent, { className: "max-h-72 overflow-y-auto text-sm whitespace-pre-wrap", children: item.detail })
7107
+ ] }) : /* @__PURE__ */ jsx("div", { className: cls, title: item.description ?? item.label, children: content })
7108
+ ]
7109
+ },
7110
+ item.id
7111
+ );
7112
+ }) })
7113
+ }
7114
+ );
7115
+ }
7116
+ function ThreadActivity({ item, children }) {
7117
+ return /* @__PURE__ */ jsx("div", { className: "flex justify-center px-3 py-2", "data-testid": `thread-activity-${item.id}`, children: /* @__PURE__ */ jsxs(
7118
+ "div",
7119
+ {
7120
+ className: "max-w-full text-center text-xs text-muted-foreground",
7121
+ title: item.description,
7122
+ children: [
7123
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-1.5", children: [
7124
+ item.avatar,
7125
+ /* @__PURE__ */ jsx("span", { children: item.label }),
7126
+ /* @__PURE__ */ jsx("time", { title: item.exactTime, children: item.time })
7127
+ ] }),
7128
+ children,
7129
+ item.detail && /* @__PURE__ */ jsx("div", { className: "mt-1 whitespace-pre-wrap break-words text-left", children: item.detail })
7130
+ ]
7131
+ }
7132
+ ) });
6117
7133
  }
6118
- function TaskActivityDialog({
6119
- open,
6120
- onOpenChange,
6121
- taskName,
6122
- events,
6123
- isLoading,
6124
- isError,
6125
- labels,
6126
- testId,
6127
- ...timeline
6128
- }) {
6129
- const l = { ...DEFAULT_TASK_ACTIVITY_LABELS, ...labels };
6130
- const id = testIdOr(testId, { testId: "task-activity" });
6131
- const count = events?.length ?? 0;
6132
- const scrollToEnd = useCallback(
6133
- (el) => {
6134
- if (count >= 0) el?.scrollIntoView?.({ block: "end" });
6135
- },
6136
- [count]
6137
- );
6138
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { presentation: "sheet", className: "max-h-[80dvh] sm:max-w-lg", "data-testid": id, children: [
6139
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
6140
- /* @__PURE__ */ jsx(DialogTitle, { children: l.title }),
6141
- /* @__PURE__ */ jsx(DialogDescription, { className: "truncate", children: taskName })
6142
- ] }),
6143
- /* @__PURE__ */ jsxs("div", { className: "max-h-[55dvh] overflow-y-auto pr-1", "data-testid": `${id}-scroll`, children: [
6144
- isLoading && !events ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.loading }) : isError && !events ? /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: l.error }) : count === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.empty }) : /* @__PURE__ */ jsx(TaskActivityTimeline, { events: events ?? [], labels, testId: id, ...timeline }),
6145
- /* @__PURE__ */ jsx("div", { ref: scrollToEnd })
6146
- ] })
6147
- ] }) });
7134
+
7135
+ // src/agents/tasks/compact-thread-activity.ts
7136
+ function compactThreadActivity(events) {
7137
+ const result = [];
7138
+ const batches = /* @__PURE__ */ new Map();
7139
+ for (const event of events) {
7140
+ if (event.kind === "notified") {
7141
+ if (["conversation_ready_for_review", "conversation_done"].includes(
7142
+ String(event.detail?.notification_type)
7143
+ ))
7144
+ continue;
7145
+ const source = event.detail?.batch_ext_id ?? event.detail?.message_ext_id;
7146
+ const key = typeof source === "string" && source ? `${event.actor_ext_id}:${source}` : event.external_id;
7147
+ let entry = batches.get(key);
7148
+ if (!entry) {
7149
+ entry = { event, label: "Notified 1 user", recipients: [] };
7150
+ batches.set(key, entry);
7151
+ result.push(entry);
7152
+ }
7153
+ if (event.to_ext_id && !entry.recipients.includes(event.to_ext_id))
7154
+ entry.recipients.push(event.to_ext_id);
7155
+ const count = Math.max(1, entry.recipients.length);
7156
+ entry.label = `Notified ${count} ${count === 1 ? "user" : "users"}`;
7157
+ } else if (["artifact_created", "artifact_edited", "document_added", "document_removed"].includes(
7158
+ event.kind
7159
+ )) {
7160
+ const labels = {
7161
+ artifact_created: "Generated",
7162
+ artifact_edited: "Edited document",
7163
+ document_added: "Added document",
7164
+ document_removed: "Removed document"
7165
+ };
7166
+ result.push({ event, label: labels[event.kind], recipients: [] });
7167
+ } else if (["created", "participant_joined", "assistant_responded", "done"].includes(event.kind)) {
7168
+ result.push({
7169
+ event,
7170
+ label: {
7171
+ created: "Started Task",
7172
+ participant_joined: "Followed Up",
7173
+ assistant_responded: "Answered",
7174
+ done: "Marked Done"
7175
+ }[event.kind],
7176
+ recipients: []
7177
+ });
7178
+ }
7179
+ }
7180
+ return result;
6148
7181
  }
6149
7182
  var DEFAULT_TASK_THREAD_CHIP_LABELS = {
6150
7183
  open: "Open thread",
@@ -6206,105 +7239,127 @@ var DEFAULT_TASK_RUNS_DIALOG_LABELS = {
6206
7239
  var STATUS_STYLE = {
6207
7240
  running: "bg-ai-soft text-ai-ink",
6208
7241
  success: "bg-green-bg text-green-text",
7242
+ completed: "bg-green-bg text-green-text",
6209
7243
  failed: "bg-red-bg text-red-text"
6210
7244
  };
6211
7245
  function TaskRunsDialog({
7246
+ inline = false,
7247
+ renderErrorReport,
7248
+ hideHeader = false,
6212
7249
  open,
6213
7250
  onOpenChange,
6214
7251
  taskName,
6215
- error,
6216
7252
  runs,
6217
7253
  isLoading,
6218
7254
  onOpenRun,
7255
+ onOpenResult,
6219
7256
  getRunHref,
6220
7257
  testIds,
6221
7258
  labels
6222
7259
  }) {
6223
7260
  const l = { ...DEFAULT_TASK_RUNS_DIALOG_LABELS, ...labels };
6224
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
6225
- DialogContent,
6226
- {
6227
- presentation: "sheet",
6228
- className: "max-h-[calc(100dvh-2rem)] max-w-lg overflow-y-auto",
6229
- "data-testid": testIdOr(testIds?.modal, { testId: "task-runs-modal" }),
6230
- children: [
6231
- /* @__PURE__ */ jsxs(DialogHeader, { children: [
6232
- /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
6233
- /* @__PURE__ */ jsx(History, { size: 16 }),
6234
- " ",
6235
- l.title(taskName)
6236
- ] }),
6237
- /* @__PURE__ */ jsx(DialogDescription, { children: l.description })
6238
- ] }),
6239
- error && /* @__PURE__ */ jsx("p", { role: "alert", className: "rounded-md bg-red-bg p-3 text-sm text-red-text", children: error }),
6240
- isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 py-8 text-muted-foreground", children: [
6241
- /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
6242
- " ",
6243
- l.loading
6244
- ] }) : runs.length === 0 ? /* @__PURE__ */ jsx(
6245
- "p",
7261
+ const columns = useMemo(
7262
+ () => [
7263
+ {
7264
+ colId: "status",
7265
+ field: "status",
7266
+ headerName: "Status",
7267
+ width: 160,
7268
+ minWidth: 140,
7269
+ cellRenderer: ({ data }) => data && /* @__PURE__ */ jsx(
7270
+ "span",
6246
7271
  {
6247
- className: "py-8 text-center text-sm text-muted-foreground",
6248
- "data-testid": testIdOr(testIds?.empty, { testId: "task-runs-empty" }),
6249
- children: l.empty
7272
+ className: cn(
7273
+ "rounded-full px-2 py-0.5 text-xs font-medium capitalize",
7274
+ STATUS_STYLE[data.status] ?? "text-muted-foreground"
7275
+ ),
7276
+ children: workflowRunStatusLabel(data.status)
6250
7277
  }
6251
- ) : /* @__PURE__ */ jsx(
6252
- "ul",
6253
- {
6254
- className: "space-y-2",
6255
- "data-testid": testIdOr(testIds?.list, { testId: "task-runs-list" }),
6256
- children: runs.map((run) => /* @__PURE__ */ jsxs(
6257
- "li",
7278
+ )
7279
+ },
7280
+ { colId: "when", field: "when", headerName: "Run", flex: 2, minWidth: 240 },
7281
+ {
7282
+ colId: "result",
7283
+ headerName: "",
7284
+ width: 280,
7285
+ minWidth: 220,
7286
+ sortable: false,
7287
+ cellRenderer: ({ data: run }) => {
7288
+ if (!run) return null;
7289
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full items-center gap-2", children: [
7290
+ run.error && renderErrorReport?.(run),
7291
+ (run.conversationId || run.resultId && onOpenResult) && /* @__PURE__ */ jsx(Button, { asChild: true, variant: "ghost", size: "sm", className: "h-7 gap-1.5", children: /* @__PURE__ */ jsxs(
7292
+ ActionLink,
6258
7293
  {
6259
- className: "flex items-center gap-3 rounded-lg bg-muted p-3",
6260
- "data-testid": testIdOr(testIds?.row, { testId: "task-run-row" }),
7294
+ href: getRunHref?.(run),
7295
+ onSelect: () => {
7296
+ if (run.conversationId) onOpenRun(run.conversationId);
7297
+ else if (run.resultId) onOpenResult?.(run.resultId);
7298
+ onOpenChange(false);
7299
+ },
7300
+ "data-testid": testIdOr(testIds?.open, { testId: "task-run-open" }),
6261
7301
  children: [
6262
- /* @__PURE__ */ jsx(
6263
- "span",
6264
- {
6265
- className: cn(
6266
- "shrink-0 rounded-full px-2 py-0.5 text-xs font-medium capitalize",
6267
- STATUS_STYLE[run.status] ?? "bg-background text-muted-foreground"
6268
- ),
6269
- children: run.status
6270
- }
6271
- ),
6272
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
6273
- /* @__PURE__ */ jsx("p", { className: "truncate text-sm", children: run.when || "\u2014" }),
6274
- run.error && /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-red-text", title: run.error, children: run.error })
6275
- ] }),
6276
- run.conversationId && /* @__PURE__ */ jsx(
6277
- Button,
6278
- {
6279
- asChild: true,
6280
- variant: "outline",
6281
- size: "sm",
6282
- className: "h-7 shrink-0 gap-1.5 pointer-coarse:h-11",
6283
- children: /* @__PURE__ */ jsxs(
6284
- ActionLink,
6285
- {
6286
- href: getRunHref?.(run),
6287
- onSelect: () => {
6288
- onOpenRun(run.conversationId);
6289
- onOpenChange(false);
6290
- },
6291
- "data-testid": testIdOr(testIds?.open, { testId: "task-run-open" }),
6292
- children: [
6293
- /* @__PURE__ */ jsx(Eye, { size: 13 }),
6294
- " ",
6295
- l.open
6296
- ]
6297
- }
6298
- )
6299
- }
6300
- )
7302
+ /* @__PURE__ */ jsx(Eye, { size: 13 }),
7303
+ " ",
7304
+ l.open
6301
7305
  ]
6302
- },
6303
- run.id
6304
- ))
7306
+ }
7307
+ ) })
7308
+ ] });
7309
+ }
7310
+ }
7311
+ ],
7312
+ [onOpenRun, onOpenResult, getRunHref, onOpenChange, testIds?.open, l.open, renderErrorReport]
7313
+ );
7314
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
7315
+ hideHeader ? null : inline ? /* @__PURE__ */ jsx(
7316
+ TabHeader,
7317
+ {
7318
+ tabs: [
7319
+ {
7320
+ id: "history",
7321
+ label: l.title(taskName),
7322
+ count: runs.length,
7323
+ countIcon: /* @__PURE__ */ jsx(History, { size: 14 }),
7324
+ presentation: "count",
7325
+ onClose: () => onOpenChange(false)
6305
7326
  }
6306
- )
6307
- ]
7327
+ ],
7328
+ activeTabId: "history",
7329
+ onTabChange: () => {
7330
+ }
7331
+ }
7332
+ ) : /* @__PURE__ */ jsxs(DialogHeader, { children: [
7333
+ /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
7334
+ /* @__PURE__ */ jsx(History, { size: 16 }),
7335
+ " ",
7336
+ l.title(taskName)
7337
+ ] }),
7338
+ /* @__PURE__ */ jsx(DialogDescription, { children: l.description })
7339
+ ] }),
7340
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx(
7341
+ GridView,
7342
+ {
7343
+ testId: testIdOr(testIds?.list, { testId: "task-runs-list" }),
7344
+ gridId: "workflow-runs",
7345
+ items: runs,
7346
+ columnDefs: columns,
7347
+ getItemId: (run) => run.id,
7348
+ getRowTestId: () => testIdOr(testIds?.row, { testId: "task-run-row" }),
7349
+ isLoading,
7350
+ loadingMessage: l.loading,
7351
+ emptyState: { title: l.empty },
7352
+ height: "100%"
7353
+ }
7354
+ ) })
7355
+ ] });
7356
+ return inline ? /* @__PURE__ */ jsx("section", { className: "flex min-h-0 flex-1 flex-col", "data-testid": "automation-history", children: content }) : /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(
7357
+ DialogContent,
7358
+ {
7359
+ presentation: "sheet",
7360
+ className: "flex h-[min(32rem,calc(100dvh-2rem))] min-h-0 max-w-3xl flex-col",
7361
+ "data-testid": testIdOr(testIds?.modal, { testId: "task-runs-modal" }),
7362
+ children: content
6308
7363
  }
6309
7364
  ) });
6310
7365
  }
@@ -6426,7 +7481,7 @@ var DEFAULT_TASK_COMPOSER_LABELS = {
6426
7481
  dueClear: "Clear date",
6427
7482
  parentTask: "Part of",
6428
7483
  parentTaskNone: "Nothing (top-level)",
6429
- visibility: "Visible to",
7484
+ visibility: "Visibility",
6430
7485
  visibilityWorkspace: "Workspace",
6431
7486
  visibilityPrivate: "Only me",
6432
7487
  assistant: "Task Assistant",
@@ -6476,8 +7531,8 @@ var DEFAULT_TASK_COMPOSER_LABELS = {
6476
7531
  empty: "No match.",
6477
7532
  cancel: "Cancel",
6478
7533
  addTask: "Add task",
6479
- addAndStart: "Add task and start",
6480
- addAndSchedule: "Save as workflow",
7534
+ addAndStart: "Start now",
7535
+ addAndSchedule: "Schedule",
6481
7536
  save: "Save changes",
6482
7537
  saving: "Saving\u2026"
6483
7538
  };
@@ -6496,7 +7551,7 @@ function defaultTaskComposerValues(workflows, initial) {
6496
7551
  afterTaskId: "",
6497
7552
  parentTaskId: "",
6498
7553
  signoffUserId: "",
6499
- shared: true,
7554
+ shared: false,
6500
7555
  description: "",
6501
7556
  dueAt: "",
6502
7557
  agentId: "",
@@ -6506,7 +7561,6 @@ function defaultTaskComposerValues(workflows, initial) {
6506
7561
  ...initial
6507
7562
  };
6508
7563
  }
6509
- var WHEN_ORDER = ["now", "once", "repeat", "event", "task"];
6510
7564
  var GLYPH2 = "size-3.5 shrink-0";
6511
7565
  function missingWhen(values, runAtPast) {
6512
7566
  if (values.when === "now" || values.when === "manual") return null;
@@ -6520,6 +7574,8 @@ function WorkflowComposer({
6520
7574
  open,
6521
7575
  onOpenChange,
6522
7576
  isEdit = false,
7577
+ saveOnly = false,
7578
+ hideRunLater = false,
6523
7579
  workflows,
6524
7580
  agents,
6525
7581
  people,
@@ -6528,6 +7584,8 @@ function WorkflowComposer({
6528
7584
  initialValues,
6529
7585
  onValuesChange,
6530
7586
  timezones = [],
7587
+ eventOptions,
7588
+ eventWorkflowOptions,
6531
7589
  goal,
6532
7590
  standingAccess,
6533
7591
  scopeSource,
@@ -6549,7 +7607,11 @@ function WorkflowComposer({
6549
7607
  const l = {
6550
7608
  ...DEFAULT_TASK_COMPOSER_LABELS,
6551
7609
  ...labels,
6552
- whenOptions: { ...DEFAULT_TASK_COMPOSER_LABELS.whenOptions, ...labels?.whenOptions },
7610
+ whenOptions: {
7611
+ ...DEFAULT_TASK_COMPOSER_LABELS.whenOptions,
7612
+ ...labels?.whenOptions,
7613
+ ...saveOnly ? { now: "When needed" } : {}
7614
+ },
6553
7615
  accessOptions: { ...DEFAULT_TASK_COMPOSER_LABELS.accessOptions, ...labels?.accessOptions }
6554
7616
  };
6555
7617
  const seed = useMemo(
@@ -6563,12 +7625,15 @@ function WorkflowComposer({
6563
7625
  seed,
6564
7626
  onValuesChange
6565
7627
  );
7628
+ const [runOnce, setRunOnce] = useState(false);
7629
+ const [automationWhen, setAutomationWhen] = useState(seed.when);
6566
7630
  const [planOpen, setPlanOpen] = useState(false);
6567
7631
  const [moreOpen, setMoreOpen] = useState(false);
6568
7632
  const [agentAutoSet, setAgentAutoSet] = useState(false);
6569
7633
  useEffect(() => {
6570
7634
  if (open) {
6571
7635
  if (valuesProp === void 0) setValues(seed);
7636
+ setRunOnce(false);
6572
7637
  setPlanOpen(false);
6573
7638
  setAgentAutoSet(false);
6574
7639
  }
@@ -6597,7 +7662,12 @@ function WorkflowComposer({
6597
7662
  const derivedName = workflow ? deriveWorkflowName(workflow, values.inputs) : "";
6598
7663
  const pickWorkflow = (next) => {
6599
7664
  const def = workflows.find((w) => w.id === next);
6600
- setValues({ ...values, workflowId: next, inputs: def ? defaultInputs(def) : {} });
7665
+ setValues({
7666
+ ...values,
7667
+ workflowId: next,
7668
+ inputs: def ? defaultInputs(def) : {},
7669
+ ...def?.documentAction ? { access: "standing" } : {}
7670
+ });
6601
7671
  };
6602
7672
  const pickWhen = (next) => {
6603
7673
  const goesScheduled = next !== "now" && next !== "manual";
@@ -6621,14 +7691,18 @@ function WorkflowComposer({
6621
7691
  setAgentAutoSet(false);
6622
7692
  set("agentId", agentId);
6623
7693
  };
6624
- const submit = () => onSubmit({
6625
- ...values,
6626
- // A scope pick is bound to explicit file ids before anything is sent.
6627
- inputs: workflow ? resolveScopeInputs(workflow, values.inputs, scopeSource) : values.inputs,
6628
- assignee: "agent",
6629
- notifyOnComplete: true,
6630
- name: values.name.trim()
6631
- });
7694
+ const submit = () => {
7695
+ const submitted = {
7696
+ ...values,
7697
+ // A scope pick is bound to explicit file ids before anything is sent.
7698
+ inputs: workflow && !workflow.documentAction ? resolveScopeInputs(workflow, values.inputs, scopeSource) : values.inputs,
7699
+ assignee: "agent",
7700
+ notifyOnComplete: true,
7701
+ name: values.name.trim()
7702
+ };
7703
+ if (runOnce) onSubmit(submitted, { runOnce: true });
7704
+ else onSubmit(submitted);
7705
+ };
6632
7706
  const pillLabels = { search: l.search, empty: l.empty };
6633
7707
  const personOptions = (people ?? []).map((p) => ({
6634
7708
  id: p.id,
@@ -6641,10 +7715,11 @@ function WorkflowComposer({
6641
7715
  label: t.name,
6642
7716
  icon: /* @__PURE__ */ jsx(CornerDownRight, { className: GLYPH2, "aria-hidden": true })
6643
7717
  }));
6644
- const whenOptions = (isEdit ? ["manual", ...WHEN_ORDER.slice(1)] : WHEN_ORDER.slice(1)).map((mode) => ({
6645
- id: mode,
6646
- label: l.whenOptions[mode]
6647
- }));
7718
+ const whenOptions = [
7719
+ { id: "manual", label: "Start now" },
7720
+ { id: "schedule", label: "Schedule" },
7721
+ { id: "event", label: "Notification" }
7722
+ ];
6648
7723
  const assistantOptions = agents.map((a) => ({ id: a.id, label: a.label }));
6649
7724
  if (values.agentId && !assistantOptions.some((a) => a.id === values.agentId)) {
6650
7725
  assistantOptions.push({ id: values.agentId, label: "Assigned agent" });
@@ -6652,18 +7727,42 @@ function WorkflowComposer({
6652
7727
  const goalNode = typeof goal === "function" ? goal(values) : goal;
6653
7728
  const pickedTemplate = workflows.find((w) => w.id === values.workflowId && !w.generic);
6654
7729
  const hint = (key) => l[key];
6655
- return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
7730
+ return /* @__PURE__ */ jsx(Dialog, { modal: false, open, onOpenChange, children: /* @__PURE__ */ jsxs(
6656
7731
  DialogContent,
6657
7732
  {
6658
- presentation: "sheet",
6659
- className: "flex max-h-[calc(100dvh-2rem)] flex-col overflow-hidden p-0 sm:max-w-xl",
7733
+ presentation: "right",
7734
+ hideCloseButton: true,
7735
+ onInteractOutside: (event) => event.preventDefault(),
7736
+ className: "flex flex-col gap-0 overflow-hidden p-0 shadow-lg",
6660
7737
  "data-testid": id,
6661
7738
  children: [
6662
- /* @__PURE__ */ jsxs(ModalHeader, { children: [
6663
- /* @__PURE__ */ jsx(DialogTitle, { children: isEdit ? l.titleEditWorkflow : pickedTemplate ? l.titleRunTemplate(pickedTemplate.title) : l.titleNewWorkflow }),
6664
- !isEdit && /* @__PURE__ */ jsx(DialogDescription, { children: l.descriptionWorkflow }),
6665
- isEdit && /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.descriptionWorkflow })
6666
- ] }),
7739
+ /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: "Automation settings" }),
7740
+ /* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.descriptionWorkflow }),
7741
+ /* @__PURE__ */ jsx(
7742
+ TabHeader,
7743
+ {
7744
+ tabs: [
7745
+ {
7746
+ id: "automation-setup",
7747
+ label: isEdit ? l.titleEditWorkflow : pickedTemplate ? l.titleRunTemplate(pickedTemplate.title) : l.titleNewWorkflow,
7748
+ presentation: "count"
7749
+ },
7750
+ ...(saveOnly || isEdit) && !workflow?.documentAction ? [{ id: "start-task", label: "Start task" }] : []
7751
+ ],
7752
+ activeTabId: runOnce ? "start-task" : "automation-setup",
7753
+ onTabChange: (tab) => {
7754
+ if (tab === "start-task" && !runOnce) {
7755
+ setAutomationWhen(values.when);
7756
+ set("when", "now");
7757
+ setRunOnce(true);
7758
+ } else if (tab === "automation-setup" && runOnce) {
7759
+ set("when", automationWhen);
7760
+ setRunOnce(false);
7761
+ }
7762
+ },
7763
+ rightContent: /* @__PURE__ */ jsx(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", "aria-label": "Close", children: /* @__PURE__ */ jsx(X, { className: "size-4" }) }) })
7764
+ }
7765
+ ),
6667
7766
  /* @__PURE__ */ jsxs(
6668
7767
  "form",
6669
7768
  {
@@ -6753,7 +7852,7 @@ function WorkflowComposer({
6753
7852
  goalNode
6754
7853
  ] })
6755
7854
  ] }),
6756
- (scheduled || isEdit) && /* @__PURE__ */ jsxs(Fragment, { children: [
7855
+ !runOnce && (scheduled || isEdit) && /* @__PURE__ */ jsxs(Fragment, { children: [
6757
7856
  /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-2", "data-testid": `${id}-when-section`, children: [
6758
7857
  /* @__PURE__ */ jsx("h3", { className: "text-sm font-medium", children: l.whenHeading }),
6759
7858
  /* @__PURE__ */ jsx(
@@ -6761,14 +7860,30 @@ function WorkflowComposer({
6761
7860
  {
6762
7861
  icon: /* @__PURE__ */ jsx(Play, { className: GLYPH2, "aria-hidden": true }),
6763
7862
  prefix: l.start,
6764
- value: values.when,
7863
+ value: values.when === "once" || values.when === "repeat" ? "schedule" : values.when === "task" ? "event" : values.when === "now" ? "manual" : values.when,
6765
7864
  options: whenOptions,
6766
- onChange: (v) => pickWhen(v),
7865
+ onChange: (v) => pickWhen(v === "schedule" ? "once" : v),
6767
7866
  labels: pillLabels,
6768
7867
  testId: `${id}-when`,
6769
7868
  className: "self-start"
6770
7869
  }
6771
7870
  ),
7871
+ (values.when === "once" || values.when === "repeat") && /* @__PURE__ */ jsx(
7872
+ PillSelect,
7873
+ {
7874
+ icon: /* @__PURE__ */ jsx(Play, { className: GLYPH2, "aria-hidden": true }),
7875
+ prefix: "Schedule",
7876
+ value: values.when,
7877
+ options: [
7878
+ { id: "once", label: "Once" },
7879
+ { id: "repeat", label: "Repeat" }
7880
+ ],
7881
+ onChange: (value) => pickWhen(value),
7882
+ labels: pillLabels,
7883
+ testId: `${id}-schedule-mode`,
7884
+ className: "self-start"
7885
+ }
7886
+ ),
6772
7887
  values.when === "once" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
6773
7888
  /* @__PURE__ */ jsx(Label, { htmlFor: "task-composer-runat", className: "sr-only", children: l.runAt }),
6774
7889
  /* @__PURE__ */ jsx(
@@ -6812,7 +7927,25 @@ function WorkflowComposer({
6812
7927
  ] }),
6813
7928
  values.when === "event" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
6814
7929
  /* @__PURE__ */ jsx(Label, { htmlFor: "task-composer-event", className: "sr-only", children: l.event }),
6815
- /* @__PURE__ */ jsx(
7930
+ eventOptions ? /* @__PURE__ */ jsx(
7931
+ PillSelect,
7932
+ {
7933
+ icon: /* @__PURE__ */ jsx(Zap, { className: GLYPH2, "aria-hidden": true }),
7934
+ prefix: l.event,
7935
+ value: values.eventKind,
7936
+ options: eventOptions.some((option) => option.id === values.eventKind) || !values.eventKind ? [...eventOptions] : [
7937
+ ...eventOptions,
7938
+ {
7939
+ id: values.eventKind,
7940
+ label: values.eventKind.replaceAll("_", " ")
7941
+ }
7942
+ ],
7943
+ onChange: (event) => set("eventKind", event),
7944
+ labels: pillLabels,
7945
+ testId: `${id}-event`,
7946
+ className: "self-start"
7947
+ }
7948
+ ) : /* @__PURE__ */ jsx(
6816
7949
  Input,
6817
7950
  {
6818
7951
  id: "task-composer-event",
@@ -6825,6 +7958,22 @@ function WorkflowComposer({
6825
7958
  ),
6826
7959
  /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.eventHint })
6827
7960
  ] }),
7961
+ values.when === "event" && values.eventKind === "workflow_completed" && eventWorkflowOptions && /* @__PURE__ */ jsx(
7962
+ PillSelect,
7963
+ {
7964
+ icon: /* @__PURE__ */ jsx(Zap, { className: GLYPH2, "aria-hidden": true }),
7965
+ prefix: "Automation",
7966
+ value: typeof values.eventFilter?.workflow_ext_id === "string" ? values.eventFilter.workflow_ext_id : "",
7967
+ options: [{ id: "", label: "Any automation" }, ...eventWorkflowOptions],
7968
+ onChange: (id2) => set(
7969
+ "eventFilter",
7970
+ id2 ? { ...values.eventFilter, workflow_ext_id: id2 } : null
7971
+ ),
7972
+ labels: pillLabels,
7973
+ testId: `${id}-event-workflow`,
7974
+ className: "self-start"
7975
+ }
7976
+ ),
6828
7977
  values.when === "task" && /* @__PURE__ */ jsx(
6829
7978
  PillSelect,
6830
7979
  {
@@ -7019,7 +8168,7 @@ function WorkflowComposer({
7019
8168
  children: l.cancel
7020
8169
  }
7021
8170
  ),
7022
- !isEdit && /* @__PURE__ */ jsx(
8171
+ !isEdit && !saveOnly && !hideRunLater && /* @__PURE__ */ jsx(
7023
8172
  Button,
7024
8173
  {
7025
8174
  type: "button",
@@ -7039,7 +8188,7 @@ function WorkflowComposer({
7039
8188
  className: "gap-1.5 pointer-coarse:min-h-11",
7040
8189
  children: [
7041
8190
  isPending && /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }),
7042
- isPending ? l.saving : isEdit ? l.save : scheduled ? l.saveWorkflow : l.runNow
8191
+ isPending ? l.saving : runOnce ? "Start now" : isEdit ? l.save : saveOnly || scheduled ? l.saveWorkflow : l.runNow
7043
8192
  ]
7044
8193
  }
7045
8194
  )
@@ -7051,7 +8200,7 @@ function WorkflowComposer({
7051
8200
  }
7052
8201
  ) });
7053
8202
  }
7054
- var WHEN_ORDER2 = ["now", "once", "repeat", "event", "task"];
8203
+ var WHEN_ORDER = ["now", "once", "repeat", "event", "task"];
7055
8204
  function formatDue2(local) {
7056
8205
  const d = new Date(local);
7057
8206
  if (Number.isNaN(d.getTime())) return local;
@@ -7154,7 +8303,7 @@ function WorkTaskComposer({
7154
8303
  label: t.name,
7155
8304
  icon: /* @__PURE__ */ jsx(CornerDownRight, { className: GLYPH3, "aria-hidden": true })
7156
8305
  }));
7157
- const whenOptions = WHEN_ORDER2.map((mode) => ({
8306
+ const whenOptions = WHEN_ORDER.map((mode) => ({
7158
8307
  id: mode,
7159
8308
  label: l.whenOptions[mode]
7160
8309
  }));
@@ -7163,8 +8312,8 @@ function WorkTaskComposer({
7163
8312
  return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
7164
8313
  DialogContent,
7165
8314
  {
7166
- presentation: "sheet",
7167
- className: "flex max-h-[calc(100dvh-2rem)] flex-col overflow-hidden p-0 sm:max-w-xl",
8315
+ presentation: "right",
8316
+ className: "flex flex-col overflow-hidden p-0",
7168
8317
  "data-testid": id,
7169
8318
  children: [
7170
8319
  /* @__PURE__ */ jsxs(ModalHeader, { children: [
@@ -7266,6 +8415,7 @@ function WorkTaskComposer({
7266
8415
  items: { shared: values.shared },
7267
8416
  onToggle: (share) => set("shared", share),
7268
8417
  label: l.visibility,
8418
+ presentation: "select",
7269
8419
  "data-testid": `${id}-visibility`
7270
8420
  }
7271
8421
  )
@@ -7519,6 +8669,210 @@ function WorkTaskComposer({
7519
8669
  function TaskComposer(props) {
7520
8670
  return props.kind === "workflow" ? /* @__PURE__ */ jsx(WorkflowComposer, { ...props }) : /* @__PURE__ */ jsx(WorkTaskComposer, { ...props });
7521
8671
  }
8672
+ function TaskReviewDialog(p) {
8673
+ const [action, setAction] = useState("forward");
8674
+ const [userId, setUserId] = useState("");
8675
+ const [note, setNote] = useState("");
8676
+ useEffect(() => {
8677
+ if (p.open) {
8678
+ setAction(p.people.length ? "forward" : p.canApprove ? "finish" : "revise");
8679
+ setUserId("");
8680
+ setNote("");
8681
+ }
8682
+ }, [p.open]);
8683
+ const valid = action === "forward" ? p.people.some((person) => person.id === userId) : action === "revise" ? p.canRevise && Boolean(note.trim()) : p.canApprove;
8684
+ return /* @__PURE__ */ jsx(Dialog, { open: p.open, onOpenChange: (next) => !p.isPending && p.onOpenChange(next), children: /* @__PURE__ */ jsxs(DialogContent, { "data-testid": "task-review-dialog", className: "sm:max-w-lg", children: [
8685
+ /* @__PURE__ */ jsxs(DialogTitle, { children: [
8686
+ "Review: ",
8687
+ p.taskName
8688
+ ] }),
8689
+ /* @__PURE__ */ jsx(DialogDescription, { children: p.canApprove ? "Approve your review and send it on, request changes, or finish the task." : "Choose who should review this work next, or ask ARBI for changes." }),
8690
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4 py-2", children: [
8691
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8692
+ /* @__PURE__ */ jsx(Label, { htmlFor: "review-next-step", children: "Next step" }),
8693
+ /* @__PURE__ */ jsxs(
8694
+ Select,
8695
+ {
8696
+ value: action,
8697
+ onValueChange: (value) => setAction(value),
8698
+ disabled: p.isPending,
8699
+ children: [
8700
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "review-next-step", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
8701
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
8702
+ p.people.length > 0 && /* @__PURE__ */ jsx(SelectItem, { value: "forward", children: p.canApprove ? "Approve and send for review" : "Send for review" }),
8703
+ p.canRevise && /* @__PURE__ */ jsx(SelectItem, { value: "revise", children: "Ask ARBI for changes" }),
8704
+ p.canApprove && /* @__PURE__ */ jsx(SelectItem, { value: "finish", children: "Approve and finish task" })
8705
+ ] })
8706
+ ]
8707
+ }
8708
+ )
8709
+ ] }),
8710
+ action === "forward" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8711
+ /* @__PURE__ */ jsx(Label, { htmlFor: "review-recipient", children: "Next reviewer" }),
8712
+ /* @__PURE__ */ jsxs(Select, { value: userId, onValueChange: setUserId, disabled: p.isPending, children: [
8713
+ /* @__PURE__ */ jsx(SelectTrigger, { id: "review-recipient", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Choose a person" }) }),
8714
+ /* @__PURE__ */ jsx(SelectContent, { children: p.people.map((person) => /* @__PURE__ */ jsx(SelectItem, { value: person.id, children: person.label }, person.id)) })
8715
+ ] })
8716
+ ] }),
8717
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8718
+ /* @__PURE__ */ jsx(Label, { htmlFor: "review-note", children: action === "revise" ? "What should ARBI change?" : "Review note (optional)" }),
8719
+ /* @__PURE__ */ jsx(
8720
+ Textarea,
8721
+ {
8722
+ id: "review-note",
8723
+ value: note,
8724
+ onChange: (e) => setNote(e.target.value),
8725
+ disabled: p.isPending,
8726
+ placeholder: action === "revise" ? "Explain what needs changing in the same draft\u2026" : "Explain what you checked and what the next reviewer should focus on\u2026"
8727
+ }
8728
+ )
8729
+ ] }),
8730
+ p.error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: p.error })
8731
+ ] }),
8732
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
8733
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => p.onOpenChange(false), disabled: p.isPending, children: "Cancel" }),
8734
+ /* @__PURE__ */ jsx(
8735
+ Button,
8736
+ {
8737
+ "data-testid": "task-review-submit",
8738
+ disabled: !valid || p.isPending,
8739
+ onClick: () => p.onSubmit({
8740
+ action,
8741
+ userId,
8742
+ note: note.trim(),
8743
+ approveCurrent: p.canApprove && action === "forward"
8744
+ }),
8745
+ children: p.isPending ? "Saving\u2026" : action === "forward" ? p.canApprove ? "Approve and send" : "Send for review" : action === "revise" ? "Send to ARBI" : "Finish task"
8746
+ }
8747
+ )
8748
+ ] })
8749
+ ] }) });
8750
+ }
8751
+ function ThreadNotifyDialog({
8752
+ open,
8753
+ onOpenChange,
8754
+ people,
8755
+ isShared,
8756
+ onNotify
8757
+ }) {
8758
+ const [selected, setSelected] = useState([]);
8759
+ const [query, setQuery] = useState("");
8760
+ const [busy, setBusy] = useState(false);
8761
+ const [error, setError] = useState(null);
8762
+ useEffect(() => {
8763
+ if (open) {
8764
+ setSelected([]);
8765
+ setQuery("");
8766
+ setError(null);
8767
+ }
8768
+ }, [open]);
8769
+ return /* @__PURE__ */ jsx(
8770
+ Dialog,
8771
+ {
8772
+ open,
8773
+ onOpenChange: (value) => {
8774
+ if (!busy) onOpenChange(value);
8775
+ },
8776
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-sm", "data-testid": "thread-notify-dialog", children: [
8777
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Notify" }),
8778
+ /* @__PURE__ */ jsx(DialogDescription, { children: isShared ? "Ask someone to follow up in this thread." : "Notifying someone shares this thread with your workspace." }),
8779
+ /* @__PURE__ */ jsx(
8780
+ Input,
8781
+ {
8782
+ "aria-label": "Find people",
8783
+ placeholder: "Find someone\u2026",
8784
+ value: query,
8785
+ onChange: (event) => setQuery(event.target.value)
8786
+ }
8787
+ ),
8788
+ /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto space-y-1", children: [
8789
+ people.filter((person) => person.label.toLowerCase().includes(query.toLowerCase())).map((person) => /* @__PURE__ */ jsxs(
8790
+ "label",
8791
+ {
8792
+ className: "flex cursor-pointer items-center gap-2 rounded px-2 py-2 hover:bg-muted",
8793
+ children: [
8794
+ /* @__PURE__ */ jsx(
8795
+ Checkbox,
8796
+ {
8797
+ disabled: busy,
8798
+ checked: selected.includes(person.id),
8799
+ onCheckedChange: (checked) => setSelected(
8800
+ (old) => checked ? [...old, person.id] : old.filter((id) => id !== person.id)
8801
+ )
8802
+ }
8803
+ ),
8804
+ person.label
8805
+ ]
8806
+ },
8807
+ person.id
8808
+ )),
8809
+ !people.length && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No other workspace members yet." })
8810
+ ] }),
8811
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }),
8812
+ /* @__PURE__ */ jsx(
8813
+ Button,
8814
+ {
8815
+ disabled: busy || !selected.length,
8816
+ "data-testid": "thread-notify-submit",
8817
+ onClick: async () => {
8818
+ setBusy(true);
8819
+ setError(null);
8820
+ try {
8821
+ await onNotify(selected);
8822
+ onOpenChange(false);
8823
+ } catch (failure) {
8824
+ setError(failure instanceof Error ? failure.message : "Could not notify people");
8825
+ } finally {
8826
+ setBusy(false);
8827
+ }
8828
+ },
8829
+ children: busy ? "Notifying\u2026" : "Notify"
8830
+ }
8831
+ )
8832
+ ] })
8833
+ }
8834
+ );
8835
+ }
8836
+ function ConversationTurnSpeaker({
8837
+ role,
8838
+ actor,
8839
+ currentUserId,
8840
+ colorClass,
8841
+ platformName = "ARBI",
8842
+ platformLogoSrc = "/favicon.svg"
8843
+ }) {
8844
+ if (!role) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2014" });
8845
+ if (role === "assistant" && !actor)
8846
+ return /* @__PURE__ */ jsx(
8847
+ UserEntity,
8848
+ {
8849
+ size: "sm",
8850
+ variant: "pill",
8851
+ interactive: false,
8852
+ picture: platformLogoSrc,
8853
+ avatarImageClassName: "object-contain p-0.5",
8854
+ initials: platformName.charAt(0),
8855
+ displayName: platformName
8856
+ }
8857
+ );
8858
+ if (!actor) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Unknown participant" });
8859
+ const isMe = actor.external_id === currentUserId;
8860
+ const displayName = isMe ? "You" : [actor.given_name, actor.family_name].filter(Boolean).join(" ");
8861
+ return /* @__PURE__ */ jsx(
8862
+ UserEntity,
8863
+ {
8864
+ size: "sm",
8865
+ variant: "pill",
8866
+ interactive: false,
8867
+ isMe,
8868
+ isAgent: actor.external_id.startsWith("agt-"),
8869
+ displayName,
8870
+ initials: `${actor.given_name.charAt(0)}${actor.family_name?.charAt(0) ?? ""}`.toUpperCase(),
8871
+ picture: actor.picture,
8872
+ colorClass
8873
+ }
8874
+ );
8875
+ }
7522
8876
  var DEFAULT_TUPLE_ARRAY_FIELD_LABELS = {
7523
8877
  addRow: "Add Row",
7524
8878
  empty: 'No examples added yet. Click "Add Row" to start.',
@@ -9175,6 +10529,6 @@ function AgentCreateView({
9175
10529
  ] });
9176
10530
  }
9177
10531
 
9178
- export { AgentAvatarField, AgentBar, AgentBarIconButton, AgentBarMenu, AgentBarNotes, AgentBarProbeAnswer, AgentBarQueuedNote, AgentBarStatus, AgentCard, AgentCreateView, AgentCreatedView, AgentCreator, AgentEditView, AgentGallery, AgentMainView, AgentSelect, AgentTypeSelector, CapabilityGrid, CapabilityTile, ConfigField, ConfigForm, ConsentActions, ConsentBulletList, ConsentCard, ConsentFootnote, ConsentHeader, ConsentMessage, ConsentNotice, ConsentPage, ConsentPermissionList, ConsentSection, ConsentStrong, ConsentText, CopyableUrl, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_BAR_LABELS, DEFAULT_AGENT_CARD_LABELS, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_GALLERY_LABELS, DEFAULT_AGENT_SELECT_LABELS, DEFAULT_AGENT_STEPS_LABELS, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_AUTHORIZE_AGENT_LABELS, DEFAULT_CONFIG_FIELD_LABELS, DEFAULT_CONFIG_FORM_LABELS, DEFAULT_CONSENT_ACTIONS_LABELS, DEFAULT_COPYABLE_URL_LABELS, DEFAULT_NEW_THREAD_DIALOG_LABELS, DEFAULT_PILL_SELECT_LABELS, DEFAULT_RECURRENCE, DEFAULT_RECURRENCE_BUILDER_LABELS, DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_SKILL_CARD_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_ROW_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_SUBAGENT_ROSTER_LABELS, DEFAULT_TASKS_CHROME_LABELS, DEFAULT_TASK_ACTIVITY_LABELS, DEFAULT_TASK_COMPOSER_LABELS, DEFAULT_TASK_LIST_LABELS, DEFAULT_TASK_OUTPUTS_CELL_LABELS, DEFAULT_TASK_PLAN_LABELS, DEFAULT_TASK_REVIEW_ACTIONS_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TASK_STATUS_PILL_LABELS, DEFAULT_TASK_THREAD_CHIP_LABELS, DEFAULT_TASK_TRIGGER_CHIP_LABELS, DEFAULT_TUPLE_ARRAY_FIELD_LABELS, DEFAULT_UPLOAD_TASK_ITEM_LABELS, DEFAULT_UPLOAD_TASK_LIST_LABELS, DEFAULT_WORKFLOWS_CHROME_LABELS, DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, DEFAULT_WORKFLOW_LIST_LABELS, DERIVED_NAME_WORDS, EMPTY_NEW_THREAD, EMPTY_WORKFLOW_SCOPE, GoalCriteria, MAX_TASK_DEPTH, NewThreadDialog, PersonPill, PillSelect, RecurrenceBuilder, SKILL_PROMPT_FALLBACK_PLACEHOLDER, SKILL_PROMPT_LABEL, STATUS_LABELS, STATUS_ORDER, STATUS_TONE, SchemaForm, SkillActionButton, SkillCard, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillRow, SkillTile, SkillTypeBadge, SkillViewToggle, StepDetail, StepNarration, StepOutcome, StepParams, StepRow, StepSummary, StepTrace, StepTraceSummary, SubAgentLane, SubStepGroup, SubagentRoster, TASK_COLUMN_ORDER, TRIGGER_LABELS, TaskActivityDialog, TaskActivityTimeline, TaskComposer, TaskMoveDialog, TaskOutputsCell, TaskPlan, TaskReviewActions, TaskRunsDialog, TaskStatusPill, TaskTable, TaskThreadChip, TaskTriggerChip, TasksToolbar, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WORKFLOW_COLUMN_ORDER, WorkflowConfigDialog, WorkflowDocumentsField, WorkflowLauncher, WorkflowsTable, WorkflowsToolbar, agentConfigSectionToValues, agentCreatorToConfigSection, asTaskStatus, authModeFor, buildLaunch, buildRRule, buildTaskRows, buildWorkflowScopeSource, composePersona, composeWorkflowPrompt, composerToTaskQuery, composerToWorkRequest, composerToWorkflowRequest, composerToWorkflowUpdate, createTaskColumns, createWorkflowColumns, createsWork, defaultInputs, defaultScopeRenderer, defaultTaskComposerValues, deriveAgentName, deriveWorkflowName, descendantIds, describeRRule, firstWords, formatElapsed, goalProgress, hasTaskFields, hasTrigger, humanizeSection, indexTasks, inferType, inputDocumentIds, inputsFromContext, isAgenticWorkflow, isEmptyWorkflowScope, isOutOfBounds, isPlainTodo, isSkillRow, isValidAgentName, isWorkflowScope, isoToLocalInput, localInputToIso, matchWorkflowScope, moveTargets, newThreadToRequest, nextCriterionId, ownerExtId, parseRRule, prettifyKey, promptFieldName, resolveScopeInputs, skillToWorkflow, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, validateInputs, workflowAccepts, workflowFromFrontmatter, workflowStatus, workflowTaskFields, workflowToComposerValues, workflowTriggerType, workflowWhen, workflowsAccepting, workflowsForHost };
9179
- //# sourceMappingURL=chunk-Y2LWA4ZO.js.map
9180
- //# sourceMappingURL=chunk-Y2LWA4ZO.js.map
10532
+ export { AgentAvatarField, AgentBar, AgentBarIconButton, AgentBarMenu, AgentBarNotes, AgentBarProbeAnswer, AgentBarQueuedNote, AgentBarStatus, AgentCard, AgentCreateView, AgentCreatedView, AgentCreator, AgentEditView, AgentGallery, AgentMainView, AgentSelect, AgentTypeSelector, CapabilityGrid, CapabilityTile, ConfigField, ConfigForm, ConsentActions, ConsentBulletList, ConsentCard, ConsentFootnote, ConsentHeader, ConsentMessage, ConsentNotice, ConsentPage, ConsentPermissionList, ConsentSection, ConsentStrong, ConsentText, ConversationListView, ConversationTurnSpeaker, CopyableUrl, DEFAULT_AGENT_AVATAR_FIELD_LABELS, DEFAULT_AGENT_BAR_LABELS, DEFAULT_AGENT_CARD_LABELS, DEFAULT_AGENT_CREATOR_LABELS, DEFAULT_AGENT_GALLERY_LABELS, DEFAULT_AGENT_SELECT_LABELS, DEFAULT_AGENT_STEPS_LABELS, DEFAULT_AGENT_TYPE_SELECTOR_LABELS, DEFAULT_AUTHORIZE_AGENT_LABELS, DEFAULT_CONFIG_FIELD_LABELS, DEFAULT_CONFIG_FORM_LABELS, DEFAULT_CONSENT_ACTIONS_LABELS, DEFAULT_COPYABLE_URL_LABELS, DEFAULT_NEW_THREAD_DIALOG_LABELS, DEFAULT_PILL_SELECT_LABELS, DEFAULT_RECURRENCE, DEFAULT_RECURRENCE_BUILDER_LABELS, DEFAULT_SCHEMA_FORM_LABELS, DEFAULT_SKILL_CARD_LABELS, DEFAULT_SKILL_EDIT_FORM_LABELS, DEFAULT_SKILL_GENERATE_FORM_LABELS, DEFAULT_SKILL_GLOBAL_BADGE_LABELS, DEFAULT_SKILL_ROW_LABELS, DEFAULT_SKILL_VIEW_TOGGLE_LABELS, DEFAULT_SUBAGENT_ROSTER_LABELS, DEFAULT_TASKS_CHROME_LABELS, DEFAULT_TASK_ACTIVITY_LABELS, DEFAULT_TASK_COMPOSER_LABELS, DEFAULT_TASK_LIST_LABELS, DEFAULT_TASK_OUTPUTS_CELL_LABELS, DEFAULT_TASK_PLAN_LABELS, DEFAULT_TASK_REVIEW_ACTIONS_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TASK_STATUS_PILL_LABELS, DEFAULT_TASK_THREAD_CHIP_LABELS, DEFAULT_TASK_TRIGGER_CHIP_LABELS, DEFAULT_TUPLE_ARRAY_FIELD_LABELS, DEFAULT_UPLOAD_TASK_ITEM_LABELS, DEFAULT_UPLOAD_TASK_LIST_LABELS, DEFAULT_WORKFLOWS_CHROME_LABELS, DEFAULT_WORKFLOW_CONFIG_DIALOG_LABELS, DEFAULT_WORKFLOW_LIST_LABELS, DERIVED_NAME_WORDS, EMPTY_NEW_THREAD, EMPTY_WORKFLOW_SCOPE, EntityChip, GoalCriteria, MAX_TASK_DEPTH, NewThreadDialog, PersonPill, PillSelect, RecurrenceBuilder, SKILL_PROMPT_FALLBACK_PLACEHOLDER, SKILL_PROMPT_LABEL, STATUS_LABELS, STATUS_ORDER, STATUS_TONE, SchemaForm, SkillActionButton, SkillCard, SkillDetail, SkillDetailSection, SkillEditForm, SkillFilterChips, SkillGenerateForm, SkillGlobalBadge, SkillRow, SkillTile, SkillTypeBadge, SkillViewToggle, StepDetail, StepNarration, StepOutcome, StepParams, StepRow, StepSummary, StepTrace, StepTraceSummary, SubAgentLane, SubStepGroup, SubagentRoster, TASK_COLUMN_ORDER, TRIGGER_LABELS, TaskActivityDialog, TaskActivityTimeline, TaskComposer, TaskFlow, TaskInbox, TaskMoveDialog, TaskOutputsCell, TaskPlan, TaskReviewActions, TaskReviewDialog, TaskRunsDialog, TaskStartDialog, TaskStatusPill, TaskTable, TaskThreadChip, TaskTriggerChip, TasksToolbar, ThreadActivity, ThreadNotifyDialog, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WORKFLOW_COLUMN_ORDER, WorkflowConfigDialog, WorkflowDocumentsField, WorkflowLauncher, WorkflowsTable, WorkflowsToolbar, agentConfigSectionToValues, agentCreatorToConfigSection, asTaskStatus, authModeFor, buildLaunch, buildRRule, buildTaskRows, buildWorkflowScopeSource, compactThreadActivity, composePersona, composeWorkflowPrompt, composerToTaskQuery, composerToWorkRequest, composerToWorkflowRequest, composerToWorkflowUpdate, createTaskColumns, createWorkflowColumns, createsWork, defaultInputs, defaultScopeRenderer, defaultTaskComposerValues, deriveAgentName, deriveWorkflowName, descendantIds, describeRRule, filterConversationRows, firstWords, formatElapsed, goalProgress, hasTaskFields, hasTrigger, humanizeSection, indexTasks, inferType, inputDocumentIds, inputsFromContext, isAgenticWorkflow, isEmptyWorkflowScope, isOutOfBounds, isPlainTodo, isSkillRow, isValidAgentName, isWorkflowScope, isoToLocalInput, localInputToIso, matchWorkflowScope, moveTargets, newThreadToRequest, nextCriterionId, ownerExtId, parseRRule, prettifyKey, promptFieldName, resolveScopeInputs, skillToWorkflow, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, validateInputs, workflowAccepts, workflowFromFrontmatter, workflowStatus, workflowTaskFields, workflowToComposerValues, workflowTriggerType, workflowWhen, workflowsAccepting, workflowsForHost };
10533
+ //# sourceMappingURL=chunk-6RXUMBTK.js.map
10534
+ //# sourceMappingURL=chunk-6RXUMBTK.js.map