@athenaintel/react 0.55.0 → 0.57.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 (164) hide show
  1. package/README.md +84 -1
  2. package/dist/agent-runtime/src/answer-label.cjs +8 -2
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
  4. package/dist/agent-runtime/src/answer-label.d.ts +10 -4
  5. package/dist/agent-runtime/src/answer-label.js +8 -2
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -1
  7. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +6 -3
  8. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
  9. package/dist/agent-runtime/src/deep-agent-transport-recipe.js +6 -3
  10. package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  11. package/dist/agent-runtime/src/edit-command.cjs +40 -19
  12. package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
  13. package/dist/agent-runtime/src/edit-command.d.ts +2 -0
  14. package/dist/agent-runtime/src/edit-command.js +41 -20
  15. package/dist/agent-runtime/src/edit-command.js.map +1 -1
  16. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +8 -0
  17. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  18. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +9 -0
  19. package/dist/agent-runtime/src/generated/runconfig-contract.js +8 -0
  20. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  21. package/dist/agent-runtime/src/history-store.cjs +426 -0
  22. package/dist/agent-runtime/src/history-store.cjs.map +1 -0
  23. package/dist/agent-runtime/src/history-store.d.ts +282 -0
  24. package/dist/agent-runtime/src/history-store.js +426 -0
  25. package/dist/agent-runtime/src/history-store.js.map +1 -0
  26. package/dist/agent-runtime/src/inbound-channel.cjs +96 -0
  27. package/dist/agent-runtime/src/inbound-channel.cjs.map +1 -0
  28. package/dist/agent-runtime/src/inbound-channel.d.ts +75 -0
  29. package/dist/agent-runtime/src/inbound-channel.js +96 -0
  30. package/dist/agent-runtime/src/inbound-channel.js.map +1 -0
  31. package/dist/agent-runtime/src/index.d.ts +6 -5
  32. package/dist/agent-runtime/src/interrupts.cjs +45 -3
  33. package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
  34. package/dist/agent-runtime/src/interrupts.d.ts +51 -4
  35. package/dist/agent-runtime/src/interrupts.js +46 -4
  36. package/dist/agent-runtime/src/interrupts.js.map +1 -1
  37. package/dist/agent-runtime/src/message-window.cjs +43 -5
  38. package/dist/agent-runtime/src/message-window.cjs.map +1 -1
  39. package/dist/agent-runtime/src/message-window.d.ts +26 -2
  40. package/dist/agent-runtime/src/message-window.js +44 -6
  41. package/dist/agent-runtime/src/message-window.js.map +1 -1
  42. package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
  43. package/dist/agent-runtime/src/offline-status.d.ts +110 -4
  44. package/dist/agent-runtime/src/offline-status.js.map +1 -1
  45. package/dist/agent-runtime/src/runtime.d.ts +1 -0
  46. package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +8 -8
  47. package/dist/agent-runtime/src/tool-metadata.cjs +16 -0
  48. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  49. package/dist/agent-runtime/src/tool-metadata.js +16 -0
  50. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  51. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +8 -16
  52. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  53. package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +1 -9
  54. package/dist/agent-runtime/src/use-deep-agent-thread.js +9 -17
  55. package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  56. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +86 -79
  57. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  58. package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +2 -27
  59. package/dist/agent-runtime/src/use-deep-agent-window-sync.js +89 -82
  60. package/dist/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -1
  61. package/dist/auth/AthenaSSOProvider.cjs +54 -12
  62. package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
  63. package/dist/auth/AthenaSSOProvider.d.ts +23 -2
  64. package/dist/auth/AthenaSSOProvider.js +54 -12
  65. package/dist/auth/AthenaSSOProvider.js.map +1 -1
  66. package/dist/auth/index.cjs +2 -0
  67. package/dist/auth/index.cjs.map +1 -1
  68. package/dist/auth/index.d.ts +1 -0
  69. package/dist/auth/index.js +2 -0
  70. package/dist/auth/index.js.map +1 -1
  71. package/dist/auth/sign-back-in.cjs +141 -0
  72. package/dist/auth/sign-back-in.cjs.map +1 -0
  73. package/dist/auth/sign-back-in.d.ts +117 -0
  74. package/dist/auth/sign-back-in.js +141 -0
  75. package/dist/auth/sign-back-in.js.map +1 -0
  76. package/dist/chat/AthenaChat.cjs +7 -2
  77. package/dist/chat/AthenaChat.cjs.map +1 -1
  78. package/dist/chat/AthenaChat.js +7 -2
  79. package/dist/chat/AthenaChat.js.map +1 -1
  80. package/dist/chat/StatewireApprovalCard.cjs +6 -2
  81. package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
  82. package/dist/chat/StatewireApprovalCard.d.ts +8 -1
  83. package/dist/chat/StatewireApprovalCard.js +7 -3
  84. package/dist/chat/StatewireApprovalCard.js.map +1 -1
  85. package/dist/chat/super-grouping/CollapsibleGroup.cjs +1 -1
  86. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  87. package/dist/chat/super-grouping/CollapsibleGroup.d.ts +6 -5
  88. package/dist/chat/super-grouping/CollapsibleGroup.js +1 -1
  89. package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
  90. package/dist/chat/super-grouping/earlier-steps-button.cjs +5 -6
  91. package/dist/chat/super-grouping/earlier-steps-button.cjs.map +1 -1
  92. package/dist/chat/super-grouping/earlier-steps-button.d.ts +6 -6
  93. package/dist/chat/super-grouping/earlier-steps-button.js +5 -6
  94. package/dist/chat/super-grouping/earlier-steps-button.js.map +1 -1
  95. package/dist/chat/super-grouping/toolkit-map.cjs +1 -0
  96. package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
  97. package/dist/chat/super-grouping/toolkit-map.js +1 -0
  98. package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
  99. package/dist/chat/super-grouping/use-turn-steps.cjs +3 -3
  100. package/dist/chat/super-grouping/use-turn-steps.js +1 -1
  101. package/dist/chat-ui/index.cjs +4 -0
  102. package/dist/chat-ui/index.cjs.map +1 -1
  103. package/dist/chat-ui/index.d.ts +1 -0
  104. package/dist/chat-ui/index.js +5 -1
  105. package/dist/chat-ui/index.js.map +1 -1
  106. package/dist/chat-ui/messages/inbound-channel-message.cjs +219 -0
  107. package/dist/chat-ui/messages/inbound-channel-message.cjs.map +1 -0
  108. package/dist/chat-ui/messages/inbound-channel-message.d.ts +60 -0
  109. package/dist/chat-ui/messages/inbound-channel-message.js +219 -0
  110. package/dist/chat-ui/messages/inbound-channel-message.js.map +1 -0
  111. package/dist/chat-ui/messages/inbound-channel-reader.cjs +184 -0
  112. package/dist/chat-ui/messages/inbound-channel-reader.cjs.map +1 -0
  113. package/dist/chat-ui/messages/inbound-channel-reader.d.ts +65 -0
  114. package/dist/chat-ui/messages/inbound-channel-reader.js +184 -0
  115. package/dist/chat-ui/messages/inbound-channel-reader.js.map +1 -0
  116. package/dist/chat-ui/messages/message-components.cjs +18 -14
  117. package/dist/chat-ui/messages/message-components.cjs.map +1 -1
  118. package/dist/chat-ui/messages/message-components.d.ts +7 -0
  119. package/dist/chat-ui/messages/message-components.js +19 -15
  120. package/dist/chat-ui/messages/message-components.js.map +1 -1
  121. package/dist/chat-ui/thread/statewire-history-edge.cjs +0 -4
  122. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  123. package/dist/chat-ui/thread/statewire-history-edge.d.ts +5 -7
  124. package/dist/chat-ui/thread/statewire-history-edge.js +1 -5
  125. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  126. package/dist/composer/sign-back-in-draft.cjs +62 -0
  127. package/dist/composer/sign-back-in-draft.cjs.map +1 -0
  128. package/dist/composer/sign-back-in-draft.d.ts +34 -0
  129. package/dist/composer/sign-back-in-draft.js +62 -0
  130. package/dist/composer/sign-back-in-draft.js.map +1 -0
  131. package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
  132. package/dist/diagnostics/athena-diagnostics.d.ts +6 -1
  133. package/dist/diagnostics/athena-diagnostics.js.map +1 -1
  134. package/dist/index.cjs +8 -0
  135. package/dist/index.cjs.map +1 -1
  136. package/dist/index.d.ts +2 -0
  137. package/dist/index.js +8 -0
  138. package/dist/index.js.map +1 -1
  139. package/dist/provider/AthenaProvider.cjs +60 -14
  140. package/dist/provider/AthenaProvider.cjs.map +1 -1
  141. package/dist/provider/AthenaProvider.js +60 -14
  142. package/dist/provider/AthenaProvider.js.map +1 -1
  143. package/dist/provider/statewire-window-context.cjs.map +1 -1
  144. package/dist/provider/statewire-window-context.d.ts +8 -8
  145. package/dist/provider/statewire-window-context.js.map +1 -1
  146. package/dist/react/package.json.cjs +1 -1
  147. package/dist/react/package.json.js +1 -1
  148. package/dist/runtime/auth.cjs +11 -0
  149. package/dist/runtime/auth.cjs.map +1 -1
  150. package/dist/runtime/auth.d.ts +18 -1
  151. package/dist/runtime/auth.js +11 -0
  152. package/dist/runtime/auth.js.map +1 -1
  153. package/dist/runtime/useAthenaStatewireRuntime.cjs +0 -2
  154. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  155. package/dist/runtime/useAthenaStatewireRuntime.d.ts +5 -5
  156. package/dist/runtime/useAthenaStatewireRuntime.js +0 -2
  157. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  158. package/dist/styles.css +1 -1
  159. package/package.json +1 -1
  160. package/dist/agent-runtime/src/history-pages.cjs +0 -279
  161. package/dist/agent-runtime/src/history-pages.cjs.map +0 -1
  162. package/dist/agent-runtime/src/history-pages.d.ts +0 -252
  163. package/dist/agent-runtime/src/history-pages.js +0 -279
  164. package/dist/agent-runtime/src/history-pages.js.map +0 -1
@@ -0,0 +1,219 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("@assistant-ui/react");
5
+ const lucideReact = require("lucide-react");
6
+ const require$$0 = require("react");
7
+ const collapsible = require("../../ui/collapsible.cjs");
8
+ const inboundChannelReader = require("./inbound-channel-reader.cjs");
9
+ const inboundChannel = require("../../agent-runtime/src/inbound-channel.cjs");
10
+ const cnfast = require("cnfast");
11
+ const SlackMark = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 2447.6 2452.5", className, "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsxRuntime.jsxs("g", { clipRule: "evenodd", fillRule: "evenodd", children: [
12
+ /* @__PURE__ */ jsxRuntime.jsx(
13
+ "path",
14
+ {
15
+ d: "m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z",
16
+ fill: "#36c5f0"
17
+ }
18
+ ),
19
+ /* @__PURE__ */ jsxRuntime.jsx(
20
+ "path",
21
+ {
22
+ d: "m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z",
23
+ fill: "#2eb67d"
24
+ }
25
+ ),
26
+ /* @__PURE__ */ jsxRuntime.jsx(
27
+ "path",
28
+ {
29
+ d: "m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z",
30
+ fill: "#ecb22e"
31
+ }
32
+ ),
33
+ /* @__PURE__ */ jsxRuntime.jsx(
34
+ "path",
35
+ {
36
+ d: "m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0",
37
+ fill: "#e01e5a"
38
+ }
39
+ )
40
+ ] }) });
41
+ const TeamsMark = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 2228.833 2073.333", className, "aria-hidden": "true", focusable: "false", children: [
42
+ /* @__PURE__ */ jsxRuntime.jsx(
43
+ "path",
44
+ {
45
+ fill: "#5059C9",
46
+ d: "M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h-1.711c-199.901.028-361.975-162-362.004-361.901V828.971c0-28.427 23.044-51.471 51.471-51.471z"
47
+ }
48
+ ),
49
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { fill: "#5059C9", cx: "1943.75", cy: "440.583", r: "233.25" }),
50
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { fill: "#7B83EB", cx: "1218.083", cy: "336.917", r: "336.917" }),
51
+ /* @__PURE__ */ jsxRuntime.jsx(
52
+ "path",
53
+ {
54
+ fill: "#7B83EB",
55
+ d: "M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z"
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsxRuntime.jsx(
59
+ "path",
60
+ {
61
+ fill: "#4B53BC",
62
+ d: "M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z"
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsxRuntime.jsx("path", { fill: "#FFF", d: "M820.211 828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088z" })
66
+ ] });
67
+ const ChannelMark = ({
68
+ kind,
69
+ className
70
+ }) => {
71
+ switch (kind) {
72
+ case "slack":
73
+ return /* @__PURE__ */ jsxRuntime.jsx(SlackMark, { className });
74
+ case "teams":
75
+ return /* @__PURE__ */ jsxRuntime.jsx(TeamsMark, { className });
76
+ case "email":
77
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MailIcon, { className: cnfast.cn("text-sky-600", className), "aria-hidden": "true" });
78
+ case "sms":
79
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareIcon, { className: cnfast.cn("text-emerald-600", className), "aria-hidden": "true" });
80
+ case "api":
81
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CodeIcon, { className: cnfast.cn("text-muted-foreground", className), "aria-hidden": "true" });
82
+ case "voice_memo":
83
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AudioLinesIcon, { className: cnfast.cn("text-violet-600", className), "aria-hidden": "true" });
84
+ default:
85
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquareIcon, { className: cnfast.cn("text-muted-foreground", className), "aria-hidden": "true" });
86
+ }
87
+ };
88
+ function firstText(parts) {
89
+ if (!Array.isArray(parts)) return "";
90
+ for (const part of parts) {
91
+ if (typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string") {
92
+ return part.text;
93
+ }
94
+ }
95
+ return "";
96
+ }
97
+ const InboundChannelFacts = ({ message }) => /* @__PURE__ */ jsxRuntime.jsxs(
98
+ "div",
99
+ {
100
+ className: "flex w-full min-w-0 flex-col gap-2 rounded-xl border border-border bg-background px-3 py-2.5 text-left text-xs",
101
+ "data-slot": "inbound-channel-facts",
102
+ children: [
103
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "What the agent received with this message" }),
104
+ message.facts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1", children: message.facts.map((fact, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "contents", children: [
105
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "whitespace-nowrap text-muted-foreground", children: fact.label }),
106
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-foreground [overflow-wrap:anywhere]", children: fact.value })
107
+ ] }, `${fact.key}-${index}`)) }) : null,
108
+ message.quoted ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
109
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "Earlier in the thread" }),
110
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap border-border border-l-2 pl-2 text-foreground [overflow-wrap:anywhere]", children: message.quoted })
111
+ ] }) : null
112
+ ]
113
+ }
114
+ );
115
+ const InboundChannelSource = ({
116
+ message,
117
+ className
118
+ }) => {
119
+ const [open, setOpen] = require$$0.useState(false);
120
+ const origin = message.origin;
121
+ const name = origin.senderName;
122
+ const handle = origin.senderHandle;
123
+ const primary = name ?? handle ?? origin.label;
124
+ const secondary = name && handle ? handle : null;
125
+ const channelLine = [origin.label, origin.place].filter(Boolean).join(" · ");
126
+ return /* @__PURE__ */ jsxRuntime.jsxs(
127
+ collapsible.Collapsible,
128
+ {
129
+ open,
130
+ onOpenChange: setOpen,
131
+ className: cnfast.cn("flex w-full min-w-0 flex-col items-end gap-1", className),
132
+ "data-slot": "inbound-channel",
133
+ "data-channel": origin.kind,
134
+ children: [
135
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group/inbound-channel relative flex min-w-0 max-w-full justify-end", children: [
136
+ /* @__PURE__ */ jsxRuntime.jsxs(
137
+ collapsible.CollapsibleTrigger,
138
+ {
139
+ "data-testid": "inbound-channel-source",
140
+ className: "flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-0.5 text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
141
+ children: [
142
+ /* @__PURE__ */ jsxRuntime.jsx(ChannelMark, { kind: origin.kind, className: "size-3.5 shrink-0" }),
143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-foreground/80", children: primary }),
144
+ secondary ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: secondary }) : null,
145
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: `, via ${channelLine}. Show what the agent received` }),
146
+ /* @__PURE__ */ jsxRuntime.jsx(
147
+ lucideReact.ChevronDownIcon,
148
+ {
149
+ className: cnfast.cn("size-3 shrink-0 transition-transform", open && "rotate-180"),
150
+ "aria-hidden": "true"
151
+ }
152
+ )
153
+ ]
154
+ }
155
+ ),
156
+ open ? null : /* @__PURE__ */ jsxRuntime.jsxs(
157
+ "div",
158
+ {
159
+ "aria-hidden": "true",
160
+ "data-slot": "inbound-channel-card",
161
+ className: "pointer-events-none absolute top-full right-0 z-20 mt-1 flex w-max max-w-xs flex-col gap-0.5 rounded-md bg-foreground px-3 py-1.5 text-left text-background text-xs opacity-0 shadow-md transition-opacity delay-0 group-focus-within/inbound-channel:opacity-100 group-hover/inbound-channel:opacity-100 group-hover/inbound-channel:delay-300",
162
+ children: [
163
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 font-medium", children: [
164
+ /* @__PURE__ */ jsxRuntime.jsx(ChannelMark, { kind: origin.kind, className: "size-3.5 shrink-0" }),
165
+ channelLine
166
+ ] }),
167
+ name ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: name }) : null,
168
+ handle ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-80", children: handle }) : null,
169
+ origin.subject ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-80", children: `${origin.kind === "voice_memo" ? "Memo" : "Subject"}: ${origin.subject}` }) : null
170
+ ]
171
+ }
172
+ )
173
+ ] }),
174
+ /* @__PURE__ */ jsxRuntime.jsx(collapsible.CollapsibleContent, { className: "w-full min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(InboundChannelFacts, { message }) })
175
+ ]
176
+ }
177
+ );
178
+ };
179
+ const InboundChannelLine = ({ className }) => {
180
+ const custom = react.useAuiState((s) => {
181
+ var _a;
182
+ return (_a = s.message.metadata) == null ? void 0 : _a.custom;
183
+ });
184
+ const parts = react.useAuiState((s) => s.message.parts);
185
+ const message = require$$0.useMemo(
186
+ () => inboundChannel.isInboundChannelMessage(custom) ? inboundChannelReader.readInboundChannelMessage({ custom, text: firstText(parts) }) : null,
187
+ [custom, parts]
188
+ );
189
+ return message ? /* @__PURE__ */ jsxRuntime.jsx(InboundChannelSource, { message, className }) : null;
190
+ };
191
+ const InboundChannelSubject = () => {
192
+ const subject = react.useAuiState((s) => {
193
+ var _a;
194
+ return inboundChannel.inboundEmailSubject((_a = s.message.metadata) == null ? void 0 : _a.custom);
195
+ });
196
+ if (!subject) return null;
197
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 font-semibold", "data-slot": "inbound-channel-subject", children: subject });
198
+ };
199
+ const wrappedTextComponents = /* @__PURE__ */ new WeakMap();
200
+ function withInboundMessageBody(Text) {
201
+ const cached = wrappedTextComponents.get(Text);
202
+ if (cached) return cached;
203
+ const InboundMessageBodyText = (props) => {
204
+ const custom = react.useAuiState((s) => {
205
+ var _a;
206
+ return (_a = s.message.metadata) == null ? void 0 : _a.custom;
207
+ });
208
+ const text = require$$0.useMemo(() => inboundChannel.inboundMessageBody({ custom, text: props.text }), [custom, props.text]);
209
+ return /* @__PURE__ */ jsxRuntime.jsx(Text, { ...props, text });
210
+ };
211
+ wrappedTextComponents.set(Text, InboundMessageBodyText);
212
+ return InboundMessageBodyText;
213
+ }
214
+ exports.ChannelMark = ChannelMark;
215
+ exports.InboundChannelLine = InboundChannelLine;
216
+ exports.InboundChannelSource = InboundChannelSource;
217
+ exports.InboundChannelSubject = InboundChannelSubject;
218
+ exports.withInboundMessageBody = withInboundMessageBody;
219
+ //# sourceMappingURL=inbound-channel-message.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-channel-message.cjs","sources":["../../../src/chat-ui/messages/inbound-channel-message.tsx"],"sourcesContent":["/**\n * A user turn that came in over a channel (Slack, email, a text, Microsoft\n * Teams, the Programmatic API, a voice memo), drawn as the words that were\n * sent under a line naming the channel and the sender.\n *\n * The channel's routing block (`<inbound-message-context>`: the facts the\n * agent is told, such as Slack ids, the numbers a text went between and how a\n * reply is delivered) leaves the bubble. The line above the bubble opens it\n * as a labelled list, and hovering the line shows the channel, the place and\n * the sender in full. Every host that renders the SDK's user message gets\n * this; a host with its own user message composes it from\n * `InboundChannelLine`, `InboundChannelSubject` and `withInboundMessageBody`\n * (or `UserMessageText`). Only a message with the `inbound_channel` envelope\n * is a channel message: tags someone types show as typed.\n *\n * The hover card is CSS, not a Radix tooltip, and the glyphs are icons the\n * chat already draws: a host that splits `node_modules` into startup vendor\n * chunks (the Office pane) would otherwise load a tooltip stack at startup for\n * a line it rarely shows.\n */\nimport { type TextMessagePartComponent, useAuiState } from \"@assistant-ui/react\";\nimport {\n inboundEmailSubject,\n inboundMessageBody,\n isInboundChannelMessage,\n} from \"@athenaintel/agent-runtime\";\nimport { AudioLinesIcon, ChevronDownIcon, CodeIcon, MailIcon, MessageSquareIcon } from \"lucide-react\";\nimport { type FC, useMemo, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"../../ui/collapsible\";\nimport {\n type InboundChannelKind,\n type InboundChannelMessage,\n readInboundChannelMessage,\n} from \"./inbound-channel-reader\";\n\n/** Slack's four-colour mark. */\nconst SlackMark: FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 2447.6 2452.5\" className={className} aria-hidden=\"true\" focusable=\"false\">\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z\"\n fill=\"#36c5f0\"\n />\n <path\n d=\"m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z\"\n fill=\"#2eb67d\"\n />\n <path\n d=\"m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z\"\n fill=\"#ecb22e\"\n />\n <path\n d=\"m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0\"\n fill=\"#e01e5a\"\n />\n </g>\n </svg>\n);\n\n/** Microsoft Teams' mark: the two people and the T tile, in flat colour. */\nconst TeamsMark: FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 2228.833 2073.333\" className={className} aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"#5059C9\"\n d=\"M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h-1.711c-199.901.028-361.975-162-362.004-361.901V828.971c0-28.427 23.044-51.471 51.471-51.471z\"\n />\n <circle fill=\"#5059C9\" cx=\"1943.75\" cy=\"440.583\" r=\"233.25\" />\n <circle fill=\"#7B83EB\" cx=\"1218.083\" cy=\"336.917\" r=\"336.917\" />\n <path\n fill=\"#7B83EB\"\n d=\"M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z\"\n />\n <path\n fill=\"#4B53BC\"\n d=\"M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z\"\n />\n <path fill=\"#FFF\" d=\"M820.211 828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088z\" />\n </svg>\n);\n\n/**\n * The channel's mark at the size `className` gives: Slack's and Teams' own\n * logos, a tinted glyph for email, texts, the API and voice memos, a speech\n * bubble for any other channel. Decorative: the line it sits on names the\n * channel.\n */\nexport const ChannelMark: FC<{ kind: InboundChannelKind; className?: string }> = ({\n kind,\n className,\n}) => {\n switch (kind) {\n case \"slack\":\n return <SlackMark className={className} />;\n case \"teams\":\n return <TeamsMark className={className} />;\n case \"email\":\n return <MailIcon className={cn(\"text-sky-600\", className)} aria-hidden=\"true\" />;\n case \"sms\":\n return <MessageSquareIcon className={cn(\"text-emerald-600\", className)} aria-hidden=\"true\" />;\n case \"api\":\n return <CodeIcon className={cn(\"text-muted-foreground\", className)} aria-hidden=\"true\" />;\n case \"voice_memo\":\n return <AudioLinesIcon className={cn(\"text-violet-600\", className)} aria-hidden=\"true\" />;\n default:\n return <MessageSquareIcon className={cn(\"text-muted-foreground\", className)} aria-hidden=\"true\" />;\n }\n};\n\n/** The first text part's words: where a channel's routing block sits. */\nfunction firstText(parts: unknown): string {\n if (!Array.isArray(parts)) return \"\";\n for (const part of parts) {\n if (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n }\n return \"\";\n}\n\n/** Everything the agent read with the message, labelled; the thread a mention came in below it. */\nconst InboundChannelFacts: FC<{ message: InboundChannelMessage }> = ({ message }) => (\n <div\n className=\"flex w-full min-w-0 flex-col gap-2 rounded-xl border border-border bg-background px-3 py-2.5 text-left text-xs\"\n data-slot=\"inbound-channel-facts\"\n >\n <p className=\"text-muted-foreground\">What the agent received with this message</p>\n {message.facts.length > 0 ? (\n <dl className=\"grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1\">\n {message.facts.map((fact, index) => (\n <div key={`${fact.key}-${index}`} className=\"contents\">\n <dt className=\"whitespace-nowrap text-muted-foreground\">{fact.label}</dt>\n <dd className=\"text-foreground [overflow-wrap:anywhere]\">{fact.value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {message.quoted ? (\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-muted-foreground\">Earlier in the thread</p>\n <p className=\"whitespace-pre-wrap border-border border-l-2 pl-2 text-foreground [overflow-wrap:anywhere]\">\n {message.quoted}\n </p>\n </div>\n ) : null}\n </div>\n);\n\n/**\n * The line above a channel message's bubble: the channel's mark, the sender's\n * name and address (an email address, a phone number), and a chevron that\n * opens what the agent received. Hovering or focusing it shows a card with\n * the channel, the place and the sender in full, while the facts are closed.\n */\nexport const InboundChannelSource: FC<{ message: InboundChannelMessage; className?: string }> = ({\n message,\n className,\n}) => {\n const [open, setOpen] = useState(false);\n const origin = message.origin;\n const name = origin.senderName;\n const handle = origin.senderHandle;\n const primary = name ?? handle ?? origin.label;\n const secondary = name && handle ? handle : null;\n const channelLine = [origin.label, origin.place].filter(Boolean).join(\" · \");\n\n return (\n <Collapsible\n open={open}\n onOpenChange={setOpen}\n className={cn(\"flex w-full min-w-0 flex-col items-end gap-1\", className)}\n data-slot=\"inbound-channel\"\n data-channel={origin.kind}\n >\n <div className=\"group/inbound-channel relative flex min-w-0 max-w-full justify-end\">\n <CollapsibleTrigger\n data-testid=\"inbound-channel-source\"\n className=\"flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-0.5 text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChannelMark kind={origin.kind} className=\"size-3.5 shrink-0\" />\n <span className=\"truncate font-medium text-foreground/80\">{primary}</span>\n {secondary ? <span className=\"truncate\">{secondary}</span> : null}\n <span className=\"sr-only\">{`, via ${channelLine}. Show what the agent received`}</span>\n <ChevronDownIcon\n className={cn(\"size-3 shrink-0 transition-transform\", open && \"rotate-180\")}\n aria-hidden=\"true\"\n />\n </CollapsibleTrigger>\n {/* The hover card: what the line says, in full (the button's own text\n carries it for screen readers). Shown below the line, over the\n bubble, after a short rest, and never while the facts are open. */}\n {open ? null : (\n <div\n aria-hidden=\"true\"\n data-slot=\"inbound-channel-card\"\n className=\"pointer-events-none absolute top-full right-0 z-20 mt-1 flex w-max max-w-xs flex-col gap-0.5 rounded-md bg-foreground px-3 py-1.5 text-left text-background text-xs opacity-0 shadow-md transition-opacity delay-0 group-focus-within/inbound-channel:opacity-100 group-hover/inbound-channel:opacity-100 group-hover/inbound-channel:delay-300\"\n >\n <span className=\"flex items-center gap-1.5 font-medium\">\n <ChannelMark kind={origin.kind} className=\"size-3.5 shrink-0\" />\n {channelLine}\n </span>\n {name ? <span>{name}</span> : null}\n {handle ? <span className=\"opacity-80\">{handle}</span> : null}\n {origin.subject ? (\n <span className=\"opacity-80\">\n {`${origin.kind === \"voice_memo\" ? \"Memo\" : \"Subject\"}: ${origin.subject}`}\n </span>\n ) : null}\n </div>\n )}\n </div>\n <CollapsibleContent className=\"w-full min-w-0\">\n <InboundChannelFacts message={message} />\n </CollapsibleContent>\n </Collapsible>\n );\n};\n\n/**\n * The line above the bubble for the assistant-ui message in scope; nothing\n * for a message without the `inbound_channel` envelope. Selects the raw\n * metadata and parts (stable for a settled message) and derives in `useMemo`.\n */\nexport const InboundChannelLine: FC<{ className?: string }> = ({ className }) => {\n const custom = useAuiState((s) => s.message.metadata?.custom);\n const parts = useAuiState((s) => s.message.parts);\n const message = useMemo(\n () =>\n isInboundChannelMessage(custom)\n ? readInboundChannelMessage({ custom, text: firstText(parts) })\n : null,\n [custom, parts],\n );\n return message ? <InboundChannelSource message={message} className={className} /> : null;\n};\n\n/** An email's subject, the bubble's first line. Nothing for any other message. */\nexport const InboundChannelSubject: FC = () => {\n const subject = useAuiState((s) => inboundEmailSubject(s.message.metadata?.custom));\n if (!subject) return null;\n return (\n <div className=\"mb-1 font-semibold\" data-slot=\"inbound-channel-subject\">\n {subject}\n </div>\n );\n};\n\nconst wrappedTextComponents = new WeakMap<TextMessagePartComponent, TextMessagePartComponent>();\n\n/**\n * `Text` showing a channel message's words without the routing block the\n * agent read ahead of them. Any other text passes through unchanged, tags a\n * person typed included. Cached per component, so a host's part map keeps a\n * stable identity.\n */\nexport function withInboundMessageBody(Text: TextMessagePartComponent): TextMessagePartComponent {\n const cached = wrappedTextComponents.get(Text);\n if (cached) return cached;\n const InboundMessageBodyText: TextMessagePartComponent = (props) => {\n const custom = useAuiState((s) => s.message.metadata?.custom);\n const text = useMemo(() => inboundMessageBody({ custom, text: props.text }), [custom, props.text]);\n return <Text {...props} text={text} />;\n };\n wrappedTextComponents.set(Text, InboundMessageBodyText);\n return InboundMessageBodyText;\n}\n"],"names":["jsx","jsxs","MailIcon","cn","MessageSquareIcon","CodeIcon","AudioLinesIcon","useState","Collapsible","CollapsibleTrigger","ChevronDownIcon","CollapsibleContent","useAuiState","useMemo","isInboundChannelMessage","readInboundChannelMessage","inboundEmailSubject","inboundMessageBody"],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * A user turn that came in over a channel (Slack, email, a text, Microsoft
3
+ * Teams, the Programmatic API, a voice memo), drawn as the words that were
4
+ * sent under a line naming the channel and the sender.
5
+ *
6
+ * The channel's routing block (`<inbound-message-context>`: the facts the
7
+ * agent is told, such as Slack ids, the numbers a text went between and how a
8
+ * reply is delivered) leaves the bubble. The line above the bubble opens it
9
+ * as a labelled list, and hovering the line shows the channel, the place and
10
+ * the sender in full. Every host that renders the SDK's user message gets
11
+ * this; a host with its own user message composes it from
12
+ * `InboundChannelLine`, `InboundChannelSubject` and `withInboundMessageBody`
13
+ * (or `UserMessageText`). Only a message with the `inbound_channel` envelope
14
+ * is a channel message: tags someone types show as typed.
15
+ *
16
+ * The hover card is CSS, not a Radix tooltip, and the glyphs are icons the
17
+ * chat already draws: a host that splits `node_modules` into startup vendor
18
+ * chunks (the Office pane) would otherwise load a tooltip stack at startup for
19
+ * a line it rarely shows.
20
+ */
21
+ import { type TextMessagePartComponent } from "@assistant-ui/react";
22
+ import { type FC } from "react";
23
+ import { type InboundChannelKind, type InboundChannelMessage } from "./inbound-channel-reader";
24
+ /**
25
+ * The channel's mark at the size `className` gives: Slack's and Teams' own
26
+ * logos, a tinted glyph for email, texts, the API and voice memos, a speech
27
+ * bubble for any other channel. Decorative: the line it sits on names the
28
+ * channel.
29
+ */
30
+ export declare const ChannelMark: FC<{
31
+ kind: InboundChannelKind;
32
+ className?: string;
33
+ }>;
34
+ /**
35
+ * The line above a channel message's bubble: the channel's mark, the sender's
36
+ * name and address (an email address, a phone number), and a chevron that
37
+ * opens what the agent received. Hovering or focusing it shows a card with
38
+ * the channel, the place and the sender in full, while the facts are closed.
39
+ */
40
+ export declare const InboundChannelSource: FC<{
41
+ message: InboundChannelMessage;
42
+ className?: string;
43
+ }>;
44
+ /**
45
+ * The line above the bubble for the assistant-ui message in scope; nothing
46
+ * for a message without the `inbound_channel` envelope. Selects the raw
47
+ * metadata and parts (stable for a settled message) and derives in `useMemo`.
48
+ */
49
+ export declare const InboundChannelLine: FC<{
50
+ className?: string;
51
+ }>;
52
+ /** An email's subject, the bubble's first line. Nothing for any other message. */
53
+ export declare const InboundChannelSubject: FC;
54
+ /**
55
+ * `Text` showing a channel message's words without the routing block the
56
+ * agent read ahead of them. Any other text passes through unchanged, tags a
57
+ * person typed included. Cached per component, so a host's part map keeps a
58
+ * stable identity.
59
+ */
60
+ export declare function withInboundMessageBody(Text: TextMessagePartComponent): TextMessagePartComponent;
@@ -0,0 +1,219 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useAuiState } from "@assistant-ui/react";
3
+ import { ChevronDownIcon, MessageSquareIcon, AudioLinesIcon, CodeIcon, MailIcon } from "lucide-react";
4
+ import { useMemo, useState } from "react";
5
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from "../../ui/collapsible.js";
6
+ import { readInboundChannelMessage } from "./inbound-channel-reader.js";
7
+ import { isInboundChannelMessage, inboundEmailSubject, inboundMessageBody } from "../../agent-runtime/src/inbound-channel.js";
8
+ import { cn } from "cnfast";
9
+ const SlackMark = ({ className }) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 2447.6 2452.5", className, "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsxs("g", { clipRule: "evenodd", fillRule: "evenodd", children: [
10
+ /* @__PURE__ */ jsx(
11
+ "path",
12
+ {
13
+ d: "m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z",
14
+ fill: "#36c5f0"
15
+ }
16
+ ),
17
+ /* @__PURE__ */ jsx(
18
+ "path",
19
+ {
20
+ d: "m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z",
21
+ fill: "#2eb67d"
22
+ }
23
+ ),
24
+ /* @__PURE__ */ jsx(
25
+ "path",
26
+ {
27
+ d: "m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z",
28
+ fill: "#ecb22e"
29
+ }
30
+ ),
31
+ /* @__PURE__ */ jsx(
32
+ "path",
33
+ {
34
+ d: "m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0",
35
+ fill: "#e01e5a"
36
+ }
37
+ )
38
+ ] }) });
39
+ const TeamsMark = ({ className }) => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 2228.833 2073.333", className, "aria-hidden": "true", focusable: "false", children: [
40
+ /* @__PURE__ */ jsx(
41
+ "path",
42
+ {
43
+ fill: "#5059C9",
44
+ d: "M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h-1.711c-199.901.028-361.975-162-362.004-361.901V828.971c0-28.427 23.044-51.471 51.471-51.471z"
45
+ }
46
+ ),
47
+ /* @__PURE__ */ jsx("circle", { fill: "#5059C9", cx: "1943.75", cy: "440.583", r: "233.25" }),
48
+ /* @__PURE__ */ jsx("circle", { fill: "#7B83EB", cx: "1218.083", cy: "336.917", r: "336.917" }),
49
+ /* @__PURE__ */ jsx(
50
+ "path",
51
+ {
52
+ fill: "#7B83EB",
53
+ d: "M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z"
54
+ }
55
+ ),
56
+ /* @__PURE__ */ jsx(
57
+ "path",
58
+ {
59
+ fill: "#4B53BC",
60
+ d: "M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z"
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsx("path", { fill: "#FFF", d: "M820.211 828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088z" })
64
+ ] });
65
+ const ChannelMark = ({
66
+ kind,
67
+ className
68
+ }) => {
69
+ switch (kind) {
70
+ case "slack":
71
+ return /* @__PURE__ */ jsx(SlackMark, { className });
72
+ case "teams":
73
+ return /* @__PURE__ */ jsx(TeamsMark, { className });
74
+ case "email":
75
+ return /* @__PURE__ */ jsx(MailIcon, { className: cn("text-sky-600", className), "aria-hidden": "true" });
76
+ case "sms":
77
+ return /* @__PURE__ */ jsx(MessageSquareIcon, { className: cn("text-emerald-600", className), "aria-hidden": "true" });
78
+ case "api":
79
+ return /* @__PURE__ */ jsx(CodeIcon, { className: cn("text-muted-foreground", className), "aria-hidden": "true" });
80
+ case "voice_memo":
81
+ return /* @__PURE__ */ jsx(AudioLinesIcon, { className: cn("text-violet-600", className), "aria-hidden": "true" });
82
+ default:
83
+ return /* @__PURE__ */ jsx(MessageSquareIcon, { className: cn("text-muted-foreground", className), "aria-hidden": "true" });
84
+ }
85
+ };
86
+ function firstText(parts) {
87
+ if (!Array.isArray(parts)) return "";
88
+ for (const part of parts) {
89
+ if (typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string") {
90
+ return part.text;
91
+ }
92
+ }
93
+ return "";
94
+ }
95
+ const InboundChannelFacts = ({ message }) => /* @__PURE__ */ jsxs(
96
+ "div",
97
+ {
98
+ className: "flex w-full min-w-0 flex-col gap-2 rounded-xl border border-border bg-background px-3 py-2.5 text-left text-xs",
99
+ "data-slot": "inbound-channel-facts",
100
+ children: [
101
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "What the agent received with this message" }),
102
+ message.facts.length > 0 ? /* @__PURE__ */ jsx("dl", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1", children: message.facts.map((fact, index) => /* @__PURE__ */ jsxs("div", { className: "contents", children: [
103
+ /* @__PURE__ */ jsx("dt", { className: "whitespace-nowrap text-muted-foreground", children: fact.label }),
104
+ /* @__PURE__ */ jsx("dd", { className: "text-foreground [overflow-wrap:anywhere]", children: fact.value })
105
+ ] }, `${fact.key}-${index}`)) }) : null,
106
+ message.quoted ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
107
+ /* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: "Earlier in the thread" }),
108
+ /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap border-border border-l-2 pl-2 text-foreground [overflow-wrap:anywhere]", children: message.quoted })
109
+ ] }) : null
110
+ ]
111
+ }
112
+ );
113
+ const InboundChannelSource = ({
114
+ message,
115
+ className
116
+ }) => {
117
+ const [open, setOpen] = useState(false);
118
+ const origin = message.origin;
119
+ const name = origin.senderName;
120
+ const handle = origin.senderHandle;
121
+ const primary = name ?? handle ?? origin.label;
122
+ const secondary = name && handle ? handle : null;
123
+ const channelLine = [origin.label, origin.place].filter(Boolean).join(" · ");
124
+ return /* @__PURE__ */ jsxs(
125
+ Collapsible,
126
+ {
127
+ open,
128
+ onOpenChange: setOpen,
129
+ className: cn("flex w-full min-w-0 flex-col items-end gap-1", className),
130
+ "data-slot": "inbound-channel",
131
+ "data-channel": origin.kind,
132
+ children: [
133
+ /* @__PURE__ */ jsxs("div", { className: "group/inbound-channel relative flex min-w-0 max-w-full justify-end", children: [
134
+ /* @__PURE__ */ jsxs(
135
+ CollapsibleTrigger,
136
+ {
137
+ "data-testid": "inbound-channel-source",
138
+ className: "flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-0.5 text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
139
+ children: [
140
+ /* @__PURE__ */ jsx(ChannelMark, { kind: origin.kind, className: "size-3.5 shrink-0" }),
141
+ /* @__PURE__ */ jsx("span", { className: "truncate font-medium text-foreground/80", children: primary }),
142
+ secondary ? /* @__PURE__ */ jsx("span", { className: "truncate", children: secondary }) : null,
143
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: `, via ${channelLine}. Show what the agent received` }),
144
+ /* @__PURE__ */ jsx(
145
+ ChevronDownIcon,
146
+ {
147
+ className: cn("size-3 shrink-0 transition-transform", open && "rotate-180"),
148
+ "aria-hidden": "true"
149
+ }
150
+ )
151
+ ]
152
+ }
153
+ ),
154
+ open ? null : /* @__PURE__ */ jsxs(
155
+ "div",
156
+ {
157
+ "aria-hidden": "true",
158
+ "data-slot": "inbound-channel-card",
159
+ className: "pointer-events-none absolute top-full right-0 z-20 mt-1 flex w-max max-w-xs flex-col gap-0.5 rounded-md bg-foreground px-3 py-1.5 text-left text-background text-xs opacity-0 shadow-md transition-opacity delay-0 group-focus-within/inbound-channel:opacity-100 group-hover/inbound-channel:opacity-100 group-hover/inbound-channel:delay-300",
160
+ children: [
161
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5 font-medium", children: [
162
+ /* @__PURE__ */ jsx(ChannelMark, { kind: origin.kind, className: "size-3.5 shrink-0" }),
163
+ channelLine
164
+ ] }),
165
+ name ? /* @__PURE__ */ jsx("span", { children: name }) : null,
166
+ handle ? /* @__PURE__ */ jsx("span", { className: "opacity-80", children: handle }) : null,
167
+ origin.subject ? /* @__PURE__ */ jsx("span", { className: "opacity-80", children: `${origin.kind === "voice_memo" ? "Memo" : "Subject"}: ${origin.subject}` }) : null
168
+ ]
169
+ }
170
+ )
171
+ ] }),
172
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "w-full min-w-0", children: /* @__PURE__ */ jsx(InboundChannelFacts, { message }) })
173
+ ]
174
+ }
175
+ );
176
+ };
177
+ const InboundChannelLine = ({ className }) => {
178
+ const custom = useAuiState((s) => {
179
+ var _a;
180
+ return (_a = s.message.metadata) == null ? void 0 : _a.custom;
181
+ });
182
+ const parts = useAuiState((s) => s.message.parts);
183
+ const message = useMemo(
184
+ () => isInboundChannelMessage(custom) ? readInboundChannelMessage({ custom, text: firstText(parts) }) : null,
185
+ [custom, parts]
186
+ );
187
+ return message ? /* @__PURE__ */ jsx(InboundChannelSource, { message, className }) : null;
188
+ };
189
+ const InboundChannelSubject = () => {
190
+ const subject = useAuiState((s) => {
191
+ var _a;
192
+ return inboundEmailSubject((_a = s.message.metadata) == null ? void 0 : _a.custom);
193
+ });
194
+ if (!subject) return null;
195
+ return /* @__PURE__ */ jsx("div", { className: "mb-1 font-semibold", "data-slot": "inbound-channel-subject", children: subject });
196
+ };
197
+ const wrappedTextComponents = /* @__PURE__ */ new WeakMap();
198
+ function withInboundMessageBody(Text) {
199
+ const cached = wrappedTextComponents.get(Text);
200
+ if (cached) return cached;
201
+ const InboundMessageBodyText = (props) => {
202
+ const custom = useAuiState((s) => {
203
+ var _a;
204
+ return (_a = s.message.metadata) == null ? void 0 : _a.custom;
205
+ });
206
+ const text = useMemo(() => inboundMessageBody({ custom, text: props.text }), [custom, props.text]);
207
+ return /* @__PURE__ */ jsx(Text, { ...props, text });
208
+ };
209
+ wrappedTextComponents.set(Text, InboundMessageBodyText);
210
+ return InboundMessageBodyText;
211
+ }
212
+ export {
213
+ ChannelMark,
214
+ InboundChannelLine,
215
+ InboundChannelSource,
216
+ InboundChannelSubject,
217
+ withInboundMessageBody
218
+ };
219
+ //# sourceMappingURL=inbound-channel-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-channel-message.js","sources":["../../../src/chat-ui/messages/inbound-channel-message.tsx"],"sourcesContent":["/**\n * A user turn that came in over a channel (Slack, email, a text, Microsoft\n * Teams, the Programmatic API, a voice memo), drawn as the words that were\n * sent under a line naming the channel and the sender.\n *\n * The channel's routing block (`<inbound-message-context>`: the facts the\n * agent is told, such as Slack ids, the numbers a text went between and how a\n * reply is delivered) leaves the bubble. The line above the bubble opens it\n * as a labelled list, and hovering the line shows the channel, the place and\n * the sender in full. Every host that renders the SDK's user message gets\n * this; a host with its own user message composes it from\n * `InboundChannelLine`, `InboundChannelSubject` and `withInboundMessageBody`\n * (or `UserMessageText`). Only a message with the `inbound_channel` envelope\n * is a channel message: tags someone types show as typed.\n *\n * The hover card is CSS, not a Radix tooltip, and the glyphs are icons the\n * chat already draws: a host that splits `node_modules` into startup vendor\n * chunks (the Office pane) would otherwise load a tooltip stack at startup for\n * a line it rarely shows.\n */\nimport { type TextMessagePartComponent, useAuiState } from \"@assistant-ui/react\";\nimport {\n inboundEmailSubject,\n inboundMessageBody,\n isInboundChannelMessage,\n} from \"@athenaintel/agent-runtime\";\nimport { AudioLinesIcon, ChevronDownIcon, CodeIcon, MailIcon, MessageSquareIcon } from \"lucide-react\";\nimport { type FC, useMemo, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Collapsible, CollapsibleContent, CollapsibleTrigger } from \"../../ui/collapsible\";\nimport {\n type InboundChannelKind,\n type InboundChannelMessage,\n readInboundChannelMessage,\n} from \"./inbound-channel-reader\";\n\n/** Slack's four-colour mark. */\nconst SlackMark: FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 2447.6 2452.5\" className={className} aria-hidden=\"true\" focusable=\"false\">\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"m897.4 0c-135.3.1-244.8 109.9-244.7 245.2-.1 135.3 109.5 245.1 244.8 245.2h244.8v-245.1c.1-135.3-109.5-245.1-244.9-245.3.1 0 .1 0 0 0m0 654h-652.6c-135.3.1-244.9 109.9-244.8 245.2-.2 135.3 109.4 245.1 244.7 245.3h652.7c135.3-.1 244.9-109.9 244.8-245.2.1-135.4-109.5-245.2-244.8-245.3z\"\n fill=\"#36c5f0\"\n />\n <path\n d=\"m2447.6 899.2c.1-135.3-109.5-245.1-244.8-245.2-135.3.1-244.9 109.9-244.8 245.2v245.3h244.8c135.3-.1 244.9-109.9 244.8-245.3zm-652.7 0v-654c.1-135.2-109.4-245-244.7-245.2-135.3.1-244.9 109.9-244.8 245.2v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.3z\"\n fill=\"#2eb67d\"\n />\n <path\n d=\"m1550.1 2452.5c135.3-.1 244.9-109.9 244.8-245.2.1-135.3-109.5-245.1-244.8-245.2h-244.8v245.2c-.1 135.2 109.5 245 244.8 245.2zm0-654.1h652.7c135.3-.1 244.9-109.9 244.8-245.2.2-135.3-109.4-245.1-244.7-245.3h-652.7c-135.3.1-244.9 109.9-244.8 245.2-.1 135.4 109.4 245.2 244.7 245.3z\"\n fill=\"#ecb22e\"\n />\n <path\n d=\"m0 1553.2c-.1 135.3 109.5 245.1 244.8 245.2 135.3-.1 244.9-109.9 244.8-245.2v-245.2h-244.8c-135.3.1-244.9 109.9-244.8 245.2zm652.7 0v654c-.2 135.3 109.4 245.1 244.7 245.3 135.3-.1 244.9-109.9 244.8-245.2v-653.9c.2-135.3-109.4-245.1-244.7-245.3-135.4 0-244.9 109.8-244.8 245.1 0 0 0 .1 0 0\"\n fill=\"#e01e5a\"\n />\n </g>\n </svg>\n);\n\n/** Microsoft Teams' mark: the two people and the T tile, in flat colour. */\nconst TeamsMark: FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 2228.833 2073.333\" className={className} aria-hidden=\"true\" focusable=\"false\">\n <path\n fill=\"#5059C9\"\n d=\"M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h-1.711c-199.901.028-361.975-162-362.004-361.901V828.971c0-28.427 23.044-51.471 51.471-51.471z\"\n />\n <circle fill=\"#5059C9\" cx=\"1943.75\" cy=\"440.583\" r=\"233.25\" />\n <circle fill=\"#7B83EB\" cx=\"1218.083\" cy=\"336.917\" r=\"336.917\" />\n <path\n fill=\"#7B83EB\"\n d=\"M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z\"\n />\n <path\n fill=\"#4B53BC\"\n d=\"M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z\"\n />\n <path fill=\"#FFF\" d=\"M820.211 828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088z\" />\n </svg>\n);\n\n/**\n * The channel's mark at the size `className` gives: Slack's and Teams' own\n * logos, a tinted glyph for email, texts, the API and voice memos, a speech\n * bubble for any other channel. Decorative: the line it sits on names the\n * channel.\n */\nexport const ChannelMark: FC<{ kind: InboundChannelKind; className?: string }> = ({\n kind,\n className,\n}) => {\n switch (kind) {\n case \"slack\":\n return <SlackMark className={className} />;\n case \"teams\":\n return <TeamsMark className={className} />;\n case \"email\":\n return <MailIcon className={cn(\"text-sky-600\", className)} aria-hidden=\"true\" />;\n case \"sms\":\n return <MessageSquareIcon className={cn(\"text-emerald-600\", className)} aria-hidden=\"true\" />;\n case \"api\":\n return <CodeIcon className={cn(\"text-muted-foreground\", className)} aria-hidden=\"true\" />;\n case \"voice_memo\":\n return <AudioLinesIcon className={cn(\"text-violet-600\", className)} aria-hidden=\"true\" />;\n default:\n return <MessageSquareIcon className={cn(\"text-muted-foreground\", className)} aria-hidden=\"true\" />;\n }\n};\n\n/** The first text part's words: where a channel's routing block sits. */\nfunction firstText(parts: unknown): string {\n if (!Array.isArray(parts)) return \"\";\n for (const part of parts) {\n if (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: unknown }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n ) {\n return (part as { text: string }).text;\n }\n }\n return \"\";\n}\n\n/** Everything the agent read with the message, labelled; the thread a mention came in below it. */\nconst InboundChannelFacts: FC<{ message: InboundChannelMessage }> = ({ message }) => (\n <div\n className=\"flex w-full min-w-0 flex-col gap-2 rounded-xl border border-border bg-background px-3 py-2.5 text-left text-xs\"\n data-slot=\"inbound-channel-facts\"\n >\n <p className=\"text-muted-foreground\">What the agent received with this message</p>\n {message.facts.length > 0 ? (\n <dl className=\"grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1\">\n {message.facts.map((fact, index) => (\n <div key={`${fact.key}-${index}`} className=\"contents\">\n <dt className=\"whitespace-nowrap text-muted-foreground\">{fact.label}</dt>\n <dd className=\"text-foreground [overflow-wrap:anywhere]\">{fact.value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n {message.quoted ? (\n <div className=\"flex flex-col gap-1\">\n <p className=\"text-muted-foreground\">Earlier in the thread</p>\n <p className=\"whitespace-pre-wrap border-border border-l-2 pl-2 text-foreground [overflow-wrap:anywhere]\">\n {message.quoted}\n </p>\n </div>\n ) : null}\n </div>\n);\n\n/**\n * The line above a channel message's bubble: the channel's mark, the sender's\n * name and address (an email address, a phone number), and a chevron that\n * opens what the agent received. Hovering or focusing it shows a card with\n * the channel, the place and the sender in full, while the facts are closed.\n */\nexport const InboundChannelSource: FC<{ message: InboundChannelMessage; className?: string }> = ({\n message,\n className,\n}) => {\n const [open, setOpen] = useState(false);\n const origin = message.origin;\n const name = origin.senderName;\n const handle = origin.senderHandle;\n const primary = name ?? handle ?? origin.label;\n const secondary = name && handle ? handle : null;\n const channelLine = [origin.label, origin.place].filter(Boolean).join(\" · \");\n\n return (\n <Collapsible\n open={open}\n onOpenChange={setOpen}\n className={cn(\"flex w-full min-w-0 flex-col items-end gap-1\", className)}\n data-slot=\"inbound-channel\"\n data-channel={origin.kind}\n >\n <div className=\"group/inbound-channel relative flex min-w-0 max-w-full justify-end\">\n <CollapsibleTrigger\n data-testid=\"inbound-channel-source\"\n className=\"flex min-w-0 max-w-full items-center gap-1.5 rounded-md px-1.5 py-0.5 text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <ChannelMark kind={origin.kind} className=\"size-3.5 shrink-0\" />\n <span className=\"truncate font-medium text-foreground/80\">{primary}</span>\n {secondary ? <span className=\"truncate\">{secondary}</span> : null}\n <span className=\"sr-only\">{`, via ${channelLine}. Show what the agent received`}</span>\n <ChevronDownIcon\n className={cn(\"size-3 shrink-0 transition-transform\", open && \"rotate-180\")}\n aria-hidden=\"true\"\n />\n </CollapsibleTrigger>\n {/* The hover card: what the line says, in full (the button's own text\n carries it for screen readers). Shown below the line, over the\n bubble, after a short rest, and never while the facts are open. */}\n {open ? null : (\n <div\n aria-hidden=\"true\"\n data-slot=\"inbound-channel-card\"\n className=\"pointer-events-none absolute top-full right-0 z-20 mt-1 flex w-max max-w-xs flex-col gap-0.5 rounded-md bg-foreground px-3 py-1.5 text-left text-background text-xs opacity-0 shadow-md transition-opacity delay-0 group-focus-within/inbound-channel:opacity-100 group-hover/inbound-channel:opacity-100 group-hover/inbound-channel:delay-300\"\n >\n <span className=\"flex items-center gap-1.5 font-medium\">\n <ChannelMark kind={origin.kind} className=\"size-3.5 shrink-0\" />\n {channelLine}\n </span>\n {name ? <span>{name}</span> : null}\n {handle ? <span className=\"opacity-80\">{handle}</span> : null}\n {origin.subject ? (\n <span className=\"opacity-80\">\n {`${origin.kind === \"voice_memo\" ? \"Memo\" : \"Subject\"}: ${origin.subject}`}\n </span>\n ) : null}\n </div>\n )}\n </div>\n <CollapsibleContent className=\"w-full min-w-0\">\n <InboundChannelFacts message={message} />\n </CollapsibleContent>\n </Collapsible>\n );\n};\n\n/**\n * The line above the bubble for the assistant-ui message in scope; nothing\n * for a message without the `inbound_channel` envelope. Selects the raw\n * metadata and parts (stable for a settled message) and derives in `useMemo`.\n */\nexport const InboundChannelLine: FC<{ className?: string }> = ({ className }) => {\n const custom = useAuiState((s) => s.message.metadata?.custom);\n const parts = useAuiState((s) => s.message.parts);\n const message = useMemo(\n () =>\n isInboundChannelMessage(custom)\n ? readInboundChannelMessage({ custom, text: firstText(parts) })\n : null,\n [custom, parts],\n );\n return message ? <InboundChannelSource message={message} className={className} /> : null;\n};\n\n/** An email's subject, the bubble's first line. Nothing for any other message. */\nexport const InboundChannelSubject: FC = () => {\n const subject = useAuiState((s) => inboundEmailSubject(s.message.metadata?.custom));\n if (!subject) return null;\n return (\n <div className=\"mb-1 font-semibold\" data-slot=\"inbound-channel-subject\">\n {subject}\n </div>\n );\n};\n\nconst wrappedTextComponents = new WeakMap<TextMessagePartComponent, TextMessagePartComponent>();\n\n/**\n * `Text` showing a channel message's words without the routing block the\n * agent read ahead of them. Any other text passes through unchanged, tags a\n * person typed included. Cached per component, so a host's part map keeps a\n * stable identity.\n */\nexport function withInboundMessageBody(Text: TextMessagePartComponent): TextMessagePartComponent {\n const cached = wrappedTextComponents.get(Text);\n if (cached) return cached;\n const InboundMessageBodyText: TextMessagePartComponent = (props) => {\n const custom = useAuiState((s) => s.message.metadata?.custom);\n const text = useMemo(() => inboundMessageBody({ custom, text: props.text }), [custom, props.text]);\n return <Text {...props} text={text} />;\n };\n wrappedTextComponents.set(Text, InboundMessageBodyText);\n return InboundMessageBodyText;\n}\n"],"names":[],"mappings":"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"}