@frontera-sdk/chat-ui 1.50.40

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 (148) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +348 -0
  3. package/dist/af-DK_CjRn6-OPBHDTNZ.js +197 -0
  4. package/dist/agent-picker.d.ts +38 -0
  5. package/dist/agent-picker.js +8 -0
  6. package/dist/as-BPtSu6VN-O4ZZEAJG.js +11 -0
  7. package/dist/be-CrQ0smca-5HIE5K27.js +11 -0
  8. package/dist/bg-CrQqGwni-3IRVPZQ7.js +11 -0
  9. package/dist/bn-NCLZcWHi-XOZJFNIB.js +11 -0
  10. package/dist/ca-SUf6Y2Om-V6F2EBCA.js +38 -0
  11. package/dist/capture-NO5ZIGP6.js +1652 -0
  12. package/dist/chat.css +3555 -0
  13. package/dist/chat.d.ts +161 -0
  14. package/dist/chat.js +60498 -0
  15. package/dist/chunk-2KEBRV3W.js +191 -0
  16. package/dist/chunk-6BPHEBCF.js +639 -0
  17. package/dist/chunk-6HYPVNVA.js +25 -0
  18. package/dist/chunk-7ADM3CKD.js +10 -0
  19. package/dist/chunk-AFVU5VT6.js +5601 -0
  20. package/dist/chunk-BEJ3HQG4.js +93 -0
  21. package/dist/chunk-CCVPZVFK.js +28 -0
  22. package/dist/chunk-DGDHKMDB.js +10 -0
  23. package/dist/chunk-FXKXDR5K.js +2166 -0
  24. package/dist/chunk-GTQH7MPF.js +129 -0
  25. package/dist/chunk-I7SXWUAN.js +1258 -0
  26. package/dist/chunk-IQRPGFLI.js +234 -0
  27. package/dist/chunk-IXDM5R55.js +23 -0
  28. package/dist/chunk-JD6ETTXC.js +178 -0
  29. package/dist/chunk-OP4MLJDA.js +215 -0
  30. package/dist/chunk-PQZ2CS26.js +2315 -0
  31. package/dist/chunk-PR4QN5HX.js +38 -0
  32. package/dist/chunk-PUIVKDV5.js +271 -0
  33. package/dist/chunk-QSSFBZAS.js +6914 -0
  34. package/dist/chunk-RAKKA3WU.js +5896 -0
  35. package/dist/chunk-RB2Y4NYC.js +681 -0
  36. package/dist/chunk-VDZH5Z3K.js +72 -0
  37. package/dist/chunk-WMN6BPPS.js +49 -0
  38. package/dist/chunk-WO6DJLFE.js +10857 -0
  39. package/dist/chunk-X5E2DJVO.js +47634 -0
  40. package/dist/chunk-XJFTVKLW.js +2687 -0
  41. package/dist/chunk-ZS6PXIZP.js +187 -0
  42. package/dist/client.d.ts +89 -0
  43. package/dist/client.js +20 -0
  44. package/dist/composer.d.ts +23 -0
  45. package/dist/composer.js +89 -0
  46. package/dist/cop-C3sk0IUo-CIZA2H43.js +11 -0
  47. package/dist/credential.d.ts +75 -0
  48. package/dist/credential.js +3 -0
  49. package/dist/cs-CmAteokq-HAKEQPB4.js +17 -0
  50. package/dist/cu-CBUlrW6Y-QTZ6ZLA4.js +32 -0
  51. package/dist/cy-BBPa6z2x-MX6DGDNW.js +11 -0
  52. package/dist/da-CCDXfXtG-5YEOHMG3.js +11 -0
  53. package/dist/de-1901-CWoAOigE-63QFSF2A.js +11 -0
  54. package/dist/de-1996-BL6awyxG-R2PHKMAB.js +11 -0
  55. package/dist/de-ch-1901-hVThVHVb-JSDB53OZ.js +11 -0
  56. package/dist/el-monoton-D3aKqTz2-2V4OOFBB.js +11 -0
  57. package/dist/el-polyton-ogVWcTzh-3U7NGQMT.js +11 -0
  58. package/dist/en-gb-B7Al27b_-UKCBQFSU.js +21 -0
  59. package/dist/es-DcaaHPU_-NOBXSOZK.js +11 -0
  60. package/dist/esm-MHF25KDL.js +3 -0
  61. package/dist/et-B_spaleu-5UAYIW62.js +11 -0
  62. package/dist/eu-Ctv_kq9Z-V5DREOPN.js +11 -0
  63. package/dist/fi-RW5VB8Yp-YSXBK7LW.js +11 -0
  64. package/dist/fr-BC2onEz9-7KH5T76G.js +11 -0
  65. package/dist/frame.d.ts +59 -0
  66. package/dist/frame.js +111 -0
  67. package/dist/fur-AC12wySk-4PD2Y72H.js +11 -0
  68. package/dist/ga-Cn6LkudM-RRAAJT3N.js +58 -0
  69. package/dist/gl-DZGc-K_G-KYSXXTCY.js +11 -0
  70. package/dist/grc-DOlGgO8T-2HXBZVJ5.js +11 -0
  71. package/dist/gu-Bjl0l-cf-4CFSVZHZ.js +11 -0
  72. package/dist/header.d.ts +78 -0
  73. package/dist/header.js +18 -0
  74. package/dist/hi-DsAaTPCC-KMCFBWK7.js +11 -0
  75. package/dist/hr-DT1SBBes-X2TIX6EI.js +11 -0
  76. package/dist/hsb-DC_ITc1e-PXLERA7R.js +46 -0
  77. package/dist/hu-DVk7Y_ka-PJPVU54B.js +11 -0
  78. package/dist/hy-e995ysyO-MZBRFX52.js +11 -0
  79. package/dist/ia-Cr4TJH0c-D3O2FHGP.js +22 -0
  80. package/dist/id-DifDyWg9-MZ2BGHWI.js +58 -0
  81. package/dist/is-BT8UVRze-CZZCKEFI.js +11 -0
  82. package/dist/it-Bt_Meacx-T4Y5JYV6.js +11 -0
  83. package/dist/ka-jyoLzyDE-ES6EXZLW.js +11 -0
  84. package/dist/kmr-Cfwhwuff-TSW2R2KS.js +11 -0
  85. package/dist/kn-C6Lov-DP-B4BL47CE.js +11 -0
  86. package/dist/la-DuvHjUWw-6K7TFU6X.js +11 -0
  87. package/dist/la-x-classic-yTyAOQEt-YWTKMM2L.js +11 -0
  88. package/dist/la-x-liturgic-CXeQb4FY-B772L5E7.js +11 -0
  89. package/dist/lib-3ZKX25RJ.js +4511 -0
  90. package/dist/lt-BBe8DlDF-4YINVOZR.js +11 -0
  91. package/dist/lv-Q2BBHnzp-TMVQ3MX2.js +11 -0
  92. package/dist/message.d.ts +64 -0
  93. package/dist/message.js +18 -0
  94. package/dist/ml-2xLVYkVY-NGZLAPIN.js +11 -0
  95. package/dist/mn-cyrl-lHM4n0oC-DGBYYUT3.js +11 -0
  96. package/dist/mn-cyrl-x-lmc-3aetruI8-QHJABMOO.js +11 -0
  97. package/dist/mr-CjWJPVmH-X5UHV65O.js +11 -0
  98. package/dist/mul-ethi-D_CMSMEq-H7UMQSOQ.js +11 -0
  99. package/dist/nb-DI8u59ch-J4CAVI4Y.js +122 -0
  100. package/dist/new-session-Dw7JOgzu.d.ts +141 -0
  101. package/dist/new-session.d.ts +4 -0
  102. package/dist/new-session.js +10 -0
  103. package/dist/nl-BHQJ6Gvn-7BH55RA7.js +52 -0
  104. package/dist/nn-ntZvarUK-KKNCHHJ4.js +122 -0
  105. package/dist/no-B8ItS0F3-3ZXIRJ6U.js +120 -0
  106. package/dist/oauth-callback.d.ts +35 -0
  107. package/dist/oauth-callback.js +18 -0
  108. package/dist/oc-P_i3-xLA-XZM6E5YZ.js +11 -0
  109. package/dist/or-50rxpoq4-5VELAFMJ.js +11 -0
  110. package/dist/pa-C54UG8eN-WEJPMZ6Z.js +11 -0
  111. package/dist/parts.d.ts +49 -0
  112. package/dist/parts.js +106 -0
  113. package/dist/pdf-cover-thumbnail-inner-4N2Q5AAG.js +36 -0
  114. package/dist/pdf-deck-view-inner-FZVLAEQR.js +575 -0
  115. package/dist/pdf-document-view-inner-6DF54JWK.js +585 -0
  116. package/dist/pdf-viewer-inner-GPES3KG2.js +256 -0
  117. package/dist/pending-cards.d.ts +26 -0
  118. package/dist/pending-cards.js +9 -0
  119. package/dist/pi-B9cgjyG1-GD5ASDDU.js +11 -0
  120. package/dist/pl-9fg-ESVt-UMX7MCJM.js +32 -0
  121. package/dist/platform.css +4013 -0
  122. package/dist/pms-BRGfm5gS-SSE3AUW5.js +11 -0
  123. package/dist/pt-Cum2_NUC-W35JYVR4.js +11 -0
  124. package/dist/rm-C0MIK9N4-IWL4YTNT.js +11 -0
  125. package/dist/ro-0fmdH0HA-46WUTOYH.js +11 -0
  126. package/dist/ru-v4l-ayaq-BUGK6XCN.js +196 -0
  127. package/dist/sa-CKY9c_Vq-4KIJOI5Y.js +11 -0
  128. package/dist/sh-cyrl-BpCRFOmq-DSLQ4UY2.js +128 -0
  129. package/dist/sh-latn-sRy4Tuaj-UNQOR63V.js +128 -0
  130. package/dist/sk-_iOeDNrQ-NCTQKH25.js +17 -0
  131. package/dist/sl-DpiklF-D-6GG5TDVN.js +11 -0
  132. package/dist/sr-cyrl-Dpzrbd0W-4Q5226YJ.js +142 -0
  133. package/dist/sv-CFm5y56M-VTWNPZ7I.js +11 -0
  134. package/dist/ta-BcghgTbD-NRT35DW6.js +11 -0
  135. package/dist/te-B5Spl2Jk-5VE6CLN4.js +11 -0
  136. package/dist/th-DWX5iPSo-N5GMOQOP.js +11 -0
  137. package/dist/theme.d.ts +49 -0
  138. package/dist/theme.js +3 -0
  139. package/dist/tk-BMbKB10q-HGWWY5L3.js +11 -0
  140. package/dist/tr-CIHIuzqc-6ISBNYLV.js +11 -0
  141. package/dist/types-BDqLaBfH.d.ts +60 -0
  142. package/dist/uk-Dir3oxLs-YQ3QZRI4.js +11 -0
  143. package/dist/univer-workbook-BSSUE5TG.css +3555 -0
  144. package/dist/univer-workbook-N5IIN7CH.js +290849 -0
  145. package/dist/vega-chart-block-NQADYNWQ.js +2857 -0
  146. package/dist/zh-latn-pinyin-BdYb-Ey_-RB542AHF.js +11 -0
  147. package/package.json +137 -0
  148. package/src/styles.css +996 -0
@@ -0,0 +1,234 @@
1
+ 'use client';
2
+ import { cn } from './chunk-DGDHKMDB.js';
3
+ import { CrossMediumIcon } from './chunk-AFVU5VT6.js';
4
+ import * as React from 'react';
5
+ import { createContext, useContext, useState, useEffect } from 'react';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
8
+
9
+ var PortalRootContext = createContext(null);
10
+ function usePortalContainer() {
11
+ return useContext(PortalRootContext);
12
+ }
13
+ function PortalRootProvider({
14
+ dark,
15
+ style,
16
+ children
17
+ }) {
18
+ const [root, setRoot] = useState(null);
19
+ useEffect(() => {
20
+ const element = document.createElement("div");
21
+ element.setAttribute("data-frontera-portal-root", "");
22
+ document.body.appendChild(element);
23
+ setRoot(element);
24
+ return () => {
25
+ element.remove();
26
+ };
27
+ }, []);
28
+ useEffect(() => {
29
+ if (!root) return;
30
+ root.className = `fr-shell${dark ? " dark" : ""}`;
31
+ root.removeAttribute("style");
32
+ for (const [key, value] of Object.entries(style ?? {})) {
33
+ if (typeof value !== "string") continue;
34
+ if (key.startsWith("--")) root.style.setProperty(key, value);
35
+ else root.style.setProperty(key, value);
36
+ }
37
+ }, [root, dark, style]);
38
+ return /* @__PURE__ */ jsx(PortalRootContext.Provider, { value: root, children });
39
+ }
40
+ function Dialog({
41
+ ...props
42
+ }) {
43
+ return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
44
+ }
45
+ function DialogPortal({
46
+ ...props
47
+ }) {
48
+ const container = usePortalContainer();
49
+ return /* @__PURE__ */ jsx(
50
+ DialogPrimitive.Portal,
51
+ {
52
+ "data-slot": "dialog-portal",
53
+ ...container ? { container } : {},
54
+ ...props
55
+ }
56
+ );
57
+ }
58
+ function DialogClose({
59
+ className,
60
+ ...props
61
+ }) {
62
+ return /* @__PURE__ */ jsx(
63
+ DialogPrimitive.Close,
64
+ {
65
+ "data-slot": "dialog-close",
66
+ className: cn("cursor-pointer", className),
67
+ ...props
68
+ }
69
+ );
70
+ }
71
+ function DialogOverlay({
72
+ className,
73
+ onClick,
74
+ ...props
75
+ }) {
76
+ return /* @__PURE__ */ jsx(
77
+ DialogPrimitive.Overlay,
78
+ {
79
+ "data-slot": "dialog-overlay",
80
+ className: cn(
81
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-100 bg-scrim",
82
+ className
83
+ ),
84
+ onClick: (e) => {
85
+ e.stopPropagation();
86
+ onClick?.(e);
87
+ },
88
+ ...props
89
+ }
90
+ );
91
+ }
92
+ function isPopperOpen() {
93
+ if (typeof document === "undefined") return false;
94
+ return !!document.querySelector(
95
+ '[data-radix-popper-content-wrapper], [data-slot="select-content"][data-state="open"]'
96
+ );
97
+ }
98
+ function hasDialogAbove(content) {
99
+ if (typeof document === "undefined" || !content) return false;
100
+ const open = document.querySelectorAll(
101
+ '[data-slot="dialog-content"][data-state="open"]'
102
+ );
103
+ if (open.length < 2) return false;
104
+ return open[open.length - 1] !== content;
105
+ }
106
+ function DialogContent({
107
+ className,
108
+ children,
109
+ overlayClassName,
110
+ showCloseButton = true,
111
+ onPointerDownOutside,
112
+ onInteractOutside,
113
+ onEscapeKeyDown,
114
+ ref,
115
+ ...props
116
+ }) {
117
+ const contentRef = React.useRef(null);
118
+ const setRefs = React.useCallback(
119
+ (node) => {
120
+ contentRef.current = node;
121
+ if (typeof ref === "function") ref(node);
122
+ else if (ref) ref.current = node;
123
+ },
124
+ [ref]
125
+ );
126
+ return /* @__PURE__ */ jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
127
+ /* @__PURE__ */ jsx(DialogOverlay, { className: overlayClassName }),
128
+ /* @__PURE__ */ jsxs(
129
+ DialogPrimitive.Content,
130
+ {
131
+ ref: setRefs,
132
+ "data-slot": "dialog-content",
133
+ className: cn(
134
+ // Width (not just max-width) carries the side gutter so a consumer's
135
+ // `max-w-*` override can't collapse it to the screen edges on phones:
136
+ // `max-width` overrides drop the calc, `width` survives them.
137
+ "bg-surface-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-100 w-[calc(100%-2rem)] max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-xl border p-6 shadow-lg duration-200",
138
+ className
139
+ ),
140
+ onPointerDownOutside: (e) => {
141
+ if (isPopperOpen() || hasDialogAbove(contentRef.current)) {
142
+ e.preventDefault();
143
+ return;
144
+ }
145
+ onPointerDownOutside?.(e);
146
+ },
147
+ onInteractOutside: (e) => {
148
+ if (isPopperOpen() || hasDialogAbove(contentRef.current)) {
149
+ e.preventDefault();
150
+ return;
151
+ }
152
+ onInteractOutside?.(e);
153
+ },
154
+ onEscapeKeyDown: (e) => {
155
+ if (hasDialogAbove(contentRef.current)) {
156
+ e.preventDefault();
157
+ return;
158
+ }
159
+ onEscapeKeyDown?.(e);
160
+ },
161
+ ...props,
162
+ children: [
163
+ children,
164
+ showCloseButton && /* @__PURE__ */ jsxs(
165
+ DialogPrimitive.Close,
166
+ {
167
+ "data-slot": "dialog-close",
168
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 flex size-7 items-center justify-center rounded-md opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4 cursor-pointer",
169
+ onClick: (e) => e.stopPropagation(),
170
+ children: [
171
+ /* @__PURE__ */ jsx(CrossMediumIcon, {}),
172
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
173
+ ]
174
+ }
175
+ )
176
+ ]
177
+ }
178
+ )
179
+ ] });
180
+ }
181
+ function DialogHeader({ className, ...props }) {
182
+ return /* @__PURE__ */ jsx(
183
+ "div",
184
+ {
185
+ "data-slot": "dialog-header",
186
+ className: cn(
187
+ "flex flex-col gap-2 text-center sm:text-left",
188
+ className
189
+ ),
190
+ ...props
191
+ }
192
+ );
193
+ }
194
+ function DialogFooter({ className, ...props }) {
195
+ return /* @__PURE__ */ jsx(
196
+ "div",
197
+ {
198
+ "data-slot": "dialog-footer",
199
+ className: cn(
200
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
201
+ className
202
+ ),
203
+ ...props
204
+ }
205
+ );
206
+ }
207
+ function DialogTitle({
208
+ className,
209
+ ...props
210
+ }) {
211
+ return /* @__PURE__ */ jsx(
212
+ DialogPrimitive.Title,
213
+ {
214
+ "data-slot": "dialog-title",
215
+ className: cn("text-lg leading-none font-semibold", className),
216
+ ...props
217
+ }
218
+ );
219
+ }
220
+ function DialogDescription({
221
+ className,
222
+ ...props
223
+ }) {
224
+ return /* @__PURE__ */ jsx(
225
+ DialogPrimitive.Description,
226
+ {
227
+ "data-slot": "dialog-description",
228
+ className: cn("text-muted-foreground text-sm", className),
229
+ ...props
230
+ }
231
+ );
232
+ }
233
+
234
+ export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, PortalRootProvider, usePortalContainer };
@@ -0,0 +1,23 @@
1
+ 'use client';
2
+ import { useSyncExternalStore } from 'react';
3
+
4
+ // src/vendor/ui/hooks/use-is-mobile.ts
5
+ var MOBILE_BREAKPOINT = 768;
6
+ var QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`;
7
+ var query = null;
8
+ function mediaQuery() {
9
+ if (!query) query = window.matchMedia(QUERY);
10
+ return query;
11
+ }
12
+ function subscribe(onChange) {
13
+ const mql = mediaQuery();
14
+ mql.addEventListener("change", onChange);
15
+ return () => mql.removeEventListener("change", onChange);
16
+ }
17
+ var getSnapshot = () => mediaQuery().matches;
18
+ var getServerSnapshot = () => false;
19
+ function useIsMobile() {
20
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
21
+ }
22
+
23
+ export { MOBILE_BREAKPOINT, useIsMobile };
@@ -0,0 +1,178 @@
1
+ 'use client';
2
+ import { getToolMeta } from './chunk-XJFTVKLW.js';
3
+ import { Button } from './chunk-GTQH7MPF.js';
4
+ import { ChevronDownMediumIcon, CrossMediumIcon } from './chunk-AFVU5VT6.js';
5
+ import { useChatClientOptional } from './chunk-7ADM3CKD.js';
6
+ import { useState, useCallback, useEffect, useMemo } from 'react';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var DEFAULT_POLL_MS = 5e3;
10
+ function PendingCards({
11
+ conversationId,
12
+ onSettled,
13
+ pollMs = DEFAULT_POLL_MS
14
+ }) {
15
+ const client = useChatClientOptional();
16
+ const [pending, setPending] = useState([]);
17
+ const [busyId, setBusyId] = useState(null);
18
+ const [error, setError] = useState(null);
19
+ const refresh = useCallback(async () => {
20
+ if (!client || !conversationId) return;
21
+ try {
22
+ const rows = await client.listPendingApprovals(conversationId);
23
+ setPending(Array.isArray(rows) ? rows : []);
24
+ } catch {
25
+ }
26
+ }, [client, conversationId]);
27
+ useEffect(() => {
28
+ void refresh();
29
+ if (!pollMs) return;
30
+ const timer = setInterval(() => void refresh(), pollMs);
31
+ return () => clearInterval(timer);
32
+ }, [refresh, pollMs]);
33
+ const open = useMemo(
34
+ () => pending.filter(
35
+ (row) => row.status === "pending" && row.pauseReason !== "needs_connect"
36
+ ),
37
+ [pending]
38
+ );
39
+ if (!client || !conversationId || open.length === 0) return null;
40
+ const settle = async (id, run) => {
41
+ setBusyId(id);
42
+ setError(null);
43
+ try {
44
+ await run();
45
+ await refresh();
46
+ onSettled?.(id);
47
+ } catch (err) {
48
+ setError(err instanceof Error ? err.message : String(err));
49
+ } finally {
50
+ setBusyId(null);
51
+ }
52
+ };
53
+ return (
54
+ /*
55
+ The rail, in the platform's own classes.
56
+
57
+ `-mb-3` with `pb-4` tucks the lower edge behind the composer so the two
58
+ read as one control; `bg-surface-inset` sets it back from the raised card
59
+ rows inside it. Copied rather than approximated — this sits directly
60
+ above the copied composer, and a near-miss reads as a bug in the product
61
+ rather than a difference in ours.
62
+ */
63
+ /* @__PURE__ */ jsxs("div", { className: "relative z-0 -mb-3 flex flex-col gap-1.5 rounded-2xl border border-border bg-surface-inset p-1.5 pb-4", children: [
64
+ open.map((row) => /* @__PURE__ */ jsx(
65
+ ApprovalCard,
66
+ {
67
+ row,
68
+ busy: busyId === row.id,
69
+ onDecide: (decision) => (
70
+ /*
71
+ No continuation, deliberately.
72
+
73
+ An approval blocks the run MID-TURN: the tool call is waiting on
74
+ the server, and deciding it releases that same run, which carries
75
+ on streaming into the message already on screen. Sending a
76
+ follow-up here would start a SECOND turn — and since the agent
77
+ would call the same tool again, that call parks again, gets
78
+ nudged again, and the conversation loops.
79
+ */
80
+ settle(row.id, () => client.respondToApproval(row.id, decision))
81
+ )
82
+ },
83
+ row.id
84
+ )),
85
+ error && /* @__PURE__ */ jsx("div", { className: "fr-error", role: "alert", children: error })
86
+ ] })
87
+ );
88
+ }
89
+ function ApprovalCard({
90
+ row,
91
+ busy,
92
+ onDecide
93
+ }) {
94
+ const [detailsOpen, setDetailsOpen] = useState(false);
95
+ const summary = row.actionSummary;
96
+ const toolName = row.toolName ?? "tool";
97
+ const meta = getToolMeta(toolName, "size-4");
98
+ const title = summary?.title ?? `${toolName} needs your approval`;
99
+ const preview = summary?.preview ?? [];
100
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-xl border border-border bg-surface-raised px-3 py-2.5", children: [
101
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5", children: [
102
+ /* @__PURE__ */ jsx("div", { className: "flex size-9 shrink-0 items-center justify-center rounded-lg border border-border bg-surface-inset text-foreground", children: meta.icon }),
103
+ /* @__PURE__ */ jsxs(
104
+ "button",
105
+ {
106
+ type: "button",
107
+ "aria-expanded": detailsOpen,
108
+ "aria-label": `${detailsOpen ? "Hide" : "Show"} details for ${title}`,
109
+ className: "group flex min-w-0 flex-1 items-center gap-2.5 text-left",
110
+ onClick: () => setDetailsOpen((open) => !open),
111
+ children: [
112
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
113
+ /* @__PURE__ */ jsx("span", { className: "line-clamp-1 text-sm font-medium text-foreground", children: title }),
114
+ /* @__PURE__ */ jsxs("span", { className: "mt-px block truncate text-xs text-muted-foreground", children: [
115
+ meta.label,
116
+ row.risk ? ` \xB7 ${row.risk}` : ""
117
+ ] })
118
+ ] }),
119
+ /* @__PURE__ */ jsx("span", { className: "flex size-6 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors group-hover:bg-surface-inset group-hover:text-foreground", children: /* @__PURE__ */ jsx(
120
+ ChevronDownMediumIcon,
121
+ {
122
+ className: `size-3.5 transition-transform ${detailsOpen ? "rotate-180" : ""}`,
123
+ "aria-hidden": true
124
+ }
125
+ ) })
126
+ ]
127
+ }
128
+ ),
129
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
130
+ /* @__PURE__ */ jsx(
131
+ Button,
132
+ {
133
+ type: "button",
134
+ size: "sm",
135
+ variant: "outline",
136
+ className: "size-8 rounded-full p-0",
137
+ disabled: busy,
138
+ "aria-label": `Deny ${title}`,
139
+ title: `Deny ${title}`,
140
+ onClick: () => onDecide("deny"),
141
+ children: /* @__PURE__ */ jsx(CrossMediumIcon, { className: "size-3.5", "aria-hidden": true })
142
+ }
143
+ ),
144
+ /* @__PURE__ */ jsx(
145
+ Button,
146
+ {
147
+ type: "button",
148
+ size: "sm",
149
+ variant: "default-neutral",
150
+ className: "h-8 rounded-full px-3.5",
151
+ disabled: busy,
152
+ "aria-label": `Approve ${title}`,
153
+ onClick: () => onDecide("approve"),
154
+ children: busy ? "Working\u2026" : "Approve"
155
+ }
156
+ )
157
+ ] })
158
+ ] }),
159
+ detailsOpen && /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1 border-t border-border pt-2 pl-[2.875rem] text-xs", children: [
160
+ summary?.description && /* @__PURE__ */ jsx("p", { className: "leading-5 text-muted-foreground", children: summary.description }),
161
+ /* @__PURE__ */ jsx(DetailRow, { label: "Tool", value: toolName }),
162
+ row.toolSource && /* @__PURE__ */ jsx(DetailRow, { label: "Integration", value: String(row.toolSource) }),
163
+ summary?.resource?.label && /* @__PURE__ */ jsx(DetailRow, { label: "Target", value: summary.resource.label }),
164
+ row.risk && /* @__PURE__ */ jsx(DetailRow, { label: "Risk", value: String(row.risk) }),
165
+ row.policyReason && /* @__PURE__ */ jsx(DetailRow, { label: "Why unsafe", value: String(row.policyReason) }),
166
+ preview.length > 0 && /* @__PURE__ */ jsx("p", { className: "pt-1 font-medium text-foreground", children: "Data / input preview" }),
167
+ preview.map((item) => /* @__PURE__ */ jsx(DetailRow, { label: item.label, value: item.value }, item.label))
168
+ ] })
169
+ ] });
170
+ }
171
+ function DetailRow({ label, value }) {
172
+ return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[minmax(5.5rem,8.5rem)_1fr] gap-2", children: [
173
+ /* @__PURE__ */ jsx("span", { className: "break-all text-muted-foreground", children: label }),
174
+ /* @__PURE__ */ jsx("span", { className: "break-words text-foreground", children: value })
175
+ ] });
176
+ }
177
+
178
+ export { PendingCards };
@@ -0,0 +1,215 @@
1
+ 'use client';
2
+ import { describeToolRow, getToolMeta, Shimmer, Collapse } from './chunk-XJFTVKLW.js';
3
+ import { cn } from './chunk-DGDHKMDB.js';
4
+ import { Code2Icon, ChevronDownMediumIcon, ProcessorIcon } from './chunk-AFVU5VT6.js';
5
+ import { memo, useState, useMemo } from 'react';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+
8
+ var RUNNING_STATES = /* @__PURE__ */ new Set([
9
+ "input-streaming",
10
+ "partial-call",
11
+ "input-available",
12
+ "call"
13
+ ]);
14
+ function memoryRelPath(path) {
15
+ const m = path.match(/(?:^|\/)memory\/(.+)$/);
16
+ if (m) return m[1];
17
+ return path.split("/").pop() || path;
18
+ }
19
+ function parseContent(content) {
20
+ const fm = content.match(/^---\n([\s\S]*?)\n---\n?/);
21
+ if (!fm) return { type: null, body: content };
22
+ const typeLine = fm[1].match(/^type:\s*["']?([^"'\n]+)["']?\s*$/m);
23
+ return { type: typeLine ? typeLine[1].trim() : null, body: content.slice(fm[0].length) };
24
+ }
25
+ function getWrite(input) {
26
+ if (!input || typeof input !== "object") return null;
27
+ const o = input;
28
+ const path = o.path ?? o.filePath ?? o.file;
29
+ if (typeof path !== "string" || typeof o.content !== "string") return null;
30
+ return { path, content: o.content };
31
+ }
32
+ function isMemoryWrite(input) {
33
+ const w = getWrite(input);
34
+ return !!w && /(?:^|\/)memory\//.test(w.path);
35
+ }
36
+ function MemoryWriteToolItem({ state, input }) {
37
+ const [open, setOpen] = useState(false);
38
+ const write = getWrite(input);
39
+ const isRunning = RUNNING_STATES.has(state);
40
+ const isError = state === "output-error" || state === "error";
41
+ const rel = write ? memoryRelPath(write.path) : "";
42
+ const { type, body } = write ? parseContent(write.content) : { type: null, body: "" };
43
+ const hasBody = !isRunning && !isError && body.trim().length > 0;
44
+ const verb = isError ? "Memory save failed" : isRunning ? "Saving to memory" : "Saved to memory";
45
+ return /* @__PURE__ */ jsx("div", { className: "relative z-10 py-0.5", children: /* @__PURE__ */ jsxs(
46
+ "button",
47
+ {
48
+ type: "button",
49
+ onClick: () => hasBody && setOpen((v) => !v),
50
+ "aria-expanded": hasBody ? open : void 0,
51
+ className: cn(
52
+ "flex w-full min-w-0 items-center gap-2 text-left text-sm",
53
+ hasBody ? "text-muted-foreground transition-colors hover:text-foreground" : "cursor-default text-muted-foreground"
54
+ ),
55
+ children: [
56
+ /* @__PURE__ */ jsx("span", { className: "flex h-7 w-4 shrink-0 items-center justify-center rounded-full bg-surface-chat", children: /* @__PURE__ */ jsx(ProcessorIcon, { className: "size-4 opacity-90" }) }),
57
+ isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", className: "min-w-0 flex-1 truncate text-sm", children: [verb, rel].filter(Boolean).join(" ") || "Saving to memory\u2026" }) : /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-1.5 truncate", children: [
58
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 font-medium text-sm", children: verb }),
59
+ rel && /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: rel })
60
+ ] })
61
+ ]
62
+ }
63
+ ) });
64
+ }
65
+ var RUNNING_STATES2 = /* @__PURE__ */ new Set([
66
+ "input-streaming",
67
+ "partial-call",
68
+ "input-available",
69
+ "call"
70
+ ]);
71
+ var TOOL_DETAIL_DISPLAY_LIMIT = 2e4;
72
+ function capToolDetailText(text) {
73
+ return text.length > TOOL_DETAIL_DISPLAY_LIMIT ? `${text.slice(0, TOOL_DETAIL_DISPLAY_LIMIT)}
74
+ \u2026 (truncated)` : text;
75
+ }
76
+ function formatToolInput(input) {
77
+ if (input == null) return "";
78
+ if (typeof input === "string") return capToolDetailText(input);
79
+ if (typeof input !== "object") return String(input);
80
+ const o = input;
81
+ const keys = Object.keys(o);
82
+ if (keys.length === 1 && typeof o[keys[0]] === "string") {
83
+ return capToolDetailText(o[keys[0]]);
84
+ }
85
+ for (const k of ["code", "command", "cmd", "script", "query", "sql"]) {
86
+ if (typeof o[k] === "string") return capToolDetailText(o[k]);
87
+ }
88
+ return formatToolOutput(o);
89
+ }
90
+ function hasToolDetail(value) {
91
+ return value != null && (typeof value !== "string" || value.length > 0);
92
+ }
93
+ function formatToolOutput(output) {
94
+ if (output == null) return "";
95
+ if (typeof output === "string") {
96
+ return capToolDetailText(output);
97
+ }
98
+ let budget = TOOL_DETAIL_DISPLAY_LIMIT * 2;
99
+ let elided = false;
100
+ try {
101
+ const s = JSON.stringify(
102
+ output,
103
+ (_key, value) => {
104
+ if (budget <= 0) {
105
+ elided = true;
106
+ return void 0;
107
+ }
108
+ if (typeof value === "string") {
109
+ budget -= value.length;
110
+ return value.length > 2e3 ? `${value.slice(0, 2e3)}\u2026` : value;
111
+ }
112
+ budget -= 8;
113
+ return value;
114
+ },
115
+ 2
116
+ );
117
+ if (s === void 0) return "\u2026 (output too large to display)";
118
+ const capped = s.length > TOOL_DETAIL_DISPLAY_LIMIT ? `${s.slice(0, TOOL_DETAIL_DISPLAY_LIMIT)}
119
+ \u2026 (truncated)` : s;
120
+ return elided && !capped.endsWith("(truncated)") ? `${capped}
121
+ \u2026 (truncated)` : capped;
122
+ } catch {
123
+ return capToolDetailText(String(output));
124
+ }
125
+ }
126
+ var ToolCallItem = memo(function ToolCallItem2({
127
+ toolName,
128
+ state,
129
+ input,
130
+ output,
131
+ errorText,
132
+ isMcp = false,
133
+ className,
134
+ preview
135
+ }) {
136
+ const [open, setOpen] = useState(false);
137
+ const cmd = useMemo(() => open ? formatToolInput(input) : "", [input, open]);
138
+ const out = useMemo(() => open ? formatToolOutput(output) : "", [open, output]);
139
+ if (isMemoryWrite(input)) {
140
+ return /* @__PURE__ */ jsx(MemoryWriteToolItem, { state, input });
141
+ }
142
+ const { verb, target, targetMono, hint, hintTone } = describeToolRow(
143
+ toolName,
144
+ state,
145
+ input,
146
+ output,
147
+ errorText
148
+ );
149
+ const isRunning = RUNNING_STATES2.has(state);
150
+ const hasPreview = !isRunning && !!preview;
151
+ const hasBody = !hasPreview && (hasToolDetail(input) || hasToolDetail(output) || !!errorText);
152
+ const plainLine = [verb, target].filter(Boolean).join(" ");
153
+ const icon = isMcp ? /* @__PURE__ */ jsx(Code2Icon, { className: "size-3.5 shrink-0" }) : getToolMeta(toolName).icon;
154
+ const hintToneClass = hintTone === "danger" ? "text-destructive" : hintTone === "success" ? "text-success" : "text-muted-foreground/70";
155
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative z-10", className), children: [
156
+ /* @__PURE__ */ jsxs(
157
+ "button",
158
+ {
159
+ type: "button",
160
+ onClick: () => hasBody && setOpen((v) => !v),
161
+ "aria-expanded": hasBody ? open : void 0,
162
+ className: cn(
163
+ "group/row flex w-full min-w-0 items-center gap-2 py-0.5 text-left text-sm",
164
+ hasBody ? "text-muted-foreground transition-colors hover:text-foreground" : "cursor-default text-muted-foreground"
165
+ ),
166
+ children: [
167
+ /* @__PURE__ */ jsx("span", { className: "flex h-7 w-4 shrink-0 items-center justify-center rounded-full bg-surface-chat [&_svg]:size-3.5 [&_svg]:opacity-90", children: icon }),
168
+ isRunning ? /* @__PURE__ */ jsx(Shimmer, { as: "span", className: "!inline-flex min-w-0 truncate text-sm", children: plainLine || "Working\u2026" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
169
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: verb }),
170
+ target && /* @__PURE__ */ jsx(
171
+ "span",
172
+ {
173
+ className: cn(
174
+ "min-w-0 truncate",
175
+ targetMono && "font-mono text-[0.8125rem]"
176
+ ),
177
+ children: target
178
+ }
179
+ )
180
+ ] }),
181
+ hasBody && /* @__PURE__ */ jsx(
182
+ ChevronDownMediumIcon,
183
+ {
184
+ className: cn(
185
+ "size-3.5 shrink-0 text-muted-foreground/60 transition-transform",
186
+ !open && "-rotate-90"
187
+ )
188
+ }
189
+ ),
190
+ !isRunning && hint && /* @__PURE__ */ jsx(
191
+ "span",
192
+ {
193
+ className: cn(
194
+ "ml-auto shrink-0 pl-2 text-xs tabular-nums",
195
+ hintToneClass
196
+ ),
197
+ children: hint
198
+ }
199
+ )
200
+ ]
201
+ }
202
+ ),
203
+ hasPreview && /* @__PURE__ */ jsx("div", { className: "mt-1.5 ml-6", children: preview }),
204
+ hasBody && open && /* @__PURE__ */ jsx(Collapse, { open, children: /* @__PURE__ */ jsx("div", { className: "mt-1.5 ml-6 rounded-lg border border-muted-foreground/10 bg-surface-raised shadow-xs", children: /* @__PURE__ */ jsxs("div", { className: "scrollbar max-h-36 space-y-2 overflow-auto p-3", children: [
205
+ cmd && /* @__PURE__ */ jsxs("pre", { className: "whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-foreground/80", children: [
206
+ /* @__PURE__ */ jsx("span", { className: "select-none text-muted-foreground", children: "> " }),
207
+ cmd
208
+ ] }),
209
+ errorText && /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: errorText }),
210
+ out && /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: out })
211
+ ] }) }) })
212
+ ] });
213
+ });
214
+
215
+ export { ToolCallItem };