@mcp-b/react-components 0.46.7 → 0.48.0

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 (130) hide show
  1. package/dist/{CodeBlock-CcteqDvA.js → CodeBlock-BSJl682D.js} +1 -1
  2. package/dist/Correspondent-7K6uNLUm.d.ts +64 -0
  3. package/dist/{FileTree-jtP9471I.js → FileTree-DvE0hNZu.js} +1 -1
  4. package/dist/{SetupChecklist-BXwSSorj.js → SetupChecklist-DeTU9YpW.js} +1 -1
  5. package/dist/ThinkChat-CwMdEum8.d.ts +185 -0
  6. package/dist/{ThinkChat-qztQ6Clo.js → ThinkChat-DiI6hhDP.js} +14 -14
  7. package/dist/ThinkThreadPicker-yFz4vvIf.d.ts +91 -0
  8. package/dist/{Workspace-DZusrEeP.d.ts → Workspace-LIoU30n7.d.ts} +13 -2
  9. package/dist/{WorkspaceFileView-D0HyoUV8.js → WorkspaceFileView-C_WnYm-a.js} +4 -4
  10. package/dist/{WorkspaceLink-DtH66bAY.js → WorkspaceLink-B1d2GIGl.js} +7 -2
  11. package/dist/WorkspaceLive-DfjH1Ypm.d.ts +61 -0
  12. package/dist/{WorkspaceMessageResponse-CJCmGvTx.js → WorkspaceMessageResponse-BqOezptB.js} +79 -40
  13. package/dist/WorkspaceMessageResponse-kJYU8Onj.d.ts +48 -0
  14. package/dist/components/agents-sdk/AgentActivity.js +1 -1
  15. package/dist/components/agents-sdk/AgentChat.js +2 -2
  16. package/dist/components/agents-sdk/BrowserLiveScreen.js +1 -1
  17. package/dist/components/agents-sdk/BrowserLiveView.js +1 -1
  18. package/dist/components/agents-sdk/BrowserReplay.js +1 -1
  19. package/dist/components/agents-sdk/BrowserRunPanel.js +1 -1
  20. package/dist/components/agents-sdk/ManagerOffice.d.ts +41 -50
  21. package/dist/components/agents-sdk/ManagerOffice.js +359 -978
  22. package/dist/components/agents-sdk/McpConnectionRequest.js +1 -1
  23. package/dist/components/agents-sdk/McpPluginCatalog.js +1 -1
  24. package/dist/components/agents-sdk/McpServerPicker.js +1 -1
  25. package/dist/components/agents-sdk/ModelSelector.js +1 -1
  26. package/dist/components/agents-sdk/PromptInputCommands.js +1 -1
  27. package/dist/components/agents-sdk/SubagentRunIndicator.js +1 -1
  28. package/dist/components/agents-sdk/ThinkChat.d.ts +1 -180
  29. package/dist/components/agents-sdk/ThinkChat.js +1 -1
  30. package/dist/components/agents-sdk/ThinkChatToolPanels.js +1 -1
  31. package/dist/components/agents-sdk/ThinkExecutionDetail.js +1 -1
  32. package/dist/components/agents-sdk/ThinkExecutionStatus.js +1 -1
  33. package/dist/components/agents-sdk/ThinkExecutionWorkbench.js +1 -1
  34. package/dist/components/agents-sdk/ThinkFullApp.d.ts +12 -3
  35. package/dist/components/agents-sdk/ThinkFullApp.js +15 -3
  36. package/dist/components/agents-sdk/ThinkRoutineBrowser.js +1 -1
  37. package/dist/components/agents-sdk/ThinkRoutineForm.js +1 -1
  38. package/dist/components/agents-sdk/ThinkRoutineLibrary.js +1 -1
  39. package/dist/components/agents-sdk/ThinkSidepanel.d.ts +20 -5
  40. package/dist/components/agents-sdk/ThinkSidepanel.js +48 -36
  41. package/dist/components/agents-sdk/ThinkThreadPicker.d.ts +1 -90
  42. package/dist/components/agents-sdk/ThinkThreadPicker.js +1 -1
  43. package/dist/components/agents-sdk/Workspace.d.ts +2 -2
  44. package/dist/components/agents-sdk/Workspace.js +13 -10
  45. package/dist/components/agents-sdk/WorkspaceBrowser.d.ts +1 -1
  46. package/dist/components/agents-sdk/WorkspaceBrowser.js +1 -1
  47. package/dist/components/agents-sdk/WorkspaceConcept.d.ts +45 -0
  48. package/dist/components/agents-sdk/WorkspaceConcept.js +42 -0
  49. package/dist/components/agents-sdk/WorkspaceCorrespondence.d.ts +96 -0
  50. package/dist/components/agents-sdk/WorkspaceCorrespondence.js +429 -0
  51. package/dist/components/agents-sdk/WorkspaceExecution.d.ts +115 -0
  52. package/dist/components/agents-sdk/WorkspaceExecution.js +330 -0
  53. package/dist/components/agents-sdk/WorkspaceExplorer.d.ts +1 -1
  54. package/dist/components/agents-sdk/WorkspaceExplorer.js +2 -2
  55. package/dist/components/agents-sdk/WorkspaceFileView.js +1 -1
  56. package/dist/components/agents-sdk/WorkspaceHeader.js +1 -1
  57. package/dist/components/agents-sdk/WorkspaceLink.js +1 -1
  58. package/dist/components/agents-sdk/WorkspaceLive.d.ts +2 -0
  59. package/dist/components/agents-sdk/WorkspaceLive.js +113 -0
  60. package/dist/components/agents-sdk/WorkspaceMessageResponse.d.ts +2 -2
  61. package/dist/components/agents-sdk/WorkspaceMessageResponse.js +2 -2
  62. package/dist/components/agents-sdk/WorkspaceMountManager.js +1 -1
  63. package/dist/components/agents-sdk/WorkspaceProject.d.ts +131 -0
  64. package/dist/components/agents-sdk/WorkspaceProject.js +238 -0
  65. package/dist/components/agents-sdk/WorkspaceUserScript.d.ts +47 -0
  66. package/dist/components/agents-sdk/WorkspaceUserScript.js +146 -0
  67. package/dist/components/ai-sdk/Activity.js +1 -1
  68. package/dist/components/ai-sdk/AgentChatStartScreen.js +1 -1
  69. package/dist/components/ai-sdk/Approval.js +1 -1
  70. package/dist/components/ai-sdk/Artifact.js +3 -3
  71. package/dist/components/ai-sdk/ChainOfThought.d.ts +1 -1
  72. package/dist/components/ai-sdk/ChainOfThought.js +1 -1
  73. package/dist/components/ai-sdk/Checkpoint.js +1 -1
  74. package/dist/components/ai-sdk/CodeBlock.js +1 -1
  75. package/dist/components/ai-sdk/ComposerLink.d.ts +4 -1
  76. package/dist/components/ai-sdk/ComposerLink.js +4 -3
  77. package/dist/components/ai-sdk/ConnectedAppCards.d.ts +29 -2
  78. package/dist/components/ai-sdk/ConnectedAppCards.js +78 -103
  79. package/dist/components/ai-sdk/Conversation.js +1 -1
  80. package/dist/components/ai-sdk/Correspondent.d.ts +2 -0
  81. package/dist/components/ai-sdk/Correspondent.js +145 -0
  82. package/dist/components/ai-sdk/Goal.js +1 -1
  83. package/dist/components/ai-sdk/MediaPreviewCard.js +1 -1
  84. package/dist/components/ai-sdk/Message.js +1 -1
  85. package/dist/components/ai-sdk/MessageScroller.js +1 -1
  86. package/dist/components/ai-sdk/MessageScrollerVirtual.js +1 -1
  87. package/dist/components/ai-sdk/Plan.js +1 -1
  88. package/dist/components/ai-sdk/PromptInput.js +1 -1
  89. package/dist/components/ai-sdk/Queue.js +1 -1
  90. package/dist/components/ai-sdk/Reasoning.js +1 -1
  91. package/dist/components/ai-sdk/Sources.js +1 -1
  92. package/dist/components/ai-sdk/Task.js +1 -1
  93. package/dist/components/extension/ChatGptSignInScreen.js +1 -1
  94. package/dist/components/extension/CodexModelSelector.js +1 -1
  95. package/dist/components/extension/ConversationTabPicker.js +1 -1
  96. package/dist/components/foundations/Checkbox.js +1 -1
  97. package/dist/components/foundations/ContextMenu.js +1 -1
  98. package/dist/components/foundations/Menubar.js +1 -1
  99. package/dist/components/foundations/SearchField.js +1 -1
  100. package/dist/components/foundations/Select.js +1 -1
  101. package/dist/components/foundations/Stepper.js +1 -1
  102. package/dist/components/foundations/Toast.js +1 -1
  103. package/dist/components/foundations/icons.d.ts +2 -2
  104. package/dist/components/foundations/icons.js +2 -2
  105. package/dist/components/general-purpose/Commit.js +2 -2
  106. package/dist/components/general-purpose/EnvironmentVariables.js +2 -2
  107. package/dist/components/general-purpose/FileTree.js +1 -1
  108. package/dist/components/general-purpose/PricingPlanCard.js +1 -1
  109. package/dist/components/general-purpose/ResponsiveSidebarShell.js +1 -1
  110. package/dist/components/general-purpose/SetupChecklist.js +1 -1
  111. package/dist/components/general-purpose/Terminal.js +2 -2
  112. package/dist/components/general-purpose/TestResults.js +1 -1
  113. package/dist/components/general-purpose/ThemeModeControl.js +1 -1
  114. package/dist/components/general-purpose/WebPreview.js +1 -1
  115. package/dist/components/nanites/AgentConnection.js +2 -2
  116. package/dist/components/nanites/AgentToolDetail.d.ts +1 -1
  117. package/dist/components/nanites/AgentToolDetail.js +2 -2
  118. package/dist/{copy-button-BABPlsc-.js → copy-button-Dk2vRe9j.js} +1 -1
  119. package/dist/{icons-ChPpNMmU.d.ts → icons-CCZGYUwU.d.ts} +6 -1
  120. package/dist/{icons-BC4HZqSK.js → icons-CeGfXO21.js} +3 -2
  121. package/dist/styles/base.css +2 -2
  122. package/dist/styles/connected-app-card.css +8 -0
  123. package/dist/styles/correspondent.css +73 -0
  124. package/dist/styles/description-list.css +3 -1
  125. package/dist/styles/index.css +2 -0
  126. package/dist/styles/manager-office.css +380 -1086
  127. package/dist/styles/workspace-concepts.css +28 -0
  128. package/dist/workspace-assets-GqsCYxqT.js +168 -0
  129. package/package.json +2 -2
  130. package/dist/WorkspaceMessageResponse-D66ty4FO.d.ts +0 -24
@@ -1,15 +1,14 @@
1
1
  import { getMcpServerIconSrc } from "../../utils/mcp-server-catalog.js";
2
2
  import { t as cx } from "../../class-names-BiMDVpUo.js";
3
3
  import { Collapsible } from "../foundations/Collapsible.js";
4
- import { $ as WarningIcon, B as PlusIcon, C as FolderIcon, D as LinkIcon, H as RefreshIcon, K as SpinnerIcon, L as PauseIcon, P as MonitorIcon, R as PencilIcon, T as InfoIcon, _ as DotIcon, a as ArrowUpIcon, b as EyeIcon, d as CheckIcon, f as ChevronDownIcon, j as MessageSquareIcon, n as ArrowDownIcon, p as ChevronRightIcon, tt as XIcon, u as CalendarIcon, v as DownloadIcon, z as PlayIcon } from "../../icons-BC4HZqSK.js";
4
+ import { B as PlusIcon, C as FolderIcon, D as LinkIcon, K as SpinnerIcon, L as PauseIcon, P as MonitorIcon, R as PencilIcon, S as FileIcon, T as InfoIcon, _ as DotIcon, d as CheckIcon, et as WarningIcon, f as ChevronDownIcon, j as MessageSquareIcon, p as ChevronRightIcon, u as CalendarIcon } from "../../icons-CeGfXO21.js";
5
5
  import { Button } from "../foundations/Button.js";
6
6
  import { AgentAttention, AgentAttentionActions, AgentAttentionBody, AgentAttentionHeader } from "../ai-sdk/AgentAttention.js";
7
7
  import { Tooltip } from "../foundations/Tooltip.js";
8
- import { Menu } from "../foundations/Menu.js";
9
8
  import { Avatar } from "../foundations/Avatar.js";
10
9
  import { AppIcon } from "../foundations/AppIcon.js";
11
10
  import { n as findCatalogMcpServerCard } from "../../mcp-server-7NR24ASj.js";
12
- import { Select } from "../foundations/Select.js";
11
+ import { CorrespondentName, correspondentHandleLabel } from "../ai-sdk/Correspondent.js";
13
12
  import { EmptyState } from "../foundations/EmptyState.js";
14
13
  import { LinkButton } from "../foundations/LinkButton.js";
15
14
  import "../foundations/icons.js";
@@ -124,26 +123,16 @@ function employeeStatusText(employee) {
124
123
  const label = statusLabels[employee.status];
125
124
  return count ? `${label} · ${count} handoff${count === 1 ? "" : "s"}` : label;
126
125
  }
127
- function statusIcon(status) {
128
- if (status === "needs-you" || status === "issue") return /* @__PURE__ */ jsx(WarningIcon, {});
129
- if (status === "unavailable") return /* @__PURE__ */ jsx(XIcon, {});
130
- if (status === "working" || status === "connecting") return /* @__PURE__ */ jsx(SpinnerIcon, {});
131
- if (status === "offline") return /* @__PURE__ */ jsx(MonitorIcon, {});
132
- return /* @__PURE__ */ jsx(PauseIcon, {});
126
+ /** One presence phrase on the office row. Counts stay in the accessible name. */
127
+ function employeePresenceCaption(employee) {
128
+ return statusLabels[employee.status];
133
129
  }
134
130
  function EmployeePresence({ employee }) {
135
- const label = employeeStatusText(employee);
136
- return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: /* @__PURE__ */ jsx("span", {
131
+ return /* @__PURE__ */ jsx("span", {
137
132
  className: "manager-office__nav-status",
138
133
  "data-status": employee.status,
139
- role: "img",
140
- "aria-label": label,
141
- children: statusIcon(employee.status)
142
- }) }), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
143
- side: "top",
144
- sideOffset: 6,
145
- children: /* @__PURE__ */ jsx(Tooltip.Popup, { children: label })
146
- }) })] });
134
+ "aria-hidden": "true"
135
+ });
147
136
  }
148
137
  /**
149
138
  * Each employee is a Chrome profile, so the bubble wears its profile color —
@@ -355,15 +344,6 @@ function relativeTime(timestamp, now) {
355
344
  if (elapsed < day) return `${Math.floor(elapsed / hour)}h`;
356
345
  return `${Math.floor(elapsed / day)}d`;
357
346
  }
358
- function routineDetail(routine) {
359
- const schedule = routine.enabled ? routine.task.schedule : `Paused · ${routine.task.schedule}`;
360
- const finishedRuns = routine.runs.filter((run) => run.completedAt != null);
361
- if (!finishedRuns.length) return schedule;
362
- return `${schedule} · ${finishedRuns.filter((run) => {
363
- const status = getThinkExecutionRunStatus(run);
364
- return status === "completed" || status === "complete";
365
- }).length} of ${finishedRuns.length} recent runs completed`;
366
- }
367
347
  function Timestamp({ now, timestamp }) {
368
348
  const date = new Date(timestamp);
369
349
  return /* @__PURE__ */ jsx("time", {
@@ -372,16 +352,6 @@ function Timestamp({ now, timestamp }) {
372
352
  children: relativeTime(timestamp, now)
373
353
  });
374
354
  }
375
- const channelDirectionLabels = {
376
- input: "In",
377
- output: "Out",
378
- both: "In · Out"
379
- };
380
- function channelDirectionIcon(direction) {
381
- if (direction === "input") return /* @__PURE__ */ jsx(ArrowDownIcon, {});
382
- if (direction === "output") return /* @__PURE__ */ jsx(ArrowUpIcon, {});
383
- return /* @__PURE__ */ jsx(RefreshIcon, {});
384
- }
385
355
  /**
386
356
  * Deliberately the same three glyphs the employee statuses use: a channel that
387
357
  * needs a sign-in is the same kind of event as an employee that needs one, and
@@ -439,13 +409,6 @@ function ChannelRow({ channel }) {
439
409
  children: channel.detail ?? channelStatusLabels[channel.status]
440
410
  })]
441
411
  }),
442
- /* @__PURE__ */ jsx("span", {
443
- className: "manager-office__channel-direction",
444
- "aria-label": `Direction: ${channelDirectionLabels[channel.direction]}`,
445
- role: "img",
446
- title: channelDirectionLabels[channel.direction],
447
- children: channelDirectionIcon(channel.direction)
448
- }),
449
412
  /* @__PURE__ */ jsxs("span", {
450
413
  className: "manager-office__channel-status",
451
414
  "data-status": channel.status,
@@ -528,32 +491,30 @@ function ManagerOfficeSidebarAlert({ className, detail, title, ...props }) {
528
491
  * content, but the Workforce header, roster identity, status language, scrolling,
529
492
  * and footer placement stay component-owned and therefore cannot drift.
530
493
  */
531
- function ManagerOfficeSidebar({ className, closeSidebarOnCompact, content, employees, renderLink, footer, officeActions, selectedEmployeeId, ...props }) {
494
+ function moveRosterFocus(event, layout) {
495
+ const nextKey = layout === "office" ? "ArrowDown" : "ArrowRight";
496
+ const prevKey = layout === "office" ? "ArrowUp" : "ArrowLeft";
497
+ if (event.key !== nextKey && event.key !== prevKey && event.key !== "Home" && event.key !== "End") return;
498
+ const links = [...event.currentTarget.querySelectorAll("a[href], button")];
499
+ const index = links.findIndex((link) => link === document.activeElement);
500
+ if (index < 0) return;
501
+ event.preventDefault();
502
+ const last = links.length - 1;
503
+ links[event.key === "Home" ? 0 : event.key === "End" ? last : event.key === nextKey ? Math.min(last, index + 1) : Math.max(0, index - 1)]?.focus();
504
+ }
505
+ function ManagerOfficeSidebar({ className, closeSidebarOnCompact, content, employees, renderLink, footer, layout = "office", officeActions, selectedEmployeeId, ...props }) {
532
506
  const rosterLabelId = React.useId();
533
- const employeeNavRef = React.useRef(null);
534
- const [employeeNavOverflows, setEmployeeNavOverflows] = React.useState(false);
535
507
  const profileColors = rosterProfileColors(employees);
536
- React.useLayoutEffect(() => {
537
- const employeeNav = employeeNavRef.current;
538
- if (!employeeNav) return;
539
- const syncOverflow = () => {
540
- const overflows = employeeNav.scrollWidth > employeeNav.clientWidth;
541
- setEmployeeNavOverflows((current) => current === overflows ? current : overflows);
542
- };
543
- syncOverflow();
544
- if (typeof ResizeObserver === "undefined") return;
545
- const observer = new ResizeObserver(syncOverflow);
546
- observer.observe(employeeNav);
547
- return () => observer.disconnect();
548
- }, [employees]);
508
+ const isChat = layout === "chat";
549
509
  return /* @__PURE__ */ jsx(Tooltip.Provider, { children: /* @__PURE__ */ jsxs("nav", {
550
510
  className: cx("manager-office__sidebar", className),
551
511
  "aria-label": "Workforce",
512
+ "data-layout": layout,
552
513
  ...props,
553
514
  children: [
554
515
  /* @__PURE__ */ jsxs("div", {
555
516
  className: "manager-office__sidebar-heading",
556
- children: [/* @__PURE__ */ jsx("strong", { children: "Workforce" }), officeActions ? /* @__PURE__ */ jsx("span", {
517
+ children: [isChat ? null : /* @__PURE__ */ jsx("strong", { children: "Workforce" }), officeActions ? /* @__PURE__ */ jsx("span", {
557
518
  className: "manager-office__sidebar-actions",
558
519
  children: officeActions
559
520
  }) : null]
@@ -564,12 +525,13 @@ function ManagerOfficeSidebar({ className, closeSidebarOnCompact, content, emplo
564
525
  children: "Employees"
565
526
  }),
566
527
  /* @__PURE__ */ jsx("ul", {
567
- ref: employeeNavRef,
568
528
  className: "manager-office__employee-nav",
529
+ role: "list",
569
530
  "aria-labelledby": rosterLabelId,
570
- "data-overflowing": employeeNavOverflows ? "true" : void 0,
531
+ onKeyDown: (event) => moveRosterFocus(event, layout),
571
532
  children: employees.map((employee, index) => {
572
533
  const selected = selectedEmployeeId === employee.id;
534
+ const status = employeeStatusText(employee);
573
535
  return /* @__PURE__ */ jsx("li", {
574
536
  className: "manager-office__employee-group",
575
537
  children: /* @__PURE__ */ jsxs(LinkButton, {
@@ -583,21 +545,25 @@ function ManagerOfficeSidebar({ className, closeSidebarOnCompact, content, emplo
583
545
  size: "sm",
584
546
  className: "manager-office__employee-link",
585
547
  "aria-current": selected ? "page" : void 0,
586
- "aria-label": `Open ${employee.name} · ${employeeStatusText(employee)}`,
587
- title: `${employee.name} · ${employeeStatusText(employee)}`,
548
+ "aria-label": `Open ${employee.name} · ${status}`,
549
+ title: isChat ? `${employee.name} · ${status}` : void 0,
588
550
  children: [/* @__PURE__ */ jsxs("span", {
589
551
  className: "manager-office__employee-avatar",
590
552
  children: [/* @__PURE__ */ jsx(EmployeeAvatar, {
591
553
  employee,
592
554
  color: profileColors.get(employee.id),
593
- index
555
+ index,
556
+ size: isChat ? "sm" : "md"
594
557
  }), /* @__PURE__ */ jsx(EmployeePresence, { employee })]
595
- }), /* @__PURE__ */ jsx("span", {
596
- className: "manager-office__identity sigvelo-visually-hidden",
597
- children: /* @__PURE__ */ jsx("strong", {
558
+ }), isChat ? null : /* @__PURE__ */ jsxs("span", {
559
+ className: "manager-office__identity",
560
+ children: [/* @__PURE__ */ jsx("strong", {
598
561
  className: "sigvelo-truncate",
599
562
  children: employee.name
600
- })
563
+ }), /* @__PURE__ */ jsx("small", {
564
+ className: "sigvelo-truncate",
565
+ children: employeePresenceCaption(employee)
566
+ })]
601
567
  })]
602
568
  })
603
569
  }, employee.id);
@@ -614,860 +580,316 @@ function ManagerOfficeSidebar({ className, closeSidebarOnCompact, content, emplo
614
580
  ]
615
581
  }) });
616
582
  }
617
- function AttentionView({ employees, renderLink, now }) {
618
- const rows = employees.flatMap((employee) => isConnected(employee) ? employee.handoffs.map((handoff) => ({
619
- employee,
620
- handoff
621
- })) : []);
622
- if (!rows.length) return /* @__PURE__ */ jsx("section", {
623
- className: "manager-office__attention",
624
- "data-recipe": "page",
625
- "aria-label": "Waiting on you",
626
- children: /* @__PURE__ */ jsx(EmptyState, {
627
- icon: /* @__PURE__ */ jsx(CheckIcon, {}),
628
- title: "No active handoffs",
629
- description: "Employee connection state remains visible in the roster."
630
- })
631
- });
632
- return /* @__PURE__ */ jsx("section", {
633
- className: "manager-office__attention",
634
- "data-recipe": "page",
635
- "aria-label": "Waiting on you",
636
- children: /* @__PURE__ */ jsx("ul", {
637
- className: "manager-office__attention-list sigvelo-stack-list",
638
- children: rows.map(({ employee, handoff }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(HandoffCard, {
639
- employee,
640
- handoff,
641
- renderLink,
642
- now,
643
- showEmployee: true
644
- }) }, `${employee.id}:${handoff.id}`))
645
- })
646
- });
583
+ function isReviewWork(work) {
584
+ return work.status === "attention" || work.status === "error";
647
585
  }
648
- const dashboardLanes = [
649
- "working",
650
- "needs-you",
651
- "done",
652
- "idle"
653
- ];
654
- const analyticsDateFormatter = new Intl.DateTimeFormat(void 0, {
655
- day: "numeric",
656
- month: "short"
657
- });
658
- function analyticsDateLabel(timestamp) {
659
- return timestamp ? analyticsDateFormatter.format(timestamp) : "—";
586
+ /** Finished or failed work the manager should open in chat — not a live-tab wait. */
587
+ function reviewWorkFor(employee) {
588
+ const waiting = new Set(employee.handoffs.map((handoff) => handoff.workId));
589
+ return employee.work.filter((work) => isReviewWork(work) && !waiting.has(work.id));
660
590
  }
661
- function toggleDashboardFilter(setter, value, checked) {
662
- setter((current) => {
663
- const next = new Set(current);
664
- if (checked) next.add(value);
665
- else next.delete(value);
666
- return next;
667
- });
591
+ function workingSetOf(work) {
592
+ return work.workingSet ?? [];
668
593
  }
669
- const dashboardLaneCopy = {
670
- working: {
671
- title: "In progress",
672
- description: "Employees working now"
673
- },
674
- "needs-you": {
675
- title: "Waiting on you",
676
- description: "Blocked or waiting for you"
677
- },
678
- done: {
679
- title: "Done",
680
- description: "Fresh outcomes to review"
681
- },
682
- idle: {
683
- title: "Idle",
684
- description: "Not working — assign something now"
594
+ function workingSetKey(item) {
595
+ if (item.kind === "file" || item.kind === "folder") return `${item.kind}:${item.path}`;
596
+ if (item.kind === "link") return `link:${item.href}`;
597
+ return `correspondent:${correspondentHandleLabel(item.correspondent.handle)}`;
598
+ }
599
+ function safeHttpUrl(url) {
600
+ try {
601
+ const parsed = new URL(url);
602
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return void 0;
603
+ return parsed.href;
604
+ } catch {
605
+ return;
685
606
  }
686
- };
687
- function dashboardCards(employees, lane) {
688
- if (lane === "idle") return employees.flatMap((employee) => {
689
- if (!isConnected(employee)) return [];
690
- const hasCurrentWork = employee.work.some((work) => [
691
- "running",
692
- "attention",
693
- "error",
694
- "interrupted"
695
- ].includes(work.status));
696
- return employee.status === "idle" && !hasCurrentWork ? [{
697
- employee,
698
- lane
699
- }] : [];
607
+ }
608
+ function providerCardForHref(href) {
609
+ let parsed;
610
+ try {
611
+ parsed = new URL(href);
612
+ } catch {
613
+ return;
614
+ }
615
+ const host = parsed.hostname.toLowerCase();
616
+ if (host === "docs.google.com" || host.endsWith(".docs.google.com")) {
617
+ if (parsed.pathname.includes("/spreadsheets/")) return findCatalogMcpServerCard({ id: "google-sheets" });
618
+ if (parsed.pathname.includes("/document/")) return findCatalogMcpServerCard({ id: "google-docs" });
619
+ if (parsed.pathname.includes("/presentation/")) return findCatalogMcpServerCard({ id: "google-slides" });
620
+ }
621
+ if (host === "drive.google.com" || host.endsWith(".drive.google.com")) return findCatalogMcpServerCard({ id: "google-drive" });
622
+ }
623
+ function workingSetLinkDetail(item) {
624
+ const card = providerCardForHref(item.href);
625
+ if (card) return card.name;
626
+ try {
627
+ return new URL(item.href).hostname.replace(/^www\./u, "");
628
+ } catch {
629
+ return item.href;
630
+ }
631
+ }
632
+ function WorkingSetMark({ item }) {
633
+ if (item.kind === "file") return /* @__PURE__ */ jsx(FileIcon, {});
634
+ if (item.kind === "folder") return /* @__PURE__ */ jsx(FolderIcon, {});
635
+ const card = providerCardForHref(item.href);
636
+ const src = card ? getMcpServerIconSrc(card) : void 0;
637
+ if (src) return /* @__PURE__ */ jsxs(AppIcon.Root, {
638
+ size: "xs",
639
+ variant: "artwork",
640
+ "aria-hidden": "true",
641
+ children: [/* @__PURE__ */ jsx(AppIcon.Image, {
642
+ src,
643
+ alt: ""
644
+ }), /* @__PURE__ */ jsx(AppIcon.Fallback, { children: (card?.name ?? item.title).slice(0, 1) })]
700
645
  });
701
- return employees.flatMap((employee) => {
702
- if (!isConnected(employee)) return lane === "needs-you" ? [{
703
- employee,
704
- lane
705
- }] : [];
706
- if (lane === "working") {
707
- const work = employee.work.find((candidate) => candidate.status === "running");
708
- return work ? [{
709
- employee,
710
- lane,
711
- work
712
- }] : [];
713
- }
714
- if (lane === "done") {
715
- const work = employee.work.find((candidate) => candidate.status === "attention");
716
- return work ? [{
717
- employee,
718
- lane,
719
- work
720
- }] : [];
721
- }
722
- const handoff = employee.handoffs[0];
723
- if (handoff) return [{
724
- employee,
725
- lane,
726
- handoff,
727
- work: employee.work.find((candidate) => candidate.id === handoff.workId)
728
- }];
729
- const work = employee.work.find((candidate) => ["error", "interrupted"].includes(candidate.status));
730
- return work ? [{
646
+ return /* @__PURE__ */ jsx(LinkIcon, {});
647
+ }
648
+ function routineDetail(routine) {
649
+ const schedule = routine.enabled ? routine.task.schedule : `Paused · ${routine.task.schedule}`;
650
+ const finishedRuns = routine.runs.filter((run) => run.completedAt != null);
651
+ if (!finishedRuns.length) return schedule;
652
+ return `${schedule} · ${finishedRuns.filter((run) => {
653
+ const status = getThinkExecutionRunStatus(run);
654
+ return status === "completed" || status === "complete";
655
+ }).length} of ${finishedRuns.length} recent runs completed`;
656
+ }
657
+ function ReviewRow({ employee, renderLink, now, showEmployee, work }) {
658
+ return /* @__PURE__ */ jsxs(LinkButton, {
659
+ render: renderLink({
660
+ kind: "work",
731
661
  employee,
732
- lane,
733
662
  work
734
- }] : [];
735
- });
736
- }
737
- function DashboardBrowserPreview({ card }) {
738
- const connectedEmployee = isConnected(card.employee) ? card.employee : null;
739
- const disconnectedDescription = isConnected(card.employee) ? "" : card.employee.statusDescription;
740
- const title = connectedEmployee ? (card.lane === "done" ? card.work?.title : connectedEmployee.browserPreview?.title) ?? card.work?.title ?? "Ready for a new assignment" : "Browser is offline";
741
- const url = connectedEmployee ? connectedEmployee.browserPreview?.url ?? "New tab" : disconnectedDescription;
742
- const state = card.lane === "working" ? "Live" : card.lane === "needs-you" ? "Paused" : card.lane === "done" ? "Result ready" : connectedEmployee ? "Idle" : "Disconnected";
743
- return /* @__PURE__ */ jsxs("div", {
744
- className: "manager-office__browser-preview",
745
- "data-lane": card.lane,
746
- role: "img",
747
- "aria-label": `${card.employee.name} browser preview: ${title}. ${state}.`,
663
+ }),
664
+ variant: "ghost",
665
+ color: "neutral",
666
+ size: "sm",
667
+ className: "manager-office__work-link",
668
+ "aria-label": `Open ${work.title} to ${threadStatusLabel(work.status).toLowerCase()}`,
748
669
  children: [
749
- /* @__PURE__ */ jsxs("div", {
750
- className: "manager-office__browser-chrome",
751
- "aria-hidden": "true",
752
- children: [
753
- /* @__PURE__ */ jsx("span", {}),
754
- /* @__PURE__ */ jsx("span", {}),
755
- /* @__PURE__ */ jsx("span", {}),
756
- /* @__PURE__ */ jsx("small", { children: url })
757
- ]
758
- }),
759
- /* @__PURE__ */ jsxs("div", {
760
- className: "manager-office__browser-page",
761
- "aria-hidden": "true",
762
- children: [
763
- /* @__PURE__ */ jsx("span", { className: "manager-office__browser-page-mark" }),
764
- /* @__PURE__ */ jsxs("span", {
765
- className: "manager-office__browser-page-copy",
766
- children: [/* @__PURE__ */ jsx("strong", { children: title }), /* @__PURE__ */ jsx("small", { children: card.work?.title ?? card.handoff?.workTitle ?? (connectedEmployee ? url : "") })]
767
- }),
768
- /* @__PURE__ */ jsxs("span", {
769
- className: "manager-office__browser-page-lines",
770
- children: [
771
- /* @__PURE__ */ jsx("i", {}),
772
- /* @__PURE__ */ jsx("i", {}),
773
- /* @__PURE__ */ jsx("i", {})
774
- ]
775
- }),
776
- card.lane === "working" ? /* @__PURE__ */ jsx("span", { className: "manager-office__browser-cursor" }) : null
777
- ]
778
- }),
670
+ /* @__PURE__ */ jsx(ThreadStatusIcon, { status: work.status }),
779
671
  /* @__PURE__ */ jsxs("span", {
780
- className: "manager-office__browser-state",
781
- "aria-hidden": "true",
782
- children: [card.lane === "working" ? /* @__PURE__ */ jsx(SpinnerIcon, {}) : card.lane === "done" ? /* @__PURE__ */ jsx(CheckIcon, {}) : null, state]
783
- })
672
+ className: "manager-office__identity",
673
+ children: [/* @__PURE__ */ jsxs("strong", {
674
+ className: "sigvelo-truncate",
675
+ children: [work.title, work.status === "attention" ? /* @__PURE__ */ jsx("span", {
676
+ className: "manager-office__unread-dot",
677
+ "aria-hidden": "true"
678
+ }) : null]
679
+ }), /* @__PURE__ */ jsxs("small", {
680
+ className: "sigvelo-truncate",
681
+ children: [
682
+ showEmployee ? `${employee.name} · ` : null,
683
+ threadStatusLabel(work.status),
684
+ " · ",
685
+ /* @__PURE__ */ jsx(Timestamp, {
686
+ timestamp: work.updatedAt,
687
+ now
688
+ })
689
+ ]
690
+ })]
691
+ }),
692
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
784
693
  ]
785
694
  });
786
695
  }
787
- function DashboardConnections({ employee }) {
788
- if (!isConnected(employee)) return /* @__PURE__ */ jsx("span", {
789
- className: "manager-office__connection-empty",
790
- children: "Browser connection offline"
696
+ function workingSetItemCaption(item) {
697
+ if (item.kind === "link") return workingSetLinkDetail(item);
698
+ return item.kind === "folder" ? "Workspace folder" : "Workspace file";
699
+ }
700
+ function WorkingSetAttachment(props) {
701
+ const { caption, label, mark, title } = props;
702
+ const contents = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
703
+ className: "manager-office__working-set-mark",
704
+ "aria-hidden": "true",
705
+ children: mark
706
+ }), /* @__PURE__ */ jsx("strong", {
707
+ className: "sigvelo-truncate",
708
+ children: title
709
+ })] });
710
+ const link = "href" in props ? /* @__PURE__ */ jsx(LinkButton, {
711
+ href: props.href,
712
+ target: "_blank",
713
+ rel: "noreferrer",
714
+ variant: "ghost",
715
+ color: "neutral",
716
+ size: "sm",
717
+ className: "manager-office__working-set-link",
718
+ "aria-label": label,
719
+ children: contents
720
+ }) : /* @__PURE__ */ jsx(LinkButton, {
721
+ render: props.render,
722
+ variant: "ghost",
723
+ color: "neutral",
724
+ size: "sm",
725
+ className: "manager-office__working-set-link",
726
+ "aria-label": label,
727
+ children: contents
791
728
  });
792
- if (!employee.channels.length) return /* @__PURE__ */ jsx("span", {
793
- className: "manager-office__connection-empty",
794
- children: "No connectors yet"
729
+ return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, { render: link }), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
730
+ side: "bottom",
731
+ sideOffset: 6,
732
+ children: /* @__PURE__ */ jsx(Tooltip.Popup, { children: caption })
733
+ }) })] });
734
+ }
735
+ function WorkingSetItemRow({ employee, item, renderLink, work }) {
736
+ if (item.kind === "correspondent") return /* @__PURE__ */ jsx("li", {
737
+ className: "manager-office__working-set-item",
738
+ children: /* @__PURE__ */ jsx(CorrespondentName, { correspondent: item.correspondent })
795
739
  });
796
- return /* @__PURE__ */ jsx("div", {
797
- className: "manager-office__dashboard-connections",
798
- "aria-label": "Connections",
799
- children: /* @__PURE__ */ jsx("span", {
800
- className: "manager-office__connection-icons",
801
- children: employee.channels.slice(0, 4).map((channel) => {
802
- const statusLabel = channel.status === "connected" ? "Connected" : channel.status === "needs-auth" ? "Needs sign-in" : "Connection error";
803
- return /* @__PURE__ */ jsxs(Tooltip.Root, { children: [/* @__PURE__ */ jsx(Tooltip.Trigger, {
804
- "aria-label": `${channel.name}: ${statusLabel}`,
805
- delay: 300,
806
- render: /* @__PURE__ */ jsx(AppIcon.Root, {
807
- size: "xs",
808
- "data-status": channel.status
809
- }),
810
- role: "img",
811
- children: /* @__PURE__ */ jsx(ChannelMark, { channel })
812
- }), /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
813
- side: "top",
814
- sideOffset: 6,
815
- children: /* @__PURE__ */ jsxs(Tooltip.Popup, { children: [
816
- channel.name,
817
- " · ",
818
- statusLabel
819
- ] })
820
- }) })] }, channel.id);
740
+ const caption = workingSetItemCaption(item);
741
+ const mark = /* @__PURE__ */ jsx(WorkingSetMark, { item });
742
+ if (item.kind === "link") {
743
+ const href = safeHttpUrl(item.href);
744
+ if (!href) return null;
745
+ return /* @__PURE__ */ jsx("li", {
746
+ className: "manager-office__working-set-item",
747
+ children: /* @__PURE__ */ jsx(WorkingSetAttachment, {
748
+ caption,
749
+ label: `${item.title} (${caption}, opens in a new tab)`,
750
+ href,
751
+ mark,
752
+ title: item.title
821
753
  })
754
+ });
755
+ }
756
+ const location = item.kind === "folder" ? "folder" : "file";
757
+ return /* @__PURE__ */ jsx("li", {
758
+ className: "manager-office__working-set-item",
759
+ children: /* @__PURE__ */ jsx(WorkingSetAttachment, {
760
+ caption,
761
+ label: `Open ${item.title} ${location} in workspace`,
762
+ render: renderLink({
763
+ kind: "workspace",
764
+ employee,
765
+ work,
766
+ path: item.path
767
+ }),
768
+ mark,
769
+ title: item.title
822
770
  })
823
771
  });
824
772
  }
825
- function dashboardCardId(card) {
826
- return `${card.lane}:${card.employee.id}:${card.work?.id ?? card.handoff?.id ?? "employee"}`;
827
- }
828
- function DashboardCard({ card, collapsed, color, index, now, onToggleCollapsed, renderLink }) {
829
- const connectedEmployee = isConnected(card.employee) ? card.employee : null;
830
- const disconnectedDescription = isConnected(card.employee) ? "" : card.employee.statusDescription;
831
- const title = card.handoff?.reason ?? card.work?.title ?? (connectedEmployee ? "No active work" : "Reconnect employee");
832
- const detail = card.handoff?.request ?? (connectedEmployee ? connectedEmployee.role : disconnectedDescription);
773
+ function WorkLane({ employee, now, renderLink, work }) {
774
+ const titleId = React.useId();
775
+ const workingSet = workingSetOf(work);
833
776
  return /* @__PURE__ */ jsxs("article", {
834
- className: "manager-office__dashboard-card",
835
- "data-collapsed": collapsed || void 0,
836
- "data-lane": card.lane,
837
- children: [/* @__PURE__ */ jsxs("header", {
838
- className: "manager-office__dashboard-card-header",
839
- children: [
840
- /* @__PURE__ */ jsx(EmployeeAvatar, {
841
- employee: card.employee,
842
- color,
843
- index,
844
- size: "md"
845
- }),
846
- /* @__PURE__ */ jsxs("span", {
847
- className: "manager-office__dashboard-card-owner",
848
- children: [/* @__PURE__ */ jsx("strong", { children: card.employee.name }), /* @__PURE__ */ jsx("small", {
849
- className: "sigvelo-truncate",
850
- children: connectedEmployee ? connectedEmployee.role : "Employee offline"
851
- })]
852
- }),
853
- /* @__PURE__ */ jsx(Button, {
854
- "aria-expanded": !collapsed,
855
- "aria-label": `${collapsed ? "Expand" : "Collapse"} ${card.employee.name} card`,
856
- className: "manager-office__dashboard-card-toggle",
857
- color: "neutral",
858
- onClick: onToggleCollapsed,
859
- size: "sm",
860
- type: "button",
861
- variant: "ghost",
862
- children: collapsed ? /* @__PURE__ */ jsx(ChevronRightIcon, {}) : /* @__PURE__ */ jsx(ChevronDownIcon, {})
863
- })
864
- ]
865
- }), !collapsed ? /* @__PURE__ */ jsxs(Fragment, { children: [
866
- card.lane === "working" || card.lane === "needs-you" && card.handoff ? /* @__PURE__ */ jsx(DashboardBrowserPreview, { card }) : null,
867
- card.lane === "done" && card.work ? /* @__PURE__ */ jsxs("section", {
868
- className: "manager-office__outcome-summary",
869
- "aria-label": "Completed outcome",
870
- children: [
871
- /* @__PURE__ */ jsx("strong", { children: card.work.title }),
872
- /* @__PURE__ */ jsx("p", { children: card.work.summary ?? `${card.work.title} is complete and ready for review.` }),
873
- /* @__PURE__ */ jsxs("span", {
874
- className: "manager-office__dashboard-updated",
875
- children: [
876
- "Completed ",
877
- /* @__PURE__ */ jsx(Timestamp, {
878
- timestamp: card.work.updatedAt,
879
- now
880
- }),
881
- " ago"
882
- ]
883
- })
884
- ]
885
- }) : /* @__PURE__ */ jsxs("div", {
886
- className: "manager-office__dashboard-card-copy",
887
- children: [
888
- /* @__PURE__ */ jsx("strong", { children: title }),
889
- /* @__PURE__ */ jsx("small", { children: detail }),
890
- card.work ? /* @__PURE__ */ jsxs("span", {
891
- className: "manager-office__dashboard-updated",
892
- children: [
893
- "Updated ",
894
- /* @__PURE__ */ jsx(Timestamp, {
895
- timestamp: card.work.updatedAt,
896
- now
897
- }),
898
- " ago"
899
- ]
900
- }) : null
901
- ]
902
- }),
903
- /* @__PURE__ */ jsx(DashboardConnections, { employee: card.employee }),
904
- /* @__PURE__ */ jsx("footer", {
905
- className: "manager-office__dashboard-card-actions",
906
- children: connectedEmployee && card.lane === "idle" ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(LinkButton, {
907
- render: renderLink({
908
- kind: "new-work",
909
- employee: connectedEmployee
910
- }),
911
- size: "sm",
912
- children: [/* @__PURE__ */ jsx(PlayIcon, {}), "Assign work"]
913
- }), /* @__PURE__ */ jsxs(LinkButton, {
777
+ className: "manager-office__lane",
778
+ "aria-labelledby": titleId,
779
+ children: [
780
+ /* @__PURE__ */ jsx("h3", {
781
+ id: titleId,
782
+ className: "manager-office__lane-heading",
783
+ children: /* @__PURE__ */ jsxs(LinkButton, {
914
784
  render: renderLink({
915
- kind: "new-routine",
916
- employee: connectedEmployee
785
+ kind: "work",
786
+ employee,
787
+ work
917
788
  }),
918
789
  variant: "ghost",
919
790
  color: "neutral",
920
791
  size: "sm",
921
- children: [/* @__PURE__ */ jsx(CalendarIcon, {}), "Set routine"]
922
- })] }) : connectedEmployee && card.handoff ? /* @__PURE__ */ jsxs(LinkButton, {
923
- render: renderLink({
924
- kind: "handoff",
925
- employee: connectedEmployee,
926
- handoff: card.handoff
927
- }),
928
- size: "sm",
929
- children: [/* @__PURE__ */ jsx(EyeIcon, {}), "Help in browser"]
930
- }) : connectedEmployee && card.work ? /* @__PURE__ */ jsxs(LinkButton, {
931
- render: renderLink({
932
- kind: "work",
933
- employee: connectedEmployee,
934
- work: card.work
935
- }),
936
- size: "sm",
937
- children: [card.lane === "done" ? /* @__PURE__ */ jsx(CheckIcon, {}) : card.lane === "needs-you" ? /* @__PURE__ */ jsx(WarningIcon, {}) : /* @__PURE__ */ jsx(EyeIcon, {}), card.lane === "done" ? "Review result" : card.lane === "needs-you" ? "Open issue" : "Watch work"]
938
- }) : /* @__PURE__ */ jsxs(LinkButton, {
939
- render: renderLink({
940
- kind: "employee",
941
- employee: card.employee
942
- }),
943
- size: "sm",
944
- children: [/* @__PURE__ */ jsx(RefreshIcon, {}), "Reconnect"]
945
- })
946
- })
947
- ] }) : null]
948
- });
949
- }
950
- function DashboardFilterMenu({ label, onToggle, options, selected }) {
951
- return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsxs(Button, {
952
- variant: "outline",
953
- color: "neutral",
954
- size: "sm",
955
- "aria-label": `${label} filter`,
956
- className: "manager-office__filter-trigger",
957
- "data-active": selected.size || void 0,
958
- render: /* @__PURE__ */ jsx(Menu.Trigger, { unstyled: true }),
959
- children: [
960
- /* @__PURE__ */ jsx("span", { children: label }),
961
- selected.size ? /* @__PURE__ */ jsx("strong", { children: selected.size }) : null,
962
- /* @__PURE__ */ jsx(ChevronDownIcon, {})
963
- ]
964
- }), /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, {
965
- sideOffset: 6,
966
- align: "start",
967
- children: /* @__PURE__ */ jsx(Menu.Popup, {
968
- className: "manager-office__filter-popup",
969
- children: /* @__PURE__ */ jsxs(Menu.Group, { children: [/* @__PURE__ */ jsx(Menu.GroupLabel, { children: label }), options.map((option) => /* @__PURE__ */ jsxs(Menu.CheckboxItem, {
970
- checked: selected.has(option.value),
971
- onCheckedChange: (checked) => onToggle(option.value, checked === true),
972
- children: [/* @__PURE__ */ jsx(Menu.CheckboxItemIndicator, {}), option.label]
973
- }, option.value))] })
974
- })
975
- }) })] });
976
- }
977
- function AssignWorkMenu({ employees, profileColors, renderLink }) {
978
- return /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsxs(Button, {
979
- size: "sm",
980
- className: "manager-office__assignment-trigger",
981
- disabled: !employees.length,
982
- render: /* @__PURE__ */ jsx(Menu.Trigger, { unstyled: true }),
983
- children: ["Assign work", /* @__PURE__ */ jsx(ChevronDownIcon, {})]
984
- }), /* @__PURE__ */ jsx(Menu.Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, {
985
- align: "end",
986
- sideOffset: 6,
987
- children: /* @__PURE__ */ jsx(Menu.Popup, {
988
- "aria-label": "Choose an AI employee",
989
- className: "manager-office__assignment-popup",
990
- children: /* @__PURE__ */ jsxs(Menu.Group, { children: [/* @__PURE__ */ jsx(Menu.GroupLabel, { children: "Choose an employee" }), employees.map((employee, index) => /* @__PURE__ */ jsxs(Menu.Item, {
991
- "aria-label": `Assign work to ${employee.name}`,
992
- className: "manager-office__assignment-item",
993
- render: renderLink({
994
- kind: "new-work",
995
- employee
996
- }),
997
- children: [
998
- /* @__PURE__ */ jsx(EmployeeAvatar, {
999
- employee,
1000
- color: profileColors.get(employee.id),
1001
- index
1002
- }),
1003
- /* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("strong", { children: employee.name }), /* @__PURE__ */ jsx("small", {
1004
- className: "sigvelo-truncate",
1005
- children: employee.role
1006
- })] }),
1007
- /* @__PURE__ */ jsx(ChevronRightIcon, {})
1008
- ]
1009
- }, employee.id))] })
1010
- })
1011
- }) })] });
1012
- }
1013
- function employeeMatchesUtilization(employee, selected) {
1014
- if (!selected.size) return true;
1015
- if (!isConnected(employee)) return selected.has("connector-issue");
1016
- const matches = [];
1017
- if (employee.browserPreview) matches.push("browser");
1018
- if (employee.routines.length) matches.push("routines");
1019
- else matches.push("no-routines");
1020
- if (employee.channels.some((channel) => channel.status !== "connected")) matches.push("connector-issue");
1021
- return matches.some((value) => selected.has(value));
1022
- }
1023
- function niceAxisMaximum(values) {
1024
- const maximum = Math.max(...values, 1);
1025
- const roughStep = maximum / 2;
1026
- const magnitude = 10 ** Math.floor(Math.log10(roughStep));
1027
- const normalized = roughStep / magnitude;
1028
- const step = (normalized <= 1 ? 1 : normalized <= 2 ? 2 : normalized <= 5 ? 5 : 10) * magnitude;
1029
- return Math.ceil(maximum / step) * step;
1030
- }
1031
- function chartY(value, maximum, height = 76) {
1032
- return height - 4 - value / maximum * (height - 10);
1033
- }
1034
- function chartPath(values, maximum, width = 260, height = 76) {
1035
- if (!values.length) return "";
1036
- return values.map((value, index) => {
1037
- const x = values.length === 1 ? width / 2 : index / (values.length - 1) * width;
1038
- const y = chartY(value, maximum, height);
1039
- return `${index ? "L" : "M"}${x.toFixed(1)},${y.toFixed(1)}`;
1040
- }).join(" ");
1041
- }
1042
- function chartAreaPath(values, maximum, width = 260, height = 76) {
1043
- const line = chartPath(values, maximum, width, height);
1044
- return line ? `${line} L${width},${height - 4} L0,${height - 4} Z` : "";
1045
- }
1046
- function chartBars(values, maximum, width = 260, height = 76) {
1047
- const barWidth = Math.max(2, width / Math.max(values.length, 1) - 3);
1048
- return values.map((value, index) => {
1049
- const barHeight = Math.max(value ? 3 : 0, value / maximum * (height - 10));
1050
- const x = values.length === 1 ? width / 2 - barWidth / 2 : index / values.length * width;
1051
- return /* @__PURE__ */ jsx("rect", {
1052
- className: "manager-office__analytics-bar",
1053
- height: barHeight,
1054
- rx: "2",
1055
- width: barWidth,
1056
- x,
1057
- y: height - 4 - barHeight
1058
- }, index);
1059
- });
1060
- }
1061
- function AnalyticsSeries({ detail, label, tone, timestamps, value, values }) {
1062
- const axisMaximum = niceAxisMaximum(values);
1063
- const axisValue = (axisValue) => {
1064
- if (tone === "roi") return `${Math.round(axisValue)}×`;
1065
- if (tone === "workload") return `${Math.round(axisValue)}h`;
1066
- return String(Math.round(axisValue));
1067
- };
1068
- const middleIndex = Math.floor(Math.max(timestamps.length - 1, 0) / 2);
1069
- return /* @__PURE__ */ jsxs("article", {
1070
- className: "manager-office__analytics-series",
1071
- "data-tone": tone,
1072
- children: [/* @__PURE__ */ jsxs("span", {
1073
- className: "manager-office__analytics-series-copy",
1074
- children: [
1075
- /* @__PURE__ */ jsx("small", { children: label }),
1076
- /* @__PURE__ */ jsx("strong", { children: value }),
1077
- /* @__PURE__ */ jsx("span", { children: detail })
1078
- ]
1079
- }), /* @__PURE__ */ jsxs("div", {
1080
- className: "manager-office__analytics-chart",
1081
- role: "img",
1082
- "aria-label": `${label} by date over the selected period, from 0 to ${axisValue(axisMaximum)}`,
1083
- children: [
1084
- /* @__PURE__ */ jsxs("span", {
1085
- className: "manager-office__analytics-y-axis",
1086
- "aria-hidden": "true",
792
+ className: "manager-office__lane-title",
793
+ "aria-label": `Open ${work.title} to ${threadStatusLabel(work.status).toLowerCase()}`,
1087
794
  children: [
1088
- /* @__PURE__ */ jsx("span", { children: axisValue(axisMaximum) }),
1089
- /* @__PURE__ */ jsx("span", { children: axisValue(axisMaximum / 2) }),
1090
- /* @__PURE__ */ jsx("span", { children: axisValue(0) })
1091
- ]
1092
- }),
1093
- /* @__PURE__ */ jsxs("svg", {
1094
- viewBox: "0 0 260 76",
1095
- "aria-hidden": "true",
1096
- preserveAspectRatio: "none",
1097
- children: [
1098
- /* @__PURE__ */ jsx("path", {
1099
- className: "manager-office__analytics-gridline",
1100
- d: "M0 4H260M0 38H260M0 72H260"
1101
- }),
1102
- /* @__PURE__ */ jsx("path", {
1103
- className: "manager-office__analytics-axis-line",
1104
- d: "M0 4V72H260"
795
+ /* @__PURE__ */ jsx(ThreadStatusIcon, { status: work.status }),
796
+ /* @__PURE__ */ jsxs("span", {
797
+ className: "manager-office__identity",
798
+ children: [/* @__PURE__ */ jsxs("strong", {
799
+ className: "sigvelo-truncate",
800
+ children: [work.title, work.status === "attention" ? /* @__PURE__ */ jsx("span", {
801
+ className: "manager-office__unread-dot",
802
+ "aria-hidden": "true"
803
+ }) : null]
804
+ }), /* @__PURE__ */ jsxs("small", {
805
+ className: "sigvelo-truncate",
806
+ children: [
807
+ threadStatusLabel(work.status),
808
+ " · ",
809
+ /* @__PURE__ */ jsx(Timestamp, {
810
+ timestamp: work.updatedAt,
811
+ now
812
+ })
813
+ ]
814
+ })]
1105
815
  }),
1106
- tone === "outcomes" ? chartBars(values, axisMaximum) : /* @__PURE__ */ jsxs(Fragment, { children: [
1107
- /* @__PURE__ */ jsx("path", {
1108
- className: "manager-office__analytics-area",
1109
- d: chartAreaPath(values, axisMaximum)
1110
- }),
1111
- /* @__PURE__ */ jsx("path", {
1112
- className: "manager-office__analytics-line",
1113
- d: chartPath(values, axisMaximum)
1114
- }),
1115
- values.length ? /* @__PURE__ */ jsx("circle", {
1116
- className: "manager-office__analytics-endpoint",
1117
- cx: "260",
1118
- cy: chartY(values.at(-1) ?? 0, axisMaximum),
1119
- r: "3"
1120
- }) : null
1121
- ] })
1122
- ]
1123
- }),
1124
- /* @__PURE__ */ jsxs("span", {
1125
- className: "manager-office__analytics-x-axis",
1126
- "aria-hidden": "true",
1127
- children: [
1128
- /* @__PURE__ */ jsx("span", { children: analyticsDateLabel(timestamps[0]) }),
1129
- /* @__PURE__ */ jsx("span", { children: analyticsDateLabel(timestamps[middleIndex]) }),
1130
- /* @__PURE__ */ jsx("span", { children: analyticsDateLabel(timestamps.at(-1)) })
816
+ /* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
1131
817
  ]
1132
818
  })
1133
- ]
1134
- })]
1135
- });
1136
- }
1137
- function aggregateAnalytics(analytics, employeeIds, now, rangeDays) {
1138
- const cutoff = now - rangeDays * 24 * 60 * 6e4;
1139
- const buckets = /* @__PURE__ */ new Map();
1140
- for (const employee of analytics) {
1141
- if (!employeeIds.has(employee.employeeId)) continue;
1142
- for (const point of employee.points) {
1143
- if (point.timestamp < cutoff || point.timestamp > now) continue;
1144
- const day = new Date(point.timestamp);
1145
- day.setHours(0, 0, 0, 0);
1146
- const timestamp = day.getTime();
1147
- const current = buckets.get(timestamp) ?? {
1148
- timestamp,
1149
- completed: 0,
1150
- workloadHours: 0,
1151
- estimatedCost: 0
1152
- };
1153
- current.completed += point.completed;
1154
- current.workloadHours += point.workloadHours;
1155
- current.estimatedCost += point.estimatedCost;
1156
- buckets.set(timestamp, current);
1157
- }
1158
- }
1159
- return [...buckets.values()].sort((left, right) => left.timestamp - right.timestamp);
1160
- }
1161
- function DashboardAnalytics({ analytics, currency, employeeIds, now, onExportReport, rangeDays, setRangeDays }) {
1162
- const points = aggregateAnalytics(analytics, new Set(employeeIds), now, rangeDays);
1163
- const completed = points.reduce((sum, point) => sum + point.completed, 0);
1164
- const workload = points.reduce((sum, point) => sum + point.workloadHours, 0);
1165
- const hourlyWageEquivalent = 45;
1166
- const monthlyCostPerEmployee = 28;
1167
- const monthlyAICost = employeeIds.length * monthlyCostPerEmployee;
1168
- const selectedPeriodAICost = monthlyAICost * rangeDays / 30;
1169
- const laborValue = workload * hourlyWageEquivalent;
1170
- const roiMultiple = selectedPeriodAICost ? laborValue / selectedPeriodAICost : 0;
1171
- const dailyAICost = monthlyAICost / 30;
1172
- const roiValues = points.map((point) => dailyAICost ? point.workloadHours * hourlyWageEquivalent / dailyAICost : 0);
1173
- const money = React.useMemo(() => new Intl.NumberFormat(void 0, {
1174
- currency,
1175
- maximumFractionDigits: 0,
1176
- style: "currency"
1177
- }), [currency]);
1178
- return /* @__PURE__ */ jsxs("section", {
1179
- className: "manager-office__analytics",
1180
- "aria-labelledby": "manager-office-analytics-title",
1181
- children: [/* @__PURE__ */ jsxs("header", {
1182
- className: "manager-office__analytics-header",
1183
- children: [/* @__PURE__ */ jsx("h2", {
1184
- id: "manager-office-analytics-title",
1185
- children: "Your workforce at a glance"
1186
- }), /* @__PURE__ */ jsxs("span", {
1187
- className: "manager-office__analytics-actions",
1188
- children: [/* @__PURE__ */ jsxs(Select.Root, {
1189
- value: String(rangeDays),
1190
- onValueChange: (value) => setRangeDays(Number(value)),
1191
- children: [/* @__PURE__ */ jsxs(Select.Trigger, {
1192
- className: "manager-office__analytics-range",
1193
- "aria-label": "Analytics time range",
1194
- children: [
1195
- /* @__PURE__ */ jsx(CalendarIcon, {}),
1196
- /* @__PURE__ */ jsxs("span", { children: [
1197
- /* @__PURE__ */ jsx("span", {
1198
- className: "manager-office__analytics-range-prefix",
1199
- children: "Last "
1200
- }),
1201
- rangeDays,
1202
- " days"
1203
- ] }),
1204
- /* @__PURE__ */ jsx(Select.Icon, { children: /* @__PURE__ */ jsx(ChevronDownIcon, {}) })
1205
- ]
1206
- }), /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, {
1207
- sideOffset: 4,
1208
- children: /* @__PURE__ */ jsx(Select.Popup, { children: /* @__PURE__ */ jsx(Select.List, { children: [
1209
- 7,
1210
- 30,
1211
- 90
1212
- ].map((days) => /* @__PURE__ */ jsxs(Select.Item, {
1213
- value: String(days),
1214
- children: [/* @__PURE__ */ jsx(Select.ItemIndicator, {}), /* @__PURE__ */ jsxs(Select.ItemText, { children: [
1215
- "Last ",
1216
- days,
1217
- " days"
1218
- ] })]
1219
- }, days)) }) })
1220
- }) })]
1221
- }), onExportReport ? /* @__PURE__ */ jsxs(Button, {
1222
- "aria-label": "Export report",
1223
- className: "manager-office__analytics-export",
1224
- title: "Export report",
1225
- type: "button",
1226
- size: "sm",
1227
- variant: "outline",
1228
- onClick: () => onExportReport({
1229
- employeeIds,
1230
- rangeDays
1231
- }),
1232
- children: [/* @__PURE__ */ jsx(DownloadIcon, {}), /* @__PURE__ */ jsxs("span", {
1233
- className: "manager-office__analytics-export-label",
1234
- children: ["Export", /* @__PURE__ */ jsx("span", {
1235
- className: "manager-office__export-report-suffix",
1236
- children: " report"
1237
- })]
1238
- })]
1239
- }) : null]
1240
- })]
1241
- }), /* @__PURE__ */ jsxs("div", {
1242
- className: "manager-office__analytics-series-grid",
1243
- children: [
1244
- /* @__PURE__ */ jsx(AnalyticsSeries, {
1245
- detail: `${(completed / Math.max(employeeIds.length, 1)).toFixed(1)} per employee`,
1246
- label: "Completed outcomes",
1247
- tone: "outcomes",
1248
- timestamps: points.map((point) => point.timestamp),
1249
- value: String(completed),
1250
- values: points.map((point) => point.completed)
1251
- }),
1252
- /* @__PURE__ */ jsx(AnalyticsSeries, {
1253
- detail: `${(workload / Math.max(employeeIds.length, 1)).toFixed(1)}h per employee`,
1254
- label: "Workload",
1255
- tone: "workload",
1256
- timestamps: points.map((point) => point.timestamp),
1257
- value: `${Math.round(workload)}h`,
1258
- values: points.map((point) => point.workloadHours)
1259
- }),
1260
- /* @__PURE__ */ jsx(AnalyticsSeries, {
1261
- detail: `${money.format(hourlyWageEquivalent)}/hr equivalent · ${money.format(monthlyCostPerEmployee)}/employee/mo`,
1262
- label: "Return on investment",
1263
- tone: "roi",
1264
- timestamps: points.map((point) => point.timestamp),
1265
- value: `${roiMultiple.toFixed(1)}×`,
1266
- values: roiValues
1267
- })
1268
- ]
1269
- })]
819
+ }),
820
+ work.summary ? /* @__PURE__ */ jsx("p", {
821
+ className: "manager-office__lane-summary",
822
+ children: work.summary
823
+ }) : null,
824
+ workingSet.length ? /* @__PURE__ */ jsx("ul", {
825
+ className: "manager-office__working-set",
826
+ role: "list",
827
+ "aria-label": "Working set",
828
+ children: workingSet.map((item) => /* @__PURE__ */ jsx(WorkingSetItemRow, {
829
+ employee,
830
+ item,
831
+ renderLink,
832
+ work
833
+ }, workingSetKey(item)))
834
+ }) : null
835
+ ]
1270
836
  });
1271
837
  }
1272
- function DashboardView({ analytics, analyticsCurrency, employees, now, onExportReport, profileColors, renderLink }) {
1273
- const lanes = dashboardLanes;
1274
- const [rangeDays, setRangeDays] = React.useState(30);
1275
- const [employeeFilters, setEmployeeFilters] = React.useState(() => /* @__PURE__ */ new Set());
1276
- const [appFilters, setAppFilters] = React.useState(() => /* @__PURE__ */ new Set());
1277
- const [utilizationFilters, setUtilizationFilters] = React.useState(() => /* @__PURE__ */ new Set());
1278
- const [collapsedLanes, setCollapsedLanes] = React.useState(() => /* @__PURE__ */ new Set());
1279
- const [collapsedCards, setCollapsedCards] = React.useState(() => /* @__PURE__ */ new Set());
1280
- const filteredEmployees = employees.filter((employee) => {
1281
- const connected = isConnected(employee);
1282
- if (employeeFilters.size && !employeeFilters.has(employee.id)) return false;
1283
- if (appFilters.size && (!connected || !employee.channels.some((channel) => appFilters.has(channel.name)))) return false;
1284
- return employeeMatchesUtilization(employee, utilizationFilters);
1285
- });
1286
- const cardsByLane = new Map(lanes.map((lane) => [lane, dashboardCards(filteredEmployees, lane)]));
1287
- const appOptions = [...new Set(employees.flatMap((employee) => isConnected(employee) ? employee.channels.map((channel) => channel.name) : []))].sort((left, right) => left.localeCompare(right)).map((name) => ({
1288
- label: name,
1289
- value: name
1290
- }));
1291
- const filtersActive = employeeFilters.size > 0 || appFilters.size > 0 || utilizationFilters.size > 0;
1292
- const activeFilterCount = employeeFilters.size + appFilters.size + utilizationFilters.size;
1293
- const clearFilters = () => {
1294
- setEmployeeFilters(/* @__PURE__ */ new Set());
1295
- setAppFilters(/* @__PURE__ */ new Set());
1296
- setUtilizationFilters(/* @__PURE__ */ new Set());
1297
- };
1298
- const toggleLane = (lane) => setCollapsedLanes((current) => {
1299
- const next = new Set(current);
1300
- if (next.has(lane)) next.delete(lane);
1301
- else next.add(lane);
1302
- return next;
1303
- });
1304
- const toggleCard = (cardId) => setCollapsedCards((current) => {
1305
- const next = new Set(current);
1306
- if (next.has(cardId)) next.delete(cardId);
1307
- else next.add(cardId);
1308
- return next;
838
+ function AttentionView({ employees, renderLink, now }) {
839
+ const waits = employees.flatMap((employee) => isConnected(employee) ? employee.handoffs.map((handoff) => ({
840
+ employee,
841
+ handoff
842
+ })) : []);
843
+ const reviews = employees.flatMap((employee) => isConnected(employee) ? reviewWorkFor(employee).map((work) => ({
844
+ employee,
845
+ work
846
+ })) : []);
847
+ if (!waits.length && !reviews.length) return /* @__PURE__ */ jsx("div", {
848
+ className: "manager-office__attention",
849
+ "data-recipe": "page",
850
+ children: /* @__PURE__ */ jsx(EmptyState, {
851
+ icon: /* @__PURE__ */ jsx(CheckIcon, {}),
852
+ title: "Nothing needs you",
853
+ description: "Employee connection state remains visible in the roster."
854
+ })
1309
855
  });
856
+ const both = waits.length > 0 && reviews.length > 0;
1310
857
  return /* @__PURE__ */ jsxs("div", {
1311
- className: "manager-office__dashboard-content",
858
+ className: "manager-office__attention",
1312
859
  "data-recipe": "page",
1313
- children: [
1314
- /* @__PURE__ */ jsxs("section", {
1315
- className: "manager-office__dashboard-controls",
1316
- "aria-label": "Workforce controls",
1317
- children: [/* @__PURE__ */ jsx("div", {
1318
- className: "manager-office__workforce-actions",
1319
- "aria-label": "Workforce actions",
1320
- children: /* @__PURE__ */ jsx(AssignWorkMenu, {
1321
- employees: employees.filter(isConnected),
1322
- profileColors,
1323
- renderLink
1324
- })
1325
- }), /* @__PURE__ */ jsxs("section", {
1326
- className: "manager-office__filters",
1327
- "aria-label": "Filter AI employees",
1328
- children: [/* @__PURE__ */ jsxs("div", {
1329
- className: "manager-office__filters-main",
1330
- children: [/* @__PURE__ */ jsxs("div", {
1331
- className: "manager-office__filters-heading",
1332
- children: [/* @__PURE__ */ jsx("strong", { children: "Filters" }), filtersActive ? /* @__PURE__ */ jsxs("span", { children: [activeFilterCount, " active"] }) : null]
1333
- }), /* @__PURE__ */ jsxs("div", {
1334
- className: "manager-office__filter-categories",
1335
- children: [
1336
- /* @__PURE__ */ jsx(DashboardFilterMenu, {
1337
- label: "Employee",
1338
- options: employees.map((employee) => ({
1339
- label: employee.name,
1340
- value: employee.id
1341
- })),
1342
- selected: employeeFilters,
1343
- onToggle: (value, checked) => toggleDashboardFilter(setEmployeeFilters, value, checked)
1344
- }),
1345
- /* @__PURE__ */ jsx(DashboardFilterMenu, {
1346
- label: "Apps",
1347
- options: appOptions,
1348
- selected: appFilters,
1349
- onToggle: (value, checked) => toggleDashboardFilter(setAppFilters, value, checked)
1350
- }),
1351
- /* @__PURE__ */ jsx(DashboardFilterMenu, {
1352
- label: "Utilization",
1353
- options: [
1354
- {
1355
- label: "Live browser connected",
1356
- value: "browser"
1357
- },
1358
- {
1359
- label: "Has routines",
1360
- value: "routines"
1361
- },
1362
- {
1363
- label: "No routines",
1364
- value: "no-routines"
1365
- },
1366
- {
1367
- label: "Connection issue",
1368
- value: "connector-issue"
1369
- }
1370
- ],
1371
- selected: utilizationFilters,
1372
- onToggle: (value, checked) => toggleDashboardFilter(setUtilizationFilters, value, checked)
1373
- }),
1374
- filtersActive ? /* @__PURE__ */ jsxs(Button, {
1375
- className: "manager-office__filter-clear",
1376
- type: "button",
1377
- variant: "ghost",
1378
- size: "sm",
1379
- onClick: clearFilters,
1380
- children: [/* @__PURE__ */ jsx(XIcon, {}), "Clear filters"]
1381
- }) : null
1382
- ]
1383
- })]
1384
- }), /* @__PURE__ */ jsxs("p", {
1385
- "aria-live": "polite",
1386
- children: [
1387
- "Showing ",
1388
- /* @__PURE__ */ jsx("strong", { children: filteredEmployees.length }),
1389
- " of ",
1390
- employees.length,
1391
- " employees"
1392
- ]
1393
- })]
1394
- })]
1395
- }),
1396
- analytics.length ? /* @__PURE__ */ jsx(DashboardAnalytics, {
1397
- analytics,
1398
- currency: analyticsCurrency,
1399
- employeeIds: filteredEmployees.map((employee) => employee.id),
1400
- now,
1401
- onExportReport,
1402
- rangeDays,
1403
- setRangeDays
1404
- }) : null,
1405
- /* @__PURE__ */ jsx("div", {
1406
- className: "manager-office__kanban",
1407
- "aria-label": "AI employee progress board",
1408
- style: { gridTemplateColumns: lanes.map((lane) => collapsedLanes.has(lane) ? "4rem" : "minmax(15rem, 1fr)").join(" ") },
1409
- children: lanes.map((lane) => {
1410
- const cards = cardsByLane.get(lane) ?? [];
1411
- const visibleCards = cards.slice(0, 5);
1412
- const headingId = `manager-office-lane-${lane}`;
1413
- const collapsed = collapsedLanes.has(lane);
1414
- return /* @__PURE__ */ jsxs("section", {
1415
- className: "manager-office__kanban-lane",
1416
- "data-collapsed": collapsed || void 0,
1417
- "data-lane": lane,
1418
- "aria-labelledby": headingId,
1419
- children: [/* @__PURE__ */ jsxs("header", {
1420
- className: "manager-office__kanban-lane-header",
1421
- children: [/* @__PURE__ */ jsxs("span", { children: [/* @__PURE__ */ jsx("h3", {
1422
- id: headingId,
1423
- children: dashboardLaneCopy[lane].title
1424
- }), /* @__PURE__ */ jsx("small", { children: dashboardLaneCopy[lane].description })] }), /* @__PURE__ */ jsxs("span", {
1425
- className: "manager-office__kanban-lane-actions",
1426
- children: [/* @__PURE__ */ jsx("strong", {
1427
- "aria-label": `${cards.length} items`,
1428
- children: cards.length
1429
- }), /* @__PURE__ */ jsx(Button, {
1430
- "aria-expanded": !collapsed,
1431
- "aria-label": `${collapsed ? "Expand" : "Collapse"} ${dashboardLaneCopy[lane].title} column`,
1432
- className: "manager-office__kanban-lane-toggle",
1433
- color: "neutral",
1434
- onClick: () => toggleLane(lane),
1435
- size: "sm",
1436
- type: "button",
1437
- variant: "ghost",
1438
- children: collapsed ? /* @__PURE__ */ jsx(ChevronRightIcon, {}) : /* @__PURE__ */ jsx(ChevronDownIcon, {})
1439
- })]
1440
- })]
1441
- }), !collapsed ? /* @__PURE__ */ jsxs("div", {
1442
- className: "manager-office__kanban-cards",
1443
- children: [
1444
- visibleCards.map((card) => /* @__PURE__ */ jsx(DashboardCard, {
1445
- card,
1446
- collapsed: collapsedCards.has(dashboardCardId(card)),
1447
- color: profileColors.get(card.employee.id),
1448
- index: employees.indexOf(card.employee),
1449
- now,
1450
- onToggleCollapsed: () => toggleCard(dashboardCardId(card)),
1451
- renderLink
1452
- }, dashboardCardId(card))),
1453
- !cards.length ? /* @__PURE__ */ jsx("p", {
1454
- className: "manager-office__kanban-empty",
1455
- children: "Nothing here right now."
1456
- }) : null,
1457
- cards.length > visibleCards.length ? /* @__PURE__ */ jsxs("p", {
1458
- className: "manager-office__kanban-more",
1459
- children: [
1460
- "+",
1461
- cards.length - visibleCards.length,
1462
- " more match · Refine filters to narrow"
1463
- ]
1464
- }) : null
1465
- ]
1466
- }) : null]
1467
- }, lane);
1468
- })
1469
- })
1470
- ]
860
+ children: [waits.length ? /* @__PURE__ */ jsxs("div", {
861
+ className: "manager-office__attention-group",
862
+ children: [both ? /* @__PURE__ */ jsx("h2", {
863
+ className: "manager-office__section-title",
864
+ children: "Needs you in the browser"
865
+ }) : null, /* @__PURE__ */ jsx("ul", {
866
+ className: "manager-office__attention-list sigvelo-stack-list",
867
+ "aria-label": "Waiting on you",
868
+ children: waits.map(({ employee, handoff }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(HandoffCard, {
869
+ employee,
870
+ handoff,
871
+ renderLink,
872
+ now,
873
+ showEmployee: true
874
+ }) }, `${employee.id}:${handoff.id}`))
875
+ })]
876
+ }) : null, reviews.length ? /* @__PURE__ */ jsxs("div", {
877
+ className: "manager-office__attention-group",
878
+ children: [/* @__PURE__ */ jsx("h2", {
879
+ className: "manager-office__section-title",
880
+ children: "Ready for you"
881
+ }), /* @__PURE__ */ jsx("ul", {
882
+ className: "manager-office__work-list sigvelo-stack-list",
883
+ "aria-label": "Ready for you",
884
+ children: reviews.map(({ employee, work }) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(ReviewRow, {
885
+ employee,
886
+ work,
887
+ renderLink,
888
+ now,
889
+ showEmployee: true
890
+ }) }, `${employee.id}:${work.id}`))
891
+ })]
892
+ }) : null]
1471
893
  });
1472
894
  }
1473
895
  function EmployeeDetail({ employee, renderLink, now, profileColor }) {
@@ -1489,19 +911,22 @@ function EmployeeDetail({ employee, renderLink, now, profileColor }) {
1489
911
  employee,
1490
912
  color: profileColor,
1491
913
  size: "lg"
1492
- }), /* @__PURE__ */ jsxs("span", {
1493
- className: "manager-office__identity",
1494
- children: [/* @__PURE__ */ jsx("strong", {
1495
- className: "sigvelo-truncate",
1496
- children: employee.name
1497
- }), /* @__PURE__ */ jsxs("small", {
1498
- className: "manager-office__role sigvelo-truncate",
1499
- children: [
1500
- employee.email,
1501
- " · ",
1502
- employee.role
1503
- ]
1504
- })]
914
+ }), /* @__PURE__ */ jsxs("div", {
915
+ className: "manager-office__briefing",
916
+ children: [
917
+ /* @__PURE__ */ jsx("strong", {
918
+ className: "sigvelo-truncate",
919
+ children: employee.name
920
+ }),
921
+ /* @__PURE__ */ jsx("small", {
922
+ className: "sigvelo-truncate",
923
+ children: employee.email
924
+ }),
925
+ /* @__PURE__ */ jsx("p", {
926
+ className: "manager-office__role",
927
+ children: employee.role
928
+ })
929
+ ]
1505
930
  })]
1506
931
  }),
1507
932
  employee.handoffs.length ? /* @__PURE__ */ jsx("section", {
@@ -1529,43 +954,22 @@ function EmployeeDetail({ employee, renderLink, now, profileColor }) {
1529
954
  className: "manager-office__section-content",
1530
955
  children: employee.work.length ? /* @__PURE__ */ jsx("ul", {
1531
956
  className: "manager-office__work-list sigvelo-stack-list",
1532
- children: employee.work.map((work) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(LinkButton, {
1533
- render: renderLink({
1534
- kind: "work",
1535
- employee,
1536
- work
1537
- }),
1538
- variant: "ghost",
1539
- color: "neutral",
1540
- size: "sm",
1541
- className: "manager-office__work-link",
1542
- children: [
1543
- /* @__PURE__ */ jsx(ThreadStatusIcon, { status: work.status }),
1544
- /* @__PURE__ */ jsxs("span", {
1545
- className: "manager-office__identity",
1546
- children: [/* @__PURE__ */ jsxs("strong", {
1547
- className: "sigvelo-truncate",
1548
- children: [work.title, work.status === "attention" ? /* @__PURE__ */ jsx("span", {
1549
- className: "manager-office__unread-dot",
1550
- "aria-hidden": "true"
1551
- }) : null]
1552
- }), /* @__PURE__ */ jsxs("small", {
1553
- className: "sigvelo-truncate",
1554
- children: [
1555
- threadStatusLabel(work.status),
1556
- " ·",
1557
- " ",
1558
- /* @__PURE__ */ jsx(Timestamp, {
1559
- timestamp: work.updatedAt,
1560
- now
1561
- })
1562
- ]
1563
- })]
1564
- }),
1565
- /* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
1566
- ]
957
+ children: employee.work.map((work) => /* @__PURE__ */ jsx("li", { children: workingSetOf(work).length ? /* @__PURE__ */ jsx(WorkLane, {
958
+ employee,
959
+ now,
960
+ renderLink,
961
+ work
962
+ }) : /* @__PURE__ */ jsx(ReviewRow, {
963
+ employee,
964
+ now,
965
+ renderLink,
966
+ showEmployee: false,
967
+ work
1567
968
  }) }, work.id))
1568
- }) : /* @__PURE__ */ jsx(EmptyState, { description: "No work yet." })
969
+ }) : /* @__PURE__ */ jsx("p", {
970
+ className: "manager-office__section-empty",
971
+ children: "No work yet."
972
+ })
1569
973
  })]
1570
974
  }), /* @__PURE__ */ jsxs("aside", {
1571
975
  className: "manager-office__employee-aside",
@@ -1614,7 +1018,10 @@ function EmployeeDetail({ employee, renderLink, now, profileColor }) {
1614
1018
  /* @__PURE__ */ jsx(ChevronRightIcon, { className: "manager-office__row-chevron" })
1615
1019
  ]
1616
1020
  }) }, routine.id))
1617
- }) : /* @__PURE__ */ jsx(EmptyState, { description: "No routines yet." })
1021
+ }) : /* @__PURE__ */ jsx("p", {
1022
+ className: "manager-office__section-empty",
1023
+ children: "No routines yet."
1024
+ })
1618
1025
  })]
1619
1026
  })
1620
1027
  }), /* @__PURE__ */ jsxs("section", {
@@ -1623,14 +1030,17 @@ function EmployeeDetail({ employee, renderLink, now, profileColor }) {
1623
1030
  className: "manager-office__section-header",
1624
1031
  children: /* @__PURE__ */ jsxs("h2", {
1625
1032
  className: "manager-office__section-title",
1626
- children: [/* @__PURE__ */ jsx(LinkIcon, {}), "Inputs & outputs"]
1033
+ children: [/* @__PURE__ */ jsx(LinkIcon, {}), "Channels"]
1627
1034
  })
1628
1035
  }), /* @__PURE__ */ jsx("div", {
1629
1036
  className: "manager-office__section-content",
1630
1037
  children: employee.channels.length ? /* @__PURE__ */ jsx("ul", {
1631
1038
  className: "manager-office__channel-list sigvelo-stack-list",
1632
1039
  children: employee.channels.map((channel) => /* @__PURE__ */ jsx(ChannelRow, { channel }, channel.id))
1633
- }) : /* @__PURE__ */ jsx(EmptyState, { description: "Nothing connected yet." })
1040
+ }) : /* @__PURE__ */ jsx("p", {
1041
+ className: "manager-office__section-empty",
1042
+ children: "Nothing connected yet."
1043
+ })
1634
1044
  })]
1635
1045
  })]
1636
1046
  })]
@@ -1639,11 +1049,12 @@ function EmployeeDetail({ employee, renderLink, now, profileColor }) {
1639
1049
  });
1640
1050
  }
1641
1051
  /**
1642
- * Multi-employee manager office: a dashboard, aggregate handoffs, employee
1643
- * roster, and one employee dossier. The consuming app owns authentication,
1644
- * Agent connections, routing, and the selected employee's full work surface.
1052
+ * Multi-employee manager office: inbox of browser waits plus ready work,
1053
+ * employee roster, and one employee dossier of work lanes. The consuming app
1054
+ * owns authentication, Agent connections, routing, and the selected
1055
+ * employee's full work surface.
1645
1056
  */
1646
- function ManagerOffice({ analytics = [], analyticsCurrency = "USD", className, emptyOfficeAction, employees, renderLink, officeActions, onExportReport, renderEmployeeActions, sidebarTogglePlacement = "sidebar", style, view, ...props }) {
1057
+ function ManagerOffice({ className, emptyOfficeAction, employees, renderLink, officeActions, renderEmployeeActions, sidebarTogglePlacement = "sidebar", style, view, ...props }) {
1647
1058
  const titleId = React.useId();
1648
1059
  const [now, setNow] = React.useState(Date.now);
1649
1060
  React.useEffect(() => {
@@ -1652,36 +1063,6 @@ function ManagerOffice({ analytics = [], analyticsCurrency = "USD", className, e
1652
1063
  }, []);
1653
1064
  const selectedEmployee = view.kind === "employee" ? employees.find((employee) => employee.id === view.employeeId) : void 0;
1654
1065
  const profileColors = rosterProfileColors(employees);
1655
- if (view.kind === "dashboard") return /* @__PURE__ */ jsx(Tooltip.Provider, { children: /* @__PURE__ */ jsxs("div", {
1656
- className: cx("manager-office", "manager-office--dashboard", className),
1657
- style,
1658
- ...props,
1659
- children: [/* @__PURE__ */ jsxs(AppTopBar.Root, {
1660
- "aria-label": "Workforce controls",
1661
- titleAlign: "start",
1662
- children: [/* @__PURE__ */ jsx(AppTopBar.Title, { render: /* @__PURE__ */ jsx("h1", {
1663
- id: titleId,
1664
- children: "Workforce"
1665
- }) }), officeActions ? /* @__PURE__ */ jsx(AppTopBar.Trailing, { children: officeActions }) : null]
1666
- }), /* @__PURE__ */ jsx("main", {
1667
- className: "manager-office__dashboard",
1668
- "aria-labelledby": titleId,
1669
- children: !employees.length ? /* @__PURE__ */ jsx(EmptyState, {
1670
- icon: /* @__PURE__ */ jsx(PlusIcon, {}),
1671
- title: "Add your first employee",
1672
- description: "Connect another profile to manage it here.",
1673
- children: emptyOfficeAction
1674
- }) : /* @__PURE__ */ jsx(DashboardView, {
1675
- analytics,
1676
- analyticsCurrency,
1677
- employees,
1678
- now,
1679
- onExportReport,
1680
- profileColors,
1681
- renderLink
1682
- })
1683
- })]
1684
- }) });
1685
1066
  const title = view.kind === "attention" ? "Waiting on you" : selectedEmployee?.name ?? "Employee";
1686
1067
  const mainLabel = view.kind === "attention" ? "Waiting on you" : `${selectedEmployee?.name ?? "Employee"} details`;
1687
1068
  return /* @__PURE__ */ jsx(Tooltip.Provider, { children: /* @__PURE__ */ jsx(ResponsiveSidebarShell, {