@appilots/sdk 0.11.3 → 0.13.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.
- package/control-transformer.js +69 -0
- package/dist/.build-meta.json +3 -3
- package/dist/{chunk-UFMTRGML.js → chunk-AJDHZRBN.js} +1097 -460
- package/dist/{chunk-5UVMNKPT.js → chunk-ALJGKORS.js} +8 -8
- package/dist/{chunk-ROXXCDIG.mjs → chunk-HRWBK35Y.mjs} +5738 -540
- package/dist/{chunk-JKLE5SLN.mjs → chunk-L3SY3Q4K.mjs} +1 -1
- package/dist/{chunk-2ZDELL54.mjs → chunk-UYBKXULM.mjs} +815 -191
- package/dist/{chunk-SUMIABJK.js → chunk-UZ2D4BVX.js} +5756 -538
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/{index-BR-33WMN.d.mts → index-CI4jmSoP.d.mts} +136 -660
- package/dist/{index-BR-33WMN.d.ts → index-CI4jmSoP.d.ts} +136 -660
- package/dist/index.d.mts +1447 -76
- package/dist/index.d.ts +1447 -76
- package/dist/index.js +1069 -672
- package/dist/index.mjs +902 -564
- package/dist/navigation/index.d.mts +22 -1
- package/dist/navigation/index.d.ts +22 -1
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/metro.d.ts +3 -5
- package/metro.js +46 -5
- package/package.json +16 -2
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { AppilotsNavigationContainer } from './chunk-
|
|
2
|
-
import { useAppilotsChat, useAppilotsActions, shouldShowSuggestedPrompts, useSuggestedPrompts } from './chunk-
|
|
3
|
-
export { appilotsSelfCheck, captureSnapshot, executeAction, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts } from './chunk-
|
|
4
|
-
import { defaultLightTheme, describeAction, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, componentRegistry } from './chunk-
|
|
5
|
-
export { AppilotsClient, AppilotsProvider, AppilotsRegistryProvider, RateLimitedError, SDK_VERSION, _patchJsxRuntimes, clearAppilotsDebugTraces, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, defaultDarkTheme, defaultLightTheme, describeAction, elementRegistry, enableAppilotsAutoTracking, getAppilotsDebugTraces, getAutoTrackingState, getGlobalConfig, getIntrospectionDiagnostics, humanizeError, initAppilots, isAutoTrackingEnabled, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-
|
|
6
|
-
import * as
|
|
7
|
-
import
|
|
8
|
-
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, ActivityIndicator, useColorScheme,
|
|
1
|
+
export { AppilotsNavigationContainer } from './chunk-L3SY3Q4K.mjs';
|
|
2
|
+
import { subscribeSpotlight, getSpotlightTarget, AppilotsI18nProvider, useAppilotsI18n, useAppilotsChat, useAppilotsActions, setSpotlightMode, shouldShowSuggestedPrompts, useSuggestedPrompts } from './chunk-UYBKXULM.mjs';
|
|
3
|
+
export { AppilotsI18nProvider, REVEAL_MARGIN, SPOTLIGHT_TTL_MS, appilotsSelfCheck, captureSnapshot, detectDeviceLocale, executeAction, getSpotlightMode, getSpotlightTarget, offsetToReveal, resolveLocale, revealTarget, setSpotlightMode, setSpotlightTarget, subscribeSpotlight, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsI18n, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts } from './chunk-UYBKXULM.mjs';
|
|
4
|
+
import { defaultLightTheme, describeAction, isRectOnScreen, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, subscribeGeometryHost, geometryAvailability, isGeometryResolved, needsWideChatLayout, componentRegistry, appilotsDebugWarn, enhancePlainAssistantContent, looksLikeMarkdown, parseMarkdownBlocks, parseInlineMarkdown, getFiberRoot, shouldSkipSubtree, isModalFiber } from './chunk-HRWBK35Y.mjs';
|
|
5
|
+
export { AppilotsClient, AppilotsProvider, AppilotsRegistryProvider, RateLimitedError, SDK_VERSION, _patchJsxRuntimes, clearAppilotsDebugTraces, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, defaultDarkTheme, defaultLightTheme, describeAction, elementRegistry, enableAppilotsAutoTracking, getAppilotsDebugTraces, getAutoTrackingState, getGlobalConfig, getIntrospectionDiagnostics, humanizeError, initAppilots, isAutoTrackingEnabled, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-HRWBK35Y.mjs';
|
|
6
|
+
import * as React8 from 'react';
|
|
7
|
+
import React8__default, { createContext, useRef, useEffect, useCallback, useSyncExternalStore, useMemo, useContext, useState } from 'react';
|
|
8
|
+
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, ActivityIndicator, useColorScheme, FlatList, Image, TextInput, KeyboardAvoidingView, Modal, Linking } from 'react-native';
|
|
9
9
|
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
|
10
10
|
import Svg, { Path } from 'react-native-svg';
|
|
11
11
|
|
|
@@ -22,6 +22,43 @@ function useSafeAreaInsetsOrDefault() {
|
|
|
22
22
|
}
|
|
23
23
|
return NO_INSETS;
|
|
24
24
|
}
|
|
25
|
+
function probeHostModalOpen() {
|
|
26
|
+
const stack = [getFiberRoot()];
|
|
27
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28
|
+
while (stack.length) {
|
|
29
|
+
const node = stack.pop();
|
|
30
|
+
if (!node || seen.has(node)) continue;
|
|
31
|
+
seen.add(node);
|
|
32
|
+
if (node.sibling) stack.push(node.sibling);
|
|
33
|
+
if (shouldSkipSubtree(node)) continue;
|
|
34
|
+
if (isModalFiber(node) && node.child) return true;
|
|
35
|
+
if (node.child) stack.push(node.child);
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
function useHostModalOpen(enabled) {
|
|
40
|
+
const [open, setOpen] = useState(false);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!enabled) {
|
|
43
|
+
setOpen(false);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
let closedSince;
|
|
47
|
+
const sample = () => {
|
|
48
|
+
if (probeHostModalOpen()) {
|
|
49
|
+
closedSince = void 0;
|
|
50
|
+
setOpen(true);
|
|
51
|
+
} else {
|
|
52
|
+
closedSince ??= Date.now();
|
|
53
|
+
if (Date.now() - closedSince >= 300) setOpen(false);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
sample();
|
|
57
|
+
const timer = setInterval(sample, 150);
|
|
58
|
+
return () => clearInterval(timer);
|
|
59
|
+
}, [enabled]);
|
|
60
|
+
return enabled && open;
|
|
61
|
+
}
|
|
25
62
|
|
|
26
63
|
// src/components/breadcrumbPresentation.ts
|
|
27
64
|
var DEFAULT_BREADCRUMB_PALETTE = {
|
|
@@ -114,6 +151,7 @@ function ActionBreadcrumb({
|
|
|
114
151
|
fontFamily,
|
|
115
152
|
palette,
|
|
116
153
|
confirmStrings,
|
|
154
|
+
locale,
|
|
117
155
|
requireApprovalFor,
|
|
118
156
|
onApprove,
|
|
119
157
|
onReject
|
|
@@ -125,7 +163,7 @@ function ActionBreadcrumb({
|
|
|
125
163
|
primary: primaryColor,
|
|
126
164
|
text: textColor
|
|
127
165
|
};
|
|
128
|
-
return /* @__PURE__ */
|
|
166
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles.container }, actions.map((action) => /* @__PURE__ */ React8__default.createElement(
|
|
129
167
|
BreadcrumbRow,
|
|
130
168
|
{
|
|
131
169
|
key: action.id,
|
|
@@ -135,6 +173,7 @@ function ActionBreadcrumb({
|
|
|
135
173
|
fontFamily,
|
|
136
174
|
palette: resolvedPalette,
|
|
137
175
|
confirmStrings,
|
|
176
|
+
locale,
|
|
138
177
|
needsApproval: requireApprovalFor?.(action) ?? false,
|
|
139
178
|
onApprove,
|
|
140
179
|
onReject
|
|
@@ -144,7 +183,7 @@ function ActionBreadcrumb({
|
|
|
144
183
|
function BreadcrumbRow(props) {
|
|
145
184
|
const { action, needsApproval } = props;
|
|
146
185
|
if (action.type === "confirm" && action.status === "pending" && needsApproval) {
|
|
147
|
-
return /* @__PURE__ */
|
|
186
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
148
187
|
ConfirmCard,
|
|
149
188
|
{
|
|
150
189
|
action,
|
|
@@ -156,7 +195,7 @@ function BreadcrumbRow(props) {
|
|
|
156
195
|
}
|
|
157
196
|
);
|
|
158
197
|
}
|
|
159
|
-
return /* @__PURE__ */
|
|
198
|
+
return /* @__PURE__ */ React8__default.createElement(RegularBreadcrumbRow, { ...props });
|
|
160
199
|
}
|
|
161
200
|
function RegularBreadcrumbRow({
|
|
162
201
|
action,
|
|
@@ -164,11 +203,12 @@ function RegularBreadcrumbRow({
|
|
|
164
203
|
textColor,
|
|
165
204
|
fontFamily,
|
|
166
205
|
palette,
|
|
206
|
+
locale,
|
|
167
207
|
needsApproval,
|
|
168
208
|
onApprove,
|
|
169
209
|
onReject
|
|
170
210
|
}) {
|
|
171
|
-
const { label, state } = describeAction(action);
|
|
211
|
+
const { label, state } = describeAction(action, locale);
|
|
172
212
|
const tone = deriveStateTone(palette)[state];
|
|
173
213
|
const fade = useRef(new Animated.Value(0)).current;
|
|
174
214
|
const pulse = useRef(new Animated.Value(1)).current;
|
|
@@ -191,22 +231,22 @@ function RegularBreadcrumbRow({
|
|
|
191
231
|
}).start();
|
|
192
232
|
}, [state, pulse]);
|
|
193
233
|
const isDestructive = isDestructiveAction(action);
|
|
194
|
-
return /* @__PURE__ */
|
|
234
|
+
return /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React8__default.createElement(
|
|
195
235
|
Animated.View,
|
|
196
236
|
{
|
|
197
237
|
style: { opacity: pulse, flexDirection: "row", alignItems: "flex-start", flex: 1 }
|
|
198
238
|
},
|
|
199
|
-
/* @__PURE__ */
|
|
200
|
-
/* @__PURE__ */
|
|
239
|
+
/* @__PURE__ */ React8__default.createElement(StateIcon, { state, tone, primaryColor }),
|
|
240
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
201
241
|
Text,
|
|
202
242
|
{
|
|
203
243
|
style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
|
|
204
244
|
accessibilityLabel: `${state}: ${label}`
|
|
205
245
|
},
|
|
206
246
|
label,
|
|
207
|
-
isDestructive && /* @__PURE__ */
|
|
247
|
+
isDestructive && /* @__PURE__ */ React8__default.createElement(Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
|
|
208
248
|
)
|
|
209
|
-
), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */
|
|
249
|
+
), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React8__default.createElement(View, { style: styles.approvalButtons }, /* @__PURE__ */ React8__default.createElement(
|
|
210
250
|
TouchableOpacity,
|
|
211
251
|
{
|
|
212
252
|
onPress: () => onReject(action.id),
|
|
@@ -215,8 +255,8 @@ function RegularBreadcrumbRow({
|
|
|
215
255
|
accessibilityLabel: "Rejeitar a\xE7\xE3o",
|
|
216
256
|
testID: "assistant-action-reject"
|
|
217
257
|
},
|
|
218
|
-
/* @__PURE__ */
|
|
219
|
-
), /* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
|
|
259
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
220
260
|
TouchableOpacity,
|
|
221
261
|
{
|
|
222
262
|
onPress: () => onApprove(action.id),
|
|
@@ -225,7 +265,7 @@ function RegularBreadcrumbRow({
|
|
|
225
265
|
accessibilityLabel: "Aprovar a\xE7\xE3o",
|
|
226
266
|
testID: "assistant-action-approve"
|
|
227
267
|
},
|
|
228
|
-
/* @__PURE__ */
|
|
268
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles.approveBtnText }, "Aprovar")
|
|
229
269
|
)));
|
|
230
270
|
}
|
|
231
271
|
function ConfirmCard({
|
|
@@ -250,7 +290,7 @@ function ConfirmCard({
|
|
|
250
290
|
cancelBackground,
|
|
251
291
|
cancelTextColor
|
|
252
292
|
} = deriveConfirmCardContent(action, palette, confirmStrings);
|
|
253
|
-
return /* @__PURE__ */
|
|
293
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
254
294
|
View,
|
|
255
295
|
{
|
|
256
296
|
style: [
|
|
@@ -259,7 +299,7 @@ function ConfirmCard({
|
|
|
259
299
|
],
|
|
260
300
|
testID: "assistant-confirm-card"
|
|
261
301
|
},
|
|
262
|
-
/* @__PURE__ */
|
|
302
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.headerRow }, /* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.glyph, { color: actionColor }] }, glyph), /* @__PURE__ */ React8__default.createElement(
|
|
263
303
|
Text,
|
|
264
304
|
{
|
|
265
305
|
style: [
|
|
@@ -269,8 +309,8 @@ function ConfirmCard({
|
|
|
269
309
|
},
|
|
270
310
|
title
|
|
271
311
|
)),
|
|
272
|
-
/* @__PURE__ */
|
|
273
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message),
|
|
313
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React8__default.createElement(
|
|
274
314
|
TouchableOpacity,
|
|
275
315
|
{
|
|
276
316
|
onPress: () => onReject?.(action.id),
|
|
@@ -279,8 +319,8 @@ function ConfirmCard({
|
|
|
279
319
|
accessibilityLabel: cancelLabel,
|
|
280
320
|
testID: "assistant-confirm-reject"
|
|
281
321
|
},
|
|
282
|
-
/* @__PURE__ */
|
|
283
|
-
), /* @__PURE__ */
|
|
322
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
|
|
323
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
284
324
|
TouchableOpacity,
|
|
285
325
|
{
|
|
286
326
|
onPress: () => onApprove?.(action.id),
|
|
@@ -293,7 +333,7 @@ function ConfirmCard({
|
|
|
293
333
|
accessibilityLabel: confirmLabel,
|
|
294
334
|
testID: "assistant-confirm-approve"
|
|
295
335
|
},
|
|
296
|
-
/* @__PURE__ */
|
|
336
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
|
|
297
337
|
))
|
|
298
338
|
);
|
|
299
339
|
}
|
|
@@ -358,7 +398,7 @@ function StateIcon({
|
|
|
358
398
|
tone,
|
|
359
399
|
primaryColor
|
|
360
400
|
}) {
|
|
361
|
-
return /* @__PURE__ */
|
|
401
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: primaryColor }) : /* @__PURE__ */ React8__default.createElement(Text, { style: [styles.iconGlyph, { color: tone.color }] }, iconGlyphFor(state)));
|
|
362
402
|
}
|
|
363
403
|
var styles = StyleSheet.create({
|
|
364
404
|
container: {
|
|
@@ -449,7 +489,7 @@ function resolvePersonalization(props, remote) {
|
|
|
449
489
|
};
|
|
450
490
|
}
|
|
451
491
|
function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
452
|
-
return /* @__PURE__ */
|
|
492
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
453
493
|
Path,
|
|
454
494
|
{
|
|
455
495
|
d: "M5 3.5h14a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-7.4l-4.6 4v-4H5a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3z",
|
|
@@ -457,8 +497,438 @@ function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
|
457
497
|
}
|
|
458
498
|
));
|
|
459
499
|
}
|
|
500
|
+
|
|
501
|
+
// src/components/internalProps.ts
|
|
502
|
+
var APPILOTS_SKIP_PROPS = {
|
|
503
|
+
__appilotsSkip: true,
|
|
504
|
+
__appilotsInternal: true
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// src/components/AgentPill.tsx
|
|
508
|
+
function toneFor(state, colors) {
|
|
509
|
+
switch (state) {
|
|
510
|
+
case "success":
|
|
511
|
+
return colors.success;
|
|
512
|
+
case "failed":
|
|
513
|
+
return colors.error;
|
|
514
|
+
default:
|
|
515
|
+
return colors.primary;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
function AgentPill({
|
|
519
|
+
label,
|
|
520
|
+
state,
|
|
521
|
+
onExpand,
|
|
522
|
+
onStop,
|
|
523
|
+
position,
|
|
524
|
+
insets,
|
|
525
|
+
colors,
|
|
526
|
+
fontFamily,
|
|
527
|
+
strings
|
|
528
|
+
}) {
|
|
529
|
+
const atTop = position === "top-left" || position === "top-right";
|
|
530
|
+
const enter = useRef(new Animated.Value(0)).current;
|
|
531
|
+
useEffect(() => {
|
|
532
|
+
Animated.spring(enter, {
|
|
533
|
+
toValue: 1,
|
|
534
|
+
useNativeDriver: true,
|
|
535
|
+
tension: 70,
|
|
536
|
+
friction: 12
|
|
537
|
+
}).start();
|
|
538
|
+
}, [enter]);
|
|
539
|
+
const translateY = enter.interpolate({
|
|
540
|
+
inputRange: [0, 1],
|
|
541
|
+
outputRange: [atTop ? -80 : 80, 0]
|
|
542
|
+
});
|
|
543
|
+
const running = state === "running" || state === "pending";
|
|
544
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
545
|
+
Animated.View,
|
|
546
|
+
{
|
|
547
|
+
...APPILOTS_SKIP_PROPS,
|
|
548
|
+
pointerEvents: "box-none",
|
|
549
|
+
style: [
|
|
550
|
+
styles2.wrapper,
|
|
551
|
+
atTop ? { top: insets.top + 8 } : { bottom: insets.bottom + 8 },
|
|
552
|
+
{ opacity: enter, transform: [{ translateY }] }
|
|
553
|
+
]
|
|
554
|
+
},
|
|
555
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
556
|
+
TouchableOpacity,
|
|
557
|
+
{
|
|
558
|
+
...APPILOTS_SKIP_PROPS,
|
|
559
|
+
testID: "appilots-agent-pill",
|
|
560
|
+
accessibilityRole: "button",
|
|
561
|
+
accessibilityLabel: strings.expandA11y,
|
|
562
|
+
activeOpacity: 0.85,
|
|
563
|
+
onPress: onExpand,
|
|
564
|
+
style: [styles2.pill, { backgroundColor: colors.surface, borderColor: colors.border }]
|
|
565
|
+
},
|
|
566
|
+
running ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: toneFor(state, colors) }) : /* @__PURE__ */ React8__default.createElement(View, { style: [styles2.dot, { backgroundColor: toneFor(state, colors) }] }),
|
|
567
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
568
|
+
Text,
|
|
569
|
+
{
|
|
570
|
+
testID: "appilots-agent-pill-label",
|
|
571
|
+
numberOfLines: 1,
|
|
572
|
+
style: [styles2.label, { color: colors.text, fontFamily }]
|
|
573
|
+
},
|
|
574
|
+
label
|
|
575
|
+
),
|
|
576
|
+
onStop ? /* @__PURE__ */ React8__default.createElement(
|
|
577
|
+
TouchableOpacity,
|
|
578
|
+
{
|
|
579
|
+
...APPILOTS_SKIP_PROPS,
|
|
580
|
+
testID: "appilots-agent-pill-stop",
|
|
581
|
+
accessibilityRole: "button",
|
|
582
|
+
accessibilityLabel: strings.stopA11y,
|
|
583
|
+
onPress: onStop,
|
|
584
|
+
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 },
|
|
585
|
+
style: [styles2.stop, { borderColor: colors.border }]
|
|
586
|
+
},
|
|
587
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: [styles2.stopGlyph, { backgroundColor: colors.textSecondary }] })
|
|
588
|
+
) : null
|
|
589
|
+
)
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
var styles2 = StyleSheet.create({
|
|
593
|
+
// `box-none` above + `position: absolute` here is what lets touches
|
|
594
|
+
// outside the pill itself reach the app underneath.
|
|
595
|
+
wrapper: {
|
|
596
|
+
position: "absolute",
|
|
597
|
+
left: 12,
|
|
598
|
+
right: 12,
|
|
599
|
+
zIndex: 999,
|
|
600
|
+
alignItems: "center"
|
|
601
|
+
},
|
|
602
|
+
pill: {
|
|
603
|
+
flexDirection: "row",
|
|
604
|
+
alignItems: "center",
|
|
605
|
+
gap: 10,
|
|
606
|
+
maxWidth: "100%",
|
|
607
|
+
paddingLeft: 14,
|
|
608
|
+
paddingRight: 8,
|
|
609
|
+
paddingVertical: 10,
|
|
610
|
+
borderRadius: 24,
|
|
611
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
612
|
+
shadowColor: "#000",
|
|
613
|
+
shadowOffset: { width: 0, height: 2 },
|
|
614
|
+
shadowOpacity: 0.18,
|
|
615
|
+
shadowRadius: 8,
|
|
616
|
+
elevation: 8
|
|
617
|
+
},
|
|
618
|
+
dot: { width: 8, height: 8, borderRadius: 4 },
|
|
619
|
+
label: { flexShrink: 1, fontSize: 14, fontWeight: "500" },
|
|
620
|
+
stop: {
|
|
621
|
+
width: 26,
|
|
622
|
+
height: 26,
|
|
623
|
+
borderRadius: 13,
|
|
624
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
625
|
+
alignItems: "center",
|
|
626
|
+
justifyContent: "center"
|
|
627
|
+
},
|
|
628
|
+
stopGlyph: { width: 9, height: 9, borderRadius: 1.5 }
|
|
629
|
+
});
|
|
630
|
+
var PADDING = 6;
|
|
631
|
+
var CAPTION_HEIGHT = 28;
|
|
632
|
+
var CAPTION_GAP = 8;
|
|
633
|
+
function SpotlightOverlay({
|
|
634
|
+
rect,
|
|
635
|
+
seq,
|
|
636
|
+
label,
|
|
637
|
+
color,
|
|
638
|
+
captionBackground,
|
|
639
|
+
captionColor,
|
|
640
|
+
fontFamily,
|
|
641
|
+
window: win
|
|
642
|
+
}) {
|
|
643
|
+
const pulse = useRef(new Animated.Value(0)).current;
|
|
644
|
+
useEffect(() => {
|
|
645
|
+
pulse.setValue(0);
|
|
646
|
+
Animated.timing(pulse, {
|
|
647
|
+
toValue: 1,
|
|
648
|
+
duration: 220,
|
|
649
|
+
useNativeDriver: true
|
|
650
|
+
}).start();
|
|
651
|
+
}, [seq, pulse]);
|
|
652
|
+
if (!isRectOnScreen(rect, win)) return null;
|
|
653
|
+
const frame = {
|
|
654
|
+
left: rect.x - PADDING,
|
|
655
|
+
top: rect.y - PADDING,
|
|
656
|
+
width: rect.width + PADDING * 2,
|
|
657
|
+
height: rect.height + PADDING * 2
|
|
658
|
+
};
|
|
659
|
+
const above = frame.top - CAPTION_GAP - CAPTION_HEIGHT >= 0;
|
|
660
|
+
const captionTop = above ? frame.top - CAPTION_GAP - CAPTION_HEIGHT : frame.top + frame.height + CAPTION_GAP;
|
|
661
|
+
const captionFits = captionTop + CAPTION_HEIGHT <= win.height;
|
|
662
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
663
|
+
View,
|
|
664
|
+
{
|
|
665
|
+
...APPILOTS_SKIP_PROPS,
|
|
666
|
+
pointerEvents: "none",
|
|
667
|
+
style: StyleSheet.absoluteFill,
|
|
668
|
+
testID: "appilots-spotlight"
|
|
669
|
+
},
|
|
670
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
671
|
+
Animated.View,
|
|
672
|
+
{
|
|
673
|
+
...APPILOTS_SKIP_PROPS,
|
|
674
|
+
pointerEvents: "none",
|
|
675
|
+
style: [
|
|
676
|
+
styles3.ring,
|
|
677
|
+
frame,
|
|
678
|
+
{ borderColor: color },
|
|
679
|
+
{
|
|
680
|
+
opacity: pulse,
|
|
681
|
+
// Settles inward: the ring arrives slightly large and snaps
|
|
682
|
+
// to the control, which reads as "this one" rather than as a
|
|
683
|
+
// box that was always there.
|
|
684
|
+
transform: [
|
|
685
|
+
{
|
|
686
|
+
scale: pulse.interpolate({ inputRange: [0, 1], outputRange: [1.08, 1] })
|
|
687
|
+
}
|
|
688
|
+
]
|
|
689
|
+
}
|
|
690
|
+
]
|
|
691
|
+
}
|
|
692
|
+
),
|
|
693
|
+
label && captionFits ? /* @__PURE__ */ React8__default.createElement(
|
|
694
|
+
Animated.View,
|
|
695
|
+
{
|
|
696
|
+
...APPILOTS_SKIP_PROPS,
|
|
697
|
+
pointerEvents: "none",
|
|
698
|
+
style: [
|
|
699
|
+
styles3.caption,
|
|
700
|
+
{
|
|
701
|
+
top: captionTop,
|
|
702
|
+
// Clamped so a control at either edge does not push the
|
|
703
|
+
// caption off screen.
|
|
704
|
+
left: Math.max(8, Math.min(frame.left, win.width - 8)),
|
|
705
|
+
maxWidth: win.width - 16,
|
|
706
|
+
backgroundColor: captionBackground,
|
|
707
|
+
opacity: pulse
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
},
|
|
711
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
712
|
+
Text,
|
|
713
|
+
{
|
|
714
|
+
testID: "appilots-spotlight-label",
|
|
715
|
+
numberOfLines: 1,
|
|
716
|
+
style: [styles3.captionText, { color: captionColor, fontFamily }]
|
|
717
|
+
},
|
|
718
|
+
label
|
|
719
|
+
)
|
|
720
|
+
) : null
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
var styles3 = StyleSheet.create({
|
|
724
|
+
ring: {
|
|
725
|
+
position: "absolute",
|
|
726
|
+
borderWidth: 2.5,
|
|
727
|
+
borderRadius: 10
|
|
728
|
+
},
|
|
729
|
+
caption: {
|
|
730
|
+
position: "absolute",
|
|
731
|
+
height: CAPTION_HEIGHT,
|
|
732
|
+
justifyContent: "center",
|
|
733
|
+
paddingHorizontal: 10,
|
|
734
|
+
borderRadius: 8
|
|
735
|
+
},
|
|
736
|
+
captionText: { fontSize: 13, fontWeight: "500" }
|
|
737
|
+
});
|
|
738
|
+
var NEVER = () => () => {
|
|
739
|
+
};
|
|
740
|
+
var NULL_TARGET = () => null;
|
|
741
|
+
function useSpotlight(enabled) {
|
|
742
|
+
const subscribe = useCallback(
|
|
743
|
+
(onChange) => enabled ? subscribeSpotlight(onChange) : NEVER(),
|
|
744
|
+
[enabled]
|
|
745
|
+
);
|
|
746
|
+
return useSyncExternalStore(subscribe, enabled ? getSpotlightTarget : NULL_TARGET, NULL_TARGET);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/components/pillStatus.ts
|
|
750
|
+
function resolvePillStatus(actions, busy, strings) {
|
|
751
|
+
for (let i = actions.length - 1; i >= 0; i--) {
|
|
752
|
+
const action = actions[i];
|
|
753
|
+
if (action.status === "executing") return describeAction(action, strings.locale);
|
|
754
|
+
}
|
|
755
|
+
if (!busy) {
|
|
756
|
+
for (let i = actions.length - 1; i >= 0; i--) {
|
|
757
|
+
const action = actions[i];
|
|
758
|
+
if (action.status === "completed" || action.status === "failed") {
|
|
759
|
+
return describeAction(action, strings.locale);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return { label: strings.done, state: "success" };
|
|
763
|
+
}
|
|
764
|
+
return { label: strings.working, state: "running" };
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// src/components/speech.ts
|
|
768
|
+
function isSpeechHost(value) {
|
|
769
|
+
if (!value || typeof value !== "object") return false;
|
|
770
|
+
const candidate = value;
|
|
771
|
+
return typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.cancel === "function";
|
|
772
|
+
}
|
|
773
|
+
function useVoiceInput({
|
|
774
|
+
host,
|
|
775
|
+
locale,
|
|
776
|
+
onTranscript
|
|
777
|
+
}) {
|
|
778
|
+
const [state, setState] = useState("idle");
|
|
779
|
+
const [partial, setPartial] = useState("");
|
|
780
|
+
const mounted = useRef(true);
|
|
781
|
+
useEffect(() => {
|
|
782
|
+
mounted.current = true;
|
|
783
|
+
return () => {
|
|
784
|
+
mounted.current = false;
|
|
785
|
+
};
|
|
786
|
+
}, []);
|
|
787
|
+
const onTranscriptRef = useRef(onTranscript);
|
|
788
|
+
onTranscriptRef.current = onTranscript;
|
|
789
|
+
const stateRef = useRef("idle");
|
|
790
|
+
stateRef.current = state;
|
|
791
|
+
useEffect(() => {
|
|
792
|
+
return () => {
|
|
793
|
+
if (stateRef.current === "listening" || stateRef.current === "starting") {
|
|
794
|
+
void host?.cancel().catch(() => {
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
}, [host]);
|
|
799
|
+
const start = useCallback(() => {
|
|
800
|
+
if (!host) return;
|
|
801
|
+
if (state !== "idle" && state !== "error") return;
|
|
802
|
+
setState("starting");
|
|
803
|
+
setPartial("");
|
|
804
|
+
host.start({ locale }).then(() => {
|
|
805
|
+
if (!mounted.current) return;
|
|
806
|
+
setState("listening");
|
|
807
|
+
}).catch((err) => {
|
|
808
|
+
appilotsDebugWarn("useVoiceInput: start failed", err);
|
|
809
|
+
if (!mounted.current) return;
|
|
810
|
+
setState("error");
|
|
811
|
+
});
|
|
812
|
+
}, [host, locale, state]);
|
|
813
|
+
const stop = useCallback(() => {
|
|
814
|
+
if (!host) return;
|
|
815
|
+
if (state !== "listening" && state !== "starting") return;
|
|
816
|
+
setState("stopping");
|
|
817
|
+
host.stop().then((text) => {
|
|
818
|
+
if (!mounted.current) return;
|
|
819
|
+
setState("idle");
|
|
820
|
+
setPartial("");
|
|
821
|
+
const trimmed = text?.trim();
|
|
822
|
+
if (trimmed) onTranscriptRef.current(trimmed);
|
|
823
|
+
}).catch((err) => {
|
|
824
|
+
appilotsDebugWarn("useVoiceInput: stop failed", err);
|
|
825
|
+
if (!mounted.current) return;
|
|
826
|
+
setState("error");
|
|
827
|
+
setPartial("");
|
|
828
|
+
});
|
|
829
|
+
}, [host, state]);
|
|
830
|
+
const cancel = useCallback(() => {
|
|
831
|
+
if (!host) return;
|
|
832
|
+
setPartial("");
|
|
833
|
+
setState("idle");
|
|
834
|
+
void host.cancel().catch((err) => appilotsDebugWarn("useVoiceInput: cancel failed", err));
|
|
835
|
+
}, [host]);
|
|
836
|
+
useEffect(() => {
|
|
837
|
+
if (!host?.onPartial) return;
|
|
838
|
+
if (state !== "listening") return;
|
|
839
|
+
const dispose = host.onPartial((text) => {
|
|
840
|
+
if (mounted.current) setPartial(text);
|
|
841
|
+
});
|
|
842
|
+
return dispose;
|
|
843
|
+
}, [host, state]);
|
|
844
|
+
return { state, partial, start, stop, cancel };
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// src/components/experience.ts
|
|
848
|
+
var DEFAULT_EXPERIENCE = {
|
|
849
|
+
presence: "sheet",
|
|
850
|
+
spotlight: "off",
|
|
851
|
+
control: "agent",
|
|
852
|
+
entry: ["fab"],
|
|
853
|
+
input: ["text"]
|
|
854
|
+
};
|
|
855
|
+
function uniq(values) {
|
|
856
|
+
return values.filter((value, index) => values.indexOf(value) === index);
|
|
857
|
+
}
|
|
858
|
+
function resolveExperience(requested, caps) {
|
|
859
|
+
const downgrades = [];
|
|
860
|
+
let presence = requested?.presence ?? DEFAULT_EXPERIENCE.presence;
|
|
861
|
+
let spotlight = requested?.spotlight ?? DEFAULT_EXPERIENCE.spotlight;
|
|
862
|
+
const control = requested?.control ?? DEFAULT_EXPERIENCE.control;
|
|
863
|
+
const entry = uniq(requested?.entry ?? DEFAULT_EXPERIENCE.entry);
|
|
864
|
+
let input = uniq(requested?.input ?? DEFAULT_EXPERIENCE.input);
|
|
865
|
+
if (spotlight !== "off" && !caps.geometry) {
|
|
866
|
+
downgrades.push({
|
|
867
|
+
field: "spotlight",
|
|
868
|
+
from: spotlight,
|
|
869
|
+
to: "off",
|
|
870
|
+
reason: 'spotlight needs Fabric window geometry, which this app cannot report. Enable the new React Native architecture, or set spotlight:"off" to silence this.'
|
|
871
|
+
});
|
|
872
|
+
spotlight = "off";
|
|
873
|
+
}
|
|
874
|
+
if (spotlight !== "off" && presence === "sheet") {
|
|
875
|
+
downgrades.push({
|
|
876
|
+
field: "presence",
|
|
877
|
+
from: "sheet",
|
|
878
|
+
to: "pill",
|
|
879
|
+
reason: 'spotlight draws on the app, which the sheet covers. Set presence:"pill" or "hidden" explicitly to silence this.'
|
|
880
|
+
});
|
|
881
|
+
presence = "pill";
|
|
882
|
+
}
|
|
883
|
+
if (control === "shared" && presence === "sheet") {
|
|
884
|
+
downgrades.push({
|
|
885
|
+
field: "presence",
|
|
886
|
+
from: "sheet",
|
|
887
|
+
to: "pill",
|
|
888
|
+
reason: 'control:"shared" needs the app to be touchable, and the sheet is a native Modal that swallows every touch. Set presence:"pill" or "hidden" to silence this.'
|
|
889
|
+
});
|
|
890
|
+
presence = "pill";
|
|
891
|
+
}
|
|
892
|
+
if (input.includes("voice") && !caps.speech) {
|
|
893
|
+
downgrades.push({
|
|
894
|
+
field: "input",
|
|
895
|
+
from: input.join("+"),
|
|
896
|
+
to: input.filter((mode) => mode !== "voice").join("+") || "text",
|
|
897
|
+
reason: 'input:"voice" needs a SpeechHost passed to <AppilotsChat speech={...} />. The SDK ships no speech engine of its own \u2014 see docs/experience.md.'
|
|
898
|
+
});
|
|
899
|
+
input = input.filter((mode) => mode !== "voice");
|
|
900
|
+
}
|
|
901
|
+
if (input.length === 0) input = ["text"];
|
|
902
|
+
return {
|
|
903
|
+
experience: { presence, spotlight, control, entry, input },
|
|
904
|
+
downgrades
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
function formatDowngrades(downgrades) {
|
|
908
|
+
return downgrades.map(
|
|
909
|
+
(d) => `[appilots] experience.${d.field}: "${d.from}" -> "${d.to}". ${d.reason}`
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
// src/components/presence.ts
|
|
914
|
+
function resolveSurface(presence, activity) {
|
|
915
|
+
if (presence === "sheet") return activity.open ? "sheet" : "none";
|
|
916
|
+
if (activity.awaitingUser) return "sheet";
|
|
917
|
+
if (activity.busy && (activity.acting || !activity.open)) return "pill";
|
|
918
|
+
if (activity.hostModalOpen && !activity.explicitlyOpened && (activity.open || activity.unread))
|
|
919
|
+
return "pill";
|
|
920
|
+
if (activity.open) return "sheet";
|
|
921
|
+
if (activity.unread) return "pill";
|
|
922
|
+
return "none";
|
|
923
|
+
}
|
|
924
|
+
function shouldReopenOnTurnEnd(presence) {
|
|
925
|
+
return presence === "pill";
|
|
926
|
+
}
|
|
927
|
+
function usesPill(presence) {
|
|
928
|
+
return presence !== "sheet";
|
|
929
|
+
}
|
|
460
930
|
function HeadsetIcon({ size = 18, color = "#ffffff" }) {
|
|
461
|
-
return /* @__PURE__ */
|
|
931
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
462
932
|
Path,
|
|
463
933
|
{
|
|
464
934
|
d: "M12 3a8 8 0 0 0-8 8v5.5A2.5 2.5 0 0 0 6.5 19H8a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H6v-1a6 6 0 0 1 12 0v1h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h1.5a2.5 2.5 0 0 0 2.5-2.5V11a8 8 0 0 0-8-8z",
|
|
@@ -499,195 +969,6 @@ function buildChatTimeline(messages, actions) {
|
|
|
499
969
|
}
|
|
500
970
|
return timeline;
|
|
501
971
|
}
|
|
502
|
-
|
|
503
|
-
// src/components/markdownContent.ts
|
|
504
|
-
var ORDERED_LINE = /^\s*(\d+)\.\s+(.+)$/;
|
|
505
|
-
var BULLET_LINE = /^\s*[-*•]\s+(.+)$/;
|
|
506
|
-
var HEADING_LINE = /^\s*(#{1,6})\s+(.+)$/;
|
|
507
|
-
var FENCE_LINE = /^\s*```\s*([A-Za-z0-9+#_-]*)\s*$/;
|
|
508
|
-
var INLINE_PATTERN = /\[([^\]\n]+)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|__(.+?)__|`([^`]+)`|\*(.+?)\*|_(.+?)_/g;
|
|
509
|
-
var MIN_ENHANCE_LENGTH = 80;
|
|
510
|
-
var SENTENCE_SPLIT = /[^.!?]+[.!?]+(?=\s+[A-ZÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕÇÑ¿¡"“]|$)|[^.!?]+$/g;
|
|
511
|
-
var CAPABILITY_SENTENCE = /^((?:No aplicativo,?|In (?:this|the) app,?|En la aplicaci[oó]n,?|Dans l['’]application,?)?(?:\s+(?:voc[eê]|voce|you|tu|usted|puedes|puede|peux))?\s*(?:pode(?:m|r)?|can|could|puedes|puede|peux|peut))\s+(.+?)\.?\s*$/i;
|
|
512
|
-
var INCLUDE_LIST_SENTENCE = /^(.+?)\s+(?:incluem|inclui|include|includes|incluye|incluyen|such as|for example|par exemple|por exemplo)\s+(.+?)\.?\s*$/i;
|
|
513
|
-
function looksLikeMarkdown(content) {
|
|
514
|
-
if (!content) return false;
|
|
515
|
-
return /\*\*.+?\*\*/.test(content) || /__.+?__/.test(content) || /`[^`\n]+`/.test(content) || /^\s*[-*•]\s+/m.test(content) || /^\s*\d+\.\s+/m.test(content) || /^\s*#{1,6}\s+/m.test(content) || /^\s*```/m.test(content) || /\[[^\]\n]+\]\(https?:\/\/[^\s)]+\)/.test(content);
|
|
516
|
-
}
|
|
517
|
-
function splitEnumeration(text) {
|
|
518
|
-
const trimmed = text.trim().replace(/\.\s*$/, "");
|
|
519
|
-
if (!trimmed) return [];
|
|
520
|
-
const commaParts = trimmed.split(",").map((part) => part.trim()).filter(Boolean);
|
|
521
|
-
if (commaParts.length <= 1) {
|
|
522
|
-
const conjParts = trimmed.split(/\s+(?:e|and|y|ou|or)\s+/i).map((part) => part.trim());
|
|
523
|
-
return conjParts.filter(Boolean);
|
|
524
|
-
}
|
|
525
|
-
const last = commaParts[commaParts.length - 1];
|
|
526
|
-
const conjMatch = last.match(/^(.+?)\s+(?:e|and|y|ou|or)\s+(.+)$/i);
|
|
527
|
-
if (conjMatch) {
|
|
528
|
-
commaParts[commaParts.length - 1] = conjMatch[1].trim();
|
|
529
|
-
commaParts.push(conjMatch[2].trim());
|
|
530
|
-
}
|
|
531
|
-
return commaParts.filter(Boolean);
|
|
532
|
-
}
|
|
533
|
-
function splitSentences(text) {
|
|
534
|
-
const matches = text.match(SENTENCE_SPLIT);
|
|
535
|
-
if (!matches) return [text.trim()];
|
|
536
|
-
return matches.map((part) => part.trim()).filter(Boolean);
|
|
537
|
-
}
|
|
538
|
-
function formatCapabilitySentence(sentence) {
|
|
539
|
-
const match = CAPABILITY_SENTENCE.exec(sentence.trim());
|
|
540
|
-
if (!match) return null;
|
|
541
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
542
|
-
if (items.length < 3) return null;
|
|
543
|
-
const intro = `${match[1].trim()}:`;
|
|
544
|
-
return `${intro}
|
|
545
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
546
|
-
}
|
|
547
|
-
function formatIncludeListSentence(sentence) {
|
|
548
|
-
const match = INCLUDE_LIST_SENTENCE.exec(sentence.trim());
|
|
549
|
-
if (!match) return null;
|
|
550
|
-
const intro = match[1].trim().replace(/[,:]\s*$/, "");
|
|
551
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
552
|
-
if (items.length < 2) return null;
|
|
553
|
-
return `${intro}:
|
|
554
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
555
|
-
}
|
|
556
|
-
function formatReadableSentence(sentence) {
|
|
557
|
-
return formatCapabilitySentence(sentence) ?? formatIncludeListSentence(sentence) ?? sentence.trim();
|
|
558
|
-
}
|
|
559
|
-
function enhancePlainAssistantContent(content) {
|
|
560
|
-
if (!content?.trim() || looksLikeMarkdown(content)) return content;
|
|
561
|
-
const trimmed = content.trim();
|
|
562
|
-
if (trimmed.length < MIN_ENHANCE_LENGTH) return content;
|
|
563
|
-
const sentences = splitSentences(trimmed);
|
|
564
|
-
if (sentences.length === 0) return content;
|
|
565
|
-
const blocks = sentences.map(formatReadableSentence);
|
|
566
|
-
const enhanced = blocks.join("\n\n");
|
|
567
|
-
return enhanced || content;
|
|
568
|
-
}
|
|
569
|
-
function needsWideChatLayout(content) {
|
|
570
|
-
if (!content?.trim()) return false;
|
|
571
|
-
const prepared = enhancePlainAssistantContent(content);
|
|
572
|
-
return looksLikeMarkdown(prepared) || /\n\n+/.test(prepared);
|
|
573
|
-
}
|
|
574
|
-
function parseMarkdownBlocks(content) {
|
|
575
|
-
const lines = content.replace(/\r\n/g, "\n").split("\n");
|
|
576
|
-
const blocks = [];
|
|
577
|
-
let paragraph = [];
|
|
578
|
-
let bulletItems = [];
|
|
579
|
-
let orderedItems = [];
|
|
580
|
-
let codeLines = null;
|
|
581
|
-
let codeLanguage;
|
|
582
|
-
const flushParagraph = () => {
|
|
583
|
-
if (paragraph.length === 0) return;
|
|
584
|
-
blocks.push({ kind: "paragraph", text: paragraph.join("\n") });
|
|
585
|
-
paragraph = [];
|
|
586
|
-
};
|
|
587
|
-
const flushBullets = () => {
|
|
588
|
-
if (bulletItems.length === 0) return;
|
|
589
|
-
blocks.push({ kind: "bullet", items: bulletItems });
|
|
590
|
-
bulletItems = [];
|
|
591
|
-
};
|
|
592
|
-
const flushOrdered = () => {
|
|
593
|
-
if (orderedItems.length === 0) return;
|
|
594
|
-
blocks.push({ kind: "ordered", items: orderedItems });
|
|
595
|
-
orderedItems = [];
|
|
596
|
-
};
|
|
597
|
-
const flushLists = () => {
|
|
598
|
-
flushBullets();
|
|
599
|
-
flushOrdered();
|
|
600
|
-
};
|
|
601
|
-
const flushCode = () => {
|
|
602
|
-
if (codeLines === null) return;
|
|
603
|
-
blocks.push({
|
|
604
|
-
kind: "codeblock",
|
|
605
|
-
code: codeLines.join("\n"),
|
|
606
|
-
...codeLanguage ? { language: codeLanguage } : {}
|
|
607
|
-
});
|
|
608
|
-
codeLines = null;
|
|
609
|
-
codeLanguage = void 0;
|
|
610
|
-
};
|
|
611
|
-
for (const line of lines) {
|
|
612
|
-
if (codeLines !== null) {
|
|
613
|
-
if (/^\s*```\s*$/.test(line)) {
|
|
614
|
-
flushCode();
|
|
615
|
-
} else {
|
|
616
|
-
codeLines.push(line);
|
|
617
|
-
}
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
|
-
const fence = FENCE_LINE.exec(line);
|
|
621
|
-
if (fence) {
|
|
622
|
-
flushParagraph();
|
|
623
|
-
flushLists();
|
|
624
|
-
codeLines = [];
|
|
625
|
-
codeLanguage = fence[1] || void 0;
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
const trimmed = line.trim();
|
|
629
|
-
if (!trimmed) {
|
|
630
|
-
flushParagraph();
|
|
631
|
-
flushLists();
|
|
632
|
-
continue;
|
|
633
|
-
}
|
|
634
|
-
const heading = HEADING_LINE.exec(line);
|
|
635
|
-
if (heading) {
|
|
636
|
-
flushParagraph();
|
|
637
|
-
flushLists();
|
|
638
|
-
const level = Math.min(heading[1].length, 3);
|
|
639
|
-
blocks.push({ kind: "heading", level, text: heading[2].trim() });
|
|
640
|
-
continue;
|
|
641
|
-
}
|
|
642
|
-
const ordered = ORDERED_LINE.exec(line);
|
|
643
|
-
if (ordered) {
|
|
644
|
-
flushParagraph();
|
|
645
|
-
flushBullets();
|
|
646
|
-
orderedItems.push(ordered[2].trim());
|
|
647
|
-
continue;
|
|
648
|
-
}
|
|
649
|
-
const bullet = BULLET_LINE.exec(line);
|
|
650
|
-
if (bullet) {
|
|
651
|
-
flushParagraph();
|
|
652
|
-
flushOrdered();
|
|
653
|
-
bulletItems.push(bullet[1].trim());
|
|
654
|
-
continue;
|
|
655
|
-
}
|
|
656
|
-
flushLists();
|
|
657
|
-
paragraph.push(line);
|
|
658
|
-
}
|
|
659
|
-
flushParagraph();
|
|
660
|
-
flushLists();
|
|
661
|
-
flushCode();
|
|
662
|
-
return blocks.length > 0 ? blocks : [{ kind: "paragraph", text: content }];
|
|
663
|
-
}
|
|
664
|
-
function parseInlineMarkdown(text) {
|
|
665
|
-
if (!text) return [{ kind: "text", value: "" }];
|
|
666
|
-
const segments = [];
|
|
667
|
-
let lastIndex = 0;
|
|
668
|
-
INLINE_PATTERN.lastIndex = 0;
|
|
669
|
-
for (let match = INLINE_PATTERN.exec(text); match; match = INLINE_PATTERN.exec(text)) {
|
|
670
|
-
if (match.index > lastIndex) {
|
|
671
|
-
segments.push({ kind: "text", value: text.slice(lastIndex, match.index) });
|
|
672
|
-
}
|
|
673
|
-
if (match[1] && match[2]) {
|
|
674
|
-
segments.push({ kind: "link", value: match[1].trim(), href: match[2] });
|
|
675
|
-
} else if (match[3] || match[4]) {
|
|
676
|
-
segments.push({ kind: "bold", value: (match[3] ?? match[4]).trim() });
|
|
677
|
-
} else if (match[5]) {
|
|
678
|
-
segments.push({ kind: "code", value: match[5] });
|
|
679
|
-
} else if (match[6] || match[7]) {
|
|
680
|
-
segments.push({ kind: "italic", value: (match[6] ?? match[7]).trim() });
|
|
681
|
-
}
|
|
682
|
-
lastIndex = INLINE_PATTERN.lastIndex;
|
|
683
|
-
}
|
|
684
|
-
if (lastIndex < text.length) {
|
|
685
|
-
segments.push({ kind: "text", value: text.slice(lastIndex) });
|
|
686
|
-
}
|
|
687
|
-
return segments.length > 0 ? segments : [{ kind: "text", value: text }];
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// src/components/ChatMarkdown.tsx
|
|
691
972
|
function segmentKey(segment, index) {
|
|
692
973
|
return `${segment.kind}-${index}-${segment.value.slice(0, 12)}`;
|
|
693
974
|
}
|
|
@@ -697,17 +978,17 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
697
978
|
const key = segmentKey(segment, index);
|
|
698
979
|
switch (segment.kind) {
|
|
699
980
|
case "bold":
|
|
700
|
-
return /* @__PURE__ */
|
|
981
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.bold] }, segment.value);
|
|
701
982
|
case "italic":
|
|
702
|
-
return /* @__PURE__ */
|
|
983
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.italic] }, segment.value);
|
|
703
984
|
case "code":
|
|
704
|
-
return /* @__PURE__ */
|
|
985
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
705
986
|
Text,
|
|
706
987
|
{
|
|
707
988
|
key,
|
|
708
989
|
style: [
|
|
709
990
|
baseStyle,
|
|
710
|
-
|
|
991
|
+
styles4.code,
|
|
711
992
|
{
|
|
712
993
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.06)"),
|
|
713
994
|
color: theme.codeColor ?? theme.color
|
|
@@ -717,14 +998,14 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
717
998
|
segment.value
|
|
718
999
|
);
|
|
719
1000
|
case "link":
|
|
720
|
-
return /* @__PURE__ */
|
|
1001
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
721
1002
|
Text,
|
|
722
1003
|
{
|
|
723
1004
|
key,
|
|
724
1005
|
accessibilityRole: "link",
|
|
725
1006
|
style: [
|
|
726
1007
|
baseStyle,
|
|
727
|
-
|
|
1008
|
+
styles4.link,
|
|
728
1009
|
{
|
|
729
1010
|
color: theme.linkColor ?? (theme.variant === "user" ? theme.color : "#2563EB")
|
|
730
1011
|
}
|
|
@@ -751,7 +1032,7 @@ function InlineMarkdown({
|
|
|
751
1032
|
fontSize: theme.fontSize,
|
|
752
1033
|
lineHeight: theme.lineHeight
|
|
753
1034
|
};
|
|
754
|
-
return /* @__PURE__ */
|
|
1035
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseStyle }, renderInlineSegments(text, theme, baseStyle));
|
|
755
1036
|
}
|
|
756
1037
|
function ChatMarkdown({ content, theme, contentWidth }) {
|
|
757
1038
|
const prepared = enhancePlainAssistantContent(content);
|
|
@@ -761,29 +1042,29 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
761
1042
|
fontSize: theme.fontSize,
|
|
762
1043
|
lineHeight: theme.lineHeight
|
|
763
1044
|
};
|
|
764
|
-
const rootStyle = contentWidth ? [
|
|
1045
|
+
const rootStyle = contentWidth ? [styles4.root, { width: contentWidth }] : styles4.root;
|
|
765
1046
|
if (!looksLikeMarkdown(prepared)) {
|
|
766
1047
|
const paragraphs = prepared.split(/\n\n+/).map((part) => part.trim()).filter(Boolean);
|
|
767
1048
|
if (paragraphs.length > 1) {
|
|
768
|
-
return /* @__PURE__ */
|
|
1049
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: rootStyle }, paragraphs.map((paragraph, index) => /* @__PURE__ */ React8__default.createElement(View, { key: `plain-p-${index}`, style: index > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(Text, { style: baseTextStyle }, paragraph))));
|
|
769
1050
|
}
|
|
770
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseTextStyle }, prepared);
|
|
771
1052
|
}
|
|
772
1053
|
const blocks = parseMarkdownBlocks(prepared);
|
|
773
|
-
return /* @__PURE__ */
|
|
1054
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: rootStyle }, blocks.map((block, blockIndex) => {
|
|
774
1055
|
if (block.kind === "paragraph") {
|
|
775
|
-
return /* @__PURE__ */
|
|
1056
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `p-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(InlineMarkdown, { text: block.text, theme }));
|
|
776
1057
|
}
|
|
777
1058
|
if (block.kind === "heading") {
|
|
778
1059
|
const scale = block.level === 1 ? 1.25 : block.level === 2 ? 1.15 : 1.05;
|
|
779
1060
|
const headingSize = Math.round((theme.fontSize ?? 15) * scale);
|
|
780
|
-
return /* @__PURE__ */
|
|
1061
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `h-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(
|
|
781
1062
|
Text,
|
|
782
1063
|
{
|
|
783
1064
|
accessibilityRole: "header",
|
|
784
1065
|
style: [
|
|
785
1066
|
baseTextStyle,
|
|
786
|
-
|
|
1067
|
+
styles4.bold,
|
|
787
1068
|
{ fontSize: headingSize, lineHeight: Math.round(headingSize * 1.35) }
|
|
788
1069
|
]
|
|
789
1070
|
},
|
|
@@ -795,23 +1076,23 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
795
1076
|
));
|
|
796
1077
|
}
|
|
797
1078
|
if (block.kind === "codeblock") {
|
|
798
|
-
return /* @__PURE__ */
|
|
1079
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
799
1080
|
View,
|
|
800
1081
|
{
|
|
801
1082
|
key: `code-${blockIndex}`,
|
|
802
1083
|
style: [
|
|
803
|
-
|
|
804
|
-
blockIndex > 0 ?
|
|
1084
|
+
styles4.codeBlock,
|
|
1085
|
+
blockIndex > 0 ? styles4.blockGap : void 0,
|
|
805
1086
|
{
|
|
806
1087
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.055)")
|
|
807
1088
|
}
|
|
808
1089
|
]
|
|
809
1090
|
},
|
|
810
|
-
/* @__PURE__ */
|
|
1091
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
811
1092
|
Text,
|
|
812
1093
|
{
|
|
813
1094
|
style: [
|
|
814
|
-
|
|
1095
|
+
styles4.code,
|
|
815
1096
|
{
|
|
816
1097
|
color: theme.codeColor ?? theme.color,
|
|
817
1098
|
fontSize: (theme.fontSize ?? 15) - 1,
|
|
@@ -824,28 +1105,28 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
824
1105
|
);
|
|
825
1106
|
}
|
|
826
1107
|
if (block.kind === "bullet") {
|
|
827
|
-
return /* @__PURE__ */
|
|
1108
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `ul-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__default.createElement(
|
|
828
1109
|
Text,
|
|
829
1110
|
{
|
|
830
1111
|
key: `ul-${blockIndex}-${itemIndex}`,
|
|
831
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1112
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
832
1113
|
},
|
|
833
1114
|
"\u2022 ",
|
|
834
1115
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
835
1116
|
)));
|
|
836
1117
|
}
|
|
837
|
-
return /* @__PURE__ */
|
|
1118
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `ol-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__default.createElement(
|
|
838
1119
|
Text,
|
|
839
1120
|
{
|
|
840
1121
|
key: `ol-${blockIndex}-${itemIndex}`,
|
|
841
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1122
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
842
1123
|
},
|
|
843
1124
|
`${itemIndex + 1}. `,
|
|
844
1125
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
845
1126
|
)));
|
|
846
1127
|
}));
|
|
847
1128
|
}
|
|
848
|
-
var
|
|
1129
|
+
var styles4 = StyleSheet.create({
|
|
849
1130
|
root: {
|
|
850
1131
|
flexShrink: 1,
|
|
851
1132
|
alignSelf: "stretch"
|
|
@@ -889,7 +1170,7 @@ function AppilotsThemeProvider({
|
|
|
889
1170
|
() => mergeThemeTokens(resolveBaseTheme(mode, systemScheme), theme ?? void 0),
|
|
890
1171
|
[mode, systemScheme, theme]
|
|
891
1172
|
);
|
|
892
|
-
return /* @__PURE__ */
|
|
1173
|
+
return /* @__PURE__ */ React8__default.createElement(ThemeContext.Provider, { value: tokens }, children);
|
|
893
1174
|
}
|
|
894
1175
|
function useAppilotsTheme() {
|
|
895
1176
|
return useContext(ThemeContext);
|
|
@@ -982,177 +1263,6 @@ var appilotsTheme = {
|
|
|
982
1263
|
fromTailwind: appilotsThemeFromTailwind
|
|
983
1264
|
};
|
|
984
1265
|
|
|
985
|
-
// src/i18n/bundles/pt-BR.ts
|
|
986
|
-
var ptBR = {
|
|
987
|
-
chatTitle: "Assistente Appilots",
|
|
988
|
-
clearButton: "Limpar",
|
|
989
|
-
inputPlaceholder: "Digite uma mensagem...",
|
|
990
|
-
emptyTitle: "Como posso ajudar?",
|
|
991
|
-
emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
|
|
992
|
-
thinking: "Pensando...",
|
|
993
|
-
statusAnalyzing: "Analisando a tela...",
|
|
994
|
-
statusWaitingApp: "Aguardando o app responder...",
|
|
995
|
-
statusAdjusting: "Ajustando o plano...",
|
|
996
|
-
poweredBy: "Powered by Appilots",
|
|
997
|
-
approve: "Aprovar",
|
|
998
|
-
reject: "Rejeitar",
|
|
999
|
-
cancelledByUser: "Cancelado pelo usu\xE1rio",
|
|
1000
|
-
confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
|
|
1001
|
-
confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
|
|
1002
|
-
confirmMessage: 'Tem certeza que deseja "{action}"?',
|
|
1003
|
-
confirmDestructiveApprove: "Sim, executar",
|
|
1004
|
-
confirmApprove: "Confirmar",
|
|
1005
|
-
confirmCancel: "Cancelar",
|
|
1006
|
-
confirmThisAction: "esta a\xE7\xE3o",
|
|
1007
|
-
unknownAction: "A\xE7\xE3o desconhecida",
|
|
1008
|
-
somethingWentWrong: "Algo deu errado",
|
|
1009
|
-
openChatA11y: "Abrir chat do assistente",
|
|
1010
|
-
closeChatA11y: "Fechar chat do assistente",
|
|
1011
|
-
stopGeneratingA11y: "Parar gera\xE7\xE3o",
|
|
1012
|
-
talkToHumanA11y: "Falar com um atendente humano",
|
|
1013
|
-
humanAgentLabel: "Atendente",
|
|
1014
|
-
escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
|
|
1015
|
-
escalationConnected: "Um atendente entrou na conversa.",
|
|
1016
|
-
escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
|
|
1017
|
-
escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
|
|
1018
|
-
escalationOfferChip: "Falar com um atendente",
|
|
1019
|
-
escalationPendingBanner: "Aguardando um atendente...",
|
|
1020
|
-
escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente"
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
// src/i18n/bundles/en.ts
|
|
1024
|
-
var en = {
|
|
1025
|
-
chatTitle: "Appilots Assistant",
|
|
1026
|
-
clearButton: "Clear",
|
|
1027
|
-
inputPlaceholder: "Type a message...",
|
|
1028
|
-
emptyTitle: "How can I help?",
|
|
1029
|
-
emptySubtitle: "I navigate, fill forms, and run actions in this app.",
|
|
1030
|
-
thinking: "Thinking...",
|
|
1031
|
-
statusAnalyzing: "Reading the screen...",
|
|
1032
|
-
statusWaitingApp: "Waiting for the app...",
|
|
1033
|
-
statusAdjusting: "Adjusting the plan...",
|
|
1034
|
-
poweredBy: "Powered by Appilots",
|
|
1035
|
-
approve: "Approve",
|
|
1036
|
-
reject: "Reject",
|
|
1037
|
-
cancelledByUser: "Cancelled by user",
|
|
1038
|
-
confirmDestructiveTitle: "Destructive action",
|
|
1039
|
-
confirmTitle: "Confirmation needed",
|
|
1040
|
-
confirmMessage: 'Are you sure you want to "{action}"?',
|
|
1041
|
-
confirmDestructiveApprove: "Yes, do it",
|
|
1042
|
-
confirmApprove: "Confirm",
|
|
1043
|
-
confirmCancel: "Cancel",
|
|
1044
|
-
confirmThisAction: "this action",
|
|
1045
|
-
unknownAction: "Unknown action",
|
|
1046
|
-
somethingWentWrong: "Something went wrong",
|
|
1047
|
-
openChatA11y: "Open assistant chat",
|
|
1048
|
-
closeChatA11y: "Close assistant chat",
|
|
1049
|
-
stopGeneratingA11y: "Stop generating",
|
|
1050
|
-
talkToHumanA11y: "Talk to a human agent",
|
|
1051
|
-
humanAgentLabel: "Agent",
|
|
1052
|
-
escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
|
|
1053
|
-
escalationConnected: "A human agent joined the conversation.",
|
|
1054
|
-
escalationResolved: "The human handoff has ended. I'm back to help you here.",
|
|
1055
|
-
escalationOffer: "If you prefer, I can bring in a person to help.",
|
|
1056
|
-
escalationOfferChip: "Talk to a human",
|
|
1057
|
-
escalationPendingBanner: "Waiting for a human agent...",
|
|
1058
|
-
escalationActiveBanner: "You're talking to a human agent"
|
|
1059
|
-
};
|
|
1060
|
-
|
|
1061
|
-
// src/i18n/bundles/es.ts
|
|
1062
|
-
var es = {
|
|
1063
|
-
chatTitle: "Asistente Appilots",
|
|
1064
|
-
clearButton: "Limpiar",
|
|
1065
|
-
inputPlaceholder: "Escribe un mensaje...",
|
|
1066
|
-
emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
|
|
1067
|
-
emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
|
|
1068
|
-
thinking: "Pensando...",
|
|
1069
|
-
statusAnalyzing: "Analizando la pantalla...",
|
|
1070
|
-
statusWaitingApp: "Esperando a la app...",
|
|
1071
|
-
statusAdjusting: "Ajustando el plan...",
|
|
1072
|
-
poweredBy: "Hecho con Appilots",
|
|
1073
|
-
approve: "Aprobar",
|
|
1074
|
-
reject: "Rechazar",
|
|
1075
|
-
cancelledByUser: "Cancelado por el usuario",
|
|
1076
|
-
confirmDestructiveTitle: "Acci\xF3n destructiva",
|
|
1077
|
-
confirmTitle: "Confirmaci\xF3n necesaria",
|
|
1078
|
-
confirmMessage: '\xBFSeguro que quieres "{action}"?',
|
|
1079
|
-
confirmDestructiveApprove: "S\xED, ejecutar",
|
|
1080
|
-
confirmApprove: "Confirmar",
|
|
1081
|
-
confirmCancel: "Cancelar",
|
|
1082
|
-
confirmThisAction: "esta acci\xF3n",
|
|
1083
|
-
unknownAction: "Acci\xF3n desconocida",
|
|
1084
|
-
somethingWentWrong: "Algo sali\xF3 mal",
|
|
1085
|
-
openChatA11y: "Abrir chat del asistente",
|
|
1086
|
-
closeChatA11y: "Cerrar chat del asistente",
|
|
1087
|
-
stopGeneratingA11y: "Detener generaci\xF3n",
|
|
1088
|
-
talkToHumanA11y: "Hablar con un agente humano",
|
|
1089
|
-
humanAgentLabel: "Agente",
|
|
1090
|
-
escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
|
|
1091
|
-
escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
|
|
1092
|
-
escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
|
|
1093
|
-
escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
|
|
1094
|
-
escalationOfferChip: "Hablar con un agente",
|
|
1095
|
-
escalationPendingBanner: "Esperando a un agente...",
|
|
1096
|
-
escalationActiveBanner: "Est\xE1s hablando con un agente humano"
|
|
1097
|
-
};
|
|
1098
|
-
var BUNDLES = {
|
|
1099
|
-
"pt-BR": ptBR,
|
|
1100
|
-
en,
|
|
1101
|
-
es
|
|
1102
|
-
};
|
|
1103
|
-
var DEFAULT_LOCALE = "en";
|
|
1104
|
-
function detectDeviceLocale() {
|
|
1105
|
-
try {
|
|
1106
|
-
let raw;
|
|
1107
|
-
if (Platform.OS === "ios") {
|
|
1108
|
-
const settings = NativeModules?.SettingsManager?.settings;
|
|
1109
|
-
raw = settings?.AppleLocale || (Array.isArray(settings?.AppleLanguages) ? settings?.AppleLanguages?.[0] : void 0);
|
|
1110
|
-
} else if (Platform.OS === "android") {
|
|
1111
|
-
raw = NativeModules?.I18nManager?.localeIdentifier;
|
|
1112
|
-
}
|
|
1113
|
-
if (!raw || typeof raw !== "string") return null;
|
|
1114
|
-
const lower = raw.toLowerCase().replace("_", "-");
|
|
1115
|
-
if (lower.startsWith("pt")) return "pt-BR";
|
|
1116
|
-
if (lower.startsWith("es")) return "es";
|
|
1117
|
-
if (lower.startsWith("en")) return "en";
|
|
1118
|
-
return null;
|
|
1119
|
-
} catch {
|
|
1120
|
-
return null;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
function resolveLocale(prop) {
|
|
1124
|
-
if (prop && BUNDLES[prop]) return prop;
|
|
1125
|
-
const detected = detectDeviceLocale();
|
|
1126
|
-
if (detected && BUNDLES[detected]) return detected;
|
|
1127
|
-
return DEFAULT_LOCALE;
|
|
1128
|
-
}
|
|
1129
|
-
var I18nContext = createContext(null);
|
|
1130
|
-
function AppilotsI18nProvider({
|
|
1131
|
-
locale,
|
|
1132
|
-
overrides,
|
|
1133
|
-
children
|
|
1134
|
-
}) {
|
|
1135
|
-
const value = useMemo(() => {
|
|
1136
|
-
const resolved = resolveLocale(locale ?? null);
|
|
1137
|
-
const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
|
|
1138
|
-
return {
|
|
1139
|
-
locale: resolved,
|
|
1140
|
-
strings: merged,
|
|
1141
|
-
t: (key) => merged[key]
|
|
1142
|
-
};
|
|
1143
|
-
}, [locale, overrides]);
|
|
1144
|
-
return /* @__PURE__ */ React7__default.createElement(I18nContext.Provider, { value }, children);
|
|
1145
|
-
}
|
|
1146
|
-
function useAppilotsI18n() {
|
|
1147
|
-
const ctx = useContext(I18nContext);
|
|
1148
|
-
if (ctx) return ctx;
|
|
1149
|
-
return {
|
|
1150
|
-
locale: DEFAULT_LOCALE,
|
|
1151
|
-
strings: BUNDLES[DEFAULT_LOCALE],
|
|
1152
|
-
t: (key) => BUNDLES[DEFAULT_LOCALE][key]
|
|
1153
|
-
};
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
1266
|
// src/components/AppilotsChat.tsx
|
|
1157
1267
|
function translateLegacyTheme(legacy) {
|
|
1158
1268
|
const out = {};
|
|
@@ -1183,31 +1293,35 @@ var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get("window");
|
|
|
1183
1293
|
var CHAT_HORIZONTAL_PADDING = 16;
|
|
1184
1294
|
var BUBBLE_HORIZONTAL_PADDING = 14;
|
|
1185
1295
|
var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
|
|
1186
|
-
var APPILOTS_SKIP_PROPS = {
|
|
1187
|
-
__appilotsSkip: true,
|
|
1188
|
-
__appilotsInternal: true
|
|
1189
|
-
};
|
|
1190
1296
|
function AppilotsChat(props) {
|
|
1191
1297
|
const { degraded } = useAppilotsContext();
|
|
1192
1298
|
if (degraded) return null;
|
|
1193
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ React8__default.createElement(AppilotsErrorBoundary, { surface: "chat", fallback: null }, /* @__PURE__ */ React8__default.createElement(AppilotsChatSurface, { ...props }));
|
|
1194
1300
|
}
|
|
1195
1301
|
function AppilotsChatSurface(props) {
|
|
1302
|
+
const [conversationLocale, setConversationLocale] = useState(null);
|
|
1196
1303
|
const { remotePersonalization } = useAppilotsContext();
|
|
1197
1304
|
const themeProp = useMemo(() => {
|
|
1198
1305
|
if (!props.theme) return void 0;
|
|
1199
1306
|
return isLegacyTheme(props.theme) ? translateLegacyTheme(props.theme) : props.theme;
|
|
1200
1307
|
}, [props.theme]);
|
|
1201
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1202
1309
|
AppilotsThemeProvider,
|
|
1203
1310
|
{
|
|
1204
1311
|
theme: resolveTheme(themeProp, remotePersonalization),
|
|
1205
1312
|
mode: resolveThemeMode(props.themeMode, remotePersonalization)
|
|
1206
1313
|
},
|
|
1207
|
-
/* @__PURE__ */
|
|
1314
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1315
|
+
AppilotsI18nProvider,
|
|
1316
|
+
{
|
|
1317
|
+
locale: conversationLocale ?? resolveLocaleProp(props.locale, remotePersonalization)
|
|
1318
|
+
},
|
|
1319
|
+
/* @__PURE__ */ React8__default.createElement(AppilotsChatInner, { ...props, onReplyLocaleChange: setConversationLocale })
|
|
1320
|
+
)
|
|
1208
1321
|
);
|
|
1209
1322
|
}
|
|
1210
1323
|
function AppilotsChatInner({
|
|
1324
|
+
onReplyLocaleChange,
|
|
1211
1325
|
visible: controlledVisible,
|
|
1212
1326
|
onClose,
|
|
1213
1327
|
placeholder,
|
|
@@ -1223,14 +1337,22 @@ function AppilotsChatInner({
|
|
|
1223
1337
|
triggerButton = "default",
|
|
1224
1338
|
triggerIcon,
|
|
1225
1339
|
triggerButtonColor: triggerButtonColorProp,
|
|
1226
|
-
triggerButtonImage: triggerButtonImageProp
|
|
1340
|
+
triggerButtonImage: triggerButtonImageProp,
|
|
1341
|
+
experience: experienceProp,
|
|
1342
|
+
speech: speechProp
|
|
1227
1343
|
}) {
|
|
1228
1344
|
const theme = useAppilotsTheme();
|
|
1229
|
-
const { strings, t } = useAppilotsI18n();
|
|
1345
|
+
const { strings, t, locale: resolvedLocale } = useAppilotsI18n();
|
|
1230
1346
|
const {
|
|
1231
1347
|
messages,
|
|
1348
|
+
mission,
|
|
1349
|
+
pauseMission,
|
|
1350
|
+
resumeMission,
|
|
1351
|
+
cancelMission,
|
|
1352
|
+
replyLocale,
|
|
1232
1353
|
isLoading,
|
|
1233
1354
|
loadingStatusKey,
|
|
1355
|
+
hasStartedActing,
|
|
1234
1356
|
sendMessage,
|
|
1235
1357
|
cancelMessage,
|
|
1236
1358
|
clearMessages,
|
|
@@ -1245,6 +1367,9 @@ function AppilotsChatInner({
|
|
|
1245
1367
|
offer: t("escalationOffer")
|
|
1246
1368
|
}
|
|
1247
1369
|
});
|
|
1370
|
+
useEffect(() => {
|
|
1371
|
+
onReplyLocaleChange(replyLocale);
|
|
1372
|
+
}, [replyLocale, onReplyLocaleChange]);
|
|
1248
1373
|
const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = useAppilotsActions({ autoExecute });
|
|
1249
1374
|
const { emit, remotePersonalization } = useAppilotsContext();
|
|
1250
1375
|
const {
|
|
@@ -1270,7 +1395,7 @@ function AppilotsChatInner({
|
|
|
1270
1395
|
);
|
|
1271
1396
|
const allActions = [...pendingActions, ...executingActions, ...completedActions];
|
|
1272
1397
|
const timeline = buildChatTimeline(messages, allActions);
|
|
1273
|
-
const lastAssistantMessageId =
|
|
1398
|
+
const lastAssistantMessageId = React8__default.useMemo(() => {
|
|
1274
1399
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1275
1400
|
if (messages[i].role === "assistant") return messages[i].id;
|
|
1276
1401
|
}
|
|
@@ -1281,7 +1406,65 @@ function AppilotsChatInner({
|
|
|
1281
1406
|
const [inputText, setInputText] = useState("");
|
|
1282
1407
|
const flatListRef = useRef(null);
|
|
1283
1408
|
const slideAnim = useRef(new Animated.Value(SCREEN_HEIGHT)).current;
|
|
1284
|
-
const
|
|
1409
|
+
const wantsSheet = mode === "inline" ? true : controlledVisible !== void 0 ? controlledVisible : internalVisible;
|
|
1410
|
+
const speechHost = isSpeechHost(speechProp) ? speechProp : null;
|
|
1411
|
+
const hasGeometry = useSyncExternalStore(
|
|
1412
|
+
subscribeGeometryHost,
|
|
1413
|
+
() => geometryAvailability() !== "unavailable",
|
|
1414
|
+
() => false
|
|
1415
|
+
);
|
|
1416
|
+
const capabilities = useMemo(
|
|
1417
|
+
() => ({ geometry: hasGeometry, speech: speechHost !== null }),
|
|
1418
|
+
[hasGeometry, speechHost]
|
|
1419
|
+
);
|
|
1420
|
+
const { experience, downgrades } = useMemo(
|
|
1421
|
+
() => resolveExperience(experienceProp, capabilities),
|
|
1422
|
+
[experienceProp, capabilities]
|
|
1423
|
+
);
|
|
1424
|
+
const presence = mode === "inline" ? "sheet" : experience.presence;
|
|
1425
|
+
useEffect(() => {
|
|
1426
|
+
if (!__DEV__ || downgrades.length === 0) return;
|
|
1427
|
+
if (!isGeometryResolved()) return;
|
|
1428
|
+
for (const line of formatDowngrades(downgrades)) {
|
|
1429
|
+
console.warn(line);
|
|
1430
|
+
}
|
|
1431
|
+
}, [downgrades, hasGeometry]);
|
|
1432
|
+
const [unreadResult, setUnreadResult] = useState(false);
|
|
1433
|
+
const [explicitlyOpened, setExplicitlyOpened] = useState(false);
|
|
1434
|
+
const requireApproval = useCallback(
|
|
1435
|
+
(action) => {
|
|
1436
|
+
if (action.status !== "pending") return false;
|
|
1437
|
+
if (action.type === "confirm") return true;
|
|
1438
|
+
return !autoExecute;
|
|
1439
|
+
},
|
|
1440
|
+
[autoExecute]
|
|
1441
|
+
);
|
|
1442
|
+
const awaitingUser = pendingActions.some((action) => requireApproval(action)) || escalation?.status === "pending" || escalation?.status === "active";
|
|
1443
|
+
const busy = isLoading || executingActions.length > 0;
|
|
1444
|
+
const acting = busy && hasStartedActing;
|
|
1445
|
+
const hostModalOpen = useHostModalOpen(
|
|
1446
|
+
usesPill(presence) && (busy || wantsSheet || unreadResult)
|
|
1447
|
+
);
|
|
1448
|
+
const surface = resolveSurface(presence, {
|
|
1449
|
+
busy,
|
|
1450
|
+
acting,
|
|
1451
|
+
awaitingUser,
|
|
1452
|
+
open: wantsSheet,
|
|
1453
|
+
unread: unreadResult,
|
|
1454
|
+
hostModalOpen,
|
|
1455
|
+
explicitlyOpened
|
|
1456
|
+
});
|
|
1457
|
+
const isVisible = mode === "inline" ? true : surface === "sheet";
|
|
1458
|
+
const spotlight = useSpotlight(experience.spotlight !== "off");
|
|
1459
|
+
useEffect(() => {
|
|
1460
|
+
setSpotlightMode(experience.spotlight);
|
|
1461
|
+
return () => setSpotlightMode("off");
|
|
1462
|
+
}, [experience.spotlight]);
|
|
1463
|
+
const { label: pillLabel, state: pillState } = surface === "pill" ? resolvePillStatus(allActions, busy, {
|
|
1464
|
+
working: strings.pillWorking,
|
|
1465
|
+
done: strings.pillDone,
|
|
1466
|
+
locale: resolvedLocale
|
|
1467
|
+
}) : { label: "", state: "pending" };
|
|
1285
1468
|
const showSuggestedPrompts = shouldShowSuggestedPrompts({
|
|
1286
1469
|
isVisible,
|
|
1287
1470
|
messageCount: messages.length,
|
|
@@ -1292,14 +1475,38 @@ function AppilotsChatInner({
|
|
|
1292
1475
|
limit: 3
|
|
1293
1476
|
});
|
|
1294
1477
|
const openChat = useCallback(() => {
|
|
1478
|
+
setExplicitlyOpened(true);
|
|
1295
1479
|
setInternalVisible(true);
|
|
1296
1480
|
emit({ type: "chat:open", timestamp: Date.now(), data: {} });
|
|
1297
1481
|
}, [emit]);
|
|
1298
1482
|
const closeChat = useCallback(() => {
|
|
1483
|
+
setExplicitlyOpened(false);
|
|
1299
1484
|
setInternalVisible(false);
|
|
1300
1485
|
onClose?.();
|
|
1301
1486
|
emit({ type: "chat:close", timestamp: Date.now(), data: {} });
|
|
1302
1487
|
}, [onClose, emit]);
|
|
1488
|
+
useEffect(() => {
|
|
1489
|
+
if (acting) setExplicitlyOpened(false);
|
|
1490
|
+
if (presence === "hidden" && acting) setInternalVisible(false);
|
|
1491
|
+
}, [presence, acting]);
|
|
1492
|
+
const wasActingRef = useRef(false);
|
|
1493
|
+
useEffect(() => {
|
|
1494
|
+
if (!usesPill(presence)) {
|
|
1495
|
+
wasActingRef.current = acting;
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
if (acting) {
|
|
1499
|
+
wasActingRef.current = true;
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
if (!wasActingRef.current) return;
|
|
1503
|
+
wasActingRef.current = false;
|
|
1504
|
+
if (shouldReopenOnTurnEnd(presence)) setInternalVisible(true);
|
|
1505
|
+
else setUnreadResult(true);
|
|
1506
|
+
}, [acting, presence]);
|
|
1507
|
+
useEffect(() => {
|
|
1508
|
+
if (surface === "sheet") setUnreadResult(false);
|
|
1509
|
+
}, [surface]);
|
|
1303
1510
|
useEffect(() => {
|
|
1304
1511
|
if (mode === "inline") return;
|
|
1305
1512
|
Animated.spring(slideAnim, {
|
|
@@ -1314,6 +1521,12 @@ function AppilotsChatInner({
|
|
|
1314
1521
|
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
|
|
1315
1522
|
}
|
|
1316
1523
|
}, [messages.length]);
|
|
1524
|
+
const voiceEnabled = experience.input.includes("voice");
|
|
1525
|
+
const voice = useVoiceInput({
|
|
1526
|
+
host: voiceEnabled ? speechHost : null,
|
|
1527
|
+
locale: resolvedLocale,
|
|
1528
|
+
onTranscript: sendMessage
|
|
1529
|
+
});
|
|
1317
1530
|
const handleSend = useCallback(() => {
|
|
1318
1531
|
if (!inputText.trim()) return;
|
|
1319
1532
|
sendMessage(inputText.trim());
|
|
@@ -1323,11 +1536,11 @@ function AppilotsChatInner({
|
|
|
1323
1536
|
({ item }) => {
|
|
1324
1537
|
if (item.role === "system") {
|
|
1325
1538
|
const isOffer = item.metadata?.escalationOffer === true;
|
|
1326
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.systemMessageContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1327
1540
|
Text,
|
|
1328
1541
|
{
|
|
1329
1542
|
style: [
|
|
1330
|
-
|
|
1543
|
+
styles5.systemMessageText,
|
|
1331
1544
|
{
|
|
1332
1545
|
color: theme.colors.textSecondary,
|
|
1333
1546
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1336,13 +1549,13 @@ function AppilotsChatInner({
|
|
|
1336
1549
|
]
|
|
1337
1550
|
},
|
|
1338
1551
|
item.content
|
|
1339
|
-
), isOffer && !escalation && /* @__PURE__ */
|
|
1552
|
+
), isOffer && !escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1340
1553
|
TouchableOpacity,
|
|
1341
1554
|
{
|
|
1342
1555
|
...APPILOTS_SKIP_PROPS,
|
|
1343
1556
|
style: [
|
|
1344
|
-
|
|
1345
|
-
|
|
1557
|
+
styles5.chip,
|
|
1558
|
+
styles5.escalationOfferChip,
|
|
1346
1559
|
{
|
|
1347
1560
|
backgroundColor: theme.colors.surface,
|
|
1348
1561
|
borderColor: theme.colors.border,
|
|
@@ -1355,12 +1568,12 @@ function AppilotsChatInner({
|
|
|
1355
1568
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1356
1569
|
testID: "escalation-offer-chip"
|
|
1357
1570
|
},
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1571
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
|
|
1572
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1360
1573
|
Text,
|
|
1361
1574
|
{
|
|
1362
1575
|
style: [
|
|
1363
|
-
|
|
1576
|
+
styles5.chipText,
|
|
1364
1577
|
{
|
|
1365
1578
|
color: theme.colors.text,
|
|
1366
1579
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1376,11 +1589,11 @@ function AppilotsChatInner({
|
|
|
1376
1589
|
const isHumanAgent = item.role === "human_agent";
|
|
1377
1590
|
const useWideAssistantLayout = !isUser && needsWideChatLayout(item.content);
|
|
1378
1591
|
if (isHumanAgent) {
|
|
1379
|
-
return /* @__PURE__ */
|
|
1592
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.humanAgentContainer, testID: "human-agent-message" }, /* @__PURE__ */ React8__default.createElement(View, { style: styles5.humanAgentLabelRow }, /* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 11, color: theme.colors.secondary }), /* @__PURE__ */ React8__default.createElement(
|
|
1380
1593
|
Text,
|
|
1381
1594
|
{
|
|
1382
1595
|
style: [
|
|
1383
|
-
|
|
1596
|
+
styles5.humanAgentLabel,
|
|
1384
1597
|
{
|
|
1385
1598
|
color: theme.colors.textSecondary,
|
|
1386
1599
|
fontFamily: theme.typography.fontFamily
|
|
@@ -1388,17 +1601,17 @@ function AppilotsChatInner({
|
|
|
1388
1601
|
]
|
|
1389
1602
|
},
|
|
1390
1603
|
escalation?.operatorName ?? strings.humanAgentLabel
|
|
1391
|
-
)), /* @__PURE__ */
|
|
1604
|
+
)), /* @__PURE__ */ React8__default.createElement(
|
|
1392
1605
|
View,
|
|
1393
1606
|
{
|
|
1394
1607
|
accessibilityLabel: item.content,
|
|
1395
1608
|
style: [
|
|
1396
|
-
|
|
1397
|
-
|
|
1609
|
+
styles5.messageBubble,
|
|
1610
|
+
styles5.assistantBubble,
|
|
1398
1611
|
{ backgroundColor: theme.colors.surface }
|
|
1399
1612
|
]
|
|
1400
1613
|
},
|
|
1401
|
-
/* @__PURE__ */
|
|
1614
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1402
1615
|
ChatMarkdown,
|
|
1403
1616
|
{
|
|
1404
1617
|
content: item.content,
|
|
@@ -1413,21 +1626,21 @@ function AppilotsChatInner({
|
|
|
1413
1626
|
)
|
|
1414
1627
|
));
|
|
1415
1628
|
}
|
|
1416
|
-
return /* @__PURE__ */
|
|
1629
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1417
1630
|
View,
|
|
1418
1631
|
{
|
|
1419
1632
|
testID: isUser ? void 0 : item.id === lastAssistantMessageId ? "assistant-last-message" : "assistant-message",
|
|
1420
1633
|
accessibilityLabel: isUser ? void 0 : item.content,
|
|
1421
1634
|
style: [
|
|
1422
|
-
|
|
1423
|
-
isUser ? [
|
|
1424
|
-
|
|
1425
|
-
useWideAssistantLayout &&
|
|
1635
|
+
styles5.messageBubble,
|
|
1636
|
+
isUser ? [styles5.userBubble, { backgroundColor: theme.colors.primary }] : [
|
|
1637
|
+
styles5.assistantBubble,
|
|
1638
|
+
useWideAssistantLayout && styles5.assistantBubbleWide,
|
|
1426
1639
|
{ backgroundColor: theme.colors.surface }
|
|
1427
1640
|
]
|
|
1428
1641
|
]
|
|
1429
1642
|
},
|
|
1430
|
-
/* @__PURE__ */
|
|
1643
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1431
1644
|
ChatMarkdown,
|
|
1432
1645
|
{
|
|
1433
1646
|
content: item.content,
|
|
@@ -1445,19 +1658,12 @@ function AppilotsChatInner({
|
|
|
1445
1658
|
},
|
|
1446
1659
|
[theme, lastAssistantMessageId, escalation, requestHuman, strings]
|
|
1447
1660
|
);
|
|
1448
|
-
const requireApproval = useCallback(
|
|
1449
|
-
(action) => {
|
|
1450
|
-
if (action.status !== "pending") return false;
|
|
1451
|
-
if (action.type === "confirm") return true;
|
|
1452
|
-
return !autoExecute;
|
|
1453
|
-
},
|
|
1454
|
-
[autoExecute]
|
|
1455
|
-
);
|
|
1456
1661
|
const renderBreadcrumb = useCallback(
|
|
1457
|
-
(actions) => /* @__PURE__ */
|
|
1662
|
+
(actions) => /* @__PURE__ */ React8__default.createElement(
|
|
1458
1663
|
ActionBreadcrumb,
|
|
1459
1664
|
{
|
|
1460
1665
|
actions,
|
|
1666
|
+
locale: resolvedLocale,
|
|
1461
1667
|
primaryColor: theme.colors.primary,
|
|
1462
1668
|
textColor: theme.colors.text,
|
|
1463
1669
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1493,6 +1699,8 @@ function AppilotsChatInner({
|
|
|
1493
1699
|
theme.colors.warning,
|
|
1494
1700
|
theme.colors.error,
|
|
1495
1701
|
theme.typography.fontFamily,
|
|
1702
|
+
strings,
|
|
1703
|
+
resolvedLocale,
|
|
1496
1704
|
requireApproval,
|
|
1497
1705
|
approveAction,
|
|
1498
1706
|
rejectAction
|
|
@@ -1505,17 +1713,17 @@ function AppilotsChatInner({
|
|
|
1505
1713
|
const showEmptySubtitle = resolvedEmptySubtitle.length > 0 && !(showSuggestedPrompts && suggestedPrompts.length > 0);
|
|
1506
1714
|
const renderAvatar = () => {
|
|
1507
1715
|
if (!assistantAvatar) {
|
|
1508
|
-
return /* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles5.headerDot, { backgroundColor: theme.colors.primary }] });
|
|
1509
1717
|
}
|
|
1510
1718
|
if (typeof assistantAvatar === "string") {
|
|
1511
|
-
return /* @__PURE__ */
|
|
1719
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: { uri: assistantAvatar }, style: styles5.headerAvatar });
|
|
1512
1720
|
}
|
|
1513
1721
|
if (typeof assistantAvatar === "number") {
|
|
1514
|
-
return /* @__PURE__ */
|
|
1722
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: assistantAvatar, style: styles5.headerAvatar });
|
|
1515
1723
|
}
|
|
1516
|
-
return /* @__PURE__ */
|
|
1724
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerAvatarSlot }, assistantAvatar);
|
|
1517
1725
|
};
|
|
1518
|
-
const showTrigger = mode === "bubble" &&
|
|
1726
|
+
const showTrigger = mode === "bubble" && surface === "none" && experience.entry.includes("fab") && controlledVisible === void 0 && triggerButton !== "none";
|
|
1519
1727
|
const fabPositionStyle = (() => {
|
|
1520
1728
|
switch (position) {
|
|
1521
1729
|
case "bottom-left":
|
|
@@ -1529,15 +1737,15 @@ function AppilotsChatInner({
|
|
|
1529
1737
|
return { bottom: 24, right: 24 };
|
|
1530
1738
|
}
|
|
1531
1739
|
})();
|
|
1532
|
-
const chatSurface = /* @__PURE__ */
|
|
1740
|
+
const chatSurface = /* @__PURE__ */ React8__default.createElement(
|
|
1533
1741
|
View,
|
|
1534
1742
|
{
|
|
1535
1743
|
...APPILOTS_SKIP_PROPS,
|
|
1536
1744
|
style: [
|
|
1537
|
-
|
|
1538
|
-
mode === "fullscreen" &&
|
|
1539
|
-
mode === "sidebar" &&
|
|
1540
|
-
mode === "inline" &&
|
|
1745
|
+
styles5.chatContainer,
|
|
1746
|
+
mode === "fullscreen" && styles5.chatContainerFullscreen,
|
|
1747
|
+
mode === "sidebar" && styles5.chatContainerSidebar,
|
|
1748
|
+
mode === "inline" && styles5.chatContainerInline,
|
|
1541
1749
|
{
|
|
1542
1750
|
backgroundColor: theme.colors.background,
|
|
1543
1751
|
borderTopLeftRadius: theme.radii.lg,
|
|
@@ -1545,11 +1753,11 @@ function AppilotsChatInner({
|
|
|
1545
1753
|
}
|
|
1546
1754
|
]
|
|
1547
1755
|
},
|
|
1548
|
-
/* @__PURE__ */
|
|
1756
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: [styles5.header, { borderBottomColor: theme.colors.border }] }, /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerLeft }, renderAvatar(), /* @__PURE__ */ React8__default.createElement(
|
|
1549
1757
|
Text,
|
|
1550
1758
|
{
|
|
1551
1759
|
style: [
|
|
1552
|
-
|
|
1760
|
+
styles5.headerTitle,
|
|
1553
1761
|
{
|
|
1554
1762
|
color: theme.colors.text,
|
|
1555
1763
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1558,50 +1766,50 @@ function AppilotsChatInner({
|
|
|
1558
1766
|
]
|
|
1559
1767
|
},
|
|
1560
1768
|
resolvedHeaderTitle
|
|
1561
|
-
)), /* @__PURE__ */
|
|
1769
|
+
)), /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerActions }, /* @__PURE__ */ React8__default.createElement(
|
|
1562
1770
|
TouchableOpacity,
|
|
1563
1771
|
{
|
|
1564
1772
|
...APPILOTS_SKIP_PROPS,
|
|
1565
1773
|
onPress: () => requestHuman("user_requested"),
|
|
1566
|
-
style:
|
|
1774
|
+
style: styles5.headerButton,
|
|
1567
1775
|
accessibilityRole: "button",
|
|
1568
1776
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1569
1777
|
testID: "escalation-header-button"
|
|
1570
1778
|
},
|
|
1571
|
-
/* @__PURE__ */
|
|
1779
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1572
1780
|
HeadsetIcon,
|
|
1573
1781
|
{
|
|
1574
1782
|
size: 16,
|
|
1575
1783
|
color: escalation ? theme.colors.primary : theme.colors.textSecondary
|
|
1576
1784
|
}
|
|
1577
1785
|
)
|
|
1578
|
-
), /* @__PURE__ */
|
|
1786
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
1579
1787
|
TouchableOpacity,
|
|
1580
1788
|
{
|
|
1581
1789
|
...APPILOTS_SKIP_PROPS,
|
|
1582
1790
|
onPress: clearMessages,
|
|
1583
|
-
style:
|
|
1791
|
+
style: styles5.headerButton,
|
|
1584
1792
|
accessibilityRole: "button",
|
|
1585
1793
|
testID: "assistant-clear"
|
|
1586
1794
|
},
|
|
1587
|
-
/* @__PURE__ */
|
|
1588
|
-
), mode !== "inline" && /* @__PURE__ */
|
|
1795
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles5.headerButtonText, { color: theme.colors.textSecondary }] }, strings.clearButton)
|
|
1796
|
+
), mode !== "inline" && /* @__PURE__ */ React8__default.createElement(
|
|
1589
1797
|
TouchableOpacity,
|
|
1590
1798
|
{
|
|
1591
1799
|
...APPILOTS_SKIP_PROPS,
|
|
1592
1800
|
onPress: closeChat,
|
|
1593
|
-
style:
|
|
1801
|
+
style: styles5.closeButton,
|
|
1594
1802
|
accessibilityRole: "button",
|
|
1595
1803
|
accessibilityLabel: strings.closeChatA11y,
|
|
1596
1804
|
testID: "assistant-close"
|
|
1597
1805
|
},
|
|
1598
|
-
/* @__PURE__ */
|
|
1806
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles5.closeButtonText, { color: theme.colors.text }] }, "\u2715")
|
|
1599
1807
|
))),
|
|
1600
|
-
escalation && /* @__PURE__ */
|
|
1808
|
+
escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1601
1809
|
View,
|
|
1602
1810
|
{
|
|
1603
1811
|
style: [
|
|
1604
|
-
|
|
1812
|
+
styles5.escalationBanner,
|
|
1605
1813
|
{
|
|
1606
1814
|
borderBottomColor: theme.colors.border,
|
|
1607
1815
|
backgroundColor: theme.colors.primary + "0d"
|
|
@@ -1609,12 +1817,12 @@ function AppilotsChatInner({
|
|
|
1609
1817
|
],
|
|
1610
1818
|
testID: "escalation-banner"
|
|
1611
1819
|
},
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
1820
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
|
|
1821
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1614
1822
|
Text,
|
|
1615
1823
|
{
|
|
1616
1824
|
style: [
|
|
1617
|
-
|
|
1825
|
+
styles5.escalationBannerText,
|
|
1618
1826
|
{
|
|
1619
1827
|
color: theme.colors.textSecondary,
|
|
1620
1828
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1625,10 +1833,11 @@ function AppilotsChatInner({
|
|
|
1625
1833
|
escalation.status === "pending" ? strings.escalationPendingBanner : strings.escalationActiveBanner
|
|
1626
1834
|
)
|
|
1627
1835
|
),
|
|
1628
|
-
/* @__PURE__ */
|
|
1836
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1629
1837
|
FlatList,
|
|
1630
1838
|
{
|
|
1631
1839
|
...APPILOTS_SKIP_PROPS,
|
|
1840
|
+
testID: "assistant-transcript",
|
|
1632
1841
|
ref: flatListRef,
|
|
1633
1842
|
data: timeline,
|
|
1634
1843
|
keyExtractor: (item) => item.type === "message" ? item.data.id : item.key,
|
|
@@ -1641,34 +1850,34 @@ function AppilotsChatInner({
|
|
|
1641
1850
|
}
|
|
1642
1851
|
return null;
|
|
1643
1852
|
},
|
|
1644
|
-
contentContainerStyle:
|
|
1645
|
-
ListEmptyComponent: /* @__PURE__ */
|
|
1853
|
+
contentContainerStyle: styles5.messageList,
|
|
1854
|
+
ListEmptyComponent: /* @__PURE__ */ React8__default.createElement(View, { style: styles5.emptyState }, emptyStateIcon && isImageSource(emptyStateIcon) ? /* @__PURE__ */ React8__default.createElement(
|
|
1646
1855
|
Image,
|
|
1647
1856
|
{
|
|
1648
1857
|
source: typeof emptyStateIcon === "string" ? { uri: emptyStateIcon } : emptyStateIcon,
|
|
1649
|
-
style:
|
|
1858
|
+
style: styles5.emptyIconImage,
|
|
1650
1859
|
resizeMode: "contain"
|
|
1651
1860
|
}
|
|
1652
|
-
) : /* @__PURE__ */
|
|
1861
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1653
1862
|
View,
|
|
1654
1863
|
{
|
|
1655
|
-
style: [
|
|
1864
|
+
style: [styles5.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
|
|
1656
1865
|
},
|
|
1657
|
-
emptyStateIcon ? /* @__PURE__ */
|
|
1658
|
-
), /* @__PURE__ */
|
|
1866
|
+
emptyStateIcon ? /* @__PURE__ */ React8__default.createElement(Text, { style: styles5.emptyIconEmoji }, emptyStateIcon) : /* @__PURE__ */ React8__default.createElement(ChatIcon, { size: 30, color: theme.colors.primary })
|
|
1867
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
1659
1868
|
Text,
|
|
1660
1869
|
{
|
|
1661
1870
|
style: [
|
|
1662
|
-
|
|
1871
|
+
styles5.emptyTitle,
|
|
1663
1872
|
{ color: theme.colors.text, fontFamily: theme.typography.fontFamily }
|
|
1664
1873
|
]
|
|
1665
1874
|
},
|
|
1666
1875
|
resolvedEmptyTitle
|
|
1667
|
-
), showEmptySubtitle && /* @__PURE__ */
|
|
1876
|
+
), showEmptySubtitle && /* @__PURE__ */ React8__default.createElement(
|
|
1668
1877
|
Text,
|
|
1669
1878
|
{
|
|
1670
1879
|
style: [
|
|
1671
|
-
|
|
1880
|
+
styles5.emptySubtitle,
|
|
1672
1881
|
{
|
|
1673
1882
|
color: theme.colors.textSecondary,
|
|
1674
1883
|
fontFamily: theme.typography.fontFamily
|
|
@@ -1677,12 +1886,12 @@ function AppilotsChatInner({
|
|
|
1677
1886
|
numberOfLines: 2
|
|
1678
1887
|
},
|
|
1679
1888
|
resolvedEmptySubtitle
|
|
1680
|
-
), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */
|
|
1889
|
+
), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.chipsContainer, testID: "assistant-suggested-prompts" }, suggestedPrompts.map((prompt) => /* @__PURE__ */ React8__default.createElement(
|
|
1681
1890
|
TouchableOpacity,
|
|
1682
1891
|
{
|
|
1683
1892
|
key: `${prompt.source}:${prompt.text}`,
|
|
1684
1893
|
style: [
|
|
1685
|
-
|
|
1894
|
+
styles5.chip,
|
|
1686
1895
|
{
|
|
1687
1896
|
backgroundColor: theme.colors.surface,
|
|
1688
1897
|
borderColor: theme.colors.border,
|
|
@@ -1693,11 +1902,11 @@ function AppilotsChatInner({
|
|
|
1693
1902
|
activeOpacity: 0.7,
|
|
1694
1903
|
accessibilityLabel: `Suggested prompt: ${prompt.text}`
|
|
1695
1904
|
},
|
|
1696
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1697
1906
|
Text,
|
|
1698
1907
|
{
|
|
1699
1908
|
style: [
|
|
1700
|
-
|
|
1909
|
+
styles5.chipText,
|
|
1701
1910
|
{
|
|
1702
1911
|
color: theme.colors.buttonText,
|
|
1703
1912
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1709,20 +1918,20 @@ function AppilotsChatInner({
|
|
|
1709
1918
|
prompt.text
|
|
1710
1919
|
)
|
|
1711
1920
|
)))),
|
|
1712
|
-
ListFooterComponent: isLoading ? /* @__PURE__ */
|
|
1921
|
+
ListFooterComponent: isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
1713
1922
|
View,
|
|
1714
1923
|
{
|
|
1715
1924
|
style: [
|
|
1716
|
-
|
|
1717
|
-
|
|
1925
|
+
styles5.messageBubble,
|
|
1926
|
+
styles5.assistantBubble,
|
|
1718
1927
|
{ backgroundColor: theme.colors.surface }
|
|
1719
1928
|
]
|
|
1720
1929
|
},
|
|
1721
|
-
/* @__PURE__ */
|
|
1930
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1722
1931
|
Text,
|
|
1723
1932
|
{
|
|
1724
1933
|
style: [
|
|
1725
|
-
|
|
1934
|
+
styles5.messageText,
|
|
1726
1935
|
{ color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
|
|
1727
1936
|
]
|
|
1728
1937
|
},
|
|
@@ -1731,22 +1940,48 @@ function AppilotsChatInner({
|
|
|
1731
1940
|
) : null
|
|
1732
1941
|
}
|
|
1733
1942
|
),
|
|
1734
|
-
/* @__PURE__ */
|
|
1943
|
+
mission && !["completed", "cancelled"].includes(mission.status) && /* @__PURE__ */ React8__default.createElement(View, { style: { padding: 12, gap: 8 }, testID: "appilots-mission-controls" }, /* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text }, testID: "appilots-mission-progress" }, mission.progressText, mission.status === "paused" ? ` \xB7 ${strings.missionPaused}` : ""), /* @__PURE__ */ React8__default.createElement(View, { style: { flexDirection: "row", gap: 12 } }, mission.status === "running" ? /* @__PURE__ */ React8__default.createElement(
|
|
1944
|
+
TouchableOpacity,
|
|
1945
|
+
{
|
|
1946
|
+
onPress: () => void pauseMission(),
|
|
1947
|
+
testID: "appilots-mission-pause",
|
|
1948
|
+
accessibilityRole: "button"
|
|
1949
|
+
},
|
|
1950
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionPause)
|
|
1951
|
+
) : mission.status !== "awaiting_approval" ? /* @__PURE__ */ React8__default.createElement(
|
|
1952
|
+
TouchableOpacity,
|
|
1953
|
+
{
|
|
1954
|
+
onPress: () => void resumeMission(),
|
|
1955
|
+
disabled: isLoading,
|
|
1956
|
+
testID: "appilots-mission-resume",
|
|
1957
|
+
accessibilityRole: "button"
|
|
1958
|
+
},
|
|
1959
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionResume)
|
|
1960
|
+
) : null, /* @__PURE__ */ React8__default.createElement(
|
|
1961
|
+
TouchableOpacity,
|
|
1962
|
+
{
|
|
1963
|
+
onPress: () => void cancelMission(),
|
|
1964
|
+
testID: "appilots-mission-cancel",
|
|
1965
|
+
accessibilityRole: "button"
|
|
1966
|
+
},
|
|
1967
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionCancel)
|
|
1968
|
+
))),
|
|
1969
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1735
1970
|
View,
|
|
1736
1971
|
{
|
|
1737
1972
|
style: [
|
|
1738
|
-
|
|
1973
|
+
styles5.inputContainer,
|
|
1739
1974
|
{
|
|
1740
1975
|
borderTopColor: theme.colors.border,
|
|
1741
1976
|
paddingBottom: Math.max(insets.bottom, 10)
|
|
1742
1977
|
}
|
|
1743
1978
|
]
|
|
1744
1979
|
},
|
|
1745
|
-
/* @__PURE__ */
|
|
1980
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1746
1981
|
TextInput,
|
|
1747
1982
|
{
|
|
1748
1983
|
style: [
|
|
1749
|
-
|
|
1984
|
+
styles5.input,
|
|
1750
1985
|
{
|
|
1751
1986
|
backgroundColor: theme.colors.surface,
|
|
1752
1987
|
color: theme.colors.text,
|
|
@@ -1763,16 +1998,35 @@ function AppilotsChatInner({
|
|
|
1763
1998
|
multiline: true,
|
|
1764
1999
|
blurOnSubmit: false,
|
|
1765
2000
|
scrollEnabled: true,
|
|
1766
|
-
editable: !isLoading,
|
|
2001
|
+
editable: !isLoading && (!mission || ["completed", "cancelled"].includes(mission.status)),
|
|
1767
2002
|
testID: "assistant-input",
|
|
1768
2003
|
__appilotsInternal: true
|
|
1769
2004
|
}
|
|
1770
2005
|
),
|
|
1771
|
-
isLoading ? /* @__PURE__ */
|
|
2006
|
+
voiceEnabled && !isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
2007
|
+
TouchableOpacity,
|
|
2008
|
+
{
|
|
2009
|
+
style: [
|
|
2010
|
+
styles5.sendButton,
|
|
2011
|
+
{
|
|
2012
|
+
backgroundColor: voice.state === "listening" || voice.state === "starting" ? theme.colors.error : theme.colors.primary + "40",
|
|
2013
|
+
borderRadius: theme.radii.md
|
|
2014
|
+
}
|
|
2015
|
+
],
|
|
2016
|
+
onPressIn: voice.start,
|
|
2017
|
+
onPressOut: voice.stop,
|
|
2018
|
+
accessibilityRole: "button",
|
|
2019
|
+
accessibilityLabel: voice.state === "listening" ? strings.micStopA11y : strings.micStartA11y,
|
|
2020
|
+
testID: "appilots-mic-button",
|
|
2021
|
+
activeOpacity: 0.7
|
|
2022
|
+
},
|
|
2023
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u25CF")
|
|
2024
|
+
) : null,
|
|
2025
|
+
isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
1772
2026
|
TouchableOpacity,
|
|
1773
2027
|
{
|
|
1774
2028
|
style: [
|
|
1775
|
-
|
|
2029
|
+
styles5.sendButton,
|
|
1776
2030
|
{
|
|
1777
2031
|
backgroundColor: theme.colors.primary,
|
|
1778
2032
|
borderRadius: theme.radii.md
|
|
@@ -1784,31 +2038,31 @@ function AppilotsChatInner({
|
|
|
1784
2038
|
testID: "appilots-stop-button",
|
|
1785
2039
|
activeOpacity: 0.7
|
|
1786
2040
|
},
|
|
1787
|
-
/* @__PURE__ */
|
|
1788
|
-
) : /* @__PURE__ */
|
|
2041
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u25A0")
|
|
2042
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1789
2043
|
TouchableOpacity,
|
|
1790
2044
|
{
|
|
1791
2045
|
style: [
|
|
1792
|
-
|
|
2046
|
+
styles5.sendButton,
|
|
1793
2047
|
{
|
|
1794
2048
|
backgroundColor: inputText.trim() ? theme.colors.primary : theme.colors.primary + "40",
|
|
1795
2049
|
borderRadius: theme.radii.md
|
|
1796
2050
|
}
|
|
1797
2051
|
],
|
|
1798
2052
|
onPress: handleSend,
|
|
1799
|
-
disabled: !inputText.trim(),
|
|
2053
|
+
disabled: !inputText.trim() || !!(mission && !["completed", "cancelled"].includes(mission.status)),
|
|
1800
2054
|
activeOpacity: 0.7,
|
|
1801
2055
|
accessibilityRole: "button",
|
|
1802
2056
|
testID: "assistant-send"
|
|
1803
2057
|
},
|
|
1804
|
-
/* @__PURE__ */
|
|
2058
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u2191")
|
|
1805
2059
|
)
|
|
1806
2060
|
),
|
|
1807
|
-
poweredByVisible && /* @__PURE__ */
|
|
2061
|
+
poweredByVisible && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.poweredByContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1808
2062
|
Text,
|
|
1809
2063
|
{
|
|
1810
2064
|
style: [
|
|
1811
|
-
|
|
2065
|
+
styles5.poweredByText,
|
|
1812
2066
|
{
|
|
1813
2067
|
color: theme.colors.textSecondary,
|
|
1814
2068
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1824,8 +2078,8 @@ function AppilotsChatInner({
|
|
|
1824
2078
|
}
|
|
1825
2079
|
const renderTrigger = () => {
|
|
1826
2080
|
if (triggerButton === "none") return null;
|
|
1827
|
-
if (triggerButton !== "default" &&
|
|
1828
|
-
return /* @__PURE__ */
|
|
2081
|
+
if (triggerButton !== "default" && React8__default.isValidElement(triggerButton)) {
|
|
2082
|
+
return /* @__PURE__ */ React8__default.createElement(View, { ...APPILOTS_SKIP_PROPS, style: [styles5.fabWrapper, fabPositionStyle] }, /* @__PURE__ */ React8__default.createElement(
|
|
1829
2083
|
TouchableOpacity,
|
|
1830
2084
|
{
|
|
1831
2085
|
...APPILOTS_SKIP_PROPS,
|
|
@@ -1838,12 +2092,12 @@ function AppilotsChatInner({
|
|
|
1838
2092
|
triggerButton
|
|
1839
2093
|
));
|
|
1840
2094
|
}
|
|
1841
|
-
return /* @__PURE__ */
|
|
2095
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1842
2096
|
TouchableOpacity,
|
|
1843
2097
|
{
|
|
1844
2098
|
...APPILOTS_SKIP_PROPS,
|
|
1845
2099
|
style: [
|
|
1846
|
-
|
|
2100
|
+
styles5.fab,
|
|
1847
2101
|
fabPositionStyle,
|
|
1848
2102
|
{ backgroundColor: triggerButtonColor ?? theme.colors.primary }
|
|
1849
2103
|
],
|
|
@@ -1853,55 +2107,113 @@ function AppilotsChatInner({
|
|
|
1853
2107
|
accessibilityLabel: strings.openChatA11y,
|
|
1854
2108
|
testID: "assistant-launcher"
|
|
1855
2109
|
},
|
|
1856
|
-
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */
|
|
2110
|
+
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React8__default.createElement(
|
|
1857
2111
|
Image,
|
|
1858
2112
|
{
|
|
1859
2113
|
source: typeof triggerButtonImage === "string" ? { uri: triggerButtonImage } : triggerButtonImage,
|
|
1860
|
-
style:
|
|
2114
|
+
style: styles5.fabImage,
|
|
1861
2115
|
resizeMode: "contain"
|
|
1862
2116
|
}
|
|
1863
|
-
) : /* @__PURE__ */
|
|
2117
|
+
) : /* @__PURE__ */ React8__default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
|
|
1864
2118
|
);
|
|
1865
2119
|
};
|
|
1866
|
-
return /* @__PURE__ */
|
|
1867
|
-
|
|
2120
|
+
return /* @__PURE__ */ React8__default.createElement(React8__default.Fragment, null, showTrigger && renderTrigger(), spotlight && experience.spotlight !== "off" ? /* @__PURE__ */ React8__default.createElement(
|
|
2121
|
+
SpotlightOverlay,
|
|
2122
|
+
{
|
|
2123
|
+
rect: spotlight.rect,
|
|
2124
|
+
seq: spotlight.seq,
|
|
2125
|
+
label: spotlight.label,
|
|
2126
|
+
color: theme.colors.primary,
|
|
2127
|
+
captionBackground: theme.colors.surface,
|
|
2128
|
+
captionColor: theme.colors.text,
|
|
2129
|
+
fontFamily: theme.typography.fontFamily,
|
|
2130
|
+
window: { width: SCREEN_WIDTH, height: SCREEN_HEIGHT }
|
|
2131
|
+
}
|
|
2132
|
+
) : null, surface === "pill" && /* @__PURE__ */ React8__default.createElement(
|
|
2133
|
+
AgentPill,
|
|
2134
|
+
{
|
|
2135
|
+
label: mission && !["completed", "cancelled"].includes(mission.status) ? mission.progressText : pillLabel,
|
|
2136
|
+
state: pillState,
|
|
2137
|
+
position,
|
|
2138
|
+
insets,
|
|
2139
|
+
fontFamily: theme.typography.fontFamily,
|
|
2140
|
+
colors: {
|
|
2141
|
+
surface: theme.colors.surface,
|
|
2142
|
+
text: theme.colors.text,
|
|
2143
|
+
textSecondary: theme.colors.textSecondary,
|
|
2144
|
+
primary: theme.colors.primary,
|
|
2145
|
+
border: theme.colors.border,
|
|
2146
|
+
success: theme.colors.success,
|
|
2147
|
+
error: theme.colors.error
|
|
2148
|
+
},
|
|
2149
|
+
strings: { expandA11y: strings.pillExpandA11y, stopA11y: strings.pillStopA11y },
|
|
2150
|
+
onExpand: openChat,
|
|
2151
|
+
onStop: busy ? cancelMessage : void 0
|
|
2152
|
+
}
|
|
2153
|
+
), /* @__PURE__ */ React8__default.createElement(SheetHost, { useModal: presence === "sheet", visible: isVisible, onRequestClose: closeChat }, /* @__PURE__ */ React8__default.createElement(
|
|
2154
|
+
Animated.View,
|
|
1868
2155
|
{
|
|
1869
2156
|
...APPILOTS_SKIP_PROPS,
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2157
|
+
pointerEvents: presence === "sheet" ? "auto" : "box-none",
|
|
2158
|
+
style: [
|
|
2159
|
+
mode === "fullscreen" ? styles5.modalContainerFullscreen : styles5.modalContainer,
|
|
2160
|
+
mode === "sidebar" && styles5.modalContainerSidebar,
|
|
2161
|
+
presence !== "sheet" && styles5.sheetContainerNoScrim,
|
|
2162
|
+
// Keeps the sheet out of the status bar / notch. It is padding
|
|
2163
|
+
// and not a margin so the scrim still covers the full screen.
|
|
2164
|
+
// Only reachable now that the sheet can grow to the top edge:
|
|
2165
|
+
// `fullscreen` and `sidebar` always could, and `bubble` does
|
|
2166
|
+
// whenever the keyboard shrinks it — without this, the header
|
|
2167
|
+
// renders under the clock.
|
|
2168
|
+
{ paddingTop: insets.top },
|
|
2169
|
+
{ transform: [{ translateY: slideAnim }] }
|
|
2170
|
+
]
|
|
1874
2171
|
},
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
|
|
2172
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
2173
|
+
KeyboardAvoidingView,
|
|
1877
2174
|
{
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
mode === "sidebar" && styles3.modalContainerSidebar,
|
|
1882
|
-
// Keeps the sheet out of the status bar / notch. It is padding
|
|
1883
|
-
// and not a margin so the scrim still covers the full screen.
|
|
1884
|
-
// Only reachable now that the sheet can grow to the top edge:
|
|
1885
|
-
// `fullscreen` and `sidebar` always could, and `bubble` does
|
|
1886
|
-
// whenever the keyboard shrinks it — without this, the header
|
|
1887
|
-
// renders under the clock.
|
|
1888
|
-
{ paddingTop: insets.top },
|
|
1889
|
-
{ transform: [{ translateY: slideAnim }] }
|
|
1890
|
-
]
|
|
2175
|
+
style: styles5.keyboardView,
|
|
2176
|
+
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
2177
|
+
keyboardVerticalOffset: 0
|
|
1891
2178
|
},
|
|
1892
|
-
|
|
1893
|
-
KeyboardAvoidingView,
|
|
1894
|
-
{
|
|
1895
|
-
style: styles3.keyboardView,
|
|
1896
|
-
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
1897
|
-
keyboardVerticalOffset: 0
|
|
1898
|
-
},
|
|
1899
|
-
chatSurface
|
|
1900
|
-
)
|
|
2179
|
+
chatSurface
|
|
1901
2180
|
)
|
|
1902
|
-
));
|
|
2181
|
+
)));
|
|
1903
2182
|
}
|
|
1904
|
-
|
|
2183
|
+
function SheetHost({
|
|
2184
|
+
useModal,
|
|
2185
|
+
visible,
|
|
2186
|
+
onRequestClose,
|
|
2187
|
+
children
|
|
2188
|
+
}) {
|
|
2189
|
+
if (useModal) {
|
|
2190
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2191
|
+
Modal,
|
|
2192
|
+
{
|
|
2193
|
+
...APPILOTS_SKIP_PROPS,
|
|
2194
|
+
visible,
|
|
2195
|
+
transparent: true,
|
|
2196
|
+
animationType: "none",
|
|
2197
|
+
onRequestClose
|
|
2198
|
+
},
|
|
2199
|
+
children
|
|
2200
|
+
);
|
|
2201
|
+
}
|
|
2202
|
+
if (!visible) return null;
|
|
2203
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2204
|
+
View,
|
|
2205
|
+
{
|
|
2206
|
+
...APPILOTS_SKIP_PROPS,
|
|
2207
|
+
pointerEvents: "box-none",
|
|
2208
|
+
style: [StyleSheet.absoluteFill, styles5.sheetOverlay]
|
|
2209
|
+
},
|
|
2210
|
+
children
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
var styles5 = StyleSheet.create({
|
|
2214
|
+
// An explicitly opened chat must not mount underneath a sibling portal.
|
|
2215
|
+
// Automatic expansion is separately deferred while the host modal is open.
|
|
2216
|
+
sheetOverlay: { zIndex: 1e3, elevation: 7 },
|
|
1905
2217
|
fab: {
|
|
1906
2218
|
position: "absolute",
|
|
1907
2219
|
width: 56,
|
|
@@ -1944,6 +2256,12 @@ var styles3 = StyleSheet.create({
|
|
|
1944
2256
|
flexDirection: "row",
|
|
1945
2257
|
justifyContent: "flex-end"
|
|
1946
2258
|
},
|
|
2259
|
+
// Non-modal presences drop the scrim entirely: dimming the app is
|
|
2260
|
+
// the opposite of the point, and a painted full-screen surface is
|
|
2261
|
+
// touch-opaque no matter what pointerEvents the parent asks for.
|
|
2262
|
+
sheetContainerNoScrim: {
|
|
2263
|
+
backgroundColor: "transparent"
|
|
2264
|
+
},
|
|
1947
2265
|
keyboardView: {
|
|
1948
2266
|
flex: 1,
|
|
1949
2267
|
justifyContent: "flex-end"
|
|
@@ -2208,6 +2526,11 @@ function ConfirmDialog(_props = {}) {
|
|
|
2208
2526
|
return null;
|
|
2209
2527
|
}
|
|
2210
2528
|
|
|
2529
|
+
// src/auto/appilotsListTotal.ts
|
|
2530
|
+
function appilotsListTotal(total) {
|
|
2531
|
+
return { appilotsTotalItemCount: total };
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2211
2534
|
// src/hoc/canHoldRef.ts
|
|
2212
2535
|
var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
2213
2536
|
var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
|
|
@@ -2234,12 +2557,19 @@ function canHoldRef(type) {
|
|
|
2234
2557
|
}
|
|
2235
2558
|
}
|
|
2236
2559
|
|
|
2560
|
+
// src/hoc/withDeclaredIdentity.ts
|
|
2561
|
+
function withDeclaredIdentity(props, declaredId, enabled) {
|
|
2562
|
+
if (!enabled || !declaredId) return props;
|
|
2563
|
+
if (props.testID != null) return props;
|
|
2564
|
+
return { ...props, testID: declaredId };
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2237
2567
|
// src/hoc/createAppilotsInput.tsx
|
|
2238
2568
|
function normalizeId(label) {
|
|
2239
2569
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2240
2570
|
}
|
|
2241
2571
|
function createAppilotsInput(WrappedComponent) {
|
|
2242
|
-
const AppilotsInput =
|
|
2572
|
+
const AppilotsInput = React8__default.forwardRef((props, ref) => {
|
|
2243
2573
|
const {
|
|
2244
2574
|
appilotsId,
|
|
2245
2575
|
appilotsScreen,
|
|
@@ -2294,10 +2624,14 @@ function createAppilotsInput(WrappedComponent) {
|
|
|
2294
2624
|
},
|
|
2295
2625
|
[ref]
|
|
2296
2626
|
);
|
|
2297
|
-
return /* @__PURE__ */
|
|
2627
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2298
2628
|
WrappedComponent,
|
|
2299
2629
|
{
|
|
2300
|
-
...
|
|
2630
|
+
...withDeclaredIdentity(
|
|
2631
|
+
{ label, value, onChangeText, ...rest },
|
|
2632
|
+
fieldId,
|
|
2633
|
+
appilotsEnabled
|
|
2634
|
+
),
|
|
2301
2635
|
...canHoldRef(WrappedComponent) ? { ref: mergedRef } : {}
|
|
2302
2636
|
}
|
|
2303
2637
|
);
|
|
@@ -2309,7 +2643,7 @@ function normalizeId2(label) {
|
|
|
2309
2643
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2310
2644
|
}
|
|
2311
2645
|
function createAppilotsButton(WrappedComponent) {
|
|
2312
|
-
const AppilotsButton =
|
|
2646
|
+
const AppilotsButton = React8__default.forwardRef((props, ref) => {
|
|
2313
2647
|
const {
|
|
2314
2648
|
appilotsId,
|
|
2315
2649
|
appilotsScreen,
|
|
@@ -2335,10 +2669,10 @@ function createAppilotsButton(WrappedComponent) {
|
|
|
2335
2669
|
componentRegistry.unregister(targetId);
|
|
2336
2670
|
};
|
|
2337
2671
|
}, [targetId, appilotsEnabled, press, title, appilotsScreen]);
|
|
2338
|
-
return /* @__PURE__ */
|
|
2672
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2339
2673
|
WrappedComponent,
|
|
2340
2674
|
{
|
|
2341
|
-
...{ title, onPress, ...rest },
|
|
2675
|
+
...withDeclaredIdentity({ title, onPress, ...rest }, targetId, appilotsEnabled),
|
|
2342
2676
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2343
2677
|
}
|
|
2344
2678
|
);
|
|
@@ -2350,7 +2684,7 @@ function normalizeId3(label) {
|
|
|
2350
2684
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2351
2685
|
}
|
|
2352
2686
|
function createAppilotsSwitch(WrappedComponent) {
|
|
2353
|
-
const AppilotsSwitch =
|
|
2687
|
+
const AppilotsSwitch = React8__default.forwardRef((props, ref) => {
|
|
2354
2688
|
const {
|
|
2355
2689
|
appilotsId,
|
|
2356
2690
|
appilotsScreen,
|
|
@@ -2381,10 +2715,14 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2381
2715
|
componentRegistry.unregister(toggleId);
|
|
2382
2716
|
};
|
|
2383
2717
|
}, [toggleId, appilotsEnabled, getValue, setValue, label, appilotsScreen]);
|
|
2384
|
-
return /* @__PURE__ */
|
|
2718
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2385
2719
|
WrappedComponent,
|
|
2386
2720
|
{
|
|
2387
|
-
...
|
|
2721
|
+
...withDeclaredIdentity(
|
|
2722
|
+
{ label, value, onValueChange, ...rest },
|
|
2723
|
+
toggleId,
|
|
2724
|
+
appilotsEnabled
|
|
2725
|
+
),
|
|
2388
2726
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2389
2727
|
}
|
|
2390
2728
|
);
|
|
@@ -2393,4 +2731,4 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2393
2731
|
return AppilotsSwitch;
|
|
2394
2732
|
}
|
|
2395
2733
|
|
|
2396
|
-
export { ActionBreadcrumb,
|
|
2734
|
+
export { ActionBreadcrumb, AgentPill, AppilotsChat, AppilotsThemeProvider, ChatIcon, ConfirmDialog, DEFAULT_EXPERIENCE, HeadsetIcon, SpotlightOverlay, appilotsListTotal, appilotsTheme, appilotsThemeFromTailwind, createAppilotsButton, createAppilotsInput, createAppilotsSwitch, formatDowngrades, resolveExperience, resolvePillStatus, resolveSurface, shouldReopenOnTurnEnd, useAppilotsTheme, useSpotlight, usesPill };
|