@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.
- package/LICENSE +202 -0
- package/README.md +348 -0
- package/dist/af-DK_CjRn6-OPBHDTNZ.js +197 -0
- package/dist/agent-picker.d.ts +38 -0
- package/dist/agent-picker.js +8 -0
- package/dist/as-BPtSu6VN-O4ZZEAJG.js +11 -0
- package/dist/be-CrQ0smca-5HIE5K27.js +11 -0
- package/dist/bg-CrQqGwni-3IRVPZQ7.js +11 -0
- package/dist/bn-NCLZcWHi-XOZJFNIB.js +11 -0
- package/dist/ca-SUf6Y2Om-V6F2EBCA.js +38 -0
- package/dist/capture-NO5ZIGP6.js +1652 -0
- package/dist/chat.css +3555 -0
- package/dist/chat.d.ts +161 -0
- package/dist/chat.js +60498 -0
- package/dist/chunk-2KEBRV3W.js +191 -0
- package/dist/chunk-6BPHEBCF.js +639 -0
- package/dist/chunk-6HYPVNVA.js +25 -0
- package/dist/chunk-7ADM3CKD.js +10 -0
- package/dist/chunk-AFVU5VT6.js +5601 -0
- package/dist/chunk-BEJ3HQG4.js +93 -0
- package/dist/chunk-CCVPZVFK.js +28 -0
- package/dist/chunk-DGDHKMDB.js +10 -0
- package/dist/chunk-FXKXDR5K.js +2166 -0
- package/dist/chunk-GTQH7MPF.js +129 -0
- package/dist/chunk-I7SXWUAN.js +1258 -0
- package/dist/chunk-IQRPGFLI.js +234 -0
- package/dist/chunk-IXDM5R55.js +23 -0
- package/dist/chunk-JD6ETTXC.js +178 -0
- package/dist/chunk-OP4MLJDA.js +215 -0
- package/dist/chunk-PQZ2CS26.js +2315 -0
- package/dist/chunk-PR4QN5HX.js +38 -0
- package/dist/chunk-PUIVKDV5.js +271 -0
- package/dist/chunk-QSSFBZAS.js +6914 -0
- package/dist/chunk-RAKKA3WU.js +5896 -0
- package/dist/chunk-RB2Y4NYC.js +681 -0
- package/dist/chunk-VDZH5Z3K.js +72 -0
- package/dist/chunk-WMN6BPPS.js +49 -0
- package/dist/chunk-WO6DJLFE.js +10857 -0
- package/dist/chunk-X5E2DJVO.js +47634 -0
- package/dist/chunk-XJFTVKLW.js +2687 -0
- package/dist/chunk-ZS6PXIZP.js +187 -0
- package/dist/client.d.ts +89 -0
- package/dist/client.js +20 -0
- package/dist/composer.d.ts +23 -0
- package/dist/composer.js +89 -0
- package/dist/cop-C3sk0IUo-CIZA2H43.js +11 -0
- package/dist/credential.d.ts +75 -0
- package/dist/credential.js +3 -0
- package/dist/cs-CmAteokq-HAKEQPB4.js +17 -0
- package/dist/cu-CBUlrW6Y-QTZ6ZLA4.js +32 -0
- package/dist/cy-BBPa6z2x-MX6DGDNW.js +11 -0
- package/dist/da-CCDXfXtG-5YEOHMG3.js +11 -0
- package/dist/de-1901-CWoAOigE-63QFSF2A.js +11 -0
- package/dist/de-1996-BL6awyxG-R2PHKMAB.js +11 -0
- package/dist/de-ch-1901-hVThVHVb-JSDB53OZ.js +11 -0
- package/dist/el-monoton-D3aKqTz2-2V4OOFBB.js +11 -0
- package/dist/el-polyton-ogVWcTzh-3U7NGQMT.js +11 -0
- package/dist/en-gb-B7Al27b_-UKCBQFSU.js +21 -0
- package/dist/es-DcaaHPU_-NOBXSOZK.js +11 -0
- package/dist/esm-MHF25KDL.js +3 -0
- package/dist/et-B_spaleu-5UAYIW62.js +11 -0
- package/dist/eu-Ctv_kq9Z-V5DREOPN.js +11 -0
- package/dist/fi-RW5VB8Yp-YSXBK7LW.js +11 -0
- package/dist/fr-BC2onEz9-7KH5T76G.js +11 -0
- package/dist/frame.d.ts +59 -0
- package/dist/frame.js +111 -0
- package/dist/fur-AC12wySk-4PD2Y72H.js +11 -0
- package/dist/ga-Cn6LkudM-RRAAJT3N.js +58 -0
- package/dist/gl-DZGc-K_G-KYSXXTCY.js +11 -0
- package/dist/grc-DOlGgO8T-2HXBZVJ5.js +11 -0
- package/dist/gu-Bjl0l-cf-4CFSVZHZ.js +11 -0
- package/dist/header.d.ts +78 -0
- package/dist/header.js +18 -0
- package/dist/hi-DsAaTPCC-KMCFBWK7.js +11 -0
- package/dist/hr-DT1SBBes-X2TIX6EI.js +11 -0
- package/dist/hsb-DC_ITc1e-PXLERA7R.js +46 -0
- package/dist/hu-DVk7Y_ka-PJPVU54B.js +11 -0
- package/dist/hy-e995ysyO-MZBRFX52.js +11 -0
- package/dist/ia-Cr4TJH0c-D3O2FHGP.js +22 -0
- package/dist/id-DifDyWg9-MZ2BGHWI.js +58 -0
- package/dist/is-BT8UVRze-CZZCKEFI.js +11 -0
- package/dist/it-Bt_Meacx-T4Y5JYV6.js +11 -0
- package/dist/ka-jyoLzyDE-ES6EXZLW.js +11 -0
- package/dist/kmr-Cfwhwuff-TSW2R2KS.js +11 -0
- package/dist/kn-C6Lov-DP-B4BL47CE.js +11 -0
- package/dist/la-DuvHjUWw-6K7TFU6X.js +11 -0
- package/dist/la-x-classic-yTyAOQEt-YWTKMM2L.js +11 -0
- package/dist/la-x-liturgic-CXeQb4FY-B772L5E7.js +11 -0
- package/dist/lib-3ZKX25RJ.js +4511 -0
- package/dist/lt-BBe8DlDF-4YINVOZR.js +11 -0
- package/dist/lv-Q2BBHnzp-TMVQ3MX2.js +11 -0
- package/dist/message.d.ts +64 -0
- package/dist/message.js +18 -0
- package/dist/ml-2xLVYkVY-NGZLAPIN.js +11 -0
- package/dist/mn-cyrl-lHM4n0oC-DGBYYUT3.js +11 -0
- package/dist/mn-cyrl-x-lmc-3aetruI8-QHJABMOO.js +11 -0
- package/dist/mr-CjWJPVmH-X5UHV65O.js +11 -0
- package/dist/mul-ethi-D_CMSMEq-H7UMQSOQ.js +11 -0
- package/dist/nb-DI8u59ch-J4CAVI4Y.js +122 -0
- package/dist/new-session-Dw7JOgzu.d.ts +141 -0
- package/dist/new-session.d.ts +4 -0
- package/dist/new-session.js +10 -0
- package/dist/nl-BHQJ6Gvn-7BH55RA7.js +52 -0
- package/dist/nn-ntZvarUK-KKNCHHJ4.js +122 -0
- package/dist/no-B8ItS0F3-3ZXIRJ6U.js +120 -0
- package/dist/oauth-callback.d.ts +35 -0
- package/dist/oauth-callback.js +18 -0
- package/dist/oc-P_i3-xLA-XZM6E5YZ.js +11 -0
- package/dist/or-50rxpoq4-5VELAFMJ.js +11 -0
- package/dist/pa-C54UG8eN-WEJPMZ6Z.js +11 -0
- package/dist/parts.d.ts +49 -0
- package/dist/parts.js +106 -0
- package/dist/pdf-cover-thumbnail-inner-4N2Q5AAG.js +36 -0
- package/dist/pdf-deck-view-inner-FZVLAEQR.js +575 -0
- package/dist/pdf-document-view-inner-6DF54JWK.js +585 -0
- package/dist/pdf-viewer-inner-GPES3KG2.js +256 -0
- package/dist/pending-cards.d.ts +26 -0
- package/dist/pending-cards.js +9 -0
- package/dist/pi-B9cgjyG1-GD5ASDDU.js +11 -0
- package/dist/pl-9fg-ESVt-UMX7MCJM.js +32 -0
- package/dist/platform.css +4013 -0
- package/dist/pms-BRGfm5gS-SSE3AUW5.js +11 -0
- package/dist/pt-Cum2_NUC-W35JYVR4.js +11 -0
- package/dist/rm-C0MIK9N4-IWL4YTNT.js +11 -0
- package/dist/ro-0fmdH0HA-46WUTOYH.js +11 -0
- package/dist/ru-v4l-ayaq-BUGK6XCN.js +196 -0
- package/dist/sa-CKY9c_Vq-4KIJOI5Y.js +11 -0
- package/dist/sh-cyrl-BpCRFOmq-DSLQ4UY2.js +128 -0
- package/dist/sh-latn-sRy4Tuaj-UNQOR63V.js +128 -0
- package/dist/sk-_iOeDNrQ-NCTQKH25.js +17 -0
- package/dist/sl-DpiklF-D-6GG5TDVN.js +11 -0
- package/dist/sr-cyrl-Dpzrbd0W-4Q5226YJ.js +142 -0
- package/dist/sv-CFm5y56M-VTWNPZ7I.js +11 -0
- package/dist/ta-BcghgTbD-NRT35DW6.js +11 -0
- package/dist/te-B5Spl2Jk-5VE6CLN4.js +11 -0
- package/dist/th-DWX5iPSo-N5GMOQOP.js +11 -0
- package/dist/theme.d.ts +49 -0
- package/dist/theme.js +3 -0
- package/dist/tk-BMbKB10q-HGWWY5L3.js +11 -0
- package/dist/tr-CIHIuzqc-6ISBNYLV.js +11 -0
- package/dist/types-BDqLaBfH.d.ts +60 -0
- package/dist/uk-Dir3oxLs-YQ3QZRI4.js +11 -0
- package/dist/univer-workbook-BSSUE5TG.css +3555 -0
- package/dist/univer-workbook-N5IIN7CH.js +290849 -0
- package/dist/vega-chart-block-NQADYNWQ.js +2857 -0
- package/dist/zh-latn-pinyin-BdYb-Ey_-RB542AHF.js +11 -0
- package/package.json +137 -0
- package/src/styles.css +996 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-DGDHKMDB.js';
|
|
3
|
+
import { CircleIcon, ChevronRightIcon } from './chunk-AFVU5VT6.js';
|
|
4
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
5
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function DropdownMenu({
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
|
|
11
|
+
}
|
|
12
|
+
function DropdownMenuTrigger({
|
|
13
|
+
...props
|
|
14
|
+
}) {
|
|
15
|
+
return /* @__PURE__ */ jsx(
|
|
16
|
+
DropdownMenuPrimitive.Trigger,
|
|
17
|
+
{
|
|
18
|
+
"data-slot": "dropdown-menu-trigger",
|
|
19
|
+
...props
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
function DropdownMenuContent({
|
|
24
|
+
className,
|
|
25
|
+
sideOffset = 4,
|
|
26
|
+
...props
|
|
27
|
+
}) {
|
|
28
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
29
|
+
DropdownMenuPrimitive.Content,
|
|
30
|
+
{
|
|
31
|
+
"data-slot": "dropdown-menu-content",
|
|
32
|
+
sideOffset,
|
|
33
|
+
className: cn(
|
|
34
|
+
// Fade only, 100ms, ease-out. The old 150ms stacked a fade with a
|
|
35
|
+
// zoom-95 and a 2px slide, on `ease` — which starts slow, so the frames
|
|
36
|
+
// that confirm the click were the slowest, and the movement made a menu
|
|
37
|
+
// read as ARRIVING rather than already being there.
|
|
38
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 duration-100 ease-out bg-surface-overlay text-popover-foreground z-100 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
|
|
39
|
+
className
|
|
40
|
+
),
|
|
41
|
+
...props
|
|
42
|
+
}
|
|
43
|
+
) });
|
|
44
|
+
}
|
|
45
|
+
function DropdownMenuItem({
|
|
46
|
+
className,
|
|
47
|
+
inset,
|
|
48
|
+
variant = "default",
|
|
49
|
+
...props
|
|
50
|
+
}) {
|
|
51
|
+
return /* @__PURE__ */ jsx(
|
|
52
|
+
DropdownMenuPrimitive.Item,
|
|
53
|
+
{
|
|
54
|
+
"data-slot": "dropdown-menu-item",
|
|
55
|
+
"data-inset": inset,
|
|
56
|
+
"data-variant": variant,
|
|
57
|
+
className: cn(
|
|
58
|
+
"focus:bg-surface-overlay-hover focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4 max-md:min-h-11 max-md:gap-3 max-md:px-3 max-md:text-[15px] max-md:[&_svg]:size-[18px]",
|
|
59
|
+
{
|
|
60
|
+
"cursor-pointer": !!props.onClick
|
|
61
|
+
},
|
|
62
|
+
className
|
|
63
|
+
),
|
|
64
|
+
...props
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function DropdownMenuRadioGroup({
|
|
69
|
+
...props
|
|
70
|
+
}) {
|
|
71
|
+
return /* @__PURE__ */ jsx(
|
|
72
|
+
DropdownMenuPrimitive.RadioGroup,
|
|
73
|
+
{
|
|
74
|
+
"data-slot": "dropdown-menu-radio-group",
|
|
75
|
+
...props
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
function DropdownMenuRadioItem({
|
|
80
|
+
className,
|
|
81
|
+
children,
|
|
82
|
+
...props
|
|
83
|
+
}) {
|
|
84
|
+
return /* @__PURE__ */ jsxs(
|
|
85
|
+
DropdownMenuPrimitive.RadioItem,
|
|
86
|
+
{
|
|
87
|
+
"data-slot": "dropdown-menu-radio-item",
|
|
88
|
+
className: cn(
|
|
89
|
+
"focus:bg-surface-overlay-hover focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm max-md:min-h-11 max-md:text-[15px] outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
|
|
90
|
+
className
|
|
91
|
+
),
|
|
92
|
+
...props,
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(CircleIcon, { className: "size-1.5! fill-current" }) }) }),
|
|
95
|
+
children
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
function DropdownMenuLabel({
|
|
101
|
+
className,
|
|
102
|
+
inset,
|
|
103
|
+
...props
|
|
104
|
+
}) {
|
|
105
|
+
return /* @__PURE__ */ jsx(
|
|
106
|
+
DropdownMenuPrimitive.Label,
|
|
107
|
+
{
|
|
108
|
+
"data-slot": "dropdown-menu-label",
|
|
109
|
+
"data-inset": inset,
|
|
110
|
+
className: cn(
|
|
111
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
...props
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
function DropdownMenuSeparator({
|
|
119
|
+
className,
|
|
120
|
+
...props
|
|
121
|
+
}) {
|
|
122
|
+
return /* @__PURE__ */ jsx(
|
|
123
|
+
DropdownMenuPrimitive.Separator,
|
|
124
|
+
{
|
|
125
|
+
"data-slot": "dropdown-menu-separator",
|
|
126
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
127
|
+
...props
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
function DropdownMenuSub({
|
|
132
|
+
...props
|
|
133
|
+
}) {
|
|
134
|
+
return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
|
|
135
|
+
}
|
|
136
|
+
function DropdownMenuSubTrigger({
|
|
137
|
+
className,
|
|
138
|
+
inset,
|
|
139
|
+
children,
|
|
140
|
+
...props
|
|
141
|
+
}) {
|
|
142
|
+
return /* @__PURE__ */ jsxs(
|
|
143
|
+
DropdownMenuPrimitive.SubTrigger,
|
|
144
|
+
{
|
|
145
|
+
"data-slot": "dropdown-menu-sub-trigger",
|
|
146
|
+
"data-inset": inset,
|
|
147
|
+
className: cn(
|
|
148
|
+
"focus:bg-surface-overlay-hover focus:text-accent-foreground data-[state=open]:bg-surface-overlay-hover data-[state=open]:text-accent-foreground [&_svg]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm max-md:min-h-11 max-md:text-[15px] outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
|
|
149
|
+
className
|
|
150
|
+
),
|
|
151
|
+
...props,
|
|
152
|
+
children: [
|
|
153
|
+
children,
|
|
154
|
+
/* @__PURE__ */ jsx(ChevronRightIcon, { className: "ml-auto size-4" })
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
function DropdownMenuSubContent({
|
|
160
|
+
className,
|
|
161
|
+
...props
|
|
162
|
+
}) {
|
|
163
|
+
return (
|
|
164
|
+
// Portaled: the parent DropdownMenuContent clips (`overflow-x-hidden`
|
|
165
|
+
// for its own scroll), so an inline submenu gets cut at the menu edge —
|
|
166
|
+
// visible on mobile where the submenu opens toward the viewport edge.
|
|
167
|
+
// The portal escapes the clip and lets collision detection flip sides.
|
|
168
|
+
/* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
169
|
+
DropdownMenuPrimitive.SubContent,
|
|
170
|
+
{
|
|
171
|
+
"data-slot": "dropdown-menu-sub-content",
|
|
172
|
+
collisionPadding: 8,
|
|
173
|
+
className: cn(
|
|
174
|
+
// Fade only, 100ms, ease-out. The old 150ms stacked a fade with a
|
|
175
|
+
// zoom-95 and a 2px slide, on `ease` — which starts slow, so the frames
|
|
176
|
+
// that confirm the click were the slowest, and the movement made a menu
|
|
177
|
+
// read as ARRIVING rather than already being there.
|
|
178
|
+
"data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 duration-100 ease-out bg-surface-overlay text-popover-foreground z-100 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
|
179
|
+
className
|
|
180
|
+
),
|
|
181
|
+
...props
|
|
182
|
+
}
|
|
183
|
+
) })
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ChatClient } from '@frontera-sdk/chat/chat-client';
|
|
2
|
+
export { ChatClient } from '@frontera-sdk/chat/chat-client';
|
|
3
|
+
import { FronteraClient } from '@frontera-sdk/core/client';
|
|
4
|
+
import { ChatCredentialProps } from './credential.js';
|
|
5
|
+
export { ResolvedCredential, useChatCredential } from './credential.js';
|
|
6
|
+
import * as react from 'react';
|
|
7
|
+
export { ArtifactVersionMeta, ChatAgent, ChatArtifact, ChatToken, PendingApproval, Session, SessionMessage, StartChatRequest } from '@frontera-sdk/chat/types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The client the copied components reach for.
|
|
11
|
+
*
|
|
12
|
+
* Platform components fetch through hooks that assume a signed-in session.
|
|
13
|
+
* Those hooks are the one part of the surface that cannot be copied, so each
|
|
14
|
+
* is re-pointed at this client — supplied once by `FronteraChat` and read by
|
|
15
|
+
* the shims under `src/vendor/lib/services`.
|
|
16
|
+
*
|
|
17
|
+
* Optional by design: a consumer composing `Message` or `Composer` by hand
|
|
18
|
+
* need not provide it, and the features that depend on data simply stay quiet
|
|
19
|
+
* rather than throwing.
|
|
20
|
+
*/
|
|
21
|
+
declare const ChatClientContext: react.Context<ChatClient | null>;
|
|
22
|
+
declare function useChatClientOptional(): ChatClient | null;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The `sub` claim of an end-user chat token, read without verifying it.
|
|
26
|
+
*
|
|
27
|
+
* Used for ONE thing: choosing which localStorage namespace this browser's
|
|
28
|
+
* side-panel records belong to. That is a scoping decision, not an
|
|
29
|
+
* authorization — the server verifies the same token on every call, and a
|
|
30
|
+
* forged one buys nothing here except a wrong namespace in its own browser.
|
|
31
|
+
*
|
|
32
|
+
* The token string itself would be the obvious key and is the wrong one: it
|
|
33
|
+
* rotates on every renewal, so the namespace would change hourly and each
|
|
34
|
+
* renewal would look like a different person. `sub` is the customer's own id
|
|
35
|
+
* for this user and survives renewal, which is exactly the lifetime the
|
|
36
|
+
* records need.
|
|
37
|
+
*
|
|
38
|
+
* Returns null for anything that is not a readable JWT — an API key, a
|
|
39
|
+
* malformed token, a payload without `sub`. Callers treat that as "no scope",
|
|
40
|
+
* which keeps records in the default namespace rather than inventing one.
|
|
41
|
+
*/
|
|
42
|
+
declare function subjectOfChatToken(token: string): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* The capabilities claim, read the same way and for the same kind of reason.
|
|
45
|
+
*
|
|
46
|
+
* Lets the composer offer only what the token can actually do — a
|
|
47
|
+
* "run without approval" option the service will refuse is worse than no
|
|
48
|
+
* option, because the reader discovers it by having their choice reverted.
|
|
49
|
+
*
|
|
50
|
+
* Not a security boundary, and not treated as one: every one of these is
|
|
51
|
+
* enforced server-side against the verified token. This just stops the UI
|
|
52
|
+
* promising something the server will decline.
|
|
53
|
+
*/
|
|
54
|
+
declare function capabilitiesOfChatToken(token: string): string[];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A `ChatClient` for the same credential the chat component uses.
|
|
58
|
+
*
|
|
59
|
+
* `null` until the first token lands — the credential is fetched, so there is
|
|
60
|
+
* a render before it exists, and every call site has to handle that anyway.
|
|
61
|
+
* Returning null says so in the type instead of throwing on the first render
|
|
62
|
+
* or handing back a client whose requests would be unauthenticated.
|
|
63
|
+
*
|
|
64
|
+
* ```tsx
|
|
65
|
+
* const { client, ready, error } = useChatClient({ tokenEndpoint: '/api/chat-token' })
|
|
66
|
+
* useEffect(() => { client?.listSessions({ limit: 20 }).then(setHistory) }, [client])
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* Pass the SAME credential props you pass to `<FronteraChat>`. Each call
|
|
70
|
+
* resolves its own credential, so a `tokenEndpoint` is hit once per hook —
|
|
71
|
+
* share one client through your own context if that matters to you.
|
|
72
|
+
*/
|
|
73
|
+
declare function useChatClient(props: ChatCredentialProps): {
|
|
74
|
+
client: ChatClient | null;
|
|
75
|
+
/**
|
|
76
|
+
* The underlying API client, as a getter.
|
|
77
|
+
*
|
|
78
|
+
* Pass it straight to `<FronteraChat client={getClient} />` when this hook
|
|
79
|
+
* already resolved a credential: the component then shares this one rather
|
|
80
|
+
* than resolving its own, which is the difference between one token per
|
|
81
|
+
* person and two on every load.
|
|
82
|
+
*/
|
|
83
|
+
getClient: () => FronteraClient | null;
|
|
84
|
+
ready: boolean;
|
|
85
|
+
error: Error | null;
|
|
86
|
+
refresh: () => Promise<unknown>;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export { ChatClientContext, ChatCredentialProps, capabilitiesOfChatToken, subjectOfChatToken, useChatClient, useChatClientOptional };
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
export { capabilitiesOfChatToken, subjectOfChatToken } from './chunk-CCVPZVFK.js';
|
|
3
|
+
import { useChatCredential } from './chunk-BEJ3HQG4.js';
|
|
4
|
+
export { useChatCredential } from './chunk-BEJ3HQG4.js';
|
|
5
|
+
export { ChatClientContext, useChatClientOptional } from './chunk-7ADM3CKD.js';
|
|
6
|
+
import './chunk-PR4QN5HX.js';
|
|
7
|
+
import { useMemo } from 'react';
|
|
8
|
+
import { ChatClient } from '@frontera-sdk/chat/chat-client';
|
|
9
|
+
export { ChatClient } from '@frontera-sdk/chat/chat-client';
|
|
10
|
+
|
|
11
|
+
function useChatClient(props) {
|
|
12
|
+
const { getClient, ready, error, refresh } = useChatCredential(props);
|
|
13
|
+
const client = useMemo(() => {
|
|
14
|
+
const resolved = getClient();
|
|
15
|
+
return resolved ? new ChatClient(resolved) : null;
|
|
16
|
+
}, [getClient, ready]);
|
|
17
|
+
return { client, getClient, ready, error, refresh };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { useChatClient };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface ComposerProps {
|
|
4
|
+
onSubmit: (text: string) => void;
|
|
5
|
+
onStop?: () => void;
|
|
6
|
+
busy?: boolean;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
/** Text dropped in from elsewhere — a suggested action, say. */
|
|
10
|
+
seed?: string;
|
|
11
|
+
onSeedConsumed?: () => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The input.
|
|
15
|
+
*
|
|
16
|
+
* A textarea rather than an input, growing with its content: people paste
|
|
17
|
+
* paragraphs into agents, and a single-line field hides everything but the
|
|
18
|
+
* end of what they wrote. Enter sends, Shift+Enter breaks the line — the
|
|
19
|
+
* convention every chat surface shares, including the platform's own.
|
|
20
|
+
*/
|
|
21
|
+
declare function Composer({ onSubmit, onStop, busy, placeholder, disabled, seed, onSeedConsumed, }: ComposerProps): react.JSX.Element;
|
|
22
|
+
|
|
23
|
+
export { Composer, type ComposerProps };
|
package/dist/composer.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import './chunk-PR4QN5HX.js';
|
|
3
|
+
import { useState, useRef, useEffect } from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
function Composer({
|
|
7
|
+
onSubmit,
|
|
8
|
+
onStop,
|
|
9
|
+
busy = false,
|
|
10
|
+
placeholder = "Ask anything\u2026",
|
|
11
|
+
disabled = false,
|
|
12
|
+
seed,
|
|
13
|
+
onSeedConsumed
|
|
14
|
+
}) {
|
|
15
|
+
const [text, setText] = useState("");
|
|
16
|
+
const area = useRef(null);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!seed) return;
|
|
19
|
+
setText((current) => current ? `${current} ${seed}` : seed);
|
|
20
|
+
onSeedConsumed?.();
|
|
21
|
+
requestAnimationFrame(() => {
|
|
22
|
+
const el = area.current;
|
|
23
|
+
if (!el) return;
|
|
24
|
+
el.focus();
|
|
25
|
+
el.setSelectionRange(el.value.length, el.value.length);
|
|
26
|
+
el.style.height = "auto";
|
|
27
|
+
el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
|
|
28
|
+
});
|
|
29
|
+
}, [seed, onSeedConsumed]);
|
|
30
|
+
function resize() {
|
|
31
|
+
const el = area.current;
|
|
32
|
+
if (!el) return;
|
|
33
|
+
el.style.height = "auto";
|
|
34
|
+
el.style.height = `${Math.min(el.scrollHeight, 200)}px`;
|
|
35
|
+
}
|
|
36
|
+
function send() {
|
|
37
|
+
const trimmed = text.trim();
|
|
38
|
+
if (!trimmed || busy || disabled) return;
|
|
39
|
+
onSubmit(trimmed);
|
|
40
|
+
setText("");
|
|
41
|
+
requestAnimationFrame(resize);
|
|
42
|
+
}
|
|
43
|
+
function onKeyDown(event) {
|
|
44
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
send();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function onFormSubmit(event) {
|
|
50
|
+
event.preventDefault();
|
|
51
|
+
send();
|
|
52
|
+
}
|
|
53
|
+
return /* @__PURE__ */ jsxs("form", { className: "fr-composer", onSubmit: onFormSubmit, children: [
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
"textarea",
|
|
56
|
+
{
|
|
57
|
+
ref: area,
|
|
58
|
+
className: "fr-composer-input",
|
|
59
|
+
rows: 1,
|
|
60
|
+
value: text,
|
|
61
|
+
placeholder,
|
|
62
|
+
disabled,
|
|
63
|
+
onChange: (e) => {
|
|
64
|
+
setText(e.target.value);
|
|
65
|
+
resize();
|
|
66
|
+
},
|
|
67
|
+
onKeyDown
|
|
68
|
+
}
|
|
69
|
+
),
|
|
70
|
+
busy && onStop ? /* @__PURE__ */ jsx("button", { type: "button", className: "fr-btn fr-btn-stop", onClick: onStop, "aria-label": "Stop", children: /* @__PURE__ */ jsx(StopIcon, {}) }) : /* @__PURE__ */ jsx(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "submit",
|
|
74
|
+
className: "fr-btn fr-btn-send",
|
|
75
|
+
disabled: !text.trim() || disabled,
|
|
76
|
+
"aria-label": "Send",
|
|
77
|
+
children: /* @__PURE__ */ jsx(SendIcon, {})
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
function SendIcon() {
|
|
83
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", className: "fr-icon", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M8 13V3M8 3 4 7M8 3l4 4", fill: "none", stroke: "currentColor", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round" }) });
|
|
84
|
+
}
|
|
85
|
+
function StopIcon() {
|
|
86
|
+
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", className: "fr-icon", "aria-hidden": true, children: /* @__PURE__ */ jsx("rect", { x: "4.5", y: "4.5", width: "7", height: "7", rx: "1.5", fill: "currentColor" }) });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { Composer };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import './chunk-PR4QN5HX.js';
|
|
3
|
+
|
|
4
|
+
// ../../node_modules/@univerjs/engine-render/lib/es/cop-C3sk0IUo.js
|
|
5
|
+
var Cop = [
|
|
6
|
+
"02,002,0002,1,2,21,12,,201,3,22,32,01,022",
|
|
7
|
+
'{"0":[{"\u2C99":[{"\u0300":[{"0":7}]}],"\u2C9B":[{"\u0300":[{"0":7}]}]}],".":[{"0":[{"\u2CAF":1,"\u2C91":1,"\u2C9D":1,"\u2CAB":1,"\u03E9":1,"\u03EB":1,"\u2C99":[{"\u0300":2}],"\u2C9B":[{"\u0300":2}],"\u2C93":[{"\u0308":2}],"\u03EF":1}],"\u2C83":0,"\u2CA5":0,"\u2C87":0,"\u03E5":0,"\u2C85":0,"\u03E7":0,"\u2C95":0,"\u2C97":0,"\u2C99":0,"\u2C9B":0,"\u2CA1":0,"\u03ED":0,"\u2CA3":0,"\u2CA7":0,"\u2CB1":[{"\u2C9F":[{"\u2CA9":0}]},0],"\u2CAD":0,"\u03E3":0,"\u2C8D":0,"\u2C8F":[{"\u2C93":0}]}],"\u2C83":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C85":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C87":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":0,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C8D":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u03E7":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},0],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C95":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":0,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C97":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C99":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}],"\u0300":[{"0":[{".":4}],"\u2C83":8,"\u2C85":8,"\u2C87":8,"\u03E7":8,"\u2C95":8,"\u2C97":8,"\u2C99":8,"\u2C9B":8,"\u2CAD":8,"\u2CA1":8,"\u2CA3":8,"\u2CA5":8,"\u2CA7":8,"\u03E5":8,"\u03ED":8,"\u03E3":8}]},3],"\u2C9B":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}],"\u0300":[{"0":[{".":4}],"\u2C83":8,"\u2C85":8,"\u2C87":8,"\u03E7":8,"\u2C95":8,"\u2C97":8,"\u2C99":8,"\u2C9B":8,"\u2CAD":8,"\u2CA1":8,"\u2CA3":8,"\u2CA5":8,"\u2CA7":8,"\u03E5":8,"\u03ED":8,"\u03E3":8}]},3],"\u2CAD":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2CA1":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},0],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":0,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2CA3":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2CA5":[{"\u2C83":0,"\u2C85":0,"\u2C87":0,"\u2C8D":4,"\u03E7":4,"\u2C95":0,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},0],"\u2C9B":[{"\u0300":[{"0":6}]},0],"\u2CAD":4,"\u2CA1":0,"\u2CA3":0,"\u2CA5":4,"\u2CA7":0,"\u03E5":0,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2CA7":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":0,"\u03E7":[{".":10},0],"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},0],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":0,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u03E5":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":0,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u03ED":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":0,"\u2C95":4,"\u2C97":0,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},0],"\u2CAD":4,"\u2CA1":4,"\u2CA3":0,"\u2CA5":4,"\u2CA7":0,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u03E3":[{"\u2C83":4,"\u2C85":4,"\u2C87":4,"\u2C8D":4,"\u03E7":4,"\u2C95":4,"\u2C97":4,"\u2C99":[{"\u0300":[{"0":6}]},4],"\u2C9B":[{"\u0300":[{"0":6}]},4],"\u2CAD":4,"\u2CA1":4,"\u2CA3":4,"\u2CA5":4,"\u2CA7":4,"\u03E5":4,"\u03ED":4,"\u03E3":4,".":4,"\u2CAF":[{"0":5}],"\u2C91":[{"0":5}],"\u2C9D":[{"0":5}],"\u2CAB":[{"0":5}],"\u03E9":[{"0":5}],"\u03EB":[{"0":5}],"\u2CC9":[{"0":5}],"\u03EF":[{"0":5}]},3],"\u2C93":[{"\u0308":[{"0":[{".":3},3]}]}],"\u2CA9":[{"\u0308":[{"0":[{".":3},3]}]}],"\u03E9":[{"0":[{".":4},9],"\u2CA3":5}],"\u2CAB":[{"0":[{".":4},3]}],"\u2C9D":[{"0":[{".":4},3]}],"\u2C91":[{"0":[{".":4},3]}],"\u2CAF":[{"0":[{".":4},3]}],"\u03EB":[{"0":[{".":4},3]}],"\u2C8F":[{"\u03E7":[{"0":[{".":10},6]}],"\u2CC9":[{"0":[{".":10},11]}],"\u2C81":12,"\u2C89":12,"\u2C9F":[{"\u2CA9":12},12],"\u2CB1":12,"\u2C93":[{"\u2C81":12,"\u2C89":12,"\u2C9F":12,"\u2CB1":12}]}],"\u2CC9":[{"0":[{".":4},9]}],"\u03EF":[{"0":[{".":4},3]}],"\u2C81":[{"\u2C89":[{"\u2C93":13},12],"\u2C9F":[{"\u2CA9":0},12],"\u2C8F":12,"\u2CB1":12,"\u2C93":[{"\u2C81":12,"\u2C89":12,"\u2C9F":12,"\u2CB1":12}]}],"\u2C89":[{"\u2C81":12,"\u2C9F":[{"\u2CA9":0},12],"\u2C8F":12,"\u2CB1":12,"\u2C93":0}],"\u2C9F":[{"\u2C81":12,"\u2C89":12,"\u2C8F":12,"\u2CB1":12,"\u2C93":[{"\u2C81":12,"\u2C89":12,"\u2C9F":12,"\u2CB1":12}],"\u2C9F":[{"\u2CA9":0}],"\u2CA9":[{"\u2C81":1,"\u2C89":1,"\u2C8F":1,"\u2C9F":1,"\u2CA9":1,"\u2CB1":1,"\u2C93":1}]}],"\u2CB1":[{"\u2C9F":[{"\u2CA9":12}]}]}',
|
|
8
|
+
[]
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
export { Cop };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { FronteraClient } from '@frontera-sdk/core/client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How a component gets its credential.
|
|
5
|
+
*
|
|
6
|
+
* Four shapes, ordered by how much the caller wants to manage. Every chat
|
|
7
|
+
* component in this package accepts the same union, so moving between
|
|
8
|
+
* `FronteraChat`, `FronteraChatFrame` and the script embed is a change of
|
|
9
|
+
* component, not of plumbing.
|
|
10
|
+
*/
|
|
11
|
+
type ChatCredentialProps = {
|
|
12
|
+
/**
|
|
13
|
+
* An endpoint on YOUR site returning `{ token, expiresAt }` for whoever
|
|
14
|
+
* is signed in. Called same-origin, so your session cookie identifies
|
|
15
|
+
* them, and refreshed automatically before expiry.
|
|
16
|
+
*
|
|
17
|
+
* The recommended shape: nothing to manage, and tokens stay short-lived
|
|
18
|
+
* without the caller having to think about it.
|
|
19
|
+
*/
|
|
20
|
+
tokenEndpoint: string;
|
|
21
|
+
apiBaseUrl?: string;
|
|
22
|
+
token?: never;
|
|
23
|
+
getToken?: never;
|
|
24
|
+
client?: never;
|
|
25
|
+
} | {
|
|
26
|
+
/**
|
|
27
|
+
* A token you already hold. You then own replacing it before it expires
|
|
28
|
+
* — pass `tokenEndpoint` instead to be rid of that.
|
|
29
|
+
*/
|
|
30
|
+
token: string;
|
|
31
|
+
apiBaseUrl: string;
|
|
32
|
+
tokenEndpoint?: never;
|
|
33
|
+
getToken?: never;
|
|
34
|
+
client?: never;
|
|
35
|
+
} | {
|
|
36
|
+
/** Fetch the token however you like; called again on refresh. */
|
|
37
|
+
getToken: () => Promise<{
|
|
38
|
+
token: string;
|
|
39
|
+
expiresAt: string;
|
|
40
|
+
apiBaseUrl?: string;
|
|
41
|
+
}>;
|
|
42
|
+
apiBaseUrl?: string;
|
|
43
|
+
tokenEndpoint?: never;
|
|
44
|
+
token?: never;
|
|
45
|
+
client?: never;
|
|
46
|
+
} | {
|
|
47
|
+
/**
|
|
48
|
+
* A client you built yourself. Pass a getter if you rotate tokens.
|
|
49
|
+
*
|
|
50
|
+
* The getter may return null: `useChatCredential` itself returns one that
|
|
51
|
+
* is null until the first token lands, and forcing callers to cast that
|
|
52
|
+
* away would push a lie into every app that shares one credential
|
|
53
|
+
* between the chat and its own sidebar.
|
|
54
|
+
*/
|
|
55
|
+
client: FronteraClient | (() => FronteraClient | null);
|
|
56
|
+
tokenEndpoint?: never;
|
|
57
|
+
token?: never;
|
|
58
|
+
getToken?: never;
|
|
59
|
+
apiBaseUrl?: never;
|
|
60
|
+
};
|
|
61
|
+
interface ResolvedCredential {
|
|
62
|
+
/** The current client, or null until the first token arrives. */
|
|
63
|
+
getClient: () => FronteraClient | null;
|
|
64
|
+
ready: boolean;
|
|
65
|
+
error: Error | null;
|
|
66
|
+
/**
|
|
67
|
+
* Force a new credential now. Wired to the transport's 401 handler, so a
|
|
68
|
+
* token that expired while the tab slept costs a retry rather than a visible
|
|
69
|
+
* failure.
|
|
70
|
+
*/
|
|
71
|
+
refresh: () => Promise<unknown>;
|
|
72
|
+
}
|
|
73
|
+
declare function useChatCredential(props: ChatCredentialProps): ResolvedCredential;
|
|
74
|
+
|
|
75
|
+
export { type ChatCredentialProps, type ResolvedCredential, useChatCredential };
|