@appilots/sdk 0.11.1 → 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-X4MPSZL3.js → chunk-AJDHZRBN.js} +1180 -487
- package/dist/{chunk-DRXUBLGY.js → chunk-ALJGKORS.js} +8 -8
- package/dist/{chunk-PQZ64CCE.mjs → chunk-HRWBK35Y.mjs} +6007 -527
- package/dist/{chunk-LLH7QCSX.mjs → chunk-L3SY3Q4K.mjs} +1 -1
- package/dist/{chunk-GSHE45YX.mjs → chunk-UYBKXULM.mjs} +903 -223
- package/dist/{chunk-KZ2BLMS4.js → chunk-UZ2D4BVX.js} +6026 -525
- 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-C01Spw6F.d.mts → index-CI4jmSoP.d.mts} +136 -549
- package/dist/{index-C01Spw6F.d.ts → index-CI4jmSoP.d.ts} +136 -549
- package/dist/index.d.mts +1472 -76
- package/dist/index.d.ts +1472 -76
- package/dist/index.js +1100 -673
- package/dist/index.mjs +933 -565
- package/dist/navigation/index.d.mts +64 -7
- package/dist/navigation/index.d.ts +64 -7
- 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,39 +231,41 @@ 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),
|
|
213
253
|
style: [styles.btn, { backgroundColor: deriveStateTone(palette).failed.iconBg }],
|
|
214
254
|
activeOpacity: 0.7,
|
|
215
|
-
accessibilityLabel: "Rejeitar a\xE7\xE3o"
|
|
255
|
+
accessibilityLabel: "Rejeitar a\xE7\xE3o",
|
|
256
|
+
testID: "assistant-action-reject"
|
|
216
257
|
},
|
|
217
|
-
/* @__PURE__ */
|
|
218
|
-
), /* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
|
|
259
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
219
260
|
TouchableOpacity,
|
|
220
261
|
{
|
|
221
262
|
onPress: () => onApprove(action.id),
|
|
222
263
|
style: [styles.btn, styles.approveBtn, { backgroundColor: primaryColor }],
|
|
223
264
|
activeOpacity: 0.7,
|
|
224
|
-
accessibilityLabel: "Aprovar a\xE7\xE3o"
|
|
265
|
+
accessibilityLabel: "Aprovar a\xE7\xE3o",
|
|
266
|
+
testID: "assistant-action-approve"
|
|
225
267
|
},
|
|
226
|
-
/* @__PURE__ */
|
|
268
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles.approveBtnText }, "Aprovar")
|
|
227
269
|
)));
|
|
228
270
|
}
|
|
229
271
|
function ConfirmCard({
|
|
@@ -248,7 +290,7 @@ function ConfirmCard({
|
|
|
248
290
|
cancelBackground,
|
|
249
291
|
cancelTextColor
|
|
250
292
|
} = deriveConfirmCardContent(action, palette, confirmStrings);
|
|
251
|
-
return /* @__PURE__ */
|
|
293
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
252
294
|
View,
|
|
253
295
|
{
|
|
254
296
|
style: [
|
|
@@ -257,7 +299,7 @@ function ConfirmCard({
|
|
|
257
299
|
],
|
|
258
300
|
testID: "assistant-confirm-card"
|
|
259
301
|
},
|
|
260
|
-
/* @__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(
|
|
261
303
|
Text,
|
|
262
304
|
{
|
|
263
305
|
style: [
|
|
@@ -267,18 +309,18 @@ function ConfirmCard({
|
|
|
267
309
|
},
|
|
268
310
|
title
|
|
269
311
|
)),
|
|
270
|
-
/* @__PURE__ */
|
|
271
|
-
/* @__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(
|
|
272
314
|
TouchableOpacity,
|
|
273
315
|
{
|
|
274
316
|
onPress: () => onReject?.(action.id),
|
|
275
317
|
style: [confirmCardStyles.btn, { backgroundColor: cancelBackground }],
|
|
276
318
|
activeOpacity: 0.7,
|
|
277
|
-
accessibilityLabel:
|
|
319
|
+
accessibilityLabel: cancelLabel,
|
|
278
320
|
testID: "assistant-confirm-reject"
|
|
279
321
|
},
|
|
280
|
-
/* @__PURE__ */
|
|
281
|
-
), /* @__PURE__ */
|
|
322
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
|
|
323
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
282
324
|
TouchableOpacity,
|
|
283
325
|
{
|
|
284
326
|
onPress: () => onApprove?.(action.id),
|
|
@@ -288,10 +330,10 @@ function ConfirmCard({
|
|
|
288
330
|
{ backgroundColor: actionColor }
|
|
289
331
|
],
|
|
290
332
|
activeOpacity: 0.7,
|
|
291
|
-
accessibilityLabel:
|
|
333
|
+
accessibilityLabel: confirmLabel,
|
|
292
334
|
testID: "assistant-confirm-approve"
|
|
293
335
|
},
|
|
294
|
-
/* @__PURE__ */
|
|
336
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
|
|
295
337
|
))
|
|
296
338
|
);
|
|
297
339
|
}
|
|
@@ -356,7 +398,7 @@ function StateIcon({
|
|
|
356
398
|
tone,
|
|
357
399
|
primaryColor
|
|
358
400
|
}) {
|
|
359
|
-
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)));
|
|
360
402
|
}
|
|
361
403
|
var styles = StyleSheet.create({
|
|
362
404
|
container: {
|
|
@@ -447,7 +489,7 @@ function resolvePersonalization(props, remote) {
|
|
|
447
489
|
};
|
|
448
490
|
}
|
|
449
491
|
function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
450
|
-
return /* @__PURE__ */
|
|
492
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
451
493
|
Path,
|
|
452
494
|
{
|
|
453
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",
|
|
@@ -455,8 +497,438 @@ function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
|
455
497
|
}
|
|
456
498
|
));
|
|
457
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
|
+
}
|
|
458
930
|
function HeadsetIcon({ size = 18, color = "#ffffff" }) {
|
|
459
|
-
return /* @__PURE__ */
|
|
931
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
460
932
|
Path,
|
|
461
933
|
{
|
|
462
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",
|
|
@@ -497,195 +969,6 @@ function buildChatTimeline(messages, actions) {
|
|
|
497
969
|
}
|
|
498
970
|
return timeline;
|
|
499
971
|
}
|
|
500
|
-
|
|
501
|
-
// src/components/markdownContent.ts
|
|
502
|
-
var ORDERED_LINE = /^\s*(\d+)\.\s+(.+)$/;
|
|
503
|
-
var BULLET_LINE = /^\s*[-*•]\s+(.+)$/;
|
|
504
|
-
var HEADING_LINE = /^\s*(#{1,6})\s+(.+)$/;
|
|
505
|
-
var FENCE_LINE = /^\s*```\s*([A-Za-z0-9+#_-]*)\s*$/;
|
|
506
|
-
var INLINE_PATTERN = /\[([^\]\n]+)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|__(.+?)__|`([^`]+)`|\*(.+?)\*|_(.+?)_/g;
|
|
507
|
-
var MIN_ENHANCE_LENGTH = 80;
|
|
508
|
-
var SENTENCE_SPLIT = /[^.!?]+[.!?]+(?=\s+[A-ZÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕÇÑ¿¡"“]|$)|[^.!?]+$/g;
|
|
509
|
-
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;
|
|
510
|
-
var INCLUDE_LIST_SENTENCE = /^(.+?)\s+(?:incluem|inclui|include|includes|incluye|incluyen|such as|for example|par exemple|por exemplo)\s+(.+?)\.?\s*$/i;
|
|
511
|
-
function looksLikeMarkdown(content) {
|
|
512
|
-
if (!content) return false;
|
|
513
|
-
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);
|
|
514
|
-
}
|
|
515
|
-
function splitEnumeration(text) {
|
|
516
|
-
const trimmed = text.trim().replace(/\.\s*$/, "");
|
|
517
|
-
if (!trimmed) return [];
|
|
518
|
-
const commaParts = trimmed.split(",").map((part) => part.trim()).filter(Boolean);
|
|
519
|
-
if (commaParts.length <= 1) {
|
|
520
|
-
const conjParts = trimmed.split(/\s+(?:e|and|y|ou|or)\s+/i).map((part) => part.trim());
|
|
521
|
-
return conjParts.filter(Boolean);
|
|
522
|
-
}
|
|
523
|
-
const last = commaParts[commaParts.length - 1];
|
|
524
|
-
const conjMatch = last.match(/^(.+?)\s+(?:e|and|y|ou|or)\s+(.+)$/i);
|
|
525
|
-
if (conjMatch) {
|
|
526
|
-
commaParts[commaParts.length - 1] = conjMatch[1].trim();
|
|
527
|
-
commaParts.push(conjMatch[2].trim());
|
|
528
|
-
}
|
|
529
|
-
return commaParts.filter(Boolean);
|
|
530
|
-
}
|
|
531
|
-
function splitSentences(text) {
|
|
532
|
-
const matches = text.match(SENTENCE_SPLIT);
|
|
533
|
-
if (!matches) return [text.trim()];
|
|
534
|
-
return matches.map((part) => part.trim()).filter(Boolean);
|
|
535
|
-
}
|
|
536
|
-
function formatCapabilitySentence(sentence) {
|
|
537
|
-
const match = CAPABILITY_SENTENCE.exec(sentence.trim());
|
|
538
|
-
if (!match) return null;
|
|
539
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
540
|
-
if (items.length < 3) return null;
|
|
541
|
-
const intro = `${match[1].trim()}:`;
|
|
542
|
-
return `${intro}
|
|
543
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
544
|
-
}
|
|
545
|
-
function formatIncludeListSentence(sentence) {
|
|
546
|
-
const match = INCLUDE_LIST_SENTENCE.exec(sentence.trim());
|
|
547
|
-
if (!match) return null;
|
|
548
|
-
const intro = match[1].trim().replace(/[,:]\s*$/, "");
|
|
549
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
550
|
-
if (items.length < 2) return null;
|
|
551
|
-
return `${intro}:
|
|
552
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
553
|
-
}
|
|
554
|
-
function formatReadableSentence(sentence) {
|
|
555
|
-
return formatCapabilitySentence(sentence) ?? formatIncludeListSentence(sentence) ?? sentence.trim();
|
|
556
|
-
}
|
|
557
|
-
function enhancePlainAssistantContent(content) {
|
|
558
|
-
if (!content?.trim() || looksLikeMarkdown(content)) return content;
|
|
559
|
-
const trimmed = content.trim();
|
|
560
|
-
if (trimmed.length < MIN_ENHANCE_LENGTH) return content;
|
|
561
|
-
const sentences = splitSentences(trimmed);
|
|
562
|
-
if (sentences.length === 0) return content;
|
|
563
|
-
const blocks = sentences.map(formatReadableSentence);
|
|
564
|
-
const enhanced = blocks.join("\n\n");
|
|
565
|
-
return enhanced || content;
|
|
566
|
-
}
|
|
567
|
-
function needsWideChatLayout(content) {
|
|
568
|
-
if (!content?.trim()) return false;
|
|
569
|
-
const prepared = enhancePlainAssistantContent(content);
|
|
570
|
-
return looksLikeMarkdown(prepared) || /\n\n+/.test(prepared);
|
|
571
|
-
}
|
|
572
|
-
function parseMarkdownBlocks(content) {
|
|
573
|
-
const lines = content.replace(/\r\n/g, "\n").split("\n");
|
|
574
|
-
const blocks = [];
|
|
575
|
-
let paragraph = [];
|
|
576
|
-
let bulletItems = [];
|
|
577
|
-
let orderedItems = [];
|
|
578
|
-
let codeLines = null;
|
|
579
|
-
let codeLanguage;
|
|
580
|
-
const flushParagraph = () => {
|
|
581
|
-
if (paragraph.length === 0) return;
|
|
582
|
-
blocks.push({ kind: "paragraph", text: paragraph.join("\n") });
|
|
583
|
-
paragraph = [];
|
|
584
|
-
};
|
|
585
|
-
const flushBullets = () => {
|
|
586
|
-
if (bulletItems.length === 0) return;
|
|
587
|
-
blocks.push({ kind: "bullet", items: bulletItems });
|
|
588
|
-
bulletItems = [];
|
|
589
|
-
};
|
|
590
|
-
const flushOrdered = () => {
|
|
591
|
-
if (orderedItems.length === 0) return;
|
|
592
|
-
blocks.push({ kind: "ordered", items: orderedItems });
|
|
593
|
-
orderedItems = [];
|
|
594
|
-
};
|
|
595
|
-
const flushLists = () => {
|
|
596
|
-
flushBullets();
|
|
597
|
-
flushOrdered();
|
|
598
|
-
};
|
|
599
|
-
const flushCode = () => {
|
|
600
|
-
if (codeLines === null) return;
|
|
601
|
-
blocks.push({
|
|
602
|
-
kind: "codeblock",
|
|
603
|
-
code: codeLines.join("\n"),
|
|
604
|
-
...codeLanguage ? { language: codeLanguage } : {}
|
|
605
|
-
});
|
|
606
|
-
codeLines = null;
|
|
607
|
-
codeLanguage = void 0;
|
|
608
|
-
};
|
|
609
|
-
for (const line of lines) {
|
|
610
|
-
if (codeLines !== null) {
|
|
611
|
-
if (/^\s*```\s*$/.test(line)) {
|
|
612
|
-
flushCode();
|
|
613
|
-
} else {
|
|
614
|
-
codeLines.push(line);
|
|
615
|
-
}
|
|
616
|
-
continue;
|
|
617
|
-
}
|
|
618
|
-
const fence = FENCE_LINE.exec(line);
|
|
619
|
-
if (fence) {
|
|
620
|
-
flushParagraph();
|
|
621
|
-
flushLists();
|
|
622
|
-
codeLines = [];
|
|
623
|
-
codeLanguage = fence[1] || void 0;
|
|
624
|
-
continue;
|
|
625
|
-
}
|
|
626
|
-
const trimmed = line.trim();
|
|
627
|
-
if (!trimmed) {
|
|
628
|
-
flushParagraph();
|
|
629
|
-
flushLists();
|
|
630
|
-
continue;
|
|
631
|
-
}
|
|
632
|
-
const heading = HEADING_LINE.exec(line);
|
|
633
|
-
if (heading) {
|
|
634
|
-
flushParagraph();
|
|
635
|
-
flushLists();
|
|
636
|
-
const level = Math.min(heading[1].length, 3);
|
|
637
|
-
blocks.push({ kind: "heading", level, text: heading[2].trim() });
|
|
638
|
-
continue;
|
|
639
|
-
}
|
|
640
|
-
const ordered = ORDERED_LINE.exec(line);
|
|
641
|
-
if (ordered) {
|
|
642
|
-
flushParagraph();
|
|
643
|
-
flushBullets();
|
|
644
|
-
orderedItems.push(ordered[2].trim());
|
|
645
|
-
continue;
|
|
646
|
-
}
|
|
647
|
-
const bullet = BULLET_LINE.exec(line);
|
|
648
|
-
if (bullet) {
|
|
649
|
-
flushParagraph();
|
|
650
|
-
flushOrdered();
|
|
651
|
-
bulletItems.push(bullet[1].trim());
|
|
652
|
-
continue;
|
|
653
|
-
}
|
|
654
|
-
flushLists();
|
|
655
|
-
paragraph.push(line);
|
|
656
|
-
}
|
|
657
|
-
flushParagraph();
|
|
658
|
-
flushLists();
|
|
659
|
-
flushCode();
|
|
660
|
-
return blocks.length > 0 ? blocks : [{ kind: "paragraph", text: content }];
|
|
661
|
-
}
|
|
662
|
-
function parseInlineMarkdown(text) {
|
|
663
|
-
if (!text) return [{ kind: "text", value: "" }];
|
|
664
|
-
const segments = [];
|
|
665
|
-
let lastIndex = 0;
|
|
666
|
-
INLINE_PATTERN.lastIndex = 0;
|
|
667
|
-
for (let match = INLINE_PATTERN.exec(text); match; match = INLINE_PATTERN.exec(text)) {
|
|
668
|
-
if (match.index > lastIndex) {
|
|
669
|
-
segments.push({ kind: "text", value: text.slice(lastIndex, match.index) });
|
|
670
|
-
}
|
|
671
|
-
if (match[1] && match[2]) {
|
|
672
|
-
segments.push({ kind: "link", value: match[1].trim(), href: match[2] });
|
|
673
|
-
} else if (match[3] || match[4]) {
|
|
674
|
-
segments.push({ kind: "bold", value: (match[3] ?? match[4]).trim() });
|
|
675
|
-
} else if (match[5]) {
|
|
676
|
-
segments.push({ kind: "code", value: match[5] });
|
|
677
|
-
} else if (match[6] || match[7]) {
|
|
678
|
-
segments.push({ kind: "italic", value: (match[6] ?? match[7]).trim() });
|
|
679
|
-
}
|
|
680
|
-
lastIndex = INLINE_PATTERN.lastIndex;
|
|
681
|
-
}
|
|
682
|
-
if (lastIndex < text.length) {
|
|
683
|
-
segments.push({ kind: "text", value: text.slice(lastIndex) });
|
|
684
|
-
}
|
|
685
|
-
return segments.length > 0 ? segments : [{ kind: "text", value: text }];
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// src/components/ChatMarkdown.tsx
|
|
689
972
|
function segmentKey(segment, index) {
|
|
690
973
|
return `${segment.kind}-${index}-${segment.value.slice(0, 12)}`;
|
|
691
974
|
}
|
|
@@ -695,17 +978,17 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
695
978
|
const key = segmentKey(segment, index);
|
|
696
979
|
switch (segment.kind) {
|
|
697
980
|
case "bold":
|
|
698
|
-
return /* @__PURE__ */
|
|
981
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.bold] }, segment.value);
|
|
699
982
|
case "italic":
|
|
700
|
-
return /* @__PURE__ */
|
|
983
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.italic] }, segment.value);
|
|
701
984
|
case "code":
|
|
702
|
-
return /* @__PURE__ */
|
|
985
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
703
986
|
Text,
|
|
704
987
|
{
|
|
705
988
|
key,
|
|
706
989
|
style: [
|
|
707
990
|
baseStyle,
|
|
708
|
-
|
|
991
|
+
styles4.code,
|
|
709
992
|
{
|
|
710
993
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.06)"),
|
|
711
994
|
color: theme.codeColor ?? theme.color
|
|
@@ -715,14 +998,14 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
715
998
|
segment.value
|
|
716
999
|
);
|
|
717
1000
|
case "link":
|
|
718
|
-
return /* @__PURE__ */
|
|
1001
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
719
1002
|
Text,
|
|
720
1003
|
{
|
|
721
1004
|
key,
|
|
722
1005
|
accessibilityRole: "link",
|
|
723
1006
|
style: [
|
|
724
1007
|
baseStyle,
|
|
725
|
-
|
|
1008
|
+
styles4.link,
|
|
726
1009
|
{
|
|
727
1010
|
color: theme.linkColor ?? (theme.variant === "user" ? theme.color : "#2563EB")
|
|
728
1011
|
}
|
|
@@ -749,7 +1032,7 @@ function InlineMarkdown({
|
|
|
749
1032
|
fontSize: theme.fontSize,
|
|
750
1033
|
lineHeight: theme.lineHeight
|
|
751
1034
|
};
|
|
752
|
-
return /* @__PURE__ */
|
|
1035
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseStyle }, renderInlineSegments(text, theme, baseStyle));
|
|
753
1036
|
}
|
|
754
1037
|
function ChatMarkdown({ content, theme, contentWidth }) {
|
|
755
1038
|
const prepared = enhancePlainAssistantContent(content);
|
|
@@ -759,29 +1042,29 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
759
1042
|
fontSize: theme.fontSize,
|
|
760
1043
|
lineHeight: theme.lineHeight
|
|
761
1044
|
};
|
|
762
|
-
const rootStyle = contentWidth ? [
|
|
1045
|
+
const rootStyle = contentWidth ? [styles4.root, { width: contentWidth }] : styles4.root;
|
|
763
1046
|
if (!looksLikeMarkdown(prepared)) {
|
|
764
1047
|
const paragraphs = prepared.split(/\n\n+/).map((part) => part.trim()).filter(Boolean);
|
|
765
1048
|
if (paragraphs.length > 1) {
|
|
766
|
-
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))));
|
|
767
1050
|
}
|
|
768
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseTextStyle }, prepared);
|
|
769
1052
|
}
|
|
770
1053
|
const blocks = parseMarkdownBlocks(prepared);
|
|
771
|
-
return /* @__PURE__ */
|
|
1054
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: rootStyle }, blocks.map((block, blockIndex) => {
|
|
772
1055
|
if (block.kind === "paragraph") {
|
|
773
|
-
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 }));
|
|
774
1057
|
}
|
|
775
1058
|
if (block.kind === "heading") {
|
|
776
1059
|
const scale = block.level === 1 ? 1.25 : block.level === 2 ? 1.15 : 1.05;
|
|
777
1060
|
const headingSize = Math.round((theme.fontSize ?? 15) * scale);
|
|
778
|
-
return /* @__PURE__ */
|
|
1061
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `h-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(
|
|
779
1062
|
Text,
|
|
780
1063
|
{
|
|
781
1064
|
accessibilityRole: "header",
|
|
782
1065
|
style: [
|
|
783
1066
|
baseTextStyle,
|
|
784
|
-
|
|
1067
|
+
styles4.bold,
|
|
785
1068
|
{ fontSize: headingSize, lineHeight: Math.round(headingSize * 1.35) }
|
|
786
1069
|
]
|
|
787
1070
|
},
|
|
@@ -793,23 +1076,23 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
793
1076
|
));
|
|
794
1077
|
}
|
|
795
1078
|
if (block.kind === "codeblock") {
|
|
796
|
-
return /* @__PURE__ */
|
|
1079
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
797
1080
|
View,
|
|
798
1081
|
{
|
|
799
1082
|
key: `code-${blockIndex}`,
|
|
800
1083
|
style: [
|
|
801
|
-
|
|
802
|
-
blockIndex > 0 ?
|
|
1084
|
+
styles4.codeBlock,
|
|
1085
|
+
blockIndex > 0 ? styles4.blockGap : void 0,
|
|
803
1086
|
{
|
|
804
1087
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.055)")
|
|
805
1088
|
}
|
|
806
1089
|
]
|
|
807
1090
|
},
|
|
808
|
-
/* @__PURE__ */
|
|
1091
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
809
1092
|
Text,
|
|
810
1093
|
{
|
|
811
1094
|
style: [
|
|
812
|
-
|
|
1095
|
+
styles4.code,
|
|
813
1096
|
{
|
|
814
1097
|
color: theme.codeColor ?? theme.color,
|
|
815
1098
|
fontSize: (theme.fontSize ?? 15) - 1,
|
|
@@ -822,28 +1105,28 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
822
1105
|
);
|
|
823
1106
|
}
|
|
824
1107
|
if (block.kind === "bullet") {
|
|
825
|
-
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(
|
|
826
1109
|
Text,
|
|
827
1110
|
{
|
|
828
1111
|
key: `ul-${blockIndex}-${itemIndex}`,
|
|
829
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1112
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
830
1113
|
},
|
|
831
1114
|
"\u2022 ",
|
|
832
1115
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
833
1116
|
)));
|
|
834
1117
|
}
|
|
835
|
-
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(
|
|
836
1119
|
Text,
|
|
837
1120
|
{
|
|
838
1121
|
key: `ol-${blockIndex}-${itemIndex}`,
|
|
839
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1122
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
840
1123
|
},
|
|
841
1124
|
`${itemIndex + 1}. `,
|
|
842
1125
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
843
1126
|
)));
|
|
844
1127
|
}));
|
|
845
1128
|
}
|
|
846
|
-
var
|
|
1129
|
+
var styles4 = StyleSheet.create({
|
|
847
1130
|
root: {
|
|
848
1131
|
flexShrink: 1,
|
|
849
1132
|
alignSelf: "stretch"
|
|
@@ -887,7 +1170,7 @@ function AppilotsThemeProvider({
|
|
|
887
1170
|
() => mergeThemeTokens(resolveBaseTheme(mode, systemScheme), theme ?? void 0),
|
|
888
1171
|
[mode, systemScheme, theme]
|
|
889
1172
|
);
|
|
890
|
-
return /* @__PURE__ */
|
|
1173
|
+
return /* @__PURE__ */ React8__default.createElement(ThemeContext.Provider, { value: tokens }, children);
|
|
891
1174
|
}
|
|
892
1175
|
function useAppilotsTheme() {
|
|
893
1176
|
return useContext(ThemeContext);
|
|
@@ -980,177 +1263,6 @@ var appilotsTheme = {
|
|
|
980
1263
|
fromTailwind: appilotsThemeFromTailwind
|
|
981
1264
|
};
|
|
982
1265
|
|
|
983
|
-
// src/i18n/bundles/pt-BR.ts
|
|
984
|
-
var ptBR = {
|
|
985
|
-
chatTitle: "Assistente Appilots",
|
|
986
|
-
clearButton: "Limpar",
|
|
987
|
-
inputPlaceholder: "Digite uma mensagem...",
|
|
988
|
-
emptyTitle: "Como posso ajudar?",
|
|
989
|
-
emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
|
|
990
|
-
thinking: "Pensando...",
|
|
991
|
-
statusAnalyzing: "Analisando a tela...",
|
|
992
|
-
statusWaitingApp: "Aguardando o app responder...",
|
|
993
|
-
statusAdjusting: "Ajustando o plano...",
|
|
994
|
-
poweredBy: "Powered by Appilots",
|
|
995
|
-
approve: "Aprovar",
|
|
996
|
-
reject: "Rejeitar",
|
|
997
|
-
cancelledByUser: "Cancelado pelo usu\xE1rio",
|
|
998
|
-
confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
|
|
999
|
-
confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
|
|
1000
|
-
confirmMessage: 'Tem certeza que deseja "{action}"?',
|
|
1001
|
-
confirmDestructiveApprove: "Sim, executar",
|
|
1002
|
-
confirmApprove: "Confirmar",
|
|
1003
|
-
confirmCancel: "Cancelar",
|
|
1004
|
-
confirmThisAction: "esta a\xE7\xE3o",
|
|
1005
|
-
unknownAction: "A\xE7\xE3o desconhecida",
|
|
1006
|
-
somethingWentWrong: "Algo deu errado",
|
|
1007
|
-
openChatA11y: "Abrir chat do assistente",
|
|
1008
|
-
closeChatA11y: "Fechar chat do assistente",
|
|
1009
|
-
stopGeneratingA11y: "Parar gera\xE7\xE3o",
|
|
1010
|
-
talkToHumanA11y: "Falar com um atendente humano",
|
|
1011
|
-
humanAgentLabel: "Atendente",
|
|
1012
|
-
escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
|
|
1013
|
-
escalationConnected: "Um atendente entrou na conversa.",
|
|
1014
|
-
escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
|
|
1015
|
-
escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
|
|
1016
|
-
escalationOfferChip: "Falar com um atendente",
|
|
1017
|
-
escalationPendingBanner: "Aguardando um atendente...",
|
|
1018
|
-
escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente"
|
|
1019
|
-
};
|
|
1020
|
-
|
|
1021
|
-
// src/i18n/bundles/en.ts
|
|
1022
|
-
var en = {
|
|
1023
|
-
chatTitle: "Appilots Assistant",
|
|
1024
|
-
clearButton: "Clear",
|
|
1025
|
-
inputPlaceholder: "Type a message...",
|
|
1026
|
-
emptyTitle: "How can I help?",
|
|
1027
|
-
emptySubtitle: "I navigate, fill forms, and run actions in this app.",
|
|
1028
|
-
thinking: "Thinking...",
|
|
1029
|
-
statusAnalyzing: "Reading the screen...",
|
|
1030
|
-
statusWaitingApp: "Waiting for the app...",
|
|
1031
|
-
statusAdjusting: "Adjusting the plan...",
|
|
1032
|
-
poweredBy: "Powered by Appilots",
|
|
1033
|
-
approve: "Approve",
|
|
1034
|
-
reject: "Reject",
|
|
1035
|
-
cancelledByUser: "Cancelled by user",
|
|
1036
|
-
confirmDestructiveTitle: "Destructive action",
|
|
1037
|
-
confirmTitle: "Confirmation needed",
|
|
1038
|
-
confirmMessage: 'Are you sure you want to "{action}"?',
|
|
1039
|
-
confirmDestructiveApprove: "Yes, do it",
|
|
1040
|
-
confirmApprove: "Confirm",
|
|
1041
|
-
confirmCancel: "Cancel",
|
|
1042
|
-
confirmThisAction: "this action",
|
|
1043
|
-
unknownAction: "Unknown action",
|
|
1044
|
-
somethingWentWrong: "Something went wrong",
|
|
1045
|
-
openChatA11y: "Open assistant chat",
|
|
1046
|
-
closeChatA11y: "Close assistant chat",
|
|
1047
|
-
stopGeneratingA11y: "Stop generating",
|
|
1048
|
-
talkToHumanA11y: "Talk to a human agent",
|
|
1049
|
-
humanAgentLabel: "Agent",
|
|
1050
|
-
escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
|
|
1051
|
-
escalationConnected: "A human agent joined the conversation.",
|
|
1052
|
-
escalationResolved: "The human handoff has ended. I'm back to help you here.",
|
|
1053
|
-
escalationOffer: "If you prefer, I can bring in a person to help.",
|
|
1054
|
-
escalationOfferChip: "Talk to a human",
|
|
1055
|
-
escalationPendingBanner: "Waiting for a human agent...",
|
|
1056
|
-
escalationActiveBanner: "You're talking to a human agent"
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
|
-
// src/i18n/bundles/es.ts
|
|
1060
|
-
var es = {
|
|
1061
|
-
chatTitle: "Asistente Appilots",
|
|
1062
|
-
clearButton: "Limpiar",
|
|
1063
|
-
inputPlaceholder: "Escribe un mensaje...",
|
|
1064
|
-
emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
|
|
1065
|
-
emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
|
|
1066
|
-
thinking: "Pensando...",
|
|
1067
|
-
statusAnalyzing: "Analizando la pantalla...",
|
|
1068
|
-
statusWaitingApp: "Esperando a la app...",
|
|
1069
|
-
statusAdjusting: "Ajustando el plan...",
|
|
1070
|
-
poweredBy: "Hecho con Appilots",
|
|
1071
|
-
approve: "Aprobar",
|
|
1072
|
-
reject: "Rechazar",
|
|
1073
|
-
cancelledByUser: "Cancelado por el usuario",
|
|
1074
|
-
confirmDestructiveTitle: "Acci\xF3n destructiva",
|
|
1075
|
-
confirmTitle: "Confirmaci\xF3n necesaria",
|
|
1076
|
-
confirmMessage: '\xBFSeguro que quieres "{action}"?',
|
|
1077
|
-
confirmDestructiveApprove: "S\xED, ejecutar",
|
|
1078
|
-
confirmApprove: "Confirmar",
|
|
1079
|
-
confirmCancel: "Cancelar",
|
|
1080
|
-
confirmThisAction: "esta acci\xF3n",
|
|
1081
|
-
unknownAction: "Acci\xF3n desconocida",
|
|
1082
|
-
somethingWentWrong: "Algo sali\xF3 mal",
|
|
1083
|
-
openChatA11y: "Abrir chat del asistente",
|
|
1084
|
-
closeChatA11y: "Cerrar chat del asistente",
|
|
1085
|
-
stopGeneratingA11y: "Detener generaci\xF3n",
|
|
1086
|
-
talkToHumanA11y: "Hablar con un agente humano",
|
|
1087
|
-
humanAgentLabel: "Agente",
|
|
1088
|
-
escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
|
|
1089
|
-
escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
|
|
1090
|
-
escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
|
|
1091
|
-
escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
|
|
1092
|
-
escalationOfferChip: "Hablar con un agente",
|
|
1093
|
-
escalationPendingBanner: "Esperando a un agente...",
|
|
1094
|
-
escalationActiveBanner: "Est\xE1s hablando con un agente humano"
|
|
1095
|
-
};
|
|
1096
|
-
var BUNDLES = {
|
|
1097
|
-
"pt-BR": ptBR,
|
|
1098
|
-
en,
|
|
1099
|
-
es
|
|
1100
|
-
};
|
|
1101
|
-
var DEFAULT_LOCALE = "en";
|
|
1102
|
-
function detectDeviceLocale() {
|
|
1103
|
-
try {
|
|
1104
|
-
let raw;
|
|
1105
|
-
if (Platform.OS === "ios") {
|
|
1106
|
-
const settings = NativeModules?.SettingsManager?.settings;
|
|
1107
|
-
raw = settings?.AppleLocale || (Array.isArray(settings?.AppleLanguages) ? settings?.AppleLanguages?.[0] : void 0);
|
|
1108
|
-
} else if (Platform.OS === "android") {
|
|
1109
|
-
raw = NativeModules?.I18nManager?.localeIdentifier;
|
|
1110
|
-
}
|
|
1111
|
-
if (!raw || typeof raw !== "string") return null;
|
|
1112
|
-
const lower = raw.toLowerCase().replace("_", "-");
|
|
1113
|
-
if (lower.startsWith("pt")) return "pt-BR";
|
|
1114
|
-
if (lower.startsWith("es")) return "es";
|
|
1115
|
-
if (lower.startsWith("en")) return "en";
|
|
1116
|
-
return null;
|
|
1117
|
-
} catch {
|
|
1118
|
-
return null;
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
function resolveLocale(prop) {
|
|
1122
|
-
if (prop && BUNDLES[prop]) return prop;
|
|
1123
|
-
const detected = detectDeviceLocale();
|
|
1124
|
-
if (detected && BUNDLES[detected]) return detected;
|
|
1125
|
-
return DEFAULT_LOCALE;
|
|
1126
|
-
}
|
|
1127
|
-
var I18nContext = createContext(null);
|
|
1128
|
-
function AppilotsI18nProvider({
|
|
1129
|
-
locale,
|
|
1130
|
-
overrides,
|
|
1131
|
-
children
|
|
1132
|
-
}) {
|
|
1133
|
-
const value = useMemo(() => {
|
|
1134
|
-
const resolved = resolveLocale(locale ?? null);
|
|
1135
|
-
const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
|
|
1136
|
-
return {
|
|
1137
|
-
locale: resolved,
|
|
1138
|
-
strings: merged,
|
|
1139
|
-
t: (key) => merged[key]
|
|
1140
|
-
};
|
|
1141
|
-
}, [locale, overrides]);
|
|
1142
|
-
return /* @__PURE__ */ React7__default.createElement(I18nContext.Provider, { value }, children);
|
|
1143
|
-
}
|
|
1144
|
-
function useAppilotsI18n() {
|
|
1145
|
-
const ctx = useContext(I18nContext);
|
|
1146
|
-
if (ctx) return ctx;
|
|
1147
|
-
return {
|
|
1148
|
-
locale: DEFAULT_LOCALE,
|
|
1149
|
-
strings: BUNDLES[DEFAULT_LOCALE],
|
|
1150
|
-
t: (key) => BUNDLES[DEFAULT_LOCALE][key]
|
|
1151
|
-
};
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
1266
|
// src/components/AppilotsChat.tsx
|
|
1155
1267
|
function translateLegacyTheme(legacy) {
|
|
1156
1268
|
const out = {};
|
|
@@ -1181,31 +1293,35 @@ var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get("window");
|
|
|
1181
1293
|
var CHAT_HORIZONTAL_PADDING = 16;
|
|
1182
1294
|
var BUBBLE_HORIZONTAL_PADDING = 14;
|
|
1183
1295
|
var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
|
|
1184
|
-
var APPILOTS_SKIP_PROPS = {
|
|
1185
|
-
__appilotsSkip: true,
|
|
1186
|
-
__appilotsInternal: true
|
|
1187
|
-
};
|
|
1188
1296
|
function AppilotsChat(props) {
|
|
1189
1297
|
const { degraded } = useAppilotsContext();
|
|
1190
1298
|
if (degraded) return null;
|
|
1191
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ React8__default.createElement(AppilotsErrorBoundary, { surface: "chat", fallback: null }, /* @__PURE__ */ React8__default.createElement(AppilotsChatSurface, { ...props }));
|
|
1192
1300
|
}
|
|
1193
1301
|
function AppilotsChatSurface(props) {
|
|
1302
|
+
const [conversationLocale, setConversationLocale] = useState(null);
|
|
1194
1303
|
const { remotePersonalization } = useAppilotsContext();
|
|
1195
1304
|
const themeProp = useMemo(() => {
|
|
1196
1305
|
if (!props.theme) return void 0;
|
|
1197
1306
|
return isLegacyTheme(props.theme) ? translateLegacyTheme(props.theme) : props.theme;
|
|
1198
1307
|
}, [props.theme]);
|
|
1199
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1200
1309
|
AppilotsThemeProvider,
|
|
1201
1310
|
{
|
|
1202
1311
|
theme: resolveTheme(themeProp, remotePersonalization),
|
|
1203
1312
|
mode: resolveThemeMode(props.themeMode, remotePersonalization)
|
|
1204
1313
|
},
|
|
1205
|
-
/* @__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
|
+
)
|
|
1206
1321
|
);
|
|
1207
1322
|
}
|
|
1208
1323
|
function AppilotsChatInner({
|
|
1324
|
+
onReplyLocaleChange,
|
|
1209
1325
|
visible: controlledVisible,
|
|
1210
1326
|
onClose,
|
|
1211
1327
|
placeholder,
|
|
@@ -1221,14 +1337,22 @@ function AppilotsChatInner({
|
|
|
1221
1337
|
triggerButton = "default",
|
|
1222
1338
|
triggerIcon,
|
|
1223
1339
|
triggerButtonColor: triggerButtonColorProp,
|
|
1224
|
-
triggerButtonImage: triggerButtonImageProp
|
|
1340
|
+
triggerButtonImage: triggerButtonImageProp,
|
|
1341
|
+
experience: experienceProp,
|
|
1342
|
+
speech: speechProp
|
|
1225
1343
|
}) {
|
|
1226
1344
|
const theme = useAppilotsTheme();
|
|
1227
|
-
const { strings, t } = useAppilotsI18n();
|
|
1345
|
+
const { strings, t, locale: resolvedLocale } = useAppilotsI18n();
|
|
1228
1346
|
const {
|
|
1229
1347
|
messages,
|
|
1348
|
+
mission,
|
|
1349
|
+
pauseMission,
|
|
1350
|
+
resumeMission,
|
|
1351
|
+
cancelMission,
|
|
1352
|
+
replyLocale,
|
|
1230
1353
|
isLoading,
|
|
1231
1354
|
loadingStatusKey,
|
|
1355
|
+
hasStartedActing,
|
|
1232
1356
|
sendMessage,
|
|
1233
1357
|
cancelMessage,
|
|
1234
1358
|
clearMessages,
|
|
@@ -1243,6 +1367,9 @@ function AppilotsChatInner({
|
|
|
1243
1367
|
offer: t("escalationOffer")
|
|
1244
1368
|
}
|
|
1245
1369
|
});
|
|
1370
|
+
useEffect(() => {
|
|
1371
|
+
onReplyLocaleChange(replyLocale);
|
|
1372
|
+
}, [replyLocale, onReplyLocaleChange]);
|
|
1246
1373
|
const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = useAppilotsActions({ autoExecute });
|
|
1247
1374
|
const { emit, remotePersonalization } = useAppilotsContext();
|
|
1248
1375
|
const {
|
|
@@ -1268,7 +1395,7 @@ function AppilotsChatInner({
|
|
|
1268
1395
|
);
|
|
1269
1396
|
const allActions = [...pendingActions, ...executingActions, ...completedActions];
|
|
1270
1397
|
const timeline = buildChatTimeline(messages, allActions);
|
|
1271
|
-
const lastAssistantMessageId =
|
|
1398
|
+
const lastAssistantMessageId = React8__default.useMemo(() => {
|
|
1272
1399
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1273
1400
|
if (messages[i].role === "assistant") return messages[i].id;
|
|
1274
1401
|
}
|
|
@@ -1279,7 +1406,65 @@ function AppilotsChatInner({
|
|
|
1279
1406
|
const [inputText, setInputText] = useState("");
|
|
1280
1407
|
const flatListRef = useRef(null);
|
|
1281
1408
|
const slideAnim = useRef(new Animated.Value(SCREEN_HEIGHT)).current;
|
|
1282
|
-
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" };
|
|
1283
1468
|
const showSuggestedPrompts = shouldShowSuggestedPrompts({
|
|
1284
1469
|
isVisible,
|
|
1285
1470
|
messageCount: messages.length,
|
|
@@ -1290,14 +1475,38 @@ function AppilotsChatInner({
|
|
|
1290
1475
|
limit: 3
|
|
1291
1476
|
});
|
|
1292
1477
|
const openChat = useCallback(() => {
|
|
1478
|
+
setExplicitlyOpened(true);
|
|
1293
1479
|
setInternalVisible(true);
|
|
1294
1480
|
emit({ type: "chat:open", timestamp: Date.now(), data: {} });
|
|
1295
1481
|
}, [emit]);
|
|
1296
1482
|
const closeChat = useCallback(() => {
|
|
1483
|
+
setExplicitlyOpened(false);
|
|
1297
1484
|
setInternalVisible(false);
|
|
1298
1485
|
onClose?.();
|
|
1299
1486
|
emit({ type: "chat:close", timestamp: Date.now(), data: {} });
|
|
1300
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]);
|
|
1301
1510
|
useEffect(() => {
|
|
1302
1511
|
if (mode === "inline") return;
|
|
1303
1512
|
Animated.spring(slideAnim, {
|
|
@@ -1312,6 +1521,12 @@ function AppilotsChatInner({
|
|
|
1312
1521
|
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
|
|
1313
1522
|
}
|
|
1314
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
|
+
});
|
|
1315
1530
|
const handleSend = useCallback(() => {
|
|
1316
1531
|
if (!inputText.trim()) return;
|
|
1317
1532
|
sendMessage(inputText.trim());
|
|
@@ -1321,11 +1536,11 @@ function AppilotsChatInner({
|
|
|
1321
1536
|
({ item }) => {
|
|
1322
1537
|
if (item.role === "system") {
|
|
1323
1538
|
const isOffer = item.metadata?.escalationOffer === true;
|
|
1324
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.systemMessageContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1325
1540
|
Text,
|
|
1326
1541
|
{
|
|
1327
1542
|
style: [
|
|
1328
|
-
|
|
1543
|
+
styles5.systemMessageText,
|
|
1329
1544
|
{
|
|
1330
1545
|
color: theme.colors.textSecondary,
|
|
1331
1546
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1334,13 +1549,13 @@ function AppilotsChatInner({
|
|
|
1334
1549
|
]
|
|
1335
1550
|
},
|
|
1336
1551
|
item.content
|
|
1337
|
-
), isOffer && !escalation && /* @__PURE__ */
|
|
1552
|
+
), isOffer && !escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1338
1553
|
TouchableOpacity,
|
|
1339
1554
|
{
|
|
1340
1555
|
...APPILOTS_SKIP_PROPS,
|
|
1341
1556
|
style: [
|
|
1342
|
-
|
|
1343
|
-
|
|
1557
|
+
styles5.chip,
|
|
1558
|
+
styles5.escalationOfferChip,
|
|
1344
1559
|
{
|
|
1345
1560
|
backgroundColor: theme.colors.surface,
|
|
1346
1561
|
borderColor: theme.colors.border,
|
|
@@ -1353,12 +1568,12 @@ function AppilotsChatInner({
|
|
|
1353
1568
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1354
1569
|
testID: "escalation-offer-chip"
|
|
1355
1570
|
},
|
|
1356
|
-
/* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1571
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
|
|
1572
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1358
1573
|
Text,
|
|
1359
1574
|
{
|
|
1360
1575
|
style: [
|
|
1361
|
-
|
|
1576
|
+
styles5.chipText,
|
|
1362
1577
|
{
|
|
1363
1578
|
color: theme.colors.text,
|
|
1364
1579
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1374,11 +1589,11 @@ function AppilotsChatInner({
|
|
|
1374
1589
|
const isHumanAgent = item.role === "human_agent";
|
|
1375
1590
|
const useWideAssistantLayout = !isUser && needsWideChatLayout(item.content);
|
|
1376
1591
|
if (isHumanAgent) {
|
|
1377
|
-
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(
|
|
1378
1593
|
Text,
|
|
1379
1594
|
{
|
|
1380
1595
|
style: [
|
|
1381
|
-
|
|
1596
|
+
styles5.humanAgentLabel,
|
|
1382
1597
|
{
|
|
1383
1598
|
color: theme.colors.textSecondary,
|
|
1384
1599
|
fontFamily: theme.typography.fontFamily
|
|
@@ -1386,17 +1601,17 @@ function AppilotsChatInner({
|
|
|
1386
1601
|
]
|
|
1387
1602
|
},
|
|
1388
1603
|
escalation?.operatorName ?? strings.humanAgentLabel
|
|
1389
|
-
)), /* @__PURE__ */
|
|
1604
|
+
)), /* @__PURE__ */ React8__default.createElement(
|
|
1390
1605
|
View,
|
|
1391
1606
|
{
|
|
1392
1607
|
accessibilityLabel: item.content,
|
|
1393
1608
|
style: [
|
|
1394
|
-
|
|
1395
|
-
|
|
1609
|
+
styles5.messageBubble,
|
|
1610
|
+
styles5.assistantBubble,
|
|
1396
1611
|
{ backgroundColor: theme.colors.surface }
|
|
1397
1612
|
]
|
|
1398
1613
|
},
|
|
1399
|
-
/* @__PURE__ */
|
|
1614
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1400
1615
|
ChatMarkdown,
|
|
1401
1616
|
{
|
|
1402
1617
|
content: item.content,
|
|
@@ -1411,21 +1626,21 @@ function AppilotsChatInner({
|
|
|
1411
1626
|
)
|
|
1412
1627
|
));
|
|
1413
1628
|
}
|
|
1414
|
-
return /* @__PURE__ */
|
|
1629
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1415
1630
|
View,
|
|
1416
1631
|
{
|
|
1417
1632
|
testID: isUser ? void 0 : item.id === lastAssistantMessageId ? "assistant-last-message" : "assistant-message",
|
|
1418
1633
|
accessibilityLabel: isUser ? void 0 : item.content,
|
|
1419
1634
|
style: [
|
|
1420
|
-
|
|
1421
|
-
isUser ? [
|
|
1422
|
-
|
|
1423
|
-
useWideAssistantLayout &&
|
|
1635
|
+
styles5.messageBubble,
|
|
1636
|
+
isUser ? [styles5.userBubble, { backgroundColor: theme.colors.primary }] : [
|
|
1637
|
+
styles5.assistantBubble,
|
|
1638
|
+
useWideAssistantLayout && styles5.assistantBubbleWide,
|
|
1424
1639
|
{ backgroundColor: theme.colors.surface }
|
|
1425
1640
|
]
|
|
1426
1641
|
]
|
|
1427
1642
|
},
|
|
1428
|
-
/* @__PURE__ */
|
|
1643
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1429
1644
|
ChatMarkdown,
|
|
1430
1645
|
{
|
|
1431
1646
|
content: item.content,
|
|
@@ -1443,19 +1658,12 @@ function AppilotsChatInner({
|
|
|
1443
1658
|
},
|
|
1444
1659
|
[theme, lastAssistantMessageId, escalation, requestHuman, strings]
|
|
1445
1660
|
);
|
|
1446
|
-
const requireApproval = useCallback(
|
|
1447
|
-
(action) => {
|
|
1448
|
-
if (action.status !== "pending") return false;
|
|
1449
|
-
if (action.type === "confirm") return true;
|
|
1450
|
-
return !autoExecute;
|
|
1451
|
-
},
|
|
1452
|
-
[autoExecute]
|
|
1453
|
-
);
|
|
1454
1661
|
const renderBreadcrumb = useCallback(
|
|
1455
|
-
(actions) => /* @__PURE__ */
|
|
1662
|
+
(actions) => /* @__PURE__ */ React8__default.createElement(
|
|
1456
1663
|
ActionBreadcrumb,
|
|
1457
1664
|
{
|
|
1458
1665
|
actions,
|
|
1666
|
+
locale: resolvedLocale,
|
|
1459
1667
|
primaryColor: theme.colors.primary,
|
|
1460
1668
|
textColor: theme.colors.text,
|
|
1461
1669
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1491,6 +1699,8 @@ function AppilotsChatInner({
|
|
|
1491
1699
|
theme.colors.warning,
|
|
1492
1700
|
theme.colors.error,
|
|
1493
1701
|
theme.typography.fontFamily,
|
|
1702
|
+
strings,
|
|
1703
|
+
resolvedLocale,
|
|
1494
1704
|
requireApproval,
|
|
1495
1705
|
approveAction,
|
|
1496
1706
|
rejectAction
|
|
@@ -1503,17 +1713,17 @@ function AppilotsChatInner({
|
|
|
1503
1713
|
const showEmptySubtitle = resolvedEmptySubtitle.length > 0 && !(showSuggestedPrompts && suggestedPrompts.length > 0);
|
|
1504
1714
|
const renderAvatar = () => {
|
|
1505
1715
|
if (!assistantAvatar) {
|
|
1506
|
-
return /* @__PURE__ */
|
|
1716
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles5.headerDot, { backgroundColor: theme.colors.primary }] });
|
|
1507
1717
|
}
|
|
1508
1718
|
if (typeof assistantAvatar === "string") {
|
|
1509
|
-
return /* @__PURE__ */
|
|
1719
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: { uri: assistantAvatar }, style: styles5.headerAvatar });
|
|
1510
1720
|
}
|
|
1511
1721
|
if (typeof assistantAvatar === "number") {
|
|
1512
|
-
return /* @__PURE__ */
|
|
1722
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: assistantAvatar, style: styles5.headerAvatar });
|
|
1513
1723
|
}
|
|
1514
|
-
return /* @__PURE__ */
|
|
1724
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerAvatarSlot }, assistantAvatar);
|
|
1515
1725
|
};
|
|
1516
|
-
const showTrigger = mode === "bubble" &&
|
|
1726
|
+
const showTrigger = mode === "bubble" && surface === "none" && experience.entry.includes("fab") && controlledVisible === void 0 && triggerButton !== "none";
|
|
1517
1727
|
const fabPositionStyle = (() => {
|
|
1518
1728
|
switch (position) {
|
|
1519
1729
|
case "bottom-left":
|
|
@@ -1527,15 +1737,15 @@ function AppilotsChatInner({
|
|
|
1527
1737
|
return { bottom: 24, right: 24 };
|
|
1528
1738
|
}
|
|
1529
1739
|
})();
|
|
1530
|
-
const chatSurface = /* @__PURE__ */
|
|
1740
|
+
const chatSurface = /* @__PURE__ */ React8__default.createElement(
|
|
1531
1741
|
View,
|
|
1532
1742
|
{
|
|
1533
1743
|
...APPILOTS_SKIP_PROPS,
|
|
1534
1744
|
style: [
|
|
1535
|
-
|
|
1536
|
-
mode === "fullscreen" &&
|
|
1537
|
-
mode === "sidebar" &&
|
|
1538
|
-
mode === "inline" &&
|
|
1745
|
+
styles5.chatContainer,
|
|
1746
|
+
mode === "fullscreen" && styles5.chatContainerFullscreen,
|
|
1747
|
+
mode === "sidebar" && styles5.chatContainerSidebar,
|
|
1748
|
+
mode === "inline" && styles5.chatContainerInline,
|
|
1539
1749
|
{
|
|
1540
1750
|
backgroundColor: theme.colors.background,
|
|
1541
1751
|
borderTopLeftRadius: theme.radii.lg,
|
|
@@ -1543,11 +1753,11 @@ function AppilotsChatInner({
|
|
|
1543
1753
|
}
|
|
1544
1754
|
]
|
|
1545
1755
|
},
|
|
1546
|
-
/* @__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(
|
|
1547
1757
|
Text,
|
|
1548
1758
|
{
|
|
1549
1759
|
style: [
|
|
1550
|
-
|
|
1760
|
+
styles5.headerTitle,
|
|
1551
1761
|
{
|
|
1552
1762
|
color: theme.colors.text,
|
|
1553
1763
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1556,46 +1766,50 @@ function AppilotsChatInner({
|
|
|
1556
1766
|
]
|
|
1557
1767
|
},
|
|
1558
1768
|
resolvedHeaderTitle
|
|
1559
|
-
)), /* @__PURE__ */
|
|
1769
|
+
)), /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerActions }, /* @__PURE__ */ React8__default.createElement(
|
|
1560
1770
|
TouchableOpacity,
|
|
1561
1771
|
{
|
|
1562
1772
|
...APPILOTS_SKIP_PROPS,
|
|
1563
1773
|
onPress: () => requestHuman("user_requested"),
|
|
1564
|
-
style:
|
|
1774
|
+
style: styles5.headerButton,
|
|
1565
1775
|
accessibilityRole: "button",
|
|
1566
1776
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1567
1777
|
testID: "escalation-header-button"
|
|
1568
1778
|
},
|
|
1569
|
-
/* @__PURE__ */
|
|
1779
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1570
1780
|
HeadsetIcon,
|
|
1571
1781
|
{
|
|
1572
1782
|
size: 16,
|
|
1573
1783
|
color: escalation ? theme.colors.primary : theme.colors.textSecondary
|
|
1574
1784
|
}
|
|
1575
1785
|
)
|
|
1576
|
-
), /* @__PURE__ */
|
|
1786
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
1577
1787
|
TouchableOpacity,
|
|
1578
1788
|
{
|
|
1579
1789
|
...APPILOTS_SKIP_PROPS,
|
|
1580
1790
|
onPress: clearMessages,
|
|
1581
|
-
style:
|
|
1791
|
+
style: styles5.headerButton,
|
|
1792
|
+
accessibilityRole: "button",
|
|
1793
|
+
testID: "assistant-clear"
|
|
1582
1794
|
},
|
|
1583
|
-
/* @__PURE__ */
|
|
1584
|
-
), 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(
|
|
1585
1797
|
TouchableOpacity,
|
|
1586
1798
|
{
|
|
1587
1799
|
...APPILOTS_SKIP_PROPS,
|
|
1588
1800
|
onPress: closeChat,
|
|
1589
|
-
style:
|
|
1590
|
-
|
|
1801
|
+
style: styles5.closeButton,
|
|
1802
|
+
accessibilityRole: "button",
|
|
1803
|
+
accessibilityLabel: strings.closeChatA11y,
|
|
1804
|
+
testID: "assistant-close"
|
|
1591
1805
|
},
|
|
1592
|
-
/* @__PURE__ */
|
|
1806
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles5.closeButtonText, { color: theme.colors.text }] }, "\u2715")
|
|
1593
1807
|
))),
|
|
1594
|
-
escalation && /* @__PURE__ */
|
|
1808
|
+
escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1595
1809
|
View,
|
|
1596
1810
|
{
|
|
1597
1811
|
style: [
|
|
1598
|
-
|
|
1812
|
+
styles5.escalationBanner,
|
|
1599
1813
|
{
|
|
1600
1814
|
borderBottomColor: theme.colors.border,
|
|
1601
1815
|
backgroundColor: theme.colors.primary + "0d"
|
|
@@ -1603,12 +1817,12 @@ function AppilotsChatInner({
|
|
|
1603
1817
|
],
|
|
1604
1818
|
testID: "escalation-banner"
|
|
1605
1819
|
},
|
|
1606
|
-
/* @__PURE__ */
|
|
1607
|
-
/* @__PURE__ */
|
|
1820
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
|
|
1821
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1608
1822
|
Text,
|
|
1609
1823
|
{
|
|
1610
1824
|
style: [
|
|
1611
|
-
|
|
1825
|
+
styles5.escalationBannerText,
|
|
1612
1826
|
{
|
|
1613
1827
|
color: theme.colors.textSecondary,
|
|
1614
1828
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1619,10 +1833,11 @@ function AppilotsChatInner({
|
|
|
1619
1833
|
escalation.status === "pending" ? strings.escalationPendingBanner : strings.escalationActiveBanner
|
|
1620
1834
|
)
|
|
1621
1835
|
),
|
|
1622
|
-
/* @__PURE__ */
|
|
1836
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1623
1837
|
FlatList,
|
|
1624
1838
|
{
|
|
1625
1839
|
...APPILOTS_SKIP_PROPS,
|
|
1840
|
+
testID: "assistant-transcript",
|
|
1626
1841
|
ref: flatListRef,
|
|
1627
1842
|
data: timeline,
|
|
1628
1843
|
keyExtractor: (item) => item.type === "message" ? item.data.id : item.key,
|
|
@@ -1635,34 +1850,34 @@ function AppilotsChatInner({
|
|
|
1635
1850
|
}
|
|
1636
1851
|
return null;
|
|
1637
1852
|
},
|
|
1638
|
-
contentContainerStyle:
|
|
1639
|
-
ListEmptyComponent: /* @__PURE__ */
|
|
1853
|
+
contentContainerStyle: styles5.messageList,
|
|
1854
|
+
ListEmptyComponent: /* @__PURE__ */ React8__default.createElement(View, { style: styles5.emptyState }, emptyStateIcon && isImageSource(emptyStateIcon) ? /* @__PURE__ */ React8__default.createElement(
|
|
1640
1855
|
Image,
|
|
1641
1856
|
{
|
|
1642
1857
|
source: typeof emptyStateIcon === "string" ? { uri: emptyStateIcon } : emptyStateIcon,
|
|
1643
|
-
style:
|
|
1858
|
+
style: styles5.emptyIconImage,
|
|
1644
1859
|
resizeMode: "contain"
|
|
1645
1860
|
}
|
|
1646
|
-
) : /* @__PURE__ */
|
|
1861
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1647
1862
|
View,
|
|
1648
1863
|
{
|
|
1649
|
-
style: [
|
|
1864
|
+
style: [styles5.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
|
|
1650
1865
|
},
|
|
1651
|
-
emptyStateIcon ? /* @__PURE__ */
|
|
1652
|
-
), /* @__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(
|
|
1653
1868
|
Text,
|
|
1654
1869
|
{
|
|
1655
1870
|
style: [
|
|
1656
|
-
|
|
1871
|
+
styles5.emptyTitle,
|
|
1657
1872
|
{ color: theme.colors.text, fontFamily: theme.typography.fontFamily }
|
|
1658
1873
|
]
|
|
1659
1874
|
},
|
|
1660
1875
|
resolvedEmptyTitle
|
|
1661
|
-
), showEmptySubtitle && /* @__PURE__ */
|
|
1876
|
+
), showEmptySubtitle && /* @__PURE__ */ React8__default.createElement(
|
|
1662
1877
|
Text,
|
|
1663
1878
|
{
|
|
1664
1879
|
style: [
|
|
1665
|
-
|
|
1880
|
+
styles5.emptySubtitle,
|
|
1666
1881
|
{
|
|
1667
1882
|
color: theme.colors.textSecondary,
|
|
1668
1883
|
fontFamily: theme.typography.fontFamily
|
|
@@ -1671,12 +1886,12 @@ function AppilotsChatInner({
|
|
|
1671
1886
|
numberOfLines: 2
|
|
1672
1887
|
},
|
|
1673
1888
|
resolvedEmptySubtitle
|
|
1674
|
-
), 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(
|
|
1675
1890
|
TouchableOpacity,
|
|
1676
1891
|
{
|
|
1677
1892
|
key: `${prompt.source}:${prompt.text}`,
|
|
1678
1893
|
style: [
|
|
1679
|
-
|
|
1894
|
+
styles5.chip,
|
|
1680
1895
|
{
|
|
1681
1896
|
backgroundColor: theme.colors.surface,
|
|
1682
1897
|
borderColor: theme.colors.border,
|
|
@@ -1687,11 +1902,11 @@ function AppilotsChatInner({
|
|
|
1687
1902
|
activeOpacity: 0.7,
|
|
1688
1903
|
accessibilityLabel: `Suggested prompt: ${prompt.text}`
|
|
1689
1904
|
},
|
|
1690
|
-
/* @__PURE__ */
|
|
1905
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1691
1906
|
Text,
|
|
1692
1907
|
{
|
|
1693
1908
|
style: [
|
|
1694
|
-
|
|
1909
|
+
styles5.chipText,
|
|
1695
1910
|
{
|
|
1696
1911
|
color: theme.colors.buttonText,
|
|
1697
1912
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1703,20 +1918,20 @@ function AppilotsChatInner({
|
|
|
1703
1918
|
prompt.text
|
|
1704
1919
|
)
|
|
1705
1920
|
)))),
|
|
1706
|
-
ListFooterComponent: isLoading ? /* @__PURE__ */
|
|
1921
|
+
ListFooterComponent: isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
1707
1922
|
View,
|
|
1708
1923
|
{
|
|
1709
1924
|
style: [
|
|
1710
|
-
|
|
1711
|
-
|
|
1925
|
+
styles5.messageBubble,
|
|
1926
|
+
styles5.assistantBubble,
|
|
1712
1927
|
{ backgroundColor: theme.colors.surface }
|
|
1713
1928
|
]
|
|
1714
1929
|
},
|
|
1715
|
-
/* @__PURE__ */
|
|
1930
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1716
1931
|
Text,
|
|
1717
1932
|
{
|
|
1718
1933
|
style: [
|
|
1719
|
-
|
|
1934
|
+
styles5.messageText,
|
|
1720
1935
|
{ color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
|
|
1721
1936
|
]
|
|
1722
1937
|
},
|
|
@@ -1725,22 +1940,48 @@ function AppilotsChatInner({
|
|
|
1725
1940
|
) : null
|
|
1726
1941
|
}
|
|
1727
1942
|
),
|
|
1728
|
-
/* @__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(
|
|
1729
1970
|
View,
|
|
1730
1971
|
{
|
|
1731
1972
|
style: [
|
|
1732
|
-
|
|
1973
|
+
styles5.inputContainer,
|
|
1733
1974
|
{
|
|
1734
1975
|
borderTopColor: theme.colors.border,
|
|
1735
1976
|
paddingBottom: Math.max(insets.bottom, 10)
|
|
1736
1977
|
}
|
|
1737
1978
|
]
|
|
1738
1979
|
},
|
|
1739
|
-
/* @__PURE__ */
|
|
1980
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1740
1981
|
TextInput,
|
|
1741
1982
|
{
|
|
1742
1983
|
style: [
|
|
1743
|
-
|
|
1984
|
+
styles5.input,
|
|
1744
1985
|
{
|
|
1745
1986
|
backgroundColor: theme.colors.surface,
|
|
1746
1987
|
color: theme.colors.text,
|
|
@@ -1757,16 +1998,35 @@ function AppilotsChatInner({
|
|
|
1757
1998
|
multiline: true,
|
|
1758
1999
|
blurOnSubmit: false,
|
|
1759
2000
|
scrollEnabled: true,
|
|
1760
|
-
editable: !isLoading,
|
|
2001
|
+
editable: !isLoading && (!mission || ["completed", "cancelled"].includes(mission.status)),
|
|
1761
2002
|
testID: "assistant-input",
|
|
1762
2003
|
__appilotsInternal: true
|
|
1763
2004
|
}
|
|
1764
2005
|
),
|
|
1765
|
-
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(
|
|
1766
2026
|
TouchableOpacity,
|
|
1767
2027
|
{
|
|
1768
2028
|
style: [
|
|
1769
|
-
|
|
2029
|
+
styles5.sendButton,
|
|
1770
2030
|
{
|
|
1771
2031
|
backgroundColor: theme.colors.primary,
|
|
1772
2032
|
borderRadius: theme.radii.md
|
|
@@ -1778,31 +2038,31 @@ function AppilotsChatInner({
|
|
|
1778
2038
|
testID: "appilots-stop-button",
|
|
1779
2039
|
activeOpacity: 0.7
|
|
1780
2040
|
},
|
|
1781
|
-
/* @__PURE__ */
|
|
1782
|
-
) : /* @__PURE__ */
|
|
2041
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u25A0")
|
|
2042
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1783
2043
|
TouchableOpacity,
|
|
1784
2044
|
{
|
|
1785
2045
|
style: [
|
|
1786
|
-
|
|
2046
|
+
styles5.sendButton,
|
|
1787
2047
|
{
|
|
1788
2048
|
backgroundColor: inputText.trim() ? theme.colors.primary : theme.colors.primary + "40",
|
|
1789
2049
|
borderRadius: theme.radii.md
|
|
1790
2050
|
}
|
|
1791
2051
|
],
|
|
1792
2052
|
onPress: handleSend,
|
|
1793
|
-
disabled: !inputText.trim(),
|
|
2053
|
+
disabled: !inputText.trim() || !!(mission && !["completed", "cancelled"].includes(mission.status)),
|
|
1794
2054
|
activeOpacity: 0.7,
|
|
1795
2055
|
accessibilityRole: "button",
|
|
1796
2056
|
testID: "assistant-send"
|
|
1797
2057
|
},
|
|
1798
|
-
/* @__PURE__ */
|
|
2058
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u2191")
|
|
1799
2059
|
)
|
|
1800
2060
|
),
|
|
1801
|
-
poweredByVisible && /* @__PURE__ */
|
|
2061
|
+
poweredByVisible && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.poweredByContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1802
2062
|
Text,
|
|
1803
2063
|
{
|
|
1804
2064
|
style: [
|
|
1805
|
-
|
|
2065
|
+
styles5.poweredByText,
|
|
1806
2066
|
{
|
|
1807
2067
|
color: theme.colors.textSecondary,
|
|
1808
2068
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1818,8 +2078,8 @@ function AppilotsChatInner({
|
|
|
1818
2078
|
}
|
|
1819
2079
|
const renderTrigger = () => {
|
|
1820
2080
|
if (triggerButton === "none") return null;
|
|
1821
|
-
if (triggerButton !== "default" &&
|
|
1822
|
-
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(
|
|
1823
2083
|
TouchableOpacity,
|
|
1824
2084
|
{
|
|
1825
2085
|
...APPILOTS_SKIP_PROPS,
|
|
@@ -1832,12 +2092,12 @@ function AppilotsChatInner({
|
|
|
1832
2092
|
triggerButton
|
|
1833
2093
|
));
|
|
1834
2094
|
}
|
|
1835
|
-
return /* @__PURE__ */
|
|
2095
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1836
2096
|
TouchableOpacity,
|
|
1837
2097
|
{
|
|
1838
2098
|
...APPILOTS_SKIP_PROPS,
|
|
1839
2099
|
style: [
|
|
1840
|
-
|
|
2100
|
+
styles5.fab,
|
|
1841
2101
|
fabPositionStyle,
|
|
1842
2102
|
{ backgroundColor: triggerButtonColor ?? theme.colors.primary }
|
|
1843
2103
|
],
|
|
@@ -1847,48 +2107,113 @@ function AppilotsChatInner({
|
|
|
1847
2107
|
accessibilityLabel: strings.openChatA11y,
|
|
1848
2108
|
testID: "assistant-launcher"
|
|
1849
2109
|
},
|
|
1850
|
-
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */
|
|
2110
|
+
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React8__default.createElement(
|
|
1851
2111
|
Image,
|
|
1852
2112
|
{
|
|
1853
2113
|
source: typeof triggerButtonImage === "string" ? { uri: triggerButtonImage } : triggerButtonImage,
|
|
1854
|
-
style:
|
|
2114
|
+
style: styles5.fabImage,
|
|
1855
2115
|
resizeMode: "contain"
|
|
1856
2116
|
}
|
|
1857
|
-
) : /* @__PURE__ */
|
|
2117
|
+
) : /* @__PURE__ */ React8__default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
|
|
1858
2118
|
);
|
|
1859
2119
|
};
|
|
1860
|
-
return /* @__PURE__ */
|
|
1861
|
-
|
|
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,
|
|
1862
2155
|
{
|
|
1863
2156
|
...APPILOTS_SKIP_PROPS,
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
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
|
+
]
|
|
1868
2171
|
},
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
|
|
2172
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
2173
|
+
KeyboardAvoidingView,
|
|
1871
2174
|
{
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
mode === "sidebar" && styles3.modalContainerSidebar,
|
|
1876
|
-
{ transform: [{ translateY: slideAnim }] }
|
|
1877
|
-
]
|
|
2175
|
+
style: styles5.keyboardView,
|
|
2176
|
+
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
2177
|
+
keyboardVerticalOffset: 0
|
|
1878
2178
|
},
|
|
1879
|
-
|
|
1880
|
-
KeyboardAvoidingView,
|
|
1881
|
-
{
|
|
1882
|
-
style: styles3.keyboardView,
|
|
1883
|
-
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
1884
|
-
keyboardVerticalOffset: 0
|
|
1885
|
-
},
|
|
1886
|
-
chatSurface
|
|
1887
|
-
)
|
|
2179
|
+
chatSurface
|
|
1888
2180
|
)
|
|
1889
|
-
));
|
|
2181
|
+
)));
|
|
1890
2182
|
}
|
|
1891
|
-
|
|
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 },
|
|
1892
2217
|
fab: {
|
|
1893
2218
|
position: "absolute",
|
|
1894
2219
|
width: 56,
|
|
@@ -1931,12 +2256,31 @@ var styles3 = StyleSheet.create({
|
|
|
1931
2256
|
flexDirection: "row",
|
|
1932
2257
|
justifyContent: "flex-end"
|
|
1933
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
|
+
},
|
|
1934
2265
|
keyboardView: {
|
|
1935
2266
|
flex: 1,
|
|
1936
2267
|
justifyContent: "flex-end"
|
|
1937
2268
|
},
|
|
2269
|
+
// The sheet has to be able to SHRINK, so its size is a maximum and not
|
|
2270
|
+
// a height. `keyboardView` is a KeyboardAvoidingView on `padding`
|
|
2271
|
+
// (`height` on Android): when the keyboard opens, the space left for
|
|
2272
|
+
// this child drops by the keyboard's height. A fixed `height` ignores
|
|
2273
|
+
// that — the sheet keeps its full size, the parent's
|
|
2274
|
+
// `justifyContent: 'flex-end'` pins it to the bottom, and it overflows
|
|
2275
|
+
// off the TOP, carrying the header away with it. Measured on a
|
|
2276
|
+
// third-party app at 0.75 × 812pt against a ~336pt keyboard: focusing
|
|
2277
|
+
// the input put the entire header off screen, close button included,
|
|
2278
|
+
// and nothing could dismiss the chat. `flex: 1` + `maxHeight` keeps the
|
|
2279
|
+
// same size with the keyboard down and shrinks instead of overflowing
|
|
2280
|
+
// with it up.
|
|
1938
2281
|
chatContainer: {
|
|
1939
|
-
|
|
2282
|
+
flex: 1,
|
|
2283
|
+
maxHeight: SCREEN_HEIGHT * 0.75,
|
|
1940
2284
|
shadowColor: "#000",
|
|
1941
2285
|
shadowOffset: { width: 0, height: -3 },
|
|
1942
2286
|
shadowOpacity: 0.1,
|
|
@@ -1944,15 +2288,19 @@ var styles3 = StyleSheet.create({
|
|
|
1944
2288
|
elevation: 10
|
|
1945
2289
|
},
|
|
1946
2290
|
chatContainerFullscreen: {
|
|
1947
|
-
|
|
2291
|
+
maxHeight: SCREEN_HEIGHT
|
|
1948
2292
|
},
|
|
1949
2293
|
chatContainerSidebar: {
|
|
1950
|
-
|
|
2294
|
+
maxHeight: SCREEN_HEIGHT,
|
|
1951
2295
|
width: SCREEN_WIDTH > 600 ? SCREEN_WIDTH * 0.4 : SCREEN_WIDTH
|
|
1952
2296
|
},
|
|
2297
|
+
// Inline renders in place with no modal and no KeyboardAvoidingView, so
|
|
2298
|
+
// it fills its host instead — the 75% cap above would shrink it to
|
|
2299
|
+
// three quarters of whatever the integrator sized the slot.
|
|
1953
2300
|
chatContainerInline: {
|
|
1954
2301
|
height: "100%",
|
|
1955
2302
|
width: "100%",
|
|
2303
|
+
maxHeight: "100%",
|
|
1956
2304
|
flex: 1
|
|
1957
2305
|
},
|
|
1958
2306
|
header: {
|
|
@@ -2178,6 +2526,11 @@ function ConfirmDialog(_props = {}) {
|
|
|
2178
2526
|
return null;
|
|
2179
2527
|
}
|
|
2180
2528
|
|
|
2529
|
+
// src/auto/appilotsListTotal.ts
|
|
2530
|
+
function appilotsListTotal(total) {
|
|
2531
|
+
return { appilotsTotalItemCount: total };
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2181
2534
|
// src/hoc/canHoldRef.ts
|
|
2182
2535
|
var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
2183
2536
|
var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
|
|
@@ -2204,12 +2557,19 @@ function canHoldRef(type) {
|
|
|
2204
2557
|
}
|
|
2205
2558
|
}
|
|
2206
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
|
+
|
|
2207
2567
|
// src/hoc/createAppilotsInput.tsx
|
|
2208
2568
|
function normalizeId(label) {
|
|
2209
2569
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2210
2570
|
}
|
|
2211
2571
|
function createAppilotsInput(WrappedComponent) {
|
|
2212
|
-
const AppilotsInput =
|
|
2572
|
+
const AppilotsInput = React8__default.forwardRef((props, ref) => {
|
|
2213
2573
|
const {
|
|
2214
2574
|
appilotsId,
|
|
2215
2575
|
appilotsScreen,
|
|
@@ -2264,10 +2624,14 @@ function createAppilotsInput(WrappedComponent) {
|
|
|
2264
2624
|
},
|
|
2265
2625
|
[ref]
|
|
2266
2626
|
);
|
|
2267
|
-
return /* @__PURE__ */
|
|
2627
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2268
2628
|
WrappedComponent,
|
|
2269
2629
|
{
|
|
2270
|
-
...
|
|
2630
|
+
...withDeclaredIdentity(
|
|
2631
|
+
{ label, value, onChangeText, ...rest },
|
|
2632
|
+
fieldId,
|
|
2633
|
+
appilotsEnabled
|
|
2634
|
+
),
|
|
2271
2635
|
...canHoldRef(WrappedComponent) ? { ref: mergedRef } : {}
|
|
2272
2636
|
}
|
|
2273
2637
|
);
|
|
@@ -2279,7 +2643,7 @@ function normalizeId2(label) {
|
|
|
2279
2643
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2280
2644
|
}
|
|
2281
2645
|
function createAppilotsButton(WrappedComponent) {
|
|
2282
|
-
const AppilotsButton =
|
|
2646
|
+
const AppilotsButton = React8__default.forwardRef((props, ref) => {
|
|
2283
2647
|
const {
|
|
2284
2648
|
appilotsId,
|
|
2285
2649
|
appilotsScreen,
|
|
@@ -2305,10 +2669,10 @@ function createAppilotsButton(WrappedComponent) {
|
|
|
2305
2669
|
componentRegistry.unregister(targetId);
|
|
2306
2670
|
};
|
|
2307
2671
|
}, [targetId, appilotsEnabled, press, title, appilotsScreen]);
|
|
2308
|
-
return /* @__PURE__ */
|
|
2672
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2309
2673
|
WrappedComponent,
|
|
2310
2674
|
{
|
|
2311
|
-
...{ title, onPress, ...rest },
|
|
2675
|
+
...withDeclaredIdentity({ title, onPress, ...rest }, targetId, appilotsEnabled),
|
|
2312
2676
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2313
2677
|
}
|
|
2314
2678
|
);
|
|
@@ -2320,7 +2684,7 @@ function normalizeId3(label) {
|
|
|
2320
2684
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2321
2685
|
}
|
|
2322
2686
|
function createAppilotsSwitch(WrappedComponent) {
|
|
2323
|
-
const AppilotsSwitch =
|
|
2687
|
+
const AppilotsSwitch = React8__default.forwardRef((props, ref) => {
|
|
2324
2688
|
const {
|
|
2325
2689
|
appilotsId,
|
|
2326
2690
|
appilotsScreen,
|
|
@@ -2351,10 +2715,14 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2351
2715
|
componentRegistry.unregister(toggleId);
|
|
2352
2716
|
};
|
|
2353
2717
|
}, [toggleId, appilotsEnabled, getValue, setValue, label, appilotsScreen]);
|
|
2354
|
-
return /* @__PURE__ */
|
|
2718
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2355
2719
|
WrappedComponent,
|
|
2356
2720
|
{
|
|
2357
|
-
...
|
|
2721
|
+
...withDeclaredIdentity(
|
|
2722
|
+
{ label, value, onValueChange, ...rest },
|
|
2723
|
+
toggleId,
|
|
2724
|
+
appilotsEnabled
|
|
2725
|
+
),
|
|
2358
2726
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2359
2727
|
}
|
|
2360
2728
|
);
|
|
@@ -2363,4 +2731,4 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2363
2731
|
return AppilotsSwitch;
|
|
2364
2732
|
}
|
|
2365
2733
|
|
|
2366
|
-
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 };
|