@arbidocs/blocks 0.4.122 → 0.4.124

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 (123) hide show
  1. package/dist/{StreamedArtifactEditor-IZWYNFMM.cjs → StreamedArtifactEditor-DNBDUNP2.cjs} +5 -5
  2. package/dist/{StreamedArtifactEditor-IZWYNFMM.cjs.map → StreamedArtifactEditor-DNBDUNP2.cjs.map} +1 -1
  3. package/dist/{StreamedArtifactEditor-HTNPG4NB.js → StreamedArtifactEditor-WDHPTWX7.js} +3 -3
  4. package/dist/{StreamedArtifactEditor-HTNPG4NB.js.map → StreamedArtifactEditor-WDHPTWX7.js.map} +1 -1
  5. package/dist/agents/index.cjs +390 -326
  6. package/dist/agents/index.js +9 -9
  7. package/dist/agents/tasks/ConversationListView.d.ts +2 -1
  8. package/dist/agents/tasks/ConversationTurnSpeaker.d.ts +3 -1
  9. package/dist/agents/tasks/TaskFlow.d.ts +17 -0
  10. package/dist/agents/tasks/ThreadLauncher.d.ts +51 -0
  11. package/dist/agents/tasks/ThreadStatusLine.d.ts +33 -0
  12. package/dist/agents/tasks/WorkflowRunStatus.d.ts +32 -0
  13. package/dist/agents/tasks/WorkflowThreadStrip.d.ts +29 -3
  14. package/dist/agents/tasks/compact-thread-activity.d.ts +5 -2
  15. package/dist/agents/tasks/index.d.ts +3 -0
  16. package/dist/agents/workflows/StepBarFrame.d.ts +18 -17
  17. package/dist/agents/workflows/StepChip.d.ts +37 -0
  18. package/dist/agents/workflows/StepDocuments.d.ts +64 -0
  19. package/dist/agents/workflows/WorkflowStepBar.d.ts +1 -2
  20. package/dist/agents/workflows/index.d.ts +2 -0
  21. package/dist/agents/workflows/stepKinds.d.ts +24 -0
  22. package/dist/artifacts/VersionTimeline.d.ts +7 -0
  23. package/dist/artifacts/index.cjs +21 -21
  24. package/dist/artifacts/index.js +1 -1
  25. package/dist/chat/ChatPage.d.ts +1 -1
  26. package/dist/chat/DraftingDocChip.d.ts +22 -0
  27. package/dist/chat/WorkflowStepChip.d.ts +23 -5
  28. package/dist/chat/chat-page-types.d.ts +18 -2
  29. package/dist/chat/flashMessage.d.ts +6 -0
  30. package/dist/chat/index.cjs +144 -131
  31. package/dist/chat/index.d.ts +2 -0
  32. package/dist/chat/index.js +4 -3
  33. package/dist/{chunk-SHASZLGD.js → chunk-3AV7HP6G.js} +3 -3
  34. package/dist/{chunk-SHASZLGD.js.map → chunk-3AV7HP6G.js.map} +1 -1
  35. package/dist/{chunk-UDK553WP.cjs → chunk-4VCKYR4D.cjs} +4 -4
  36. package/dist/{chunk-UDK553WP.cjs.map → chunk-4VCKYR4D.cjs.map} +1 -1
  37. package/dist/chunk-7HAM7Y5U.js +907 -0
  38. package/dist/chunk-7HAM7Y5U.js.map +1 -0
  39. package/dist/{chunk-TCNYKDYE.js → chunk-CXLVI3SB.js} +73 -40
  40. package/dist/chunk-CXLVI3SB.js.map +1 -0
  41. package/dist/{chunk-N7ARMX3O.cjs → chunk-D7WCGOD4.cjs} +3 -3
  42. package/dist/{chunk-N7ARMX3O.cjs.map → chunk-D7WCGOD4.cjs.map} +1 -1
  43. package/dist/{chunk-ZP4IFW2E.js → chunk-EJSJ27HV.js} +733 -185
  44. package/dist/chunk-EJSJ27HV.js.map +1 -0
  45. package/dist/{chunk-AY32GGKU.js → chunk-ERNMU6RV.js} +132 -752
  46. package/dist/chunk-ERNMU6RV.js.map +1 -0
  47. package/dist/{chunk-XFZ7HNPG.js → chunk-ETN5EZI4.js} +3 -3
  48. package/dist/{chunk-XFZ7HNPG.js.map → chunk-ETN5EZI4.js.map} +1 -1
  49. package/dist/{chunk-Z2NSU7D5.cjs → chunk-FL5TEBTM.cjs} +770 -216
  50. package/dist/chunk-FL5TEBTM.cjs.map +1 -0
  51. package/dist/chunk-HM23LXUP.cjs +976 -0
  52. package/dist/chunk-HM23LXUP.cjs.map +1 -0
  53. package/dist/{chunk-WN64RF46.js → chunk-HQH35JWC.js} +3 -3
  54. package/dist/{chunk-WN64RF46.js.map → chunk-HQH35JWC.js.map} +1 -1
  55. package/dist/{chunk-XSUOEJB3.cjs → chunk-MRURIBBB.cjs} +163 -837
  56. package/dist/chunk-MRURIBBB.cjs.map +1 -0
  57. package/dist/{chunk-65HZ36MY.js → chunk-OTDGTBAS.js} +20 -3
  58. package/dist/chunk-OTDGTBAS.js.map +1 -0
  59. package/dist/{chunk-CK4C3IQR.cjs → chunk-VMZXFYHK.cjs} +47 -6
  60. package/dist/chunk-VMZXFYHK.cjs.map +1 -0
  61. package/dist/{chunk-SVJQWLOF.cjs → chunk-W4GXDARU.cjs} +20 -3
  62. package/dist/chunk-W4GXDARU.cjs.map +1 -0
  63. package/dist/{chunk-US5ASM4G.cjs → chunk-WEUCLOBB.cjs} +5 -5
  64. package/dist/{chunk-US5ASM4G.cjs.map → chunk-WEUCLOBB.cjs.map} +1 -1
  65. package/dist/{chunk-S2KVJYBD.cjs → chunk-WV4IDVDQ.cjs} +76 -43
  66. package/dist/chunk-WV4IDVDQ.cjs.map +1 -0
  67. package/dist/{chunk-2FUJXMGO.js → chunk-Y4X3RBFI.js} +44 -6
  68. package/dist/{chunk-CK4C3IQR.cjs.map → chunk-Y4X3RBFI.js.map} +1 -1
  69. package/dist/collaboration/index.cjs +1 -1
  70. package/dist/collaboration/index.js +1 -1
  71. package/dist/connect/docx.cjs +4 -4
  72. package/dist/connect/docx.js +3 -3
  73. package/dist/connect/index.cjs +68 -51
  74. package/dist/connect/index.cjs.map +1 -1
  75. package/dist/connect/index.js +37 -20
  76. package/dist/connect/index.js.map +1 -1
  77. package/dist/connection/WorkflowRunThread.d.ts +4 -4
  78. package/dist/connection/ai.d.ts +2 -0
  79. package/dist/facts/index.cjs +1 -1
  80. package/dist/facts/index.js +1 -1
  81. package/dist/files/index.cjs +3 -3
  82. package/dist/files/index.js +3 -3
  83. package/dist/index.cjs +728 -652
  84. package/dist/index.js +16 -16
  85. package/dist/settings/index.cjs +1 -1
  86. package/dist/settings/index.js +1 -1
  87. package/dist/shell/index.cjs +10 -10
  88. package/dist/shell/index.js +2 -2
  89. package/dist/site/index.cjs +5 -5
  90. package/dist/site/index.js +1 -1
  91. package/dist/studio/index.cjs +6 -5
  92. package/dist/studio/index.cjs.map +1 -1
  93. package/dist/studio/index.js +5 -4
  94. package/dist/studio/index.js.map +1 -1
  95. package/dist/workflow-canvas/WorkflowCanvas.d.ts +0 -9
  96. package/dist/workflow-canvas/edit.d.ts +2 -11
  97. package/dist/workflow-canvas/index.cjs +63 -87
  98. package/dist/workflow-canvas/index.cjs.map +1 -1
  99. package/dist/workflow-canvas/index.js +14 -38
  100. package/dist/workflow-canvas/index.js.map +1 -1
  101. package/node_modules/@arbidocs/coedit/dist/commands.cjs +25 -13
  102. package/node_modules/@arbidocs/coedit/dist/commands.cjs.map +1 -1
  103. package/node_modules/@arbidocs/coedit/dist/commands.d.cts +3 -1
  104. package/node_modules/@arbidocs/coedit/dist/commands.d.ts +3 -1
  105. package/node_modules/@arbidocs/coedit/dist/commands.js +25 -14
  106. package/node_modules/@arbidocs/coedit/dist/commands.js.map +1 -1
  107. package/node_modules/@arbidocs/coedit/package.json +1 -1
  108. package/package.json +4 -4
  109. package/src/blocks.css +168 -0
  110. package/src/workflow-canvas/canvas.css +2 -40
  111. package/dist/chunk-2FUJXMGO.js.map +0 -1
  112. package/dist/chunk-65HZ36MY.js.map +0 -1
  113. package/dist/chunk-AY32GGKU.js.map +0 -1
  114. package/dist/chunk-B4SRYJLM.cjs +0 -107
  115. package/dist/chunk-B4SRYJLM.cjs.map +0 -1
  116. package/dist/chunk-HOXKR26S.js +0 -103
  117. package/dist/chunk-HOXKR26S.js.map +0 -1
  118. package/dist/chunk-S2KVJYBD.cjs.map +0 -1
  119. package/dist/chunk-SVJQWLOF.cjs.map +0 -1
  120. package/dist/chunk-TCNYKDYE.js.map +0 -1
  121. package/dist/chunk-XSUOEJB3.cjs.map +0 -1
  122. package/dist/chunk-Z2NSU7D5.cjs.map +0 -1
  123. package/dist/chunk-ZP4IFW2E.js.map +0 -1
@@ -1,28 +1,28 @@
1
1
  "use client";
2
- import { QuickActionDialogHeader, AddFilesFirst, ScopePicker, StartTiles } from './chunk-P5ST47VY.js';
3
2
  import { DocumentPicker, MultiSelect } from './chunk-4XJZ6AAY.js';
4
3
  import { EmptyState } from './chunk-P6GHJSLR.js';
5
- import { defaultInputs, validateInputs, SchemaForm, isWorkflowScope, fieldToFrontmatter, workflowFromFrontmatter, workflowSteps, initialRunInputs, stepPhase, composeStepPrompt, useWorkflowView, composeWorkflowPrompt, DEFAULT_TASK_ACTIVITY_LABELS, TaskActivityTimeline, isRunFinished, StepBarFrame, stepLevels, eventWaitingDocuments, waitingForDocumentsText, buildLaunch, waitingDocuments, PhaseMark, STEP_LABEL_CURRENT, STEP_LABEL, STEP_LABEL_MAX, STEP_EXTRA, STEP_PILL, stepPillTone } from './chunk-AY32GGKU.js';
6
- import { FoldSection } from './chunk-XD2M6LIG.js';
4
+ import { SchemaForm, useWorkflowView, DEFAULT_TASK_ACTIVITY_LABELS, TaskActivityTimeline, activeStepId, DEFAULT_STEP_BAR_LABELS, StepBarFrame, STEP_LABEL_CURRENT, STEP_LABEL, STEP_LABEL_MAX } from './chunk-ERNMU6RV.js';
7
5
  import { TriStateFilterMenu } from './chunk-6S5FLMWG.js';
8
6
  import { CellHoverIcon } from './chunk-RFXJYIDV.js';
9
7
  import { ToneBadge } from './chunk-5LXQPP2K.js';
10
- import { ActionLink } from './chunk-S7PSMMRG.js';
11
8
  import { SelectionBar, SelectionBarAction } from './chunk-NUNKSZKU.js';
12
9
  import { FilterInput } from './chunk-YU2KUMGE.js';
13
10
  import { GridView } from './chunk-N5YEF3LC.js';
14
- import { useMentionAutocomplete } from './chunk-HOXKR26S.js';
15
- import { toMessageMentions, extractMentions, MentionMenu } from './chunk-AA3PT6KR.js';
16
- import { useIsPhone } from './chunk-SLSBJRWW.js';
11
+ import { QuickActionDialogHeader, AddFilesFirst, ScopePicker, StartTiles } from './chunk-P5ST47VY.js';
12
+ import { FoldSection } from './chunk-XD2M6LIG.js';
13
+ import { ActionLink } from './chunk-S7PSMMRG.js';
17
14
  import { TabHeader } from './chunk-4WWM3GQ5.js';
18
15
  import { ModalHeader } from './chunk-TX2ZICS7.js';
16
+ import { DEFAULT_STEP_RECORD_LABELS, DEFAULT_STEP_DOCUMENT_LABELS, DEFAULT_STEP_KIND_LABELS, defaultInputs, validateInputs, isWorkflowScope, fieldToFrontmatter, workflowFromFrontmatter, workflowSteps, initialRunInputs, stepPhase, composeStepPrompt, useMentionAutocomplete, composeWorkflowPrompt, StepChip, StepDocumentButton, stepLevels, isRunFinished, stepKindOf, stepDocuments, eventWaitingDocuments, waitingForDocumentsText, buildLaunch, STEP_KIND_ICONS, StepDocumentCards, StepRecord, splitDocRef, waitingDocuments } from './chunk-7HAM7Y5U.js';
17
+ import { toMessageMentions, extractMentions, MentionMenu } from './chunk-AA3PT6KR.js';
18
+ import { useIsPhone } from './chunk-SLSBJRWW.js';
19
19
  import { testIdOr, prefixedTestId } from './chunk-7F6CBP3Z.js';
20
20
  import { useBlocksEnvironment } from './chunk-76JDDMSP.js';
21
21
  import { formatCount, initials } from './chunk-OXF2IFXG.js';
22
22
  import { memo, forwardRef, useState, useMemo, useId, useEffect, useRef, useCallback, useLayoutEffect } from 'react';
23
- 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, VisibilityToggle, EntityPill, ThreadVisibilityIcon, DialogClose, Popover, PopoverTrigger, PopoverContent, Command, CommandInput, CommandList, CommandEmpty, CommandItem, DropdownMenuSeparator, badgeVariants, Checkbox } from '@arbidocs/react/ui';
23
+ 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, VisibilityToggle, EntityPill, ThreadVisibilityIcon, DialogClose, Popover, PopoverTrigger, PopoverContent, Command, CommandInput, CommandList, CommandEmpty, CommandItem, DropdownMenuSeparator, badgeVariants, Checkbox, PopoverClose } from '@arbidocs/react/ui';
24
24
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
25
- 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, AlertCircle, KeyRound, Workflow, ChevronsUpDown, ChevronsDownUp, ListTodo, CheckCheck, MoreHorizontal, CalendarClock, History, ChevronUp, Pause, Activity, Hourglass, MoreVertical, TriangleAlert, CheckSquare, Square, CheckCircle2, SquareArrowOutUpRight, ArrowLeft, LayoutGrid, List, CornerLeftUp, CornerUpLeft, UserRound, CircleDashed, RotateCcw, ListPlus, Link2, Clock, Bell, MousePointerClick, Flag, ArrowUpRight, Zap } from 'lucide-react';
25
+ 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, AlertCircle, KeyRound, Workflow, ChevronsUpDown, ChevronsDownUp, ListTodo, CheckCheck, MoreHorizontal, CalendarClock, History, ArrowUpRight, SendHorizontal, Zap, MessagesSquare, ChevronUp, Pause, Activity, Hourglass, MoreVertical, TriangleAlert, CheckSquare, Square, CheckCircle2, SquareArrowOutUpRight, ArrowLeft, LayoutGrid, List, CornerLeftUp, CornerUpLeft, CircleDashed, RotateCcw, ListPlus, Clock, CircleCheck, Hand, Link2, Bell, MousePointerClick, Flag } from 'lucide-react';
26
26
 
27
27
  function useControllableState(value, defaultValue, onChange) {
28
28
  const [inner, setInner] = useState(defaultValue);
@@ -4364,6 +4364,62 @@ function TaskInbox(p) {
4364
4364
  )
4365
4365
  ] });
4366
4366
  }
4367
+ var DEFAULT_THREAD_STATE_LABELS = {
4368
+ generating: "Generating",
4369
+ needs: "Needs {name}",
4370
+ next: "Up next",
4371
+ ready: "Ready",
4372
+ todo: "To do",
4373
+ done: "Done",
4374
+ failed: "Failed",
4375
+ queued: "Queued",
4376
+ access: "Needs access"
4377
+ };
4378
+ var LOOK = {
4379
+ generating: {
4380
+ icon: /* @__PURE__ */ jsx(Loader2, { className: "animate-spin" }),
4381
+ className: "text-amber-700 dark:text-amber-300"
4382
+ },
4383
+ needs: { icon: /* @__PURE__ */ jsx(Hand, {}), className: "text-orange-700 dark:text-orange-300" },
4384
+ next: { icon: /* @__PURE__ */ jsx(Clock, {}), className: "text-muted-foreground" },
4385
+ ready: { icon: /* @__PURE__ */ jsx(CircleCheck, {}), className: "text-emerald-700 dark:text-emerald-400" },
4386
+ todo: { icon: /* @__PURE__ */ jsx(CircleDashed, {}), className: "text-muted-foreground" },
4387
+ done: { icon: /* @__PURE__ */ jsx(CheckCheck, {}), className: "text-muted-foreground" },
4388
+ failed: { icon: /* @__PURE__ */ jsx(AlertCircle, {}), className: "text-red-text" },
4389
+ queued: { icon: /* @__PURE__ */ jsx(Clock, {}), className: "text-amber-700 dark:text-amber-300" },
4390
+ access: { icon: /* @__PURE__ */ jsx(KeyRound, {}), className: "text-red-text" }
4391
+ };
4392
+ function ThreadStatusLine({
4393
+ state,
4394
+ name = "you",
4395
+ detail,
4396
+ extra,
4397
+ labels,
4398
+ className,
4399
+ testId
4400
+ }) {
4401
+ const l = { ...DEFAULT_THREAD_STATE_LABELS, ...labels };
4402
+ const { icon, className: tone } = LOOK[state];
4403
+ const word = l[state].replace("{name}", name);
4404
+ return /* @__PURE__ */ jsxs(
4405
+ "span",
4406
+ {
4407
+ className: cn("flex min-w-0 items-center gap-1.5 text-xs leading-tight", className),
4408
+ title: detail ? `${word} \xB7 ${detail}` : word,
4409
+ "data-state": state,
4410
+ "data-testid": testId,
4411
+ children: [
4412
+ /* @__PURE__ */ jsx("span", { className: cn("flex shrink-0 [&_svg]:size-3.5", tone), "aria-hidden": true, children: icon }),
4413
+ /* @__PURE__ */ jsx("span", { className: cn("shrink-0 font-medium", tone), children: word }),
4414
+ extra,
4415
+ detail && /* @__PURE__ */ jsxs("span", { className: "min-w-0 truncate text-foreground", children: [
4416
+ "\xB7 ",
4417
+ detail
4418
+ ] })
4419
+ ]
4420
+ }
4421
+ );
4422
+ }
4367
4423
  function EntityChip({
4368
4424
  variant = "pill",
4369
4425
  icon,
@@ -4447,13 +4503,14 @@ function ConversationListView(p) {
4447
4503
  [p.conversations, q, p.labelText, p.doneFilter, p.visibilityFilters, p.meetingFilter]
4448
4504
  );
4449
4505
  const selectedRows = p.conversations.filter((c) => selected.has(c.external_id));
4506
+ const hasLabels = p.conversations.some((c) => !!p.labelText?.(c));
4450
4507
  const columns = useMemo(
4451
4508
  () => [
4452
4509
  {
4453
4510
  colId: "name",
4454
4511
  headerName: "Thread",
4455
- flex: 1,
4456
- minWidth: 180,
4512
+ flex: 2,
4513
+ minWidth: 200,
4457
4514
  valueGetter: ({ data }) => data?.title?.trim() || "Untitled thread",
4458
4515
  cellRenderer: ({ data }) => data && /* @__PURE__ */ jsxs("div", { className: "group flex h-full min-w-0 items-center gap-2", children: [
4459
4516
  /* @__PURE__ */ jsx("div", { className: "min-w-0", children: liveProps.current.renderThread ? liveProps.current.renderThread(data) : /* @__PURE__ */ jsx(
@@ -4467,6 +4524,18 @@ function ConversationListView(p) {
4467
4524
  testId: `thread-open-${data.external_id}`
4468
4525
  }
4469
4526
  ) }),
4527
+ (data.message_count ?? 0) > 0 && /* @__PURE__ */ jsxs(
4528
+ "span",
4529
+ {
4530
+ className: "inline-flex h-5 shrink-0 items-center gap-0.5 self-center rounded-full bg-muted px-1.5 text-[10px] font-medium leading-none tabular-nums text-muted-foreground",
4531
+ title: `${data.message_count} ${data.message_count === 1 ? "message" : "messages"}`,
4532
+ "data-testid": `thread-messages-${data.external_id}`,
4533
+ children: [
4534
+ /* @__PURE__ */ jsx(MessageSquare, { className: "size-3", "aria-hidden": true }),
4535
+ data.message_count
4536
+ ]
4537
+ }
4538
+ ),
4470
4539
  (data.is_owner !== false || liveProps.current.canEditShared) && /* @__PURE__ */ jsx(
4471
4540
  "button",
4472
4541
  {
@@ -4480,72 +4549,51 @@ function ConversationListView(p) {
4480
4549
  )
4481
4550
  ] })
4482
4551
  },
4483
- ...liveProps.current.renderLabels ? [
4552
+ // Labels only when a thread has some (an empty column only takes the names' room), and never
4553
+ // on a phone, where the status is what a row must say.
4554
+ ...liveProps.current.renderLabels && hasLabels && !isPhone ? [
4484
4555
  {
4485
4556
  colId: "labels",
4486
4557
  headerName: "Labels",
4487
- ...isPhone ? { width: 200 } : { flex: 0.5, minWidth: 160 },
4558
+ flex: 0.5,
4559
+ minWidth: 100,
4488
4560
  valueGetter: ({ data }) => data ? liveProps.current.labelText?.(data) ?? "" : "",
4489
4561
  cellRenderer: ({ data }) => data && liveProps.current.renderLabels?.(data)
4490
4562
  }
4491
4563
  ] : [],
4492
- ...liveProps.current.renderBy || liveProps.current.renderOwner ? [
4493
- {
4494
- colId: liveProps.current.renderBy ? "by" : "owner",
4495
- headerName: liveProps.current.renderBy ? "Last message by" : "Owner",
4496
- width: 160,
4497
- hide: isPhone,
4498
- cellRenderer: ({ data }) => data && (liveProps.current.renderBy || liveProps.current.renderOwner)?.(data)
4499
- }
4500
- ] : [],
4501
4564
  {
4502
4565
  colId: "status",
4503
4566
  headerName: "Status",
4504
- width: 150,
4505
- hide: isPhone,
4567
+ width: isPhone ? 170 : 240,
4506
4568
  valueGetter: ({ data }) => data?.status,
4507
- cellRenderer: ({ data }) => data && (liveProps.current.renderStatus ? liveProps.current.renderStatus(data) : /* @__PURE__ */ jsx(TaskStatusPill, { id: data.external_id, status: data.status }))
4508
- },
4509
- {
4510
- valueGetter: ({ data }) => data?.message_count,
4511
- colId: "messages",
4512
- headerName: "Messages",
4513
- width: 110,
4514
- hide: isPhone,
4515
- valueFormatter: ({ value }) => value == null ? "\u2014" : String(value),
4516
- cellClass: "text-muted-foreground"
4569
+ cellRenderer: ({ data }) => data && (liveProps.current.renderStatus ? liveProps.current.renderStatus(data) : /* @__PURE__ */ jsx(
4570
+ ThreadStatusLine,
4571
+ {
4572
+ state: data.status === "done" ? "done" : data.status === "todo" ? "todo" : "ready"
4573
+ }
4574
+ ))
4517
4575
  },
4518
- ...liveProps.current.onToggleShared ? [
4576
+ // Who spoke last (their face) and when: the two read together, at the row's end.
4577
+ ...liveProps.current.renderBy || liveProps.current.renderOwner ? [
4519
4578
  {
4520
- colId: "visibility",
4521
- headerName: "Visibility",
4522
- width: 170,
4579
+ colId: liveProps.current.renderBy ? "by" : "owner",
4580
+ headerName: liveProps.current.renderBy ? "By" : "Owner",
4581
+ width: 64,
4523
4582
  hide: isPhone,
4524
- cellClass: "cell-hcenter",
4525
4583
  sortable: false,
4526
4584
  resizable: false,
4527
- cellRenderer: ({ data }) => data && /* @__PURE__ */ jsx(
4528
- VisibilityToggle,
4529
- {
4530
- items: [data],
4531
- showLabel: true,
4532
- label: data.is_shared ? "Workspace" : "Only Me",
4533
- disabled: data.is_owner === false,
4534
- onToggle: () => liveProps.current.onToggleShared?.(data, !data.is_shared),
4535
- "data-testid": `thread-shared-${data.external_id}`
4536
- }
4537
- )
4585
+ cellRenderer: ({ data }) => data && (liveProps.current.renderBy || liveProps.current.renderOwner)?.(data)
4538
4586
  }
4539
4587
  ] : [],
4540
4588
  {
4541
4589
  colId: "activity",
4542
4590
  initialSort: "desc",
4543
- headerName: "Activity",
4544
- width: 160,
4591
+ headerName: "Updated",
4592
+ width: 128,
4545
4593
  hide: isPhone,
4546
4594
  valueGetter: ({ data }) => data?.last_message_updated_at || data?.updated_at || data?.created_at || "",
4547
4595
  valueFormatter: ({ value }) => value ? liveProps.current.formatDate(value) : "\u2014",
4548
- cellClass: "text-muted-foreground"
4596
+ cellClass: "flex items-center text-xs text-muted-foreground/80"
4549
4597
  }
4550
4598
  ],
4551
4599
  [
@@ -4554,10 +4602,14 @@ function ConversationListView(p) {
4554
4602
  Boolean(p.renderOwner),
4555
4603
  Boolean(p.renderBy),
4556
4604
  Boolean(p.renderStatus),
4557
- Boolean(p.onToggleShared),
4558
- isPhone
4605
+ isPhone,
4606
+ hasLabels
4559
4607
  ]
4560
4608
  );
4609
+ const centred = useMemo(
4610
+ () => columns.map((c) => ({ cellClass: "flex items-center", ...c })),
4611
+ [columns]
4612
+ );
4561
4613
  return /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col", "data-testid": "conversation-list-view", children: [
4562
4614
  p.showHeader !== false && /* @__PURE__ */ jsx(
4563
4615
  TabHeader,
@@ -4602,7 +4654,7 @@ function ConversationListView(p) {
4602
4654
  {
4603
4655
  testId: "threads-grid",
4604
4656
  items: rows,
4605
- columnDefs: columns,
4657
+ columnDefs: centred,
4606
4658
  getItemId: (row) => row.external_id,
4607
4659
  getRowTestId: (row) => `thread-row-${row.external_id}`,
4608
4660
  onRowClick: p.onOpen,
@@ -4611,7 +4663,7 @@ function ConversationListView(p) {
4611
4663
  loadingMessage: "Loading threads\u2026",
4612
4664
  emptyState: {
4613
4665
  title: q ? "No threads match" : "No conversations yet",
4614
- message: "Use New Task to ask ARBI, bring in people, or both."
4666
+ message: p.footer ? "Type below to ask ARBI, bring in people, or both." : "Use New Task to ask ARBI, bring in people, or both."
4615
4667
  },
4616
4668
  selection: p.selectionActions ? {
4617
4669
  mode: "multiple",
@@ -4628,6 +4680,7 @@ function ConversationListView(p) {
4628
4680
  }
4629
4681
  }
4630
4682
  ) }),
4683
+ p.footer,
4631
4684
  p.selectionActions && /* @__PURE__ */ jsx(SelectionBar, { count: selectedRows.length, onClear: () => setSelected(/* @__PURE__ */ new Set()), children: (compact) => p.selectionActions?.(selectedRows, compact, () => setSelected(/* @__PURE__ */ new Set())) })
4632
4685
  ] });
4633
4686
  }
@@ -6251,24 +6304,28 @@ function TaskFlow({
6251
6304
  const el = e.currentTarget;
6252
6305
  following.current = el.scrollWidth - el.scrollLeft - el.clientWidth < 24;
6253
6306
  },
6254
- children: /* @__PURE__ */ jsx("ol", { className: "flex w-max min-w-full items-center gap-1", children: items.map((item, i) => {
6255
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [
6256
- /* @__PURE__ */ jsx("span", { className: "shrink-0", children: item.avatar }),
6257
- /* @__PURE__ */ jsxs("span", { className: "min-w-0 text-left", children: [
6258
- /* @__PURE__ */ jsx("span", { className: "block max-w-32 truncate text-[11px] leading-tight font-medium", children: item.label }),
6259
- /* @__PURE__ */ jsx(
6307
+ children: /* @__PURE__ */ jsx("ol", { className: "flex w-max min-w-full items-center gap-1 py-0.5", children: items.map((item, i) => {
6308
+ const chip = (props) => /* @__PURE__ */ jsx(
6309
+ StepChip,
6310
+ {
6311
+ kind: "adhoc",
6312
+ phase: "ready",
6313
+ icon: item.avatar,
6314
+ label: item.label,
6315
+ current: item.current,
6316
+ labelClassName: "max-w-32 truncate",
6317
+ title: item.description ?? item.label,
6318
+ className: "shrink-0 [&_.wf-badge]:bg-transparent",
6319
+ ...props,
6320
+ children: /* @__PURE__ */ jsx(
6260
6321
  "span",
6261
6322
  {
6262
- className: "block text-[10px] leading-tight text-muted-foreground",
6323
+ className: "shrink-0 text-[10px] font-normal text-muted-foreground",
6263
6324
  title: item.exactTime,
6264
6325
  children: item.time
6265
6326
  }
6266
6327
  )
6267
- ] })
6268
- ] });
6269
- const cls = cn(
6270
- "flex shrink-0 items-center gap-1.5 rounded-md px-1 py-0.5",
6271
- item.current && "bg-accent text-accent-foreground"
6328
+ }
6272
6329
  );
6273
6330
  return /* @__PURE__ */ jsxs(
6274
6331
  "li",
@@ -6276,26 +6333,11 @@ function TaskFlow({
6276
6333
  className: "flex shrink-0 items-center gap-1",
6277
6334
  "data-testid": `thread-flow-${item.id}`,
6278
6335
  children: [
6279
- i > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3 shrink-0 text-muted-foreground", "aria-hidden": true }),
6280
- item.onSelect ? /* @__PURE__ */ jsx(
6281
- "button",
6282
- {
6283
- className: cn(cls, "hover:bg-muted"),
6284
- onClick: item.onSelect,
6285
- title: item.description ?? item.label,
6286
- children: content
6287
- }
6288
- ) : item.detail ? /* @__PURE__ */ jsxs(Popover, { children: [
6289
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6290
- "button",
6291
- {
6292
- className: cn(cls, "hover:bg-muted"),
6293
- title: item.description ?? item.label,
6294
- children: content
6295
- }
6296
- ) }),
6336
+ i > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "wf-link wf-kind-adhoc w-3 flex-none", "data-done": true }),
6337
+ item.onSelect ? chip({ onClick: item.onSelect }) : item.detail ? /* @__PURE__ */ jsxs(Popover, { children: [
6338
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: chip({}) }),
6297
6339
  /* @__PURE__ */ jsx(PopoverContent, { className: "max-h-72 overflow-y-auto text-sm whitespace-pre-wrap", children: item.detail })
6298
- ] }) : /* @__PURE__ */ jsx("div", { className: cls, title: item.description ?? item.label, children: content })
6340
+ ] }) : chip({ inert: true })
6299
6341
  ]
6300
6342
  },
6301
6343
  item.id
@@ -6305,6 +6347,54 @@ function TaskFlow({
6305
6347
  );
6306
6348
  }
6307
6349
  function ThreadActivity({ item, children }) {
6350
+ if (item.stepChip) {
6351
+ const { kind, phase, icon, document } = item.stepChip;
6352
+ const done = phase === "done" || phase === "skipped";
6353
+ return /* @__PURE__ */ jsxs(
6354
+ "div",
6355
+ {
6356
+ className: cn(`wf-kind-${kind}`, "flex flex-col items-center gap-1 px-3 py-2"),
6357
+ "data-testid": `thread-activity-${item.id}`,
6358
+ title: item.description,
6359
+ children: [
6360
+ /* @__PURE__ */ jsxs("div", { className: "flex w-full max-w-xl items-center gap-2", children: [
6361
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "wf-link", "data-done": done || void 0 }),
6362
+ /* @__PURE__ */ jsx(
6363
+ StepChip,
6364
+ {
6365
+ inert: true,
6366
+ kind,
6367
+ phase,
6368
+ icon,
6369
+ label: item.label,
6370
+ className: cn("shrink-0", document && "rounded-r-none"),
6371
+ children: /* @__PURE__ */ jsx(
6372
+ "time",
6373
+ {
6374
+ className: "shrink-0 text-[10px] font-normal text-muted-foreground",
6375
+ title: item.exactTime,
6376
+ children: item.time
6377
+ }
6378
+ )
6379
+ }
6380
+ ),
6381
+ document && /* @__PURE__ */ jsx(
6382
+ StepDocumentButton,
6383
+ {
6384
+ kind,
6385
+ name: document.name,
6386
+ onOpen: document.onOpen,
6387
+ showName: true,
6388
+ testId: `thread-activity-${item.id}-open-document`
6389
+ }
6390
+ ),
6391
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "wf-link", "data-done": done || void 0 })
6392
+ ] }),
6393
+ children
6394
+ ]
6395
+ }
6396
+ );
6397
+ }
6308
6398
  return /* @__PURE__ */ jsx("div", { className: "flex justify-center px-3 py-2", "data-testid": `thread-activity-${item.id}`, children: /* @__PURE__ */ jsxs(
6309
6399
  "div",
6310
6400
  {
@@ -6322,6 +6412,298 @@ function ThreadActivity({ item, children }) {
6322
6412
  }
6323
6413
  ) });
6324
6414
  }
6415
+ var DEFAULT_THREAD_LAUNCHER_LABELS = {
6416
+ placeholder: "Start a new thread: ask ARBI, or @mention people\u2026",
6417
+ todoPlaceholder: "What needs doing?",
6418
+ withArbi: "With ARBI",
6419
+ todo: "To-do",
6420
+ source: "Who does the work",
6421
+ start: "Start",
6422
+ schedule: "Schedule",
6423
+ started: "Started \u201C{title}\u201D",
6424
+ open: "Open",
6425
+ dismiss: "Dismiss",
6426
+ shared: "Workspace",
6427
+ private: "Only Me"
6428
+ };
6429
+ var NO_PEOPLE2 = [];
6430
+ function ThreadLauncher({
6431
+ workflows,
6432
+ people = NO_PEOPLE2,
6433
+ isPending,
6434
+ error,
6435
+ startLabel,
6436
+ onStart,
6437
+ onLater,
6438
+ onOpen,
6439
+ autoFocus,
6440
+ labels,
6441
+ className
6442
+ }) {
6443
+ const l = { ...DEFAULT_THREAD_LAUNCHER_LABELS, ...labels };
6444
+ const [prompt, setPrompt] = useState("");
6445
+ const [choice, setChoice] = useState("prompt");
6446
+ const [shared, setShared] = useState(false);
6447
+ const [started, setStarted] = useState(null);
6448
+ const textareaRef = useRef(null);
6449
+ const mention = useMentionAutocomplete({
6450
+ value: prompt,
6451
+ onValueChange: setPrompt,
6452
+ candidates: people,
6453
+ textareaRef
6454
+ });
6455
+ const todo = choice === "todo";
6456
+ const workflowId = choice === "prompt" || todo ? null : choice;
6457
+ const workflow = workflows.find((w) => w.external_id === workflowId);
6458
+ const valid = workflowId ? Boolean(workflow) : Boolean(prompt.trim());
6459
+ const values = {
6460
+ prompt: prompt.trim(),
6461
+ workflowId,
6462
+ todo,
6463
+ shared,
6464
+ mentions: toMessageMentions(extractMentions(prompt, people))
6465
+ };
6466
+ const start = async () => {
6467
+ if (!valid || isPending) return;
6468
+ try {
6469
+ const made = await onStart(values);
6470
+ setStarted(made ?? null);
6471
+ setPrompt("");
6472
+ setChoice("prompt");
6473
+ textareaRef.current?.focus();
6474
+ } catch {
6475
+ }
6476
+ };
6477
+ return /* @__PURE__ */ jsx(
6478
+ "div",
6479
+ {
6480
+ className: cn("shrink-0 border-t border-border bg-background px-3 pb-3 pt-2", className),
6481
+ "data-testid": "thread-launcher",
6482
+ children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-3xl", children: [
6483
+ started && /* @__PURE__ */ jsxs(
6484
+ "div",
6485
+ {
6486
+ className: "mb-2 flex min-w-0 items-center gap-2 text-xs",
6487
+ role: "status",
6488
+ "data-testid": "thread-launcher-started",
6489
+ children: [
6490
+ /* @__PURE__ */ jsx("span", { className: "flex size-4 shrink-0 items-center justify-center rounded-full bg-emerald-600 text-white dark:bg-emerald-500", children: /* @__PURE__ */ jsx(Check, { className: "size-3", strokeWidth: 3 }) }),
6491
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate text-muted-foreground", children: l.started.replace("{title}", started.title) }),
6492
+ /* @__PURE__ */ jsxs(
6493
+ Button,
6494
+ {
6495
+ variant: "link",
6496
+ size: "sm",
6497
+ className: "h-auto shrink-0 gap-0.5 p-0 text-xs",
6498
+ onClick: () => onOpen(started.id),
6499
+ "data-testid": "thread-launcher-open",
6500
+ children: [
6501
+ l.open,
6502
+ /* @__PURE__ */ jsx(ArrowUpRight, { className: "size-3" })
6503
+ ]
6504
+ }
6505
+ ),
6506
+ /* @__PURE__ */ jsx(
6507
+ "button",
6508
+ {
6509
+ type: "button",
6510
+ className: "ml-auto shrink-0 rounded p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground",
6511
+ "aria-label": l.dismiss,
6512
+ onClick: () => setStarted(null),
6513
+ children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
6514
+ }
6515
+ )
6516
+ ]
6517
+ }
6518
+ ),
6519
+ /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-card shadow-sm focus-within:border-ring", children: [
6520
+ workflow ? /* @__PURE__ */ jsx("p", { className: "px-3 pt-2.5 text-sm font-medium", "data-testid": "thread-launcher-workflow", children: workflow.name }) : /* @__PURE__ */ jsxs("div", { className: "relative", children: [
6521
+ /* @__PURE__ */ jsx(
6522
+ Textarea,
6523
+ {
6524
+ ref: textareaRef,
6525
+ value: prompt,
6526
+ rows: 1,
6527
+ autoFocus,
6528
+ onChange: (event) => mention.onValueChange(event.target.value),
6529
+ onKeyDown: (event) => {
6530
+ mention.nav.handleKeyDown(event);
6531
+ if (event.defaultPrevented || mention.isOpen) return;
6532
+ if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
6533
+ event.preventDefault();
6534
+ void start();
6535
+ }
6536
+ },
6537
+ ...mention.isOpen ? mention.nav.comboboxProps : {},
6538
+ ...mention.textareaProps,
6539
+ disabled: isPending,
6540
+ placeholder: todo ? l.todoPlaceholder : l.placeholder,
6541
+ "aria-label": todo ? l.todoPlaceholder : l.placeholder,
6542
+ className: "field-sizing-content max-h-40 min-h-10 resize-none border-0 bg-transparent px-3 pt-2.5 shadow-none focus-visible:ring-0",
6543
+ "data-testid": "thread-launcher-input"
6544
+ }
6545
+ ),
6546
+ /* @__PURE__ */ jsx(
6547
+ MentionMenu,
6548
+ {
6549
+ open: mention.isOpen,
6550
+ placement: "above",
6551
+ items: mention.items,
6552
+ selectedIndex: mention.nav.selectedIndex,
6553
+ setSelectedIndex: mention.nav.setSelectedIndex,
6554
+ listboxId: mention.nav.listboxId,
6555
+ onSelect: mention.pick
6556
+ }
6557
+ )
6558
+ ] }),
6559
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-2 pb-1.5", children: [
6560
+ /* @__PURE__ */ jsxs(Select, { value: choice, onValueChange: setChoice, disabled: isPending, children: [
6561
+ /* @__PURE__ */ jsx(
6562
+ SelectTrigger,
6563
+ {
6564
+ "aria-label": l.source,
6565
+ className: "h-7 w-auto max-w-[45%] border-0 bg-transparent px-1.5 text-xs font-normal text-muted-foreground shadow-none hover:bg-muted",
6566
+ "data-testid": "thread-launcher-source",
6567
+ children: /* @__PURE__ */ jsx(SelectValue, {})
6568
+ }
6569
+ ),
6570
+ /* @__PURE__ */ jsxs(SelectContent, { children: [
6571
+ /* @__PURE__ */ jsx(SelectItem, { value: "prompt", children: l.withArbi }),
6572
+ /* @__PURE__ */ jsx(SelectItem, { value: "todo", children: l.todo }),
6573
+ workflows.map((w) => /* @__PURE__ */ jsx(SelectItem, { value: w.external_id, children: w.name }, w.external_id))
6574
+ ] })
6575
+ ] }),
6576
+ error && /* @__PURE__ */ jsx("p", { role: "alert", className: "min-w-0 truncate text-xs text-destructive", title: error, children: error }),
6577
+ /* @__PURE__ */ jsxs("div", { className: "ml-auto flex items-center gap-1.5", children: [
6578
+ /* @__PURE__ */ jsx(
6579
+ VisibilityToggle,
6580
+ {
6581
+ items: { shared },
6582
+ onToggle: setShared,
6583
+ label: shared ? l.shared : l.private,
6584
+ disabled: isPending,
6585
+ "data-testid": "thread-launcher-visibility"
6586
+ }
6587
+ ),
6588
+ onLater && /* @__PURE__ */ jsx(
6589
+ Button,
6590
+ {
6591
+ variant: "ghost",
6592
+ size: "icon",
6593
+ className: "size-8 text-muted-foreground",
6594
+ disabled: !valid || isPending,
6595
+ onClick: () => onLater(values),
6596
+ "aria-label": l.schedule,
6597
+ title: l.schedule,
6598
+ "data-testid": "thread-launcher-later",
6599
+ children: /* @__PURE__ */ jsx(CalendarClock, { className: "size-4" })
6600
+ }
6601
+ ),
6602
+ /* @__PURE__ */ jsx(
6603
+ Button,
6604
+ {
6605
+ size: "icon",
6606
+ className: "size-8",
6607
+ disabled: !valid || isPending,
6608
+ onClick: () => void start(),
6609
+ "aria-label": startLabel ?? l.start,
6610
+ title: startLabel ?? l.start,
6611
+ "data-testid": "thread-launcher-start",
6612
+ children: isPending ? /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsx(SendHorizontal, { className: "size-4" })
6613
+ }
6614
+ )
6615
+ ] })
6616
+ ] })
6617
+ ] })
6618
+ ] })
6619
+ }
6620
+ );
6621
+ }
6622
+ var DEFAULT_WORKFLOW_RUN_STATUS_LABELS = {
6623
+ allDone: "all {count} steps done"
6624
+ };
6625
+ var SEGMENT = {
6626
+ done: "bg-[hsl(var(--wf-accent))]",
6627
+ running: "bg-[hsl(var(--wf-accent))] animate-pulse",
6628
+ waiting: "bg-[hsl(var(--wf-accent)/0.3)] ring-1 ring-inset ring-[hsl(var(--wf-accent))]",
6629
+ failed: "bg-destructive",
6630
+ skipped: "ring-1 ring-inset ring-muted-foreground/40",
6631
+ ready: "ring-1 ring-inset ring-[hsl(var(--wf-accent)/0.7)]",
6632
+ blocked: "ring-1 ring-inset ring-[hsl(var(--wf-accent)/0.7)]"
6633
+ };
6634
+ function WorkflowRunStatus({
6635
+ steps,
6636
+ states,
6637
+ assigneeOf,
6638
+ labels,
6639
+ isLoading,
6640
+ workStatus,
6641
+ maxSegments = 7,
6642
+ className,
6643
+ testId = "workflow-run-status"
6644
+ }) {
6645
+ const l = { ...DEFAULT_WORKFLOW_RUN_STATUS_LABELS, ...labels };
6646
+ const ordered = stepLevels(steps).flat();
6647
+ const phaseOf = (id) => isLoading ? "blocked" : stepPhase(steps, states, id);
6648
+ const finished = !isLoading && isRunFinished(steps, states);
6649
+ const atId = finished || isLoading ? void 0 : activeStepId(stepLevels(steps), phaseOf);
6650
+ const at = ordered.find((s) => s.id === atId);
6651
+ const phase = at ? phaseOf(at.id) : "done";
6652
+ const assignee = at && ["ready", "waiting"].includes(phase) ? assigneeOf?.(at) : void 0;
6653
+ const state = finished ? workStatus === "done" ? "done" : "ready" : phase === "running" ? "generating" : phase === "failed" ? "failed" : assignee ? "needs" : "next";
6654
+ const detail = at ? at.title : finished ? (l.allDone ?? "").replace("{count}", String(ordered.length)) : void 0;
6655
+ const n = ordered.length;
6656
+ const size = Math.min(maxSegments, n);
6657
+ const centre = at ? ordered.indexOf(at) : n - 1;
6658
+ const start = Math.max(0, Math.min(n - size, centre - Math.floor(size / 2)));
6659
+ const shown = ordered.slice(start, start + size);
6660
+ const ellipsis = (side) => /* @__PURE__ */ jsx(
6661
+ "span",
6662
+ {
6663
+ className: "px-0.5 text-[10px] leading-none text-muted-foreground",
6664
+ "data-testid": `${testId}-more-${side}`,
6665
+ children: "\u2026"
6666
+ }
6667
+ );
6668
+ return /* @__PURE__ */ jsxs(
6669
+ "div",
6670
+ {
6671
+ className: cn("flex min-w-0 flex-col justify-center gap-1", className),
6672
+ "data-testid": testId,
6673
+ "data-phase": phase,
6674
+ children: [
6675
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5", "aria-hidden": true, children: [
6676
+ start > 0 && ellipsis("before"),
6677
+ shown.map((s) => /* @__PURE__ */ jsx(
6678
+ "span",
6679
+ {
6680
+ className: cn(
6681
+ `wf-kind-${stepKindOf(s)}`,
6682
+ "h-1.5 w-3 shrink-0 rounded-full",
6683
+ SEGMENT[phaseOf(s.id)],
6684
+ s.id === atId && "w-5"
6685
+ ),
6686
+ title: s.title,
6687
+ "data-phase": phaseOf(s.id)
6688
+ },
6689
+ s.id
6690
+ )),
6691
+ start + size < n && ellipsis("after")
6692
+ ] }),
6693
+ isLoading ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-tight", children: "\xA0" }) : /* @__PURE__ */ jsx(
6694
+ ThreadStatusLine,
6695
+ {
6696
+ state,
6697
+ name: assignee,
6698
+ detail,
6699
+ labels,
6700
+ testId: `${testId}-line`
6701
+ }
6702
+ )
6703
+ ]
6704
+ }
6705
+ );
6706
+ }
6325
6707
  var STEP_KINDS = /* @__PURE__ */ new Set([
6326
6708
  "step_started",
6327
6709
  "step_waiting",
@@ -6353,13 +6735,21 @@ function groupThreadActivity(steps, items) {
6353
6735
  }
6354
6736
  var DEFAULT_WORKFLOW_THREAD_STRIP_LABELS = {
6355
6737
  happened: "{count} in this step",
6738
+ updates: "{count} updates in this step",
6356
6739
  nothingYet: "Nothing here yet.",
6357
6740
  skip: "Skip this step",
6358
6741
  startedBy: "Started by {step} in {thread}",
6359
6742
  signalled: "This step signalled \u201C{signal}\u201D",
6360
6743
  linkedRun: "Started on \u201C{signal}\u201D: open its thread",
6361
6744
  waitingFor: "Waiting for {name}",
6362
- sentBack: "Sent back to be done again"
6745
+ sentBack: "Sent back to be done again",
6746
+ started: "Started",
6747
+ after: "After",
6748
+ beforeSteps: "Before the first step",
6749
+ afterSteps: "After the last step",
6750
+ kinds: DEFAULT_STEP_KIND_LABELS,
6751
+ documents: DEFAULT_STEP_DOCUMENT_LABELS,
6752
+ record: DEFAULT_STEP_RECORD_LABELS
6363
6753
  };
6364
6754
  function WorkflowThreadStartedBy({
6365
6755
  origin,
@@ -6429,7 +6819,7 @@ function Entry({ item }) {
6429
6819
  )
6430
6820
  ] })
6431
6821
  ] });
6432
- return item.onSelect ? /* @__PURE__ */ jsx(
6822
+ return item.onSelect ? /* @__PURE__ */ jsx(PopoverClose, { asChild: true, children: /* @__PURE__ */ jsx(
6433
6823
  "button",
6434
6824
  {
6435
6825
  type: "button",
@@ -6438,7 +6828,77 @@ function Entry({ item }) {
6438
6828
  "data-testid": `thread-flow-${item.id}`,
6439
6829
  children: content
6440
6830
  }
6441
- ) : /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1.5 px-1 py-0.5", "data-testid": `thread-flow-${item.id}`, children: content });
6831
+ ) }) : /* @__PURE__ */ jsx("span", { className: "flex items-center gap-1.5 px-1 py-0.5", "data-testid": `thread-flow-${item.id}`, children: content });
6832
+ }
6833
+ var BEADS_PX = 32;
6834
+ var DOC_BUTTON_PX = 34;
6835
+ function Beads({ items, label }) {
6836
+ if (!items.length) return null;
6837
+ const faces = /* @__PURE__ */ new Map();
6838
+ for (const item of items) {
6839
+ const key = item.actor ?? item.id;
6840
+ faces.delete(key);
6841
+ faces.set(key, item.avatar);
6842
+ }
6843
+ const shown = [...faces.entries()].slice(-3);
6844
+ return /* @__PURE__ */ jsxs(
6845
+ "span",
6846
+ {
6847
+ className: "flex shrink-0 items-center gap-1",
6848
+ title: label.replace("{count}", String(items.length)),
6849
+ children: [
6850
+ /* @__PURE__ */ jsx("span", { className: "wf-beads [&_svg]:size-4", "aria-hidden": true, children: shown.map(([key, avatar]) => /* @__PURE__ */ jsx("span", { children: avatar }, key)) }),
6851
+ /* @__PURE__ */ jsx("span", { className: "text-[10px] font-normal tabular-nums text-muted-foreground", "aria-hidden": true, children: items.length }),
6852
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: label.replace("{count}", String(items.length)) })
6853
+ ]
6854
+ }
6855
+ );
6856
+ }
6857
+ function PopoverHeading({
6858
+ kind,
6859
+ icon,
6860
+ overline,
6861
+ title
6862
+ }) {
6863
+ return /* @__PURE__ */ jsxs("div", { className: cn(`wf-kind-${kind}`, "flex items-center gap-2 px-1 pb-1"), children: [
6864
+ /* @__PURE__ */ jsx("span", { className: "wf-badge flex size-7 shrink-0 items-center justify-center rounded-md [&_svg]:size-4", children: icon }),
6865
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
6866
+ /* @__PURE__ */ jsx("span", { className: "wf-kind-text block truncate text-[10px] font-semibold uppercase tracking-wider", children: overline }),
6867
+ /* @__PURE__ */ jsx("span", { className: "block truncate text-sm font-semibold leading-snug", children: title })
6868
+ ] })
6869
+ ] });
6870
+ }
6871
+ function EntriesChip({
6872
+ kind,
6873
+ icon,
6874
+ label,
6875
+ items,
6876
+ extra,
6877
+ heading,
6878
+ testId
6879
+ }) {
6880
+ const latest = items.at(-1);
6881
+ return /* @__PURE__ */ jsxs(Popover, { children: [
6882
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6883
+ StepChip,
6884
+ {
6885
+ kind,
6886
+ phase: "ready",
6887
+ icon,
6888
+ label,
6889
+ labelClassName: "max-w-40 truncate",
6890
+ title: latest ? `${label} \xB7 ${latest.label} \xB7 ${latest.time}` : label,
6891
+ className: "shrink-0",
6892
+ "data-testid": testId,
6893
+ children: /* @__PURE__ */ jsx(Beads, { items, label: heading })
6894
+ }
6895
+ ) }),
6896
+ /* @__PURE__ */ jsxs(PopoverContent, { align: "start", className: "w-72 space-y-1 p-2", "data-testid": `${testId}-menu`, children: [
6897
+ /* @__PURE__ */ jsx(PopoverHeading, { kind, icon, overline: heading, title: label }),
6898
+ extra,
6899
+ items.map((item) => /* @__PURE__ */ jsx(Entry, { item }, item.id))
6900
+ ] })
6901
+ ] });
6442
6902
  }
6443
6903
  function WorkflowThreadStrip({
6444
6904
  steps,
@@ -6450,18 +6910,27 @@ function WorkflowThreadStrip({
6450
6910
  signals = [],
6451
6911
  startedBy,
6452
6912
  assigneeOf,
6913
+ nameOfDoc,
6914
+ onOpenDocument,
6915
+ inputs = {},
6916
+ nameOf,
6453
6917
  labels,
6454
6918
  barLabels,
6455
6919
  className
6456
6920
  }) {
6457
6921
  const l = { ...DEFAULT_WORKFLOW_THREAD_STRIP_LABELS, ...labels };
6922
+ const barL = { ...DEFAULT_STEP_BAR_LABELS, ...barLabels };
6458
6923
  const grouped = groupThreadActivity(steps, items);
6459
6924
  const strays = signals.filter((s) => !steps.some((step) => step.id === s.step));
6460
- const chevron = /* @__PURE__ */ jsx(ChevronRight, { className: "size-3 shrink-0 text-muted-foreground" });
6925
+ const link = /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "wf-link wf-kind-start max-w-6", "data-done": true });
6461
6926
  const [selected, setSelected] = useState(null);
6462
6927
  const [open, setOpen] = useState(null);
6463
6928
  const phaseOf = (id) => stepPhase(steps, states, id);
6464
6929
  const iconOf = (step) => step.icon && renderIcon ? renderIcon(step.icon) : void 0;
6930
+ const glyphOf = (step) => {
6931
+ const KindIcon = STEP_KIND_ICONS[stepKindOf(step)];
6932
+ return iconOf(step) ?? /* @__PURE__ */ jsx(KindIcon, {});
6933
+ };
6465
6934
  const waitingOf = (id) => {
6466
6935
  const step = steps.find((s) => s.id === id);
6467
6936
  const phase = phaseOf(id);
@@ -6470,94 +6939,167 @@ function WorkflowThreadStrip({
6470
6939
  const name = step && (phase === "ready" || phase === "waiting") ? assigneeOf?.(step) : void 0;
6471
6940
  return name ? l.waitingFor.replace("{name}", name) : void 0;
6472
6941
  };
6473
- const pill = (step, isCurrent, narrow = false) => {
6942
+ const pill = (step, isCurrent) => {
6474
6943
  const phase = phaseOf(step.id);
6475
6944
  const happened = grouped.byStep[step.id] ?? [];
6476
6945
  const assignee = phase === "ready" || phase === "waiting" ? assigneeOf?.(step) : void 0;
6477
6946
  const waiting = waitingOf(step.id);
6478
6947
  const sentBack = states[step.id]?.sentBack;
6479
- return /* @__PURE__ */ jsxs(Popover, { open: open === step.id, onOpenChange: (o) => setOpen(o ? step.id : null), children: [
6480
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
6481
- "button",
6948
+ const kind = stepKindOf(step);
6949
+ const documents = stepDocuments(steps, states, step.id);
6950
+ const latestDoc = onOpenDocument ? documents.at(-1) : void 0;
6951
+ const finished = ["done", "skipped", "failed"].includes(phase);
6952
+ const chip = /* @__PURE__ */ jsxs(
6953
+ Popover,
6954
+ {
6955
+ open: open === step.id,
6956
+ onOpenChange: (o) => {
6957
+ setOpen(o ? step.id : null);
6958
+ if (o) setSelected(step.id);
6959
+ },
6960
+ children: [
6961
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
6962
+ StepChip,
6963
+ {
6964
+ kind,
6965
+ phase,
6966
+ icon: glyphOf(step),
6967
+ label: step.title,
6968
+ current: isCurrent,
6969
+ heading: /* @__PURE__ */ jsxs(Fragment, { children: [
6970
+ l.kinds[kind],
6971
+ assignee && /* @__PURE__ */ jsxs("span", { "data-testid": `workflow-thread-step-${step.id}-assignee`, children: [
6972
+ " \xB7 ",
6973
+ waiting
6974
+ ] })
6975
+ ] }),
6976
+ labelClassName: isCurrent ? STEP_LABEL_CURRENT : cn(STEP_LABEL, STEP_LABEL_MAX),
6977
+ className: cn(latestDoc && "rounded-r-none"),
6978
+ title: waiting ? `${step.title} \xB7 ${waiting}` : step.title,
6979
+ "data-testid": `workflow-thread-step-${step.id}`,
6980
+ children: [
6981
+ sentBack && /* @__PURE__ */ jsx(
6982
+ CornerUpLeft,
6983
+ {
6984
+ className: "size-3 shrink-0 text-amber-600 dark:text-amber-400",
6985
+ "aria-label": l.sentBack,
6986
+ "data-testid": `workflow-thread-step-${step.id}-sent-back`
6987
+ }
6988
+ ),
6989
+ /* @__PURE__ */ jsx(Beads, { items: happened, label: l.updates })
6990
+ ]
6991
+ }
6992
+ ) }),
6993
+ /* @__PURE__ */ jsxs(
6994
+ PopoverContent,
6995
+ {
6996
+ align: "start",
6997
+ className: "w-80 space-y-1.5 p-2",
6998
+ "data-testid": `workflow-thread-step-${step.id}-menu`,
6999
+ children: [
7000
+ /* @__PURE__ */ jsx(
7001
+ PopoverHeading,
7002
+ {
7003
+ kind,
7004
+ icon: glyphOf(step),
7005
+ overline: `${l.kinds[kind]} \xB7 ${waiting ?? barL.phases[phase]}`,
7006
+ title: step.title
7007
+ }
7008
+ ),
7009
+ sentBack && /* @__PURE__ */ jsx("p", { className: "px-1 text-xs text-amber-700 dark:text-amber-300", children: l.sentBack }),
7010
+ /* @__PURE__ */ jsx(
7011
+ StepDocumentCards,
7012
+ {
7013
+ refs: documents,
7014
+ heading: step.kind === "review" ? phase === "done" ? l.documents.approved : l.documents.toApprove : l.documents.produced,
7015
+ nameOfDoc,
7016
+ onOpen: onOpenDocument,
7017
+ labels: l.documents,
7018
+ testId: `workflow-thread-step-${step.id}-docs`
7019
+ }
7020
+ ),
7021
+ /* @__PURE__ */ jsx(
7022
+ StepRecord,
7023
+ {
7024
+ step,
7025
+ state: states[step.id],
7026
+ inputs,
7027
+ nameOf,
7028
+ labels: l.record,
7029
+ testId: `workflow-thread-step-${step.id}-record`
7030
+ }
7031
+ ),
7032
+ (happened.length > 0 || !finished) && /* @__PURE__ */ jsx("p", { className: "px-1 text-xs font-medium text-muted-foreground", children: happened.length ? l.happened.replace("{count}", String(happened.length)) : l.nothingYet }),
7033
+ happened.map((item) => /* @__PURE__ */ jsx(Entry, { item }, item.id)),
7034
+ renderStepAction?.(step, phase),
7035
+ onSkip && ["ready", "blocked", "failed", "waiting"].includes(phase) && /* @__PURE__ */ jsx(
7036
+ "button",
7037
+ {
7038
+ type: "button",
7039
+ onClick: () => onSkip(step.id),
7040
+ className: "w-full rounded-md px-1 py-1 text-left text-xs text-muted-foreground hover:bg-accent",
7041
+ "data-testid": `workflow-thread-step-${step.id}-skip`,
7042
+ children: l.skip
7043
+ }
7044
+ )
7045
+ ]
7046
+ }
7047
+ )
7048
+ ]
7049
+ }
7050
+ );
7051
+ return latestDoc ? /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center", children: [
7052
+ chip,
7053
+ /* @__PURE__ */ jsx(
7054
+ StepDocumentButton,
6482
7055
  {
6483
- type: "button",
6484
- className: cn(STEP_PILL, "py-0.5", stepPillTone(phase, isCurrent)),
6485
- "aria-current": isCurrent ? "step" : void 0,
6486
- title: waiting ? `${step.title} \xB7 ${waiting}` : step.title,
6487
- "data-phase": phase,
6488
- "data-testid": `workflow-thread-step-${step.id}`,
6489
- children: [
6490
- /* @__PURE__ */ jsx(PhaseMark, { phase, icon: iconOf(step) }),
6491
- /* @__PURE__ */ jsx("span", { className: isCurrent ? STEP_LABEL_CURRENT : cn(STEP_LABEL, STEP_LABEL_MAX), children: step.title }),
6492
- sentBack && /* @__PURE__ */ jsx(
6493
- CornerUpLeft,
6494
- {
6495
- className: "size-3 shrink-0 text-amber-600 dark:text-amber-400",
6496
- "aria-label": l.sentBack,
6497
- "data-testid": `workflow-thread-step-${step.id}-sent-back`
6498
- }
6499
- ),
6500
- assignee && isCurrent && !narrow && /* @__PURE__ */ jsxs(
6501
- "span",
6502
- {
6503
- className: cn(STEP_EXTRA, "flex max-w-[12rem] items-center gap-0.5"),
6504
- title: waiting,
6505
- "data-testid": `workflow-thread-step-${step.id}-assignee`,
6506
- children: [
6507
- /* @__PURE__ */ jsx(UserRound, { className: "size-3 shrink-0" }),
6508
- /* @__PURE__ */ jsx("span", { className: "truncate", children: waiting })
6509
- ]
6510
- }
6511
- ),
6512
- happened.length > 0 && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full bg-muted px-1.5 text-[10px] font-normal text-muted-foreground", children: happened.length })
6513
- ]
7056
+ kind,
7057
+ name: nameOfDoc?.(splitDocRef(latestDoc).id) ?? latestDoc,
7058
+ onOpen: () => onOpenDocument?.(latestDoc),
7059
+ testId: `workflow-thread-step-${step.id}-open-document`
6514
7060
  }
6515
- ) }),
6516
- /* @__PURE__ */ jsxs(
6517
- PopoverContent,
7061
+ )
7062
+ ] }) : chip;
7063
+ };
7064
+ const leading = startedBy || grouped.before.length ? /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
7065
+ grouped.before.length ? /* @__PURE__ */ jsx(
7066
+ EntriesChip,
7067
+ {
7068
+ kind: "start",
7069
+ icon: /* @__PURE__ */ jsx(Zap, {}),
7070
+ label: l.started,
7071
+ items: grouped.before,
7072
+ heading: l.beforeSteps,
7073
+ extra: startedBy && /* @__PURE__ */ jsx(WorkflowThreadStartedBy, { origin: startedBy, labels }),
7074
+ testId: "workflow-thread-start"
7075
+ }
7076
+ ) : startedBy && /* @__PURE__ */ jsx(WorkflowThreadStartedBy, { origin: startedBy, labels }),
7077
+ link
7078
+ ] }) : null;
7079
+ const trailing = grouped.after.length || strays.length ? /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
7080
+ grouped.after.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
7081
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "wf-link max-w-6" }),
7082
+ /* @__PURE__ */ jsx(
7083
+ EntriesChip,
6518
7084
  {
6519
- align: "start",
6520
- className: "w-72 space-y-1 p-2",
6521
- "data-testid": `workflow-thread-step-${step.id}-menu`,
6522
- children: [
6523
- /* @__PURE__ */ jsx("p", { className: "px-1 text-xs font-semibold", children: step.title }),
6524
- waiting && /* @__PURE__ */ jsx("p", { className: "px-1 text-xs", "data-testid": `workflow-thread-step-${step.id}-waiting-for`, children: waiting }),
6525
- sentBack && /* @__PURE__ */ jsx("p", { className: "px-1 text-xs text-amber-700 dark:text-amber-300", children: l.sentBack }),
6526
- /* @__PURE__ */ jsx("p", { className: "px-1 text-xs font-medium text-muted-foreground", children: happened.length ? l.happened.replace("{count}", String(happened.length)) : l.nothingYet }),
6527
- happened.map((item) => /* @__PURE__ */ jsx(Entry, { item }, item.id)),
6528
- renderStepAction?.(step, phase),
6529
- onSkip && ["ready", "blocked", "failed", "waiting"].includes(phase) && /* @__PURE__ */ jsx(
6530
- "button",
6531
- {
6532
- type: "button",
6533
- onClick: () => onSkip(step.id),
6534
- className: "w-full rounded-md px-1 py-1 text-left text-xs text-muted-foreground hover:bg-accent",
6535
- "data-testid": `workflow-thread-step-${step.id}-skip`,
6536
- children: l.skip
6537
- }
6538
- )
6539
- ]
7085
+ kind: "adhoc",
7086
+ icon: /* @__PURE__ */ jsx(MessagesSquare, {}),
7087
+ label: l.after,
7088
+ items: grouped.after,
7089
+ heading: l.afterSteps,
7090
+ testId: "workflow-thread-after"
6540
7091
  }
6541
7092
  )
6542
- ] });
6543
- };
6544
- const leading = startedBy || grouped.before.length ? /* @__PURE__ */ jsxs("ol", { className: "flex shrink-0 items-center gap-1", children: [
6545
- startedBy && /* @__PURE__ */ jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6546
- /* @__PURE__ */ jsx(WorkflowThreadStartedBy, { origin: startedBy, labels }),
6547
- chevron
6548
7093
  ] }),
6549
- grouped.before.map((item) => /* @__PURE__ */ jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6550
- /* @__PURE__ */ jsx(Entry, { item }),
6551
- chevron
6552
- ] }, item.id))
6553
- ] }) : null;
6554
- const trailing = grouped.after.length || strays.length ? /* @__PURE__ */ jsxs("ol", { className: "flex shrink-0 items-center gap-1", children: [
6555
- grouped.after.map((item) => /* @__PURE__ */ jsxs("li", { className: "flex shrink-0 items-center gap-1", children: [
6556
- chevron,
6557
- /* @__PURE__ */ jsx(Entry, { item })
6558
- ] }, item.id)),
6559
- strays.map((s) => /* @__PURE__ */ jsx("li", { className: "flex shrink-0 items-center gap-1", children: /* @__PURE__ */ jsx(SignalPill, { signal: s, l }) }, `${s.step}-${s.signal}`))
7094
+ strays.map((s) => /* @__PURE__ */ jsx(SignalPill, { signal: s, l }, `${s.step}-${s.signal}`))
6560
7095
  ] }) : null;
7096
+ const at = steps.find((s) => s.id === (selected ?? activeStepId(stepLevels(steps), phaseOf)));
7097
+ const headingPx = (step) => `${l.kinds[stepKindOf(step)]} \xB7 ${waitingOf(step.id) ?? ""}`.length * 5.6 - step.title.length * 6.5;
7098
+ const reserve = {
7099
+ always: (at ? Math.max(0, headingPx(at)) : 0) + steps.filter((s) => grouped.byStep[s.id]?.length).length * BEADS_PX + (onOpenDocument ? steps.filter((s) => stepDocuments(steps, states, s.id).length).length * DOC_BUTTON_PX : 0),
7100
+ leading: leading ? 150 : 0,
7101
+ trailing: trailing ? 120 : 0
7102
+ };
6561
7103
  return /* @__PURE__ */ jsx("div", { className: cn("min-w-0 flex-1", className), "data-testid": "workflow-thread-strip", children: /* @__PURE__ */ jsx(
6562
7104
  StepBarFrame,
6563
7105
  {
@@ -6568,16 +7110,13 @@ function WorkflowThreadStrip({
6568
7110
  setSelected(id);
6569
7111
  setOpen(id);
6570
7112
  },
6571
- renderStep: (step, _level, win, narrow) => pill(
6572
- step,
6573
- step.id === win.levels[win.currentLevel]?.primary.id || step.id === selected,
6574
- narrow
6575
- ),
6576
- noteOf: waitingOf,
7113
+ renderStep: (step, _level, win) => pill(step, step.id === win.levels[win.currentLevel]?.primary.id || step.id === selected),
6577
7114
  renderAfter: (level) => signals.filter((s) => level.steps.some((step) => step.id === s.step)).map((s) => /* @__PURE__ */ jsx(SignalPill, { signal: s, l }, `${s.step}-${s.signal}`)),
6578
7115
  leading,
6579
7116
  trailing,
6580
- icon: iconOf,
7117
+ reservePx: reserve,
7118
+ icon: glyphOf,
7119
+ kindOf: stepKindOf,
6581
7120
  labels: { waitingFor: l.waitingFor, ...barLabels },
6582
7121
  tid: (suffix) => `workflow-thread-${suffix}`
6583
7122
  }
@@ -6624,7 +7163,14 @@ var STEP_LABELS = {
6624
7163
  step_progress: "Signed",
6625
7164
  step_sent_back: "Sent back"
6626
7165
  };
6627
- function compactThreadActivity(events) {
7166
+ var STEP_VERBS = {
7167
+ step_started: "started",
7168
+ step_done: "done",
7169
+ step_skipped: "skipped",
7170
+ step_failed: "failed",
7171
+ step_sent_back: "sent back"
7172
+ };
7173
+ function compactThreadActivity(events, stepTitleOf) {
6628
7174
  const result = [];
6629
7175
  const batches = /* @__PURE__ */ new Map();
6630
7176
  for (const event of events) {
@@ -6647,9 +7193,10 @@ function compactThreadActivity(events) {
6647
7193
  entry.label = `Notified ${count} ${count === 1 ? "user" : "users"}`;
6648
7194
  } else if (STEP_LABELS[event.kind]) {
6649
7195
  const documents = eventWaitingDocuments(event.detail);
7196
+ const title = typeof event.detail?.step === "string" ? stepTitleOf?.(event.detail.step) : void 0;
6650
7197
  result.push({
6651
7198
  event,
6652
- label: documents ? waitingForDocumentsText(documents.length) : STEP_LABELS[event.kind],
7199
+ label: documents ? waitingForDocumentsText(documents.length) : title && STEP_VERBS[event.kind] ? `${title} ${STEP_VERBS[event.kind]}` : STEP_LABELS[event.kind],
6653
7200
  recipients: []
6654
7201
  });
6655
7202
  } else if (["artifact_created", "artifact_edited", "document_added", "document_removed"].includes(
@@ -6678,13 +7225,13 @@ function compactThreadActivity(events) {
6678
7225
  "done"
6679
7226
  ].includes(event.kind)) {
6680
7227
  const labels = {
6681
- created: "Started Task",
7228
+ created: "Started thread",
6682
7229
  participant_joined: "Followed Up",
6683
7230
  assistant_responded: "Answered",
6684
7231
  // A stopped turn logs its own crumb, so the header no longer reads the previous
6685
7232
  // answer's "Answered" as the outcome of the turn that was stopped.
6686
7233
  assistant_stopped: "Stopped",
6687
- done: "Marked Done"
7234
+ done: "Marked done"
6688
7235
  };
6689
7236
  result.push({
6690
7237
  event,
@@ -8229,7 +8776,8 @@ function ConversationTurnSpeaker({
8229
8776
  currentUserId,
8230
8777
  colorClass,
8231
8778
  platformName = "ARBI",
8232
- platformLogoSrc = "/favicon.svg"
8779
+ platformLogoSrc = "/favicon.svg",
8780
+ variant = "pill"
8233
8781
  }) {
8234
8782
  if (!role) return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "\u2014" });
8235
8783
  if (role === "assistant" && !actor)
@@ -8237,7 +8785,7 @@ function ConversationTurnSpeaker({
8237
8785
  UserEntity,
8238
8786
  {
8239
8787
  size: "sm",
8240
- variant: "pill",
8788
+ variant,
8241
8789
  interactive: false,
8242
8790
  picture: platformLogoSrc,
8243
8791
  avatarImageClassName: "object-contain p-0.5",
@@ -8252,7 +8800,7 @@ function ConversationTurnSpeaker({
8252
8800
  UserEntity,
8253
8801
  {
8254
8802
  size: "sm",
8255
- variant: "pill",
8803
+ variant,
8256
8804
  interactive: false,
8257
8805
  isMe,
8258
8806
  isAgent: actor.external_id.startsWith("agt-"),
@@ -9923,6 +10471,6 @@ function AgentCreateView({
9923
10471
  ] });
9924
10472
  }
9925
10473
 
9926
- 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_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_COMPOSER_LABELS, DEFAULT_TASK_LIST_LABELS, DEFAULT_TASK_OUTPUTS_CELL_LABELS, DEFAULT_TASK_PLAN_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, DEFAULT_WORKFLOW_THREAD_STRIP_LABELS, DERIVED_NAME_WORDS, EMPTY_NEW_THREAD, EntityChip, GoalCriteria, MAX_TASK_DEPTH, NewThreadDialog, PersonPill, PillSelect, RecurrenceBuilder, STATUS_LABELS, STATUS_ORDER, STATUS_TONE, 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, TaskComposer, TaskFlow, TaskInbox, TaskMoveDialog, TaskOutputsCell, TaskPlan, TaskRunsDialog, TaskStartDialog, TaskStatusPill, TaskTable, TaskThreadChip, TaskTriggerChip, TasksToolbar, ThreadActivity, ThreadNotifyDialog, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WORKFLOW_COLUMN_ORDER, WorkflowConfigDialog, WorkflowDocumentsField, WorkflowLauncher, WorkflowThreadStartedBy, WorkflowThreadStrip, WorkflowsTable, WorkflowsToolbar, agentConfigSectionToValues, agentCreatorToConfigSection, asTaskStatus, authModeFor, buildRRule, buildTaskRows, buildWorkflowScopeSource, compactThreadActivity, composePersona, composerToTaskQuery, composerToWorkRequest, composerToWorkflowRequest, composerToWorkflowUpdate, createTaskColumns, createWorkflowColumns, createsWork, defaultScopeRenderer, defaultTaskComposerValues, deriveAgentName, deriveWorkflowName, descendantIds, describeRRule, filterConversationRows, firstWords, formatElapsed, goalProgress, groupThreadActivity, hasTaskFields, hasTrigger, humanizeSection, indexTasks, inferType, inputDocumentIds, isAgenticWorkflow, isOutOfBounds, isPlainTodo, isSkillRow, isValidAgentName, isoToLocalInput, linkedRunsFromActivity, localInputToIso, matchWorkflowScope, moveTargets, newThreadToRequest, nextCriterionId, ownerExtId, parseRRule, prettifyKey, resolveScopeInputs, skillSlug, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, useWorkflowPreview, workflowFromSkillMarkdown, workflowStatus, workflowTaskFields, workflowToComposerValues, workflowToSkillMarkdown, workflowTriggerType, workflowWhen };
9927
- //# sourceMappingURL=chunk-ZP4IFW2E.js.map
9928
- //# sourceMappingURL=chunk-ZP4IFW2E.js.map
10474
+ 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_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_COMPOSER_LABELS, DEFAULT_TASK_LIST_LABELS, DEFAULT_TASK_OUTPUTS_CELL_LABELS, DEFAULT_TASK_PLAN_LABELS, DEFAULT_TASK_RUNS_DIALOG_LABELS, DEFAULT_TASK_STATUS_PILL_LABELS, DEFAULT_TASK_THREAD_CHIP_LABELS, DEFAULT_TASK_TRIGGER_CHIP_LABELS, DEFAULT_THREAD_LAUNCHER_LABELS, DEFAULT_THREAD_STATE_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, DEFAULT_WORKFLOW_RUN_STATUS_LABELS, DEFAULT_WORKFLOW_THREAD_STRIP_LABELS, DERIVED_NAME_WORDS, EMPTY_NEW_THREAD, EntityChip, GoalCriteria, MAX_TASK_DEPTH, NewThreadDialog, PersonPill, PillSelect, RecurrenceBuilder, STATUS_LABELS, STATUS_ORDER, STATUS_TONE, 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, TaskComposer, TaskFlow, TaskInbox, TaskMoveDialog, TaskOutputsCell, TaskPlan, TaskRunsDialog, TaskStartDialog, TaskStatusPill, TaskTable, TaskThreadChip, TaskTriggerChip, TasksToolbar, ThreadActivity, ThreadLauncher, ThreadNotifyDialog, ThreadStatusLine, TupleArrayField, UploadTaskItem, UploadTaskList, WEEKDAYS, WORKFLOW_COLUMN_ORDER, WorkflowConfigDialog, WorkflowDocumentsField, WorkflowLauncher, WorkflowRunStatus, WorkflowThreadStartedBy, WorkflowThreadStrip, WorkflowsTable, WorkflowsToolbar, agentConfigSectionToValues, agentCreatorToConfigSection, asTaskStatus, authModeFor, buildRRule, buildTaskRows, buildWorkflowScopeSource, compactThreadActivity, composePersona, composerToTaskQuery, composerToWorkRequest, composerToWorkflowRequest, composerToWorkflowUpdate, createTaskColumns, createWorkflowColumns, createsWork, defaultScopeRenderer, defaultTaskComposerValues, deriveAgentName, deriveWorkflowName, descendantIds, describeRRule, filterConversationRows, firstWords, formatElapsed, goalProgress, groupThreadActivity, hasTaskFields, hasTrigger, humanizeSection, indexTasks, inferType, inputDocumentIds, isAgenticWorkflow, isOutOfBounds, isPlainTodo, isSkillRow, isValidAgentName, isoToLocalInput, linkedRunsFromActivity, localInputToIso, matchWorkflowScope, moveTargets, newThreadToRequest, nextCriterionId, ownerExtId, parseRRule, prettifyKey, resolveScopeInputs, skillSlug, stripPersonaPreamble, summarizeAgent, summarizeCapabilities, taskComposerToCreateRequest, taskComposerToUpdateRequest, taskNeedsAccess, taskToComposerValues, useWorkflowPreview, workflowFromSkillMarkdown, workflowStatus, workflowTaskFields, workflowToComposerValues, workflowToSkillMarkdown, workflowTriggerType, workflowWhen };
10475
+ //# sourceMappingURL=chunk-EJSJ27HV.js.map
10476
+ //# sourceMappingURL=chunk-EJSJ27HV.js.map