@vinaverse/react-native 0.1.0-alpha.10 → 0.1.0-alpha.11

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.
@@ -0,0 +1,624 @@
1
+ import { Button, useChat, FailureSlot, FailureActionButton, ChatContextProvider, ChatHeader, DisclosureBar, MessageList } from './chunk-KSHDF3MG.js';
2
+ import { useTheme, useNativeLifecycle, themeProblems, ThemeProvider, useAgentSweep } from './chunk-EFEXTVIT.js';
3
+ import { useAgentRuntime, useAgentConversation, useAgentName } from '@vinaverse/react/agent';
4
+ export { AgentRuntimeProvider, forgetGreeting, greetedKey, useAgentConversation, useAgentFeatures, useAgentLauncher, useAgentName, useAgentProfile, useAgentRuntime, useAgentStatus, useAgentStatusState } from '@vinaverse/react/agent';
5
+ import { useCopy, useConversationSelector, bannedWordsIn, CopyProvider } from '@vinaverse/react';
6
+ import { useState, memo, useCallback, useMemo, useEffect, useRef } from 'react';
7
+ import { View, TextInput, Text, Platform, KeyboardAvoidingView } from 'react-native';
8
+ import { codePoints, MAX_TEXT } from '@vinaverse/client/conversation';
9
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
+ import { motion } from '@vinaverse/tokens';
11
+
12
+ function DefaultComposer(props) {
13
+ const { t, direction } = useCopy();
14
+ const { colors, radius, space, font, size } = useTheme();
15
+ const [text, setText] = useState("");
16
+ const length = codePoints(text);
17
+ const canSend = text.trim().length > 0 && length <= MAX_TEXT;
18
+ const send = () => {
19
+ if (!canSend) return;
20
+ props.onSend(text);
21
+ setText("");
22
+ };
23
+ return /* @__PURE__ */ jsxs(
24
+ View,
25
+ {
26
+ style: {
27
+ flexDirection: "row",
28
+ alignItems: "flex-end",
29
+ gap: space.sm,
30
+ paddingHorizontal: space.lg,
31
+ paddingVertical: space.sm,
32
+ borderTopWidth: 1,
33
+ borderTopColor: colors.divider,
34
+ backgroundColor: colors.background
35
+ },
36
+ children: [
37
+ /* @__PURE__ */ jsx(
38
+ TextInput,
39
+ {
40
+ value: text,
41
+ onChangeText: setText,
42
+ placeholder: props.placeholder,
43
+ placeholderTextColor: colors.textMuted,
44
+ accessibilityLabel: props.placeholder,
45
+ multiline: true,
46
+ maxLength: MAX_TEXT * 2,
47
+ testID: "vinaverse-composer-input",
48
+ style: {
49
+ flex: 1,
50
+ minHeight: size.touchTarget,
51
+ maxHeight: 140,
52
+ paddingHorizontal: space.md,
53
+ paddingVertical: space.sm,
54
+ borderRadius: radius.lg,
55
+ borderWidth: 1,
56
+ borderColor: colors.border,
57
+ color: colors.text,
58
+ backgroundColor: colors.surface,
59
+ fontSize: font.size.md,
60
+ textAlign: direction === "rtl" ? "right" : "left",
61
+ writingDirection: direction,
62
+ ...font.family ? { fontFamily: font.family } : {}
63
+ }
64
+ }
65
+ ),
66
+ props.responding && !text ? /* @__PURE__ */ jsx(
67
+ Button,
68
+ {
69
+ label: t("stop"),
70
+ onPress: props.onStop,
71
+ testID: "vinaverse-stop"
72
+ }
73
+ ) : /* @__PURE__ */ jsx(
74
+ Button,
75
+ {
76
+ label: t("send"),
77
+ variant: "primary",
78
+ disabled: !canSend,
79
+ onPress: send,
80
+ testID: "vinaverse-send"
81
+ }
82
+ )
83
+ ]
84
+ }
85
+ );
86
+ }
87
+ var Composer = /* @__PURE__ */ memo(function Composer2(props) {
88
+ const { store, slots } = useChat();
89
+ const { t } = useCopy();
90
+ const takeover = useConversationSelector(store, (v) => v.takeover);
91
+ const name = useConversationSelector(store, (v) => v.agent.name);
92
+ const responding = useConversationSelector(store, (v) => v.responding);
93
+ const { onError } = props;
94
+ const onSend = useCallback(
95
+ (text) => {
96
+ try {
97
+ store.send(text);
98
+ } catch (error) {
99
+ onError?.(error);
100
+ }
101
+ },
102
+ [store, onError]
103
+ );
104
+ const onStop = useCallback(() => store.cancel(), [store]);
105
+ const placeholder = takeover ? t("composerPlaceholderTakeover", {
106
+ by: takeover.by || t("staffFallbackRole")
107
+ }) : t("composerPlaceholder", { agent: name ?? t("agentFallbackName") });
108
+ const Slot = slots.Composer;
109
+ const own = { placeholder, responding, onSend, onStop };
110
+ return Slot ? /* @__PURE__ */ jsx(Slot, { ...own, Default: DefaultComposer }) : /* @__PURE__ */ jsx(DefaultComposer, { ...own });
111
+ });
112
+ var CONNECTING_DELAY = motion.bannerDelay;
113
+ var StatusBanner = /* @__PURE__ */ memo(function StatusBanner2() {
114
+ const { store, slots } = useChat();
115
+ const { t } = useCopy();
116
+ const banner = useConversationSelector(store, (v) => v.banner);
117
+ const status = useConversationSelector(store, (v) => v.status);
118
+ const conversationId = useConversationSelector(
119
+ store,
120
+ (v) => v.conversationId
121
+ );
122
+ const unavailable = useMemo(
123
+ () => ({
124
+ kind: "unavailable",
125
+ reason: status,
126
+ retry: () => store.start(),
127
+ conversationId
128
+ }),
129
+ [store, status, conversationId]
130
+ );
131
+ const [late, setLate] = useState(false);
132
+ useEffect(() => {
133
+ setLate(false);
134
+ if (banner !== "connecting") return;
135
+ const timer = setTimeout(() => setLate(true), CONNECTING_DELAY);
136
+ return () => clearTimeout(timer);
137
+ }, [banner]);
138
+ if (banner === null || banner === "connecting" && !late) return null;
139
+ if (banner === "unavailable")
140
+ return /* @__PURE__ */ jsx(
141
+ FailureSlot,
142
+ {
143
+ slot: slots.Unavailable,
144
+ state: unavailable,
145
+ Default: DefaultUnavailable
146
+ }
147
+ );
148
+ const text = {
149
+ connecting: t("bannerConnecting"),
150
+ reconnecting: t("bannerReconnecting"),
151
+ offline: t("bannerOffline"),
152
+ continued_elsewhere: t("bannerContinuedElsewhere")
153
+ }[banner];
154
+ const action = banner === "continued_elsewhere" ? /* @__PURE__ */ jsx(
155
+ Button,
156
+ {
157
+ label: t("continueHere"),
158
+ variant: "text",
159
+ onPress: () => void store.continueHere()
160
+ }
161
+ ) : banner === "offline" ? /* @__PURE__ */ jsx(
162
+ Button,
163
+ {
164
+ label: t("tryAgain"),
165
+ variant: "text",
166
+ onPress: () => store.start()
167
+ }
168
+ ) : null;
169
+ return /* @__PURE__ */ jsx(Banner, { text, children: action });
170
+ });
171
+ function DefaultUnavailable(props) {
172
+ const { t } = useCopy();
173
+ const { retry } = props.state;
174
+ return /* @__PURE__ */ jsxs(Banner, { text: t("bannerUnavailable"), children: [
175
+ retry ? /* @__PURE__ */ jsx(Button, { label: t("tryAgain"), variant: "text", onPress: retry }) : null,
176
+ /* @__PURE__ */ jsx(FailureActionButton, { state: props.state })
177
+ ] });
178
+ }
179
+ function Banner(props) {
180
+ const { colors, space, font } = useTheme();
181
+ return /* @__PURE__ */ jsxs(
182
+ View,
183
+ {
184
+ accessibilityLiveRegion: "polite",
185
+ accessibilityRole: "alert",
186
+ style: {
187
+ flexDirection: "row",
188
+ alignItems: "center",
189
+ justifyContent: "space-between",
190
+ gap: space.sm,
191
+ paddingHorizontal: space.lg,
192
+ paddingVertical: space.xs,
193
+ backgroundColor: colors.surface,
194
+ borderBottomWidth: 1,
195
+ borderBottomColor: colors.divider
196
+ },
197
+ children: [
198
+ /* @__PURE__ */ jsx(
199
+ Text,
200
+ {
201
+ style: { color: colors.text, fontSize: font.size.sm, flexShrink: 1 },
202
+ children: props.text
203
+ }
204
+ ),
205
+ props.children
206
+ ]
207
+ }
208
+ );
209
+ }
210
+ function VinaverseChatProvider(props) {
211
+ const {
212
+ conversation,
213
+ components,
214
+ agentAvatar,
215
+ timeZone,
216
+ starters,
217
+ imagePolicy
218
+ } = props;
219
+ const handlers = useRef(props);
220
+ handlers.current = props;
221
+ const slots = useStableSlots(components);
222
+ const hasAction = props.failureAction !== void 0;
223
+ const actionLabel = props.failureAction?.label;
224
+ const failureAction = useMemo(
225
+ () => hasAction ? { label: actionLabel } : null,
226
+ [hasAction, actionLabel]
227
+ );
228
+ const value = useMemo(
229
+ () => ({
230
+ store: conversation,
231
+ handlers,
232
+ slots,
233
+ agentAvatar,
234
+ timeZone,
235
+ failureAction,
236
+ starters,
237
+ imagePolicy
238
+ }),
239
+ [
240
+ conversation,
241
+ slots,
242
+ agentAvatar,
243
+ timeZone,
244
+ failureAction,
245
+ starters,
246
+ imagePolicy
247
+ ]
248
+ );
249
+ useNativeLifecycle(conversation);
250
+ useEffect(() => {
251
+ conversation.start();
252
+ }, [conversation]);
253
+ const { onWarning, theme, copy } = props;
254
+ useEffect(() => {
255
+ if (!onWarning) return;
256
+ for (const problem of themeProblems(theme))
257
+ onWarning(`Vinaverse theme: ${problem}`, { code: "theme" });
258
+ for (const key of bannedWordsIn(copy ?? {}))
259
+ onWarning(
260
+ `Vinaverse copy: "${key}" says assistant, bot or crew; the copy says agent.`,
261
+ { code: "copy" }
262
+ );
263
+ }, [onWarning, theme, copy]);
264
+ return /* @__PURE__ */ jsx(CopyProvider, { locale: props.locale, copy: props.copy, children: /* @__PURE__ */ jsx(ThemeProvider, { theme: props.theme, colorScheme: props.colorScheme, children: /* @__PURE__ */ jsx(ChatContextProvider, { value, children: props.children }) }) });
265
+ }
266
+ function VinaverseChat(props) {
267
+ return /* @__PURE__ */ jsx(VinaverseChatProvider, { ...props, children: /* @__PURE__ */ jsx(
268
+ Layout,
269
+ {
270
+ hideHeader: props.hideHeader === true,
271
+ keyboardVerticalOffset: props.keyboardVerticalOffset ?? 0,
272
+ keyboardBehavior: props.keyboardBehavior ?? (Platform.OS === "ios" ? "padding" : "none"),
273
+ style: props.style,
274
+ onError: props.onWarning,
275
+ suggestion: props.suggestion ?? null,
276
+ suggestionTestID: props.suggestionTestID ?? "vinaverse-suggestion",
277
+ footer: props.footer
278
+ }
279
+ ) });
280
+ }
281
+ function Layout(props) {
282
+ const { colors } = useTheme();
283
+ const { direction } = useCopy();
284
+ const { onError } = props;
285
+ const reportError = useMemo(
286
+ () => onError ? (e) => onError(String(e), { code: "send_failed" }) : void 0,
287
+ [onError]
288
+ );
289
+ return /* @__PURE__ */ jsxs(
290
+ KeyboardAvoidingView,
291
+ {
292
+ ...props.keyboardBehavior === "none" ? { enabled: false } : { behavior: props.keyboardBehavior },
293
+ keyboardVerticalOffset: props.keyboardVerticalOffset,
294
+ style: [
295
+ { flex: 1, backgroundColor: colors.background, direction },
296
+ props.style
297
+ ],
298
+ children: [
299
+ props.hideHeader ? null : /* @__PURE__ */ jsx(ChatHeader, {}),
300
+ /* @__PURE__ */ jsx(DisclosureBar, {}),
301
+ /* @__PURE__ */ jsx(StatusBanner, {}),
302
+ /* @__PURE__ */ jsx(View, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(MessageList, {}) }),
303
+ props.suggestion ? /* @__PURE__ */ jsx(Suggestion, { chip: props.suggestion, testID: props.suggestionTestID }) : null,
304
+ /* @__PURE__ */ jsx(Composer, { ...reportError ? { onError: reportError } : {} }),
305
+ props.footer
306
+ ]
307
+ }
308
+ );
309
+ }
310
+ function Suggestion(props) {
311
+ const { store, handlers } = useChat();
312
+ const { space } = useTheme();
313
+ return /* @__PURE__ */ jsx(View, { style: { paddingHorizontal: space.lg, alignItems: "flex-start" }, children: /* @__PURE__ */ jsx(
314
+ Button,
315
+ {
316
+ label: props.chip.label,
317
+ testID: props.testID,
318
+ onPress: () => {
319
+ store.send(props.chip.message);
320
+ handlers.current?.onChip?.(props.chip);
321
+ }
322
+ }
323
+ ) });
324
+ }
325
+ function useStableSlots(slots) {
326
+ const held = useRef({});
327
+ const next = slots ?? {};
328
+ if (!sameSlots(held.current, next)) held.current = next;
329
+ return held.current;
330
+ }
331
+ function sameSlots(a, b) {
332
+ const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
333
+ for (const key of keys) {
334
+ if (key === "cards") {
335
+ const ca = a.cards ?? {};
336
+ const cb = b.cards ?? {};
337
+ const kinds = /* @__PURE__ */ new Set([...Object.keys(ca), ...Object.keys(cb)]);
338
+ for (const kind of kinds) if (ca[kind] !== cb[kind]) return false;
339
+ } else if (a[key] !== b[key]) return false;
340
+ }
341
+ return true;
342
+ }
343
+ function AgentChat(props) {
344
+ const {
345
+ agentKey,
346
+ place,
347
+ entryPoint,
348
+ askAbout,
349
+ onContact,
350
+ onOpenPrivacy,
351
+ components,
352
+ agentName,
353
+ opener,
354
+ openerTestID,
355
+ ...chat
356
+ } = props;
357
+ const runtime = useAgentRuntime();
358
+ useAgentSweep(runtime);
359
+ const { conversation, state, startNew } = useAgentConversation(agentKey, {
360
+ place: place ?? null,
361
+ entryPoint: entryPoint ?? null
362
+ });
363
+ const store = conversation.store;
364
+ const spoke = useConversationSelector(
365
+ store,
366
+ (v) => v.items.some((i) => i.type === "message" && i.role === "person")
367
+ );
368
+ const { Ended, Unreachable, UnavailableScreen, Footer, ...slots } = components ?? {};
369
+ const copy = useMemo(
370
+ () => agentName ? { ...props.copy, agentFallbackName: agentName } : props.copy,
371
+ [agentName, props.copy]
372
+ );
373
+ const events = {
374
+ onOpenTarget: chat.onOpenTarget ? (target, card) => {
375
+ runtime.emit({
376
+ type: "target_opened",
377
+ key: conversation.key,
378
+ cardId: card.id,
379
+ kind: target.type
380
+ });
381
+ chat.onOpenTarget?.(target, card);
382
+ } : void 0,
383
+ onOpenLink: chat.onOpenLink ? (link, card) => {
384
+ runtime.emit({
385
+ type: "link_opened",
386
+ key: conversation.key,
387
+ cardId: card.id,
388
+ kind: card.kind
389
+ });
390
+ chat.onOpenLink?.(link, card);
391
+ } : void 0,
392
+ onChip: (chip) => {
393
+ runtime.emit({ type: "chip_tapped", key: conversation.key });
394
+ chat.onChip?.(chip);
395
+ }
396
+ };
397
+ const shared = {
398
+ ...chat,
399
+ ...events.onOpenTarget ? { onOpenTarget: events.onOpenTarget } : {},
400
+ ...events.onOpenLink ? { onOpenLink: events.onOpenLink } : {},
401
+ onChip: events.onChip,
402
+ ...copy ? { copy } : {},
403
+ ...onContact && !chat.failureAction ? { failureAction: { onPress: () => onContact() } } : {},
404
+ conversation: store,
405
+ components: slots
406
+ };
407
+ if (state.failure === "ended") {
408
+ const own = {
409
+ onStartNew: startNew,
410
+ reason: state.reason,
411
+ code: state.code,
412
+ onContact
413
+ };
414
+ return /* @__PURE__ */ jsx(VinaverseChatProvider, { ...shared, children: /* @__PURE__ */ jsx(Centered, { children: Ended ? /* @__PURE__ */ jsx(Ended, { ...own, Default: DefaultEnded }) : /* @__PURE__ */ jsx(DefaultEnded, { ...own }) }) });
415
+ }
416
+ if (state.failure === "unreachable") {
417
+ const own = {
418
+ onRetry: conversation.retry,
419
+ reason: state.reason,
420
+ onContact
421
+ };
422
+ return /* @__PURE__ */ jsx(VinaverseChatProvider, { ...shared, children: /* @__PURE__ */ jsx(Centered, { children: Unreachable ? /* @__PURE__ */ jsx(Unreachable, { ...own, Default: DefaultUnreachable }) : /* @__PURE__ */ jsx(DefaultUnreachable, { ...own }) }) });
423
+ }
424
+ if (state.failure === "unavailable") {
425
+ const own = {
426
+ reason: state.reason,
427
+ code: state.code,
428
+ onContact,
429
+ onRetry: conversation.retry
430
+ };
431
+ return /* @__PURE__ */ jsx(VinaverseChatProvider, { ...shared, children: /* @__PURE__ */ jsx(Centered, { children: UnavailableScreen ? /* @__PURE__ */ jsx(UnavailableScreen, { ...own, Default: DefaultUnavailableScreen }) : /* @__PURE__ */ jsx(DefaultUnavailableScreen, { ...own }) }) });
432
+ }
433
+ const offered = opener && !spoke ? opener : null;
434
+ return /* @__PURE__ */ jsx(
435
+ VinaverseChat,
436
+ {
437
+ ...shared,
438
+ suggestion: offered ?? (state.moved && askAbout ? { label: askAbout, message: askAbout } : null),
439
+ ...offered ? { suggestionTestID: openerTestID ?? "vinaverse-opener" } : {},
440
+ footer: Footer === null ? null : /* @__PURE__ */ jsx(
441
+ FooterFor,
442
+ {
443
+ store,
444
+ state,
445
+ rate: conversation.rate,
446
+ canRate: conversation.canRate,
447
+ Footer,
448
+ onOpenPrivacy
449
+ }
450
+ )
451
+ }
452
+ );
453
+ }
454
+ function FooterFor(props) {
455
+ const newest = useConversationSelector(props.store, newestWholeReply);
456
+ const turnId = newest && props.canRate(newest) ? newest : null;
457
+ const own = {
458
+ turnId,
459
+ rating: turnId ? props.state.ratings.get(turnId) : void 0,
460
+ onRate: (rating) => {
461
+ if (turnId) props.rate(turnId, rating);
462
+ },
463
+ onOpenPrivacy: props.onOpenPrivacy
464
+ };
465
+ const { Footer } = props;
466
+ return Footer ? /* @__PURE__ */ jsx(Footer, { ...own, Default: AgentFooter }) : /* @__PURE__ */ jsx(AgentFooter, { ...own });
467
+ }
468
+ function newestWholeReply(view) {
469
+ for (let i = view.items.length - 1; i >= 0; i--) {
470
+ const item = view.items[i];
471
+ if (item?.type !== "message" || item.role !== "agent") continue;
472
+ const whole = item.state === "sent" && !item.partial && !item.refusal && item.key.startsWith("a:");
473
+ return whole ? item.key.slice(2) : null;
474
+ }
475
+ return null;
476
+ }
477
+ function Centered(props) {
478
+ const { colors, space } = useTheme();
479
+ return /* @__PURE__ */ jsx(
480
+ View,
481
+ {
482
+ style: {
483
+ flex: 1,
484
+ alignItems: "center",
485
+ justifyContent: "center",
486
+ padding: space.xl,
487
+ backgroundColor: colors.background
488
+ },
489
+ children: props.children
490
+ }
491
+ );
492
+ }
493
+ function Notice(props) {
494
+ const { colors, space, font } = useTheme();
495
+ return /* @__PURE__ */ jsxs(
496
+ View,
497
+ {
498
+ accessibilityRole: "alert",
499
+ style: { alignItems: "center", gap: space.md },
500
+ children: [
501
+ /* @__PURE__ */ jsx(
502
+ Text,
503
+ {
504
+ style: {
505
+ color: colors.text,
506
+ fontSize: font.size.lg,
507
+ fontWeight: "600",
508
+ textAlign: "center"
509
+ },
510
+ children: props.title
511
+ }
512
+ ),
513
+ /* @__PURE__ */ jsx(
514
+ Text,
515
+ {
516
+ style: {
517
+ color: colors.textMuted,
518
+ fontSize: font.size.md,
519
+ textAlign: "center"
520
+ },
521
+ children: props.body
522
+ }
523
+ ),
524
+ props.action && props.onPress ? /* @__PURE__ */ jsx(
525
+ Button,
526
+ {
527
+ label: props.action,
528
+ variant: "primary",
529
+ onPress: props.onPress
530
+ }
531
+ ) : null
532
+ ]
533
+ }
534
+ );
535
+ }
536
+ function DefaultEnded(props) {
537
+ const { t } = useCopy();
538
+ return /* @__PURE__ */ jsx(
539
+ Notice,
540
+ {
541
+ title: t("agentEnded"),
542
+ body: t("agentEndedBody"),
543
+ action: t("agentStartOver"),
544
+ onPress: props.onStartNew
545
+ }
546
+ );
547
+ }
548
+ function DefaultUnavailableScreen(props) {
549
+ const { t } = useCopy();
550
+ const name = useAgentName(t("agentFallbackName"));
551
+ const title = t("agentOff", { agent: name });
552
+ return /* @__PURE__ */ jsx(
553
+ Notice,
554
+ {
555
+ title: title.charAt(0).toUpperCase() + title.slice(1),
556
+ body: t("agentOffBody"),
557
+ ...props.onContact ? { action: t("talkToPerson"), onPress: props.onContact } : {}
558
+ }
559
+ );
560
+ }
561
+ function DefaultUnreachable(props) {
562
+ const { t } = useCopy();
563
+ const name = useAgentName(t("agentFallbackName"));
564
+ return /* @__PURE__ */ jsx(
565
+ Notice,
566
+ {
567
+ title: t("agentUnreachable", { agent: name }),
568
+ body: t("agentUnreachableBody"),
569
+ action: t("tryAgain"),
570
+ onPress: props.onRetry
571
+ }
572
+ );
573
+ }
574
+ function AgentFooter(props) {
575
+ const { t } = useCopy();
576
+ const { colors, space, font } = useTheme();
577
+ const muted = { color: colors.textMuted, fontSize: font.size.sm };
578
+ return /* @__PURE__ */ jsxs(
579
+ View,
580
+ {
581
+ style: {
582
+ flexDirection: "row",
583
+ flexWrap: "wrap",
584
+ alignItems: "center",
585
+ gap: space.xs,
586
+ paddingHorizontal: space.lg
587
+ },
588
+ children: [
589
+ props.turnId === null ? null : props.rating ? /* @__PURE__ */ jsx(Text, { style: muted, children: t("helpfulThanks") }) : /* @__PURE__ */ jsxs(Fragment, { children: [
590
+ /* @__PURE__ */ jsx(Text, { style: muted, children: t("helpful") }),
591
+ /* @__PURE__ */ jsx(
592
+ Button,
593
+ {
594
+ label: t("helpfulYes"),
595
+ variant: "text",
596
+ onPress: () => props.onRate("up")
597
+ }
598
+ ),
599
+ /* @__PURE__ */ jsx(
600
+ Button,
601
+ {
602
+ label: t("helpfulNo"),
603
+ variant: "text",
604
+ onPress: () => props.onRate("down")
605
+ }
606
+ )
607
+ ] }),
608
+ props.onOpenPrivacy ? /* @__PURE__ */ jsx(
609
+ Button,
610
+ {
611
+ label: t("privacy"),
612
+ variant: "text",
613
+ role: "link",
614
+ onPress: props.onOpenPrivacy
615
+ }
616
+ ) : null
617
+ ]
618
+ }
619
+ );
620
+ }
621
+
622
+ export { AgentChat, AgentFooter, Composer, DefaultComposer, DefaultEnded, DefaultUnavailable, DefaultUnavailableScreen, DefaultUnreachable, StatusBanner, VinaverseChat, VinaverseChatProvider, newestWholeReply };
623
+ //# sourceMappingURL=chunk-2J2LIJLW.js.map
624
+ //# sourceMappingURL=chunk-2J2LIJLW.js.map