@appilots/sdk 0.11.3 → 0.14.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-2ZDELL54.mjs → chunk-6JWU3NBT.mjs} +860 -208
- package/dist/{chunk-ROXXCDIG.mjs → chunk-AKAMWKO6.mjs} +5795 -546
- package/dist/{chunk-5UVMNKPT.js → chunk-GDCBLSYT.js} +8 -8
- package/dist/{chunk-UFMTRGML.js → chunk-JGUDXRXN.js} +1143 -477
- package/dist/{chunk-JKLE5SLN.mjs → chunk-N66DUP54.mjs} +1 -1
- package/dist/{chunk-SUMIABJK.js → chunk-QAZ4TN3Z.js} +5817 -544
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/{index-BR-33WMN.d.mts → index-wMMetyrj.d.mts} +169 -660
- package/dist/{index-BR-33WMN.d.ts → index-wMMetyrj.d.ts} +169 -660
- package/dist/index.d.mts +1500 -76
- package/dist/index.d.ts +1500 -76
- package/dist/index.js +1442 -720
- package/dist/index.mjs +1271 -612
- package/dist/navigation/index.d.mts +22 -1
- package/dist/navigation/index.d.ts +22 -1
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/metro.d.ts +3 -5
- package/metro.js +46 -5
- package/package.json +16 -2
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { AppilotsNavigationContainer } from './chunk-
|
|
2
|
-
import { useAppilotsChat, useAppilotsActions, shouldShowSuggestedPrompts, useSuggestedPrompts } from './chunk-
|
|
3
|
-
export { appilotsSelfCheck, captureSnapshot, executeAction, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts } from './chunk-
|
|
4
|
-
import { defaultLightTheme, describeAction, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, componentRegistry } from './chunk-
|
|
5
|
-
export { AppilotsClient, AppilotsProvider, AppilotsRegistryProvider, RateLimitedError, SDK_VERSION, _patchJsxRuntimes, clearAppilotsDebugTraces, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, defaultDarkTheme, defaultLightTheme, describeAction, elementRegistry, enableAppilotsAutoTracking, getAppilotsDebugTraces, getAutoTrackingState, getGlobalConfig, getIntrospectionDiagnostics, humanizeError, initAppilots, isAutoTrackingEnabled, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-
|
|
6
|
-
import * as
|
|
7
|
-
import
|
|
8
|
-
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, ActivityIndicator, useColorScheme,
|
|
1
|
+
export { AppilotsNavigationContainer } from './chunk-N66DUP54.mjs';
|
|
2
|
+
import { subscribeSpotlight, getSpotlightTarget, AppilotsI18nProvider, useAppilotsI18n, useAppilotsChat, useAppilotsActions, setSpotlightMode, shouldShowSuggestedPrompts, useSuggestedPrompts, subscribeSpotlightAnnouncement } from './chunk-6JWU3NBT.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-6JWU3NBT.mjs';
|
|
4
|
+
import { defaultLightTheme, describeAction, confirmExpiresAt, isRectOnScreen, mergeThemeTokens, resolveBaseTheme, useAppilotsContext, AppilotsErrorBoundary, isSpeechHost, subscribeGeometryHost, geometryAvailability, isGeometryResolved, needsWideChatLayout, componentRegistry, startStillWorkingTimer, appilotsDebugWarn, enhancePlainAssistantContent, looksLikeMarkdown, parseMarkdownBlocks, parseInlineMarkdown, getFiberRoot, shouldSkipSubtree, isModalFiber } from './chunk-AKAMWKO6.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, isSpeechHost, listRegistry, mergeThemeTokens, recordAppilotsDebugTrace, registerScreen, setCurrentScreen, subscribeAppilotsDebugTraces, useAppilotsContext, useResolvedRegistry } from './chunk-AKAMWKO6.mjs';
|
|
6
|
+
import * as React8 from 'react';
|
|
7
|
+
import React8__default, { createContext, useRef, useEffect, useState, useCallback, useSyncExternalStore, useMemo, useContext } from 'react';
|
|
8
|
+
import { StyleSheet, Dimensions, Platform, View, Animated, Text, TouchableOpacity, AccessibilityInfo, ActivityIndicator, useColorScheme, useWindowDimensions, 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 = {
|
|
@@ -79,13 +116,15 @@ var PT_BR_CONFIRM_FALLBACK = {
|
|
|
79
116
|
confirmDestructiveApprove: "Sim, executar",
|
|
80
117
|
confirmApprove: "Confirmar",
|
|
81
118
|
confirmCancel: "Cancelar",
|
|
82
|
-
confirmThisAction: "esta a\xE7\xE3o"
|
|
119
|
+
confirmThisAction: "esta a\xE7\xE3o",
|
|
120
|
+
confirmExpired: "Esta confirma\xE7\xE3o expirou. Pe\xE7a de novo ao assistente para continuar."
|
|
83
121
|
};
|
|
84
122
|
function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE, strings) {
|
|
85
123
|
const payload = action.payload ?? {};
|
|
86
124
|
const isDestructive = isDestructiveAction(action);
|
|
87
125
|
const copy = { ...PT_BR_CONFIRM_FALLBACK, ...strings ?? {} };
|
|
88
|
-
const
|
|
126
|
+
const described = typeof payload.actionDescription === "string" ? payload.actionDescription : "";
|
|
127
|
+
const actionName = described || copy.confirmThisAction;
|
|
89
128
|
const message = typeof payload.message === "string" && payload.message || copy.confirmMessage.replace("{action}", actionName);
|
|
90
129
|
const title = typeof payload.title === "string" && payload.title || (isDestructive ? copy.confirmDestructiveTitle : copy.confirmTitle);
|
|
91
130
|
const confirmLabel = typeof payload.confirmLabel === "string" && payload.confirmLabel || (isDestructive ? copy.confirmDestructiveApprove : copy.confirmApprove);
|
|
@@ -96,6 +135,10 @@ function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE,
|
|
|
96
135
|
message,
|
|
97
136
|
confirmLabel,
|
|
98
137
|
cancelLabel,
|
|
138
|
+
// A bare "Confirm" heard out of context says nothing about what it does.
|
|
139
|
+
confirmA11yLabel: described ? `${confirmLabel}: ${described}` : confirmLabel,
|
|
140
|
+
cancelA11yLabel: described ? `${cancelLabel}: ${described}` : cancelLabel,
|
|
141
|
+
expiredMessage: copy.confirmExpired ?? PT_BR_CONFIRM_FALLBACK.confirmExpired,
|
|
99
142
|
glyph: isDestructive ? "\u26A0" : "?",
|
|
100
143
|
actionColor: isDestructive ? palette.error : palette.primary,
|
|
101
144
|
cardBackground: palette.surface,
|
|
@@ -105,6 +148,79 @@ function deriveConfirmCardContent(action, palette = DEFAULT_BREADCRUMB_PALETTE,
|
|
|
105
148
|
cancelTextColor: palette.textSecondary
|
|
106
149
|
};
|
|
107
150
|
}
|
|
151
|
+
var TARGET_ANNOUNCEMENT = {
|
|
152
|
+
"pt-BR": {
|
|
153
|
+
press: "Tocando em {label}",
|
|
154
|
+
toggle: "Alternando {label}",
|
|
155
|
+
focus: "Selecionando {label}",
|
|
156
|
+
fill: "Preenchendo {label}"
|
|
157
|
+
},
|
|
158
|
+
en: {
|
|
159
|
+
press: "Tapping {label}",
|
|
160
|
+
toggle: "Toggling {label}",
|
|
161
|
+
focus: "Selecting {label}",
|
|
162
|
+
fill: "Filling in {label}"
|
|
163
|
+
},
|
|
164
|
+
es: {
|
|
165
|
+
press: "Tocando {label}",
|
|
166
|
+
toggle: "Cambiando {label}",
|
|
167
|
+
focus: "Seleccionando {label}",
|
|
168
|
+
fill: "Rellenando {label}"
|
|
169
|
+
},
|
|
170
|
+
fr: {
|
|
171
|
+
press: "Appui sur {label}",
|
|
172
|
+
toggle: "Bascule de {label}",
|
|
173
|
+
focus: "S\xE9lection de {label}",
|
|
174
|
+
fill: "Saisie de {label}"
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
function targetAnnouncement(verb, label, locale = "pt-BR") {
|
|
178
|
+
return (TARGET_ANNOUNCEMENT[locale] ?? TARGET_ANNOUNCEMENT["pt-BR"])[verb].replace(
|
|
179
|
+
"{label}",
|
|
180
|
+
label
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
function executorNamesTarget(action) {
|
|
184
|
+
if (action.type === "form_fill") return true;
|
|
185
|
+
if (action.type !== "ui_interaction") return false;
|
|
186
|
+
const interaction = action.payload?.action;
|
|
187
|
+
return !["scroll", "scroll_to"].includes(String(interaction ?? "press"));
|
|
188
|
+
}
|
|
189
|
+
function actionAnnouncement(action, locale, named) {
|
|
190
|
+
const { state, label } = describeAction(action, locale);
|
|
191
|
+
if (state === "failed") return label;
|
|
192
|
+
const executorNames = executorNamesTarget(action);
|
|
193
|
+
if (state === "running") return executorNames ? null : label;
|
|
194
|
+
if (state === "success") return executorNames && !named ? label : null;
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
var reduceMotion = false;
|
|
198
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
199
|
+
var subscription;
|
|
200
|
+
function set(value) {
|
|
201
|
+
if (value === reduceMotion) return;
|
|
202
|
+
reduceMotion = value;
|
|
203
|
+
for (const listener of listeners) listener();
|
|
204
|
+
}
|
|
205
|
+
function subscribe(onChange) {
|
|
206
|
+
listeners.add(onChange);
|
|
207
|
+
if (!subscription) {
|
|
208
|
+
subscription = AccessibilityInfo.addEventListener("reduceMotionChanged", set);
|
|
209
|
+
AccessibilityInfo.isReduceMotionEnabled().then(set, () => {
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return () => {
|
|
213
|
+
listeners.delete(onChange);
|
|
214
|
+
if (listeners.size === 0) {
|
|
215
|
+
subscription?.remove();
|
|
216
|
+
subscription = void 0;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
var get = () => reduceMotion;
|
|
221
|
+
function useReduceMotion() {
|
|
222
|
+
return useSyncExternalStore(subscribe, get, get);
|
|
223
|
+
}
|
|
108
224
|
|
|
109
225
|
// src/components/ActionBreadcrumb.tsx
|
|
110
226
|
function ActionBreadcrumb({
|
|
@@ -114,9 +230,11 @@ function ActionBreadcrumb({
|
|
|
114
230
|
fontFamily,
|
|
115
231
|
palette,
|
|
116
232
|
confirmStrings,
|
|
233
|
+
locale,
|
|
117
234
|
requireApprovalFor,
|
|
118
235
|
onApprove,
|
|
119
|
-
onReject
|
|
236
|
+
onReject,
|
|
237
|
+
onConfirmCardGone
|
|
120
238
|
}) {
|
|
121
239
|
if (actions.length === 0) return null;
|
|
122
240
|
const resolvedPalette = {
|
|
@@ -125,7 +243,7 @@ function ActionBreadcrumb({
|
|
|
125
243
|
primary: primaryColor,
|
|
126
244
|
text: textColor
|
|
127
245
|
};
|
|
128
|
-
return /* @__PURE__ */
|
|
246
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles.container }, actions.map((action) => /* @__PURE__ */ React8__default.createElement(
|
|
129
247
|
BreadcrumbRow,
|
|
130
248
|
{
|
|
131
249
|
key: action.id,
|
|
@@ -135,16 +253,18 @@ function ActionBreadcrumb({
|
|
|
135
253
|
fontFamily,
|
|
136
254
|
palette: resolvedPalette,
|
|
137
255
|
confirmStrings,
|
|
256
|
+
locale,
|
|
138
257
|
needsApproval: requireApprovalFor?.(action) ?? false,
|
|
139
258
|
onApprove,
|
|
140
|
-
onReject
|
|
259
|
+
onReject,
|
|
260
|
+
onConfirmCardGone
|
|
141
261
|
}
|
|
142
262
|
)));
|
|
143
263
|
}
|
|
144
264
|
function BreadcrumbRow(props) {
|
|
145
265
|
const { action, needsApproval } = props;
|
|
146
266
|
if (action.type === "confirm" && action.status === "pending" && needsApproval) {
|
|
147
|
-
return /* @__PURE__ */
|
|
267
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
148
268
|
ConfirmCard,
|
|
149
269
|
{
|
|
150
270
|
action,
|
|
@@ -152,11 +272,12 @@ function BreadcrumbRow(props) {
|
|
|
152
272
|
fontFamily: props.fontFamily,
|
|
153
273
|
confirmStrings: props.confirmStrings,
|
|
154
274
|
onApprove: props.onApprove,
|
|
155
|
-
onReject: props.onReject
|
|
275
|
+
onReject: props.onReject,
|
|
276
|
+
onGone: props.onConfirmCardGone
|
|
156
277
|
}
|
|
157
278
|
);
|
|
158
279
|
}
|
|
159
|
-
return /* @__PURE__ */
|
|
280
|
+
return /* @__PURE__ */ React8__default.createElement(RegularBreadcrumbRow, { ...props });
|
|
160
281
|
}
|
|
161
282
|
function RegularBreadcrumbRow({
|
|
162
283
|
action,
|
|
@@ -164,49 +285,49 @@ function RegularBreadcrumbRow({
|
|
|
164
285
|
textColor,
|
|
165
286
|
fontFamily,
|
|
166
287
|
palette,
|
|
288
|
+
locale,
|
|
167
289
|
needsApproval,
|
|
168
290
|
onApprove,
|
|
169
291
|
onReject
|
|
170
292
|
}) {
|
|
171
|
-
const { label, state } = describeAction(action);
|
|
293
|
+
const { label, state } = describeAction(action, locale);
|
|
172
294
|
const tone = deriveStateTone(palette)[state];
|
|
173
295
|
const fade = useRef(new Animated.Value(0)).current;
|
|
174
296
|
const pulse = useRef(new Animated.Value(1)).current;
|
|
175
297
|
const lastState = useRef(state);
|
|
298
|
+
const reduceMotion2 = useReduceMotion();
|
|
176
299
|
useEffect(() => {
|
|
300
|
+
if (reduceMotion2) {
|
|
301
|
+
fade.setValue(1);
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
177
304
|
Animated.timing(fade, {
|
|
178
305
|
toValue: 1,
|
|
179
306
|
duration: 180,
|
|
180
307
|
useNativeDriver: true
|
|
181
308
|
}).start();
|
|
182
|
-
}, [fade]);
|
|
309
|
+
}, [fade, reduceMotion2]);
|
|
183
310
|
useEffect(() => {
|
|
184
311
|
if (lastState.current === state) return;
|
|
185
312
|
lastState.current = state;
|
|
313
|
+
if (reduceMotion2) return;
|
|
186
314
|
pulse.setValue(0.4);
|
|
187
315
|
Animated.timing(pulse, {
|
|
188
316
|
toValue: 1,
|
|
189
317
|
duration: 220,
|
|
190
318
|
useNativeDriver: true
|
|
191
319
|
}).start();
|
|
192
|
-
}, [state, pulse]);
|
|
320
|
+
}, [state, pulse, reduceMotion2]);
|
|
193
321
|
const isDestructive = isDestructiveAction(action);
|
|
194
|
-
return /* @__PURE__ */
|
|
195
|
-
|
|
322
|
+
return /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React8__default.createElement(Animated.View, { style: [styles.labelGroup, { opacity: pulse }] }, /* @__PURE__ */ React8__default.createElement(StateIcon, { state, tone, primaryColor }), /* @__PURE__ */ React8__default.createElement(
|
|
323
|
+
Text,
|
|
196
324
|
{
|
|
197
|
-
style: {
|
|
325
|
+
style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
|
|
326
|
+
accessibilityLabel: `${state}: ${label}`
|
|
198
327
|
},
|
|
199
|
-
|
|
200
|
-
/* @__PURE__ */
|
|
201
|
-
|
|
202
|
-
{
|
|
203
|
-
style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
|
|
204
|
-
accessibilityLabel: `${state}: ${label}`
|
|
205
|
-
},
|
|
206
|
-
label,
|
|
207
|
-
isDestructive && /* @__PURE__ */ React7__default.createElement(Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
|
|
208
|
-
)
|
|
209
|
-
), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React7__default.createElement(View, { style: styles.approvalButtons }, /* @__PURE__ */ React7__default.createElement(
|
|
328
|
+
label,
|
|
329
|
+
isDestructive && /* @__PURE__ */ React8__default.createElement(Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
|
|
330
|
+
)), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React8__default.createElement(View, { style: styles.approvalButtons }, /* @__PURE__ */ React8__default.createElement(
|
|
210
331
|
TouchableOpacity,
|
|
211
332
|
{
|
|
212
333
|
onPress: () => onReject(action.id),
|
|
@@ -215,8 +336,8 @@ function RegularBreadcrumbRow({
|
|
|
215
336
|
accessibilityLabel: "Rejeitar a\xE7\xE3o",
|
|
216
337
|
testID: "assistant-action-reject"
|
|
217
338
|
},
|
|
218
|
-
/* @__PURE__ */
|
|
219
|
-
), /* @__PURE__ */
|
|
339
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
|
|
340
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
220
341
|
TouchableOpacity,
|
|
221
342
|
{
|
|
222
343
|
onPress: () => onApprove(action.id),
|
|
@@ -225,16 +346,18 @@ function RegularBreadcrumbRow({
|
|
|
225
346
|
accessibilityLabel: "Aprovar a\xE7\xE3o",
|
|
226
347
|
testID: "assistant-action-approve"
|
|
227
348
|
},
|
|
228
|
-
/* @__PURE__ */
|
|
349
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles.approveBtnText }, "Aprovar")
|
|
229
350
|
)));
|
|
230
351
|
}
|
|
352
|
+
var MIN_TOUCH_TARGET = 44;
|
|
231
353
|
function ConfirmCard({
|
|
232
354
|
action,
|
|
233
355
|
palette,
|
|
234
356
|
fontFamily,
|
|
235
357
|
confirmStrings,
|
|
236
358
|
onApprove,
|
|
237
|
-
onReject
|
|
359
|
+
onReject,
|
|
360
|
+
onGone
|
|
238
361
|
}) {
|
|
239
362
|
const {
|
|
240
363
|
isDestructive,
|
|
@@ -242,6 +365,9 @@ function ConfirmCard({
|
|
|
242
365
|
message,
|
|
243
366
|
confirmLabel,
|
|
244
367
|
cancelLabel,
|
|
368
|
+
confirmA11yLabel,
|
|
369
|
+
cancelA11yLabel,
|
|
370
|
+
expiredMessage,
|
|
245
371
|
glyph,
|
|
246
372
|
actionColor,
|
|
247
373
|
cardBackground,
|
|
@@ -250,50 +376,91 @@ function ConfirmCard({
|
|
|
250
376
|
cancelBackground,
|
|
251
377
|
cancelTextColor
|
|
252
378
|
} = deriveConfirmCardContent(action, palette, confirmStrings);
|
|
253
|
-
|
|
379
|
+
const summaryRef = useRef(null);
|
|
380
|
+
const expiresAt = confirmExpiresAt(action);
|
|
381
|
+
const [expired, setExpired] = useState(() => expiresAt !== void 0 && expiresAt <= Date.now());
|
|
382
|
+
const onGoneRef = useRef(onGone);
|
|
383
|
+
onGoneRef.current = onGone;
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (summaryRef.current) AccessibilityInfo.sendAccessibilityEvent(summaryRef.current, "focus");
|
|
386
|
+
return () => onGoneRef.current?.();
|
|
387
|
+
}, []);
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (expiresAt === void 0 || expired) return;
|
|
390
|
+
const timer = setTimeout(() => setExpired(true), expiresAt - Date.now());
|
|
391
|
+
return () => clearTimeout(timer);
|
|
392
|
+
}, [expiresAt, expired]);
|
|
393
|
+
useEffect(() => {
|
|
394
|
+
if (expired) AccessibilityInfo.announceForAccessibility(expiredMessage);
|
|
395
|
+
}, [expired, expiredMessage]);
|
|
396
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
254
397
|
View,
|
|
255
398
|
{
|
|
256
399
|
style: [
|
|
257
400
|
confirmCardStyles.card,
|
|
258
401
|
{ backgroundColor: cardBackground, borderColor: cardBorderColor }
|
|
259
402
|
],
|
|
260
|
-
testID: "assistant-confirm-card"
|
|
403
|
+
testID: "assistant-confirm-card",
|
|
404
|
+
onAccessibilityEscape: () => onReject?.(action.id)
|
|
261
405
|
},
|
|
262
|
-
/* @__PURE__ */
|
|
406
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
407
|
+
View,
|
|
408
|
+
{
|
|
409
|
+
ref: summaryRef,
|
|
410
|
+
accessible: true,
|
|
411
|
+
accessibilityLabel: `${title}. ${message}`,
|
|
412
|
+
accessibilityLiveRegion: "polite"
|
|
413
|
+
},
|
|
414
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.headerRow }, /* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.glyph, { color: actionColor }] }, glyph), /* @__PURE__ */ React8__default.createElement(
|
|
415
|
+
Text,
|
|
416
|
+
{
|
|
417
|
+
style: [
|
|
418
|
+
confirmCardStyles.title,
|
|
419
|
+
{ color: isDestructive ? palette.error : palette.text, fontFamily }
|
|
420
|
+
]
|
|
421
|
+
},
|
|
422
|
+
title
|
|
423
|
+
)),
|
|
424
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message)
|
|
425
|
+
),
|
|
426
|
+
expired && /* @__PURE__ */ React8__default.createElement(
|
|
263
427
|
Text,
|
|
264
428
|
{
|
|
265
|
-
style: [
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
]
|
|
429
|
+
style: [confirmCardStyles.expired, { color: palette.error, fontFamily }],
|
|
430
|
+
accessibilityLiveRegion: "assertive",
|
|
431
|
+
testID: "assistant-confirm-expired"
|
|
269
432
|
},
|
|
270
|
-
|
|
271
|
-
)
|
|
272
|
-
/* @__PURE__ */
|
|
273
|
-
/* @__PURE__ */ React7__default.createElement(View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React7__default.createElement(
|
|
433
|
+
expiredMessage
|
|
434
|
+
),
|
|
435
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React8__default.createElement(
|
|
274
436
|
TouchableOpacity,
|
|
275
437
|
{
|
|
276
438
|
onPress: () => onReject?.(action.id),
|
|
277
439
|
style: [confirmCardStyles.btn, { backgroundColor: cancelBackground }],
|
|
278
440
|
activeOpacity: 0.7,
|
|
279
|
-
|
|
441
|
+
accessibilityRole: "button",
|
|
442
|
+
accessibilityLabel: cancelA11yLabel,
|
|
280
443
|
testID: "assistant-confirm-reject"
|
|
281
444
|
},
|
|
282
|
-
/* @__PURE__ */
|
|
283
|
-
), /* @__PURE__ */
|
|
445
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
|
|
446
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
284
447
|
TouchableOpacity,
|
|
285
448
|
{
|
|
286
449
|
onPress: () => onApprove?.(action.id),
|
|
450
|
+
disabled: expired,
|
|
287
451
|
style: [
|
|
288
452
|
confirmCardStyles.btn,
|
|
289
453
|
confirmCardStyles.confirmBtn,
|
|
290
|
-
{ backgroundColor: actionColor }
|
|
454
|
+
{ backgroundColor: actionColor },
|
|
455
|
+
expired && confirmCardStyles.disabledBtn
|
|
291
456
|
],
|
|
292
457
|
activeOpacity: 0.7,
|
|
293
|
-
|
|
458
|
+
accessibilityRole: "button",
|
|
459
|
+
accessibilityState: { disabled: expired },
|
|
460
|
+
accessibilityLabel: confirmA11yLabel,
|
|
294
461
|
testID: "assistant-confirm-approve"
|
|
295
462
|
},
|
|
296
|
-
/* @__PURE__ */
|
|
463
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
|
|
297
464
|
))
|
|
298
465
|
);
|
|
299
466
|
}
|
|
@@ -327,18 +494,33 @@ var confirmCardStyles = StyleSheet.create({
|
|
|
327
494
|
// color set inline — theme-driven (textSecondary).
|
|
328
495
|
marginBottom: 12
|
|
329
496
|
},
|
|
497
|
+
// Wraps: on one line the two buttons ran off the LEFT edge at iOS AX5
|
|
498
|
+
// and Cancel was unreachable — on the one card that gates something
|
|
499
|
+
// irreversible.
|
|
330
500
|
buttons: {
|
|
331
501
|
flexDirection: "row",
|
|
502
|
+
flexWrap: "wrap",
|
|
332
503
|
gap: 8,
|
|
333
504
|
justifyContent: "flex-end"
|
|
334
505
|
},
|
|
335
506
|
btn: {
|
|
507
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
508
|
+
maxWidth: "100%",
|
|
509
|
+
justifyContent: "center",
|
|
336
510
|
paddingHorizontal: 14,
|
|
337
511
|
paddingVertical: 8,
|
|
338
512
|
borderRadius: 10,
|
|
339
513
|
minWidth: 96,
|
|
340
514
|
alignItems: "center"
|
|
341
515
|
},
|
|
516
|
+
disabledBtn: {
|
|
517
|
+
opacity: 0.4
|
|
518
|
+
},
|
|
519
|
+
expired: {
|
|
520
|
+
fontSize: 13,
|
|
521
|
+
fontWeight: "600",
|
|
522
|
+
marginBottom: 12
|
|
523
|
+
},
|
|
342
524
|
cancelText: {
|
|
343
525
|
fontSize: 13,
|
|
344
526
|
fontWeight: "600"
|
|
@@ -358,7 +540,11 @@ function StateIcon({
|
|
|
358
540
|
tone,
|
|
359
541
|
primaryColor
|
|
360
542
|
}) {
|
|
361
|
-
return /* @__PURE__ */
|
|
543
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: primaryColor }) : (
|
|
544
|
+
// Decorative, inside a fixed circle: capped so it cannot clip. The
|
|
545
|
+
// state is also in the row's accessibilityLabel.
|
|
546
|
+
/* @__PURE__ */ React8__default.createElement(Text, { maxFontSizeMultiplier: 1.3, style: [styles.iconGlyph, { color: tone.color }] }, iconGlyphFor(state))
|
|
547
|
+
));
|
|
362
548
|
}
|
|
363
549
|
var styles = StyleSheet.create({
|
|
364
550
|
container: {
|
|
@@ -366,12 +552,26 @@ var styles = StyleSheet.create({
|
|
|
366
552
|
marginBottom: 8,
|
|
367
553
|
paddingVertical: 4
|
|
368
554
|
},
|
|
555
|
+
// Wraps so Approve/Reject drop below the label at large text sizes. On
|
|
556
|
+
// one line they squeezed the label to zero width (iOS AX5): the user was
|
|
557
|
+
// asked to approve an action they could not read.
|
|
369
558
|
row: {
|
|
370
559
|
flexDirection: "row",
|
|
560
|
+
flexWrap: "wrap",
|
|
561
|
+
gap: 8,
|
|
371
562
|
alignItems: "center",
|
|
372
563
|
paddingVertical: 6,
|
|
373
564
|
paddingHorizontal: 4
|
|
374
565
|
},
|
|
566
|
+
labelGroup: {
|
|
567
|
+
flexDirection: "row",
|
|
568
|
+
alignItems: "flex-start",
|
|
569
|
+
flexGrow: 1,
|
|
570
|
+
flexShrink: 1,
|
|
571
|
+
flexBasis: 0,
|
|
572
|
+
// What forces the wrap: the label keeps at least half the row.
|
|
573
|
+
minWidth: "50%"
|
|
574
|
+
},
|
|
375
575
|
iconCircle: {
|
|
376
576
|
width: 22,
|
|
377
577
|
height: 22,
|
|
@@ -399,9 +599,11 @@ var styles = StyleSheet.create({
|
|
|
399
599
|
approvalButtons: {
|
|
400
600
|
flexDirection: "row",
|
|
401
601
|
gap: 6,
|
|
402
|
-
marginLeft:
|
|
602
|
+
marginLeft: "auto"
|
|
403
603
|
},
|
|
404
604
|
btn: {
|
|
605
|
+
minHeight: MIN_TOUCH_TARGET,
|
|
606
|
+
justifyContent: "center",
|
|
405
607
|
paddingHorizontal: 10,
|
|
406
608
|
paddingVertical: 5,
|
|
407
609
|
borderRadius: 8
|
|
@@ -449,7 +651,7 @@ function resolvePersonalization(props, remote) {
|
|
|
449
651
|
};
|
|
450
652
|
}
|
|
451
653
|
function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
452
|
-
return /* @__PURE__ */
|
|
654
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
453
655
|
Path,
|
|
454
656
|
{
|
|
455
657
|
d: "M5 3.5h14a3 3 0 0 1 3 3v9a3 3 0 0 1-3 3h-7.4l-4.6 4v-4H5a3 3 0 0 1-3-3v-9a3 3 0 0 1 3-3z",
|
|
@@ -457,8 +659,524 @@ function ChatIcon({ size = 24, color = "#ffffff" }) {
|
|
|
457
659
|
}
|
|
458
660
|
));
|
|
459
661
|
}
|
|
662
|
+
|
|
663
|
+
// src/components/internalProps.ts
|
|
664
|
+
var APPILOTS_SKIP_PROPS = {
|
|
665
|
+
__appilotsSkip: true,
|
|
666
|
+
__appilotsInternal: true
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
// src/components/AgentPill.tsx
|
|
670
|
+
var PILL_MAX_FONT_SCALE = 1.5;
|
|
671
|
+
function toneFor(state, colors) {
|
|
672
|
+
switch (state) {
|
|
673
|
+
case "success":
|
|
674
|
+
return colors.success;
|
|
675
|
+
case "failed":
|
|
676
|
+
return colors.error;
|
|
677
|
+
default:
|
|
678
|
+
return colors.primary;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
function AgentPill({
|
|
682
|
+
label,
|
|
683
|
+
state,
|
|
684
|
+
onExpand,
|
|
685
|
+
expandRef,
|
|
686
|
+
onStop,
|
|
687
|
+
position,
|
|
688
|
+
insets,
|
|
689
|
+
colors,
|
|
690
|
+
fontFamily,
|
|
691
|
+
strings
|
|
692
|
+
}) {
|
|
693
|
+
const atTop = position === "top-left" || position === "top-right";
|
|
694
|
+
const reduceMotion2 = useReduceMotion();
|
|
695
|
+
const enter = useRef(new Animated.Value(0)).current;
|
|
696
|
+
useEffect(() => {
|
|
697
|
+
if (reduceMotion2) {
|
|
698
|
+
enter.setValue(1);
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
Animated.spring(enter, {
|
|
702
|
+
toValue: 1,
|
|
703
|
+
useNativeDriver: true,
|
|
704
|
+
tension: 70,
|
|
705
|
+
friction: 12
|
|
706
|
+
}).start();
|
|
707
|
+
}, [enter, reduceMotion2]);
|
|
708
|
+
const translateY = enter.interpolate({
|
|
709
|
+
inputRange: [0, 1],
|
|
710
|
+
outputRange: [atTop ? -80 : 80, 0]
|
|
711
|
+
});
|
|
712
|
+
const running = state === "running" || state === "pending";
|
|
713
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
714
|
+
Animated.View,
|
|
715
|
+
{
|
|
716
|
+
...APPILOTS_SKIP_PROPS,
|
|
717
|
+
pointerEvents: "box-none",
|
|
718
|
+
style: [
|
|
719
|
+
styles2.wrapper,
|
|
720
|
+
atTop ? { top: insets.top + 8 } : { bottom: insets.bottom + 8 },
|
|
721
|
+
{ opacity: enter, transform: [{ translateY }] }
|
|
722
|
+
]
|
|
723
|
+
},
|
|
724
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
725
|
+
TouchableOpacity,
|
|
726
|
+
{
|
|
727
|
+
...APPILOTS_SKIP_PROPS,
|
|
728
|
+
ref: expandRef,
|
|
729
|
+
testID: "appilots-agent-pill",
|
|
730
|
+
accessibilityRole: "button",
|
|
731
|
+
accessibilityLabel: strings.expandA11y,
|
|
732
|
+
activeOpacity: 0.85,
|
|
733
|
+
onPress: onExpand,
|
|
734
|
+
style: [styles2.pill, { backgroundColor: colors.surface, borderColor: colors.border }]
|
|
735
|
+
},
|
|
736
|
+
running ? /* @__PURE__ */ React8__default.createElement(ActivityIndicator, { size: "small", color: toneFor(state, colors) }) : /* @__PURE__ */ React8__default.createElement(View, { style: [styles2.dot, { backgroundColor: toneFor(state, colors) }] }),
|
|
737
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
738
|
+
Text,
|
|
739
|
+
{
|
|
740
|
+
testID: "appilots-agent-pill-label",
|
|
741
|
+
numberOfLines: 2,
|
|
742
|
+
maxFontSizeMultiplier: PILL_MAX_FONT_SCALE,
|
|
743
|
+
style: [styles2.label, { color: colors.text, fontFamily }]
|
|
744
|
+
},
|
|
745
|
+
label
|
|
746
|
+
),
|
|
747
|
+
onStop ? /* @__PURE__ */ React8__default.createElement(
|
|
748
|
+
TouchableOpacity,
|
|
749
|
+
{
|
|
750
|
+
...APPILOTS_SKIP_PROPS,
|
|
751
|
+
testID: "appilots-agent-pill-stop",
|
|
752
|
+
accessibilityRole: "button",
|
|
753
|
+
accessibilityLabel: strings.stopA11y,
|
|
754
|
+
onPress: onStop,
|
|
755
|
+
hitSlop: { top: 12, bottom: 12, left: 12, right: 12 },
|
|
756
|
+
style: [styles2.stop, { borderColor: colors.border }]
|
|
757
|
+
},
|
|
758
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: [styles2.stopGlyph, { backgroundColor: colors.textSecondary }] })
|
|
759
|
+
) : null
|
|
760
|
+
)
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
var styles2 = StyleSheet.create({
|
|
764
|
+
// `box-none` above + `position: absolute` here is what lets touches
|
|
765
|
+
// outside the pill itself reach the app underneath.
|
|
766
|
+
wrapper: {
|
|
767
|
+
position: "absolute",
|
|
768
|
+
left: 12,
|
|
769
|
+
right: 12,
|
|
770
|
+
zIndex: 999,
|
|
771
|
+
alignItems: "center"
|
|
772
|
+
},
|
|
773
|
+
pill: {
|
|
774
|
+
flexDirection: "row",
|
|
775
|
+
alignItems: "center",
|
|
776
|
+
gap: 10,
|
|
777
|
+
maxWidth: "100%",
|
|
778
|
+
paddingLeft: 14,
|
|
779
|
+
paddingRight: 8,
|
|
780
|
+
paddingVertical: 10,
|
|
781
|
+
borderRadius: 24,
|
|
782
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
783
|
+
shadowColor: "#000",
|
|
784
|
+
shadowOffset: { width: 0, height: 2 },
|
|
785
|
+
shadowOpacity: 0.18,
|
|
786
|
+
shadowRadius: 8,
|
|
787
|
+
elevation: 8
|
|
788
|
+
},
|
|
789
|
+
dot: { width: 8, height: 8, borderRadius: 4 },
|
|
790
|
+
label: { flexShrink: 1, fontSize: 14, fontWeight: "500" },
|
|
791
|
+
stop: {
|
|
792
|
+
width: 26,
|
|
793
|
+
height: 26,
|
|
794
|
+
borderRadius: 13,
|
|
795
|
+
borderWidth: StyleSheet.hairlineWidth,
|
|
796
|
+
alignItems: "center",
|
|
797
|
+
justifyContent: "center"
|
|
798
|
+
},
|
|
799
|
+
stopGlyph: { width: 9, height: 9, borderRadius: 1.5 }
|
|
800
|
+
});
|
|
801
|
+
var PADDING = 6;
|
|
802
|
+
var CAPTION_HEIGHT = 28;
|
|
803
|
+
var CAPTION_GAP = 8;
|
|
804
|
+
function SpotlightOverlay({
|
|
805
|
+
rect,
|
|
806
|
+
seq,
|
|
807
|
+
label,
|
|
808
|
+
color,
|
|
809
|
+
captionBackground,
|
|
810
|
+
captionColor,
|
|
811
|
+
fontFamily,
|
|
812
|
+
window: win
|
|
813
|
+
}) {
|
|
814
|
+
const reduceMotion2 = useReduceMotion();
|
|
815
|
+
const pulse = useRef(new Animated.Value(reduceMotion2 ? 1 : 0)).current;
|
|
816
|
+
useEffect(() => {
|
|
817
|
+
if (reduceMotion2) {
|
|
818
|
+
pulse.stopAnimation();
|
|
819
|
+
pulse.setValue(1);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
pulse.setValue(0);
|
|
823
|
+
Animated.timing(pulse, {
|
|
824
|
+
toValue: 1,
|
|
825
|
+
duration: 220,
|
|
826
|
+
useNativeDriver: true
|
|
827
|
+
}).start();
|
|
828
|
+
}, [seq, pulse, reduceMotion2]);
|
|
829
|
+
if (!isRectOnScreen(rect, win)) return null;
|
|
830
|
+
const frame = {
|
|
831
|
+
left: rect.x - PADDING,
|
|
832
|
+
top: rect.y - PADDING,
|
|
833
|
+
width: rect.width + PADDING * 2,
|
|
834
|
+
height: rect.height + PADDING * 2
|
|
835
|
+
};
|
|
836
|
+
const above = frame.top - CAPTION_GAP - CAPTION_HEIGHT >= 0;
|
|
837
|
+
const captionTop = above ? frame.top - CAPTION_GAP - CAPTION_HEIGHT : frame.top + frame.height + CAPTION_GAP;
|
|
838
|
+
const captionFits = captionTop + CAPTION_HEIGHT <= win.height;
|
|
839
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
840
|
+
View,
|
|
841
|
+
{
|
|
842
|
+
...APPILOTS_SKIP_PROPS,
|
|
843
|
+
pointerEvents: "none",
|
|
844
|
+
style: StyleSheet.absoluteFill,
|
|
845
|
+
testID: "appilots-spotlight"
|
|
846
|
+
},
|
|
847
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
848
|
+
Animated.View,
|
|
849
|
+
{
|
|
850
|
+
...APPILOTS_SKIP_PROPS,
|
|
851
|
+
pointerEvents: "none",
|
|
852
|
+
style: [
|
|
853
|
+
styles3.ring,
|
|
854
|
+
frame,
|
|
855
|
+
{ borderColor: color },
|
|
856
|
+
{
|
|
857
|
+
opacity: pulse,
|
|
858
|
+
// Settles inward: the ring arrives slightly large and snaps
|
|
859
|
+
// to the control, which reads as "this one" rather than as a
|
|
860
|
+
// box that was always there.
|
|
861
|
+
transform: [
|
|
862
|
+
{
|
|
863
|
+
scale: pulse.interpolate({ inputRange: [0, 1], outputRange: [1.08, 1] })
|
|
864
|
+
}
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
]
|
|
868
|
+
}
|
|
869
|
+
),
|
|
870
|
+
label && captionFits ? /* @__PURE__ */ React8__default.createElement(
|
|
871
|
+
Animated.View,
|
|
872
|
+
{
|
|
873
|
+
...APPILOTS_SKIP_PROPS,
|
|
874
|
+
pointerEvents: "none",
|
|
875
|
+
style: [
|
|
876
|
+
styles3.caption,
|
|
877
|
+
{
|
|
878
|
+
top: captionTop,
|
|
879
|
+
// Clamped so a control at either edge does not push the
|
|
880
|
+
// caption off screen.
|
|
881
|
+
left: Math.max(8, Math.min(frame.left, win.width - 8)),
|
|
882
|
+
maxWidth: win.width - 16,
|
|
883
|
+
backgroundColor: captionBackground,
|
|
884
|
+
opacity: pulse
|
|
885
|
+
}
|
|
886
|
+
]
|
|
887
|
+
},
|
|
888
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
889
|
+
Text,
|
|
890
|
+
{
|
|
891
|
+
testID: "appilots-spotlight-label",
|
|
892
|
+
numberOfLines: 1,
|
|
893
|
+
style: [styles3.captionText, { color: captionColor, fontFamily }]
|
|
894
|
+
},
|
|
895
|
+
label
|
|
896
|
+
)
|
|
897
|
+
) : null
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
var styles3 = StyleSheet.create({
|
|
901
|
+
ring: {
|
|
902
|
+
position: "absolute",
|
|
903
|
+
borderWidth: 2.5,
|
|
904
|
+
borderRadius: 10
|
|
905
|
+
},
|
|
906
|
+
caption: {
|
|
907
|
+
position: "absolute",
|
|
908
|
+
height: CAPTION_HEIGHT,
|
|
909
|
+
justifyContent: "center",
|
|
910
|
+
paddingHorizontal: 10,
|
|
911
|
+
borderRadius: 8
|
|
912
|
+
},
|
|
913
|
+
captionText: { fontSize: 13, fontWeight: "500" }
|
|
914
|
+
});
|
|
915
|
+
var NEVER = () => () => {
|
|
916
|
+
};
|
|
917
|
+
var NULL_TARGET = () => null;
|
|
918
|
+
function useSpotlight(enabled) {
|
|
919
|
+
const subscribe2 = useCallback(
|
|
920
|
+
(onChange) => enabled ? subscribeSpotlight(onChange) : NEVER(),
|
|
921
|
+
[enabled]
|
|
922
|
+
);
|
|
923
|
+
return useSyncExternalStore(subscribe2, enabled ? getSpotlightTarget : NULL_TARGET, NULL_TARGET);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
// src/components/pillStatus.ts
|
|
927
|
+
function resolvePillStatus(actions, busy, strings) {
|
|
928
|
+
for (let i = actions.length - 1; i >= 0; i--) {
|
|
929
|
+
const action = actions[i];
|
|
930
|
+
if (action.status === "executing") return describeAction(action, strings.locale);
|
|
931
|
+
}
|
|
932
|
+
if (!busy) {
|
|
933
|
+
for (let i = actions.length - 1; i >= 0; i--) {
|
|
934
|
+
const action = actions[i];
|
|
935
|
+
if (action.status === "completed" || action.status === "failed") {
|
|
936
|
+
return describeAction(action, strings.locale);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return { label: strings.done, state: "success" };
|
|
940
|
+
}
|
|
941
|
+
return { label: strings.working, state: "running" };
|
|
942
|
+
}
|
|
943
|
+
var STREAMING_PREFIX = "streaming_";
|
|
944
|
+
function announce(message) {
|
|
945
|
+
if (Platform.OS === "ios" && AccessibilityInfo.announceForAccessibilityWithOptions) {
|
|
946
|
+
AccessibilityInfo.announceForAccessibilityWithOptions(message, { queue: true });
|
|
947
|
+
} else {
|
|
948
|
+
AccessibilityInfo.announceForAccessibility(message);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
var speakable = (content) => content.replace(/[*`#]+/g, "").trim();
|
|
952
|
+
function useChatAnnouncements({
|
|
953
|
+
messages,
|
|
954
|
+
actions,
|
|
955
|
+
awaitingApproval,
|
|
956
|
+
acting,
|
|
957
|
+
locale,
|
|
958
|
+
strings
|
|
959
|
+
}) {
|
|
960
|
+
const seenMessages = useRef(null);
|
|
961
|
+
if (!seenMessages.current) seenMessages.current = new Set(messages.map((m) => m.id));
|
|
962
|
+
const seenActions = useRef(null);
|
|
963
|
+
if (!seenActions.current) seenActions.current = new Map(actions.map((a) => [a.id, a.status]));
|
|
964
|
+
const prev = useRef({ awaitingApproval, acting });
|
|
965
|
+
const namedSinceSettle = useRef(false);
|
|
966
|
+
const localeRef = useRef(locale);
|
|
967
|
+
localeRef.current = locale;
|
|
968
|
+
useEffect(
|
|
969
|
+
() => subscribeSpotlightAnnouncement((label, verb) => {
|
|
970
|
+
namedSinceSettle.current = true;
|
|
971
|
+
announce(targetAnnouncement(verb, label, localeRef.current));
|
|
972
|
+
}),
|
|
973
|
+
[]
|
|
974
|
+
);
|
|
975
|
+
useEffect(() => {
|
|
976
|
+
const out = [];
|
|
977
|
+
for (const message of messages) {
|
|
978
|
+
if (message.role === "user" || message.id.startsWith(STREAMING_PREFIX)) continue;
|
|
979
|
+
if (seenMessages.current.has(message.id)) continue;
|
|
980
|
+
seenMessages.current.add(message.id);
|
|
981
|
+
const text = speakable(message.content);
|
|
982
|
+
if (text) out.push(text);
|
|
983
|
+
}
|
|
984
|
+
for (const action of actions) {
|
|
985
|
+
if (action.type === "confirm") continue;
|
|
986
|
+
if (seenActions.current.get(action.id) === action.status) continue;
|
|
987
|
+
seenActions.current.set(action.id, action.status);
|
|
988
|
+
const line = actionAnnouncement(action, locale, namedSinceSettle.current);
|
|
989
|
+
if (action.status === "completed" || action.status === "failed") {
|
|
990
|
+
namedSinceSettle.current = false;
|
|
991
|
+
}
|
|
992
|
+
if (line) out.push(line);
|
|
993
|
+
}
|
|
994
|
+
if (awaitingApproval && !prev.current.awaitingApproval) out.push(strings.a11yAwaitingApproval);
|
|
995
|
+
if (prev.current.acting && !acting) out.push(strings.a11yTurnDone);
|
|
996
|
+
prev.current = { awaitingApproval, acting };
|
|
997
|
+
for (const line of out) announce(line);
|
|
998
|
+
}, [messages, actions, awaitingApproval, acting, locale, strings]);
|
|
999
|
+
}
|
|
1000
|
+
function useStillWorking(active, template) {
|
|
1001
|
+
const [seconds, setSeconds] = useState(0);
|
|
1002
|
+
useEffect(() => {
|
|
1003
|
+
setSeconds(0);
|
|
1004
|
+
if (!active) return;
|
|
1005
|
+
return startStillWorkingTimer((elapsed) => {
|
|
1006
|
+
setSeconds(elapsed);
|
|
1007
|
+
AccessibilityInfo.announceForAccessibility(template.replace("{seconds}", String(elapsed)));
|
|
1008
|
+
});
|
|
1009
|
+
}, [active, template]);
|
|
1010
|
+
return seconds;
|
|
1011
|
+
}
|
|
1012
|
+
function useVoiceInput({
|
|
1013
|
+
host,
|
|
1014
|
+
locale,
|
|
1015
|
+
onTranscript
|
|
1016
|
+
}) {
|
|
1017
|
+
const [state, setState] = useState("idle");
|
|
1018
|
+
const [partial, setPartial] = useState("");
|
|
1019
|
+
const mounted = useRef(true);
|
|
1020
|
+
useEffect(() => {
|
|
1021
|
+
mounted.current = true;
|
|
1022
|
+
return () => {
|
|
1023
|
+
mounted.current = false;
|
|
1024
|
+
};
|
|
1025
|
+
}, []);
|
|
1026
|
+
const onTranscriptRef = useRef(onTranscript);
|
|
1027
|
+
onTranscriptRef.current = onTranscript;
|
|
1028
|
+
const stateRef = useRef("idle");
|
|
1029
|
+
stateRef.current = state;
|
|
1030
|
+
useEffect(() => {
|
|
1031
|
+
return () => {
|
|
1032
|
+
if (stateRef.current === "listening" || stateRef.current === "starting") {
|
|
1033
|
+
void host?.cancel().catch(() => {
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
}, [host]);
|
|
1038
|
+
const start = useCallback(() => {
|
|
1039
|
+
if (!host) return;
|
|
1040
|
+
if (state !== "idle" && state !== "error") return;
|
|
1041
|
+
setState("starting");
|
|
1042
|
+
setPartial("");
|
|
1043
|
+
host.start({ locale }).then(() => {
|
|
1044
|
+
if (!mounted.current) return;
|
|
1045
|
+
setState("listening");
|
|
1046
|
+
}).catch((err) => {
|
|
1047
|
+
appilotsDebugWarn("useVoiceInput: start failed", err);
|
|
1048
|
+
if (!mounted.current) return;
|
|
1049
|
+
setState("error");
|
|
1050
|
+
});
|
|
1051
|
+
}, [host, locale, state]);
|
|
1052
|
+
const stop = useCallback(() => {
|
|
1053
|
+
if (!host) return;
|
|
1054
|
+
if (state !== "listening" && state !== "starting") return;
|
|
1055
|
+
setState("stopping");
|
|
1056
|
+
host.stop().then((text) => {
|
|
1057
|
+
if (!mounted.current) return;
|
|
1058
|
+
setState("idle");
|
|
1059
|
+
setPartial("");
|
|
1060
|
+
const trimmed = text?.trim();
|
|
1061
|
+
if (trimmed) onTranscriptRef.current(trimmed);
|
|
1062
|
+
}).catch((err) => {
|
|
1063
|
+
appilotsDebugWarn("useVoiceInput: stop failed", err);
|
|
1064
|
+
if (!mounted.current) return;
|
|
1065
|
+
setState("error");
|
|
1066
|
+
setPartial("");
|
|
1067
|
+
});
|
|
1068
|
+
}, [host, state]);
|
|
1069
|
+
const cancel = useCallback(() => {
|
|
1070
|
+
if (!host) return;
|
|
1071
|
+
setPartial("");
|
|
1072
|
+
setState("idle");
|
|
1073
|
+
void host.cancel().catch((err) => appilotsDebugWarn("useVoiceInput: cancel failed", err));
|
|
1074
|
+
}, [host]);
|
|
1075
|
+
useEffect(() => {
|
|
1076
|
+
if (!host?.onPartial) return;
|
|
1077
|
+
if (state !== "listening") return;
|
|
1078
|
+
const dispose = host.onPartial((text) => {
|
|
1079
|
+
if (mounted.current) setPartial(text);
|
|
1080
|
+
});
|
|
1081
|
+
return dispose;
|
|
1082
|
+
}, [host, state]);
|
|
1083
|
+
useEffect(() => {
|
|
1084
|
+
if (!host?.onEnd) return;
|
|
1085
|
+
if (state !== "listening") return;
|
|
1086
|
+
return host.onEnd((error) => {
|
|
1087
|
+
if (!mounted.current) return;
|
|
1088
|
+
setPartial("");
|
|
1089
|
+
setState(error ? "error" : "idle");
|
|
1090
|
+
});
|
|
1091
|
+
}, [host, state]);
|
|
1092
|
+
return { state, partial, start, stop, cancel };
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// src/components/experience.ts
|
|
1096
|
+
var DEFAULT_EXPERIENCE = {
|
|
1097
|
+
presence: "sheet",
|
|
1098
|
+
spotlight: "off",
|
|
1099
|
+
control: "agent",
|
|
1100
|
+
entry: ["fab"],
|
|
1101
|
+
input: ["text"]
|
|
1102
|
+
};
|
|
1103
|
+
function uniq(values) {
|
|
1104
|
+
return values.filter((value, index) => values.indexOf(value) === index);
|
|
1105
|
+
}
|
|
1106
|
+
function resolveExperience(requested, caps) {
|
|
1107
|
+
const downgrades = [];
|
|
1108
|
+
let presence = requested?.presence ?? DEFAULT_EXPERIENCE.presence;
|
|
1109
|
+
let spotlight = requested?.spotlight ?? DEFAULT_EXPERIENCE.spotlight;
|
|
1110
|
+
const control = requested?.control ?? DEFAULT_EXPERIENCE.control;
|
|
1111
|
+
const entry = uniq(requested?.entry ?? DEFAULT_EXPERIENCE.entry);
|
|
1112
|
+
let input = uniq(requested?.input ?? DEFAULT_EXPERIENCE.input);
|
|
1113
|
+
if (spotlight !== "off" && !caps.geometry) {
|
|
1114
|
+
downgrades.push({
|
|
1115
|
+
field: "spotlight",
|
|
1116
|
+
from: spotlight,
|
|
1117
|
+
to: "off",
|
|
1118
|
+
reason: 'spotlight needs Fabric window geometry, which this app cannot report. Enable the new React Native architecture, or set spotlight:"off" to silence this.'
|
|
1119
|
+
});
|
|
1120
|
+
spotlight = "off";
|
|
1121
|
+
}
|
|
1122
|
+
if (spotlight !== "off" && presence === "sheet") {
|
|
1123
|
+
downgrades.push({
|
|
1124
|
+
field: "presence",
|
|
1125
|
+
from: "sheet",
|
|
1126
|
+
to: "pill",
|
|
1127
|
+
reason: 'spotlight draws on the app, which the sheet covers. Set presence:"pill" or "hidden" explicitly to silence this.'
|
|
1128
|
+
});
|
|
1129
|
+
presence = "pill";
|
|
1130
|
+
}
|
|
1131
|
+
if (control === "shared" && presence === "sheet") {
|
|
1132
|
+
downgrades.push({
|
|
1133
|
+
field: "presence",
|
|
1134
|
+
from: "sheet",
|
|
1135
|
+
to: "pill",
|
|
1136
|
+
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.'
|
|
1137
|
+
});
|
|
1138
|
+
presence = "pill";
|
|
1139
|
+
}
|
|
1140
|
+
if (input.includes("voice") && !caps.speech) {
|
|
1141
|
+
downgrades.push({
|
|
1142
|
+
field: "input",
|
|
1143
|
+
from: input.join("+"),
|
|
1144
|
+
to: input.filter((mode) => mode !== "voice").join("+") || "text",
|
|
1145
|
+
reason: 'input:"voice" needs a SpeechHost passed to <AppilotsChat speech={...} />. The SDK ships no speech engine of its own \u2014 see https://docs.appilots.com/docs/guides/voice-input.'
|
|
1146
|
+
});
|
|
1147
|
+
input = input.filter((mode) => mode !== "voice");
|
|
1148
|
+
}
|
|
1149
|
+
if (input.length === 0) input = ["text"];
|
|
1150
|
+
return {
|
|
1151
|
+
experience: { presence, spotlight, control, entry, input },
|
|
1152
|
+
downgrades
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
function formatDowngrades(downgrades) {
|
|
1156
|
+
return downgrades.map(
|
|
1157
|
+
(d) => `[appilots] experience.${d.field}: "${d.from}" -> "${d.to}". ${d.reason}`
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/components/presence.ts
|
|
1162
|
+
function resolveSurface(presence, activity) {
|
|
1163
|
+
if (presence === "sheet") return activity.open ? "sheet" : "none";
|
|
1164
|
+
if (activity.awaitingUser) return "sheet";
|
|
1165
|
+
if (activity.busy && (activity.acting || !activity.open)) return "pill";
|
|
1166
|
+
if (activity.hostModalOpen && !activity.explicitlyOpened && (activity.open || activity.unread))
|
|
1167
|
+
return "pill";
|
|
1168
|
+
if (activity.open) return "sheet";
|
|
1169
|
+
if (activity.unread) return "pill";
|
|
1170
|
+
return "none";
|
|
1171
|
+
}
|
|
1172
|
+
function shouldReopenOnTurnEnd(presence) {
|
|
1173
|
+
return presence === "pill";
|
|
1174
|
+
}
|
|
1175
|
+
function usesPill(presence) {
|
|
1176
|
+
return presence !== "sheet";
|
|
1177
|
+
}
|
|
460
1178
|
function HeadsetIcon({ size = 18, color = "#ffffff" }) {
|
|
461
|
-
return /* @__PURE__ */
|
|
1179
|
+
return /* @__PURE__ */ React8.createElement(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8.createElement(
|
|
462
1180
|
Path,
|
|
463
1181
|
{
|
|
464
1182
|
d: "M12 3a8 8 0 0 0-8 8v5.5A2.5 2.5 0 0 0 6.5 19H8a1 1 0 0 0 1-1v-5a1 1 0 0 0-1-1H6v-1a6 6 0 0 1 12 0v1h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h1.5a2.5 2.5 0 0 0 2.5-2.5V11a8 8 0 0 0-8-8z",
|
|
@@ -499,195 +1217,6 @@ function buildChatTimeline(messages, actions) {
|
|
|
499
1217
|
}
|
|
500
1218
|
return timeline;
|
|
501
1219
|
}
|
|
502
|
-
|
|
503
|
-
// src/components/markdownContent.ts
|
|
504
|
-
var ORDERED_LINE = /^\s*(\d+)\.\s+(.+)$/;
|
|
505
|
-
var BULLET_LINE = /^\s*[-*•]\s+(.+)$/;
|
|
506
|
-
var HEADING_LINE = /^\s*(#{1,6})\s+(.+)$/;
|
|
507
|
-
var FENCE_LINE = /^\s*```\s*([A-Za-z0-9+#_-]*)\s*$/;
|
|
508
|
-
var INLINE_PATTERN = /\[([^\]\n]+)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|__(.+?)__|`([^`]+)`|\*(.+?)\*|_(.+?)_/g;
|
|
509
|
-
var MIN_ENHANCE_LENGTH = 80;
|
|
510
|
-
var SENTENCE_SPLIT = /[^.!?]+[.!?]+(?=\s+[A-ZÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕÇÑ¿¡"“]|$)|[^.!?]+$/g;
|
|
511
|
-
var CAPABILITY_SENTENCE = /^((?:No aplicativo,?|In (?:this|the) app,?|En la aplicaci[oó]n,?|Dans l['’]application,?)?(?:\s+(?:voc[eê]|voce|you|tu|usted|puedes|puede|peux))?\s*(?:pode(?:m|r)?|can|could|puedes|puede|peux|peut))\s+(.+?)\.?\s*$/i;
|
|
512
|
-
var INCLUDE_LIST_SENTENCE = /^(.+?)\s+(?:incluem|inclui|include|includes|incluye|incluyen|such as|for example|par exemple|por exemplo)\s+(.+?)\.?\s*$/i;
|
|
513
|
-
function looksLikeMarkdown(content) {
|
|
514
|
-
if (!content) return false;
|
|
515
|
-
return /\*\*.+?\*\*/.test(content) || /__.+?__/.test(content) || /`[^`\n]+`/.test(content) || /^\s*[-*•]\s+/m.test(content) || /^\s*\d+\.\s+/m.test(content) || /^\s*#{1,6}\s+/m.test(content) || /^\s*```/m.test(content) || /\[[^\]\n]+\]\(https?:\/\/[^\s)]+\)/.test(content);
|
|
516
|
-
}
|
|
517
|
-
function splitEnumeration(text) {
|
|
518
|
-
const trimmed = text.trim().replace(/\.\s*$/, "");
|
|
519
|
-
if (!trimmed) return [];
|
|
520
|
-
const commaParts = trimmed.split(",").map((part) => part.trim()).filter(Boolean);
|
|
521
|
-
if (commaParts.length <= 1) {
|
|
522
|
-
const conjParts = trimmed.split(/\s+(?:e|and|y|ou|or)\s+/i).map((part) => part.trim());
|
|
523
|
-
return conjParts.filter(Boolean);
|
|
524
|
-
}
|
|
525
|
-
const last = commaParts[commaParts.length - 1];
|
|
526
|
-
const conjMatch = last.match(/^(.+?)\s+(?:e|and|y|ou|or)\s+(.+)$/i);
|
|
527
|
-
if (conjMatch) {
|
|
528
|
-
commaParts[commaParts.length - 1] = conjMatch[1].trim();
|
|
529
|
-
commaParts.push(conjMatch[2].trim());
|
|
530
|
-
}
|
|
531
|
-
return commaParts.filter(Boolean);
|
|
532
|
-
}
|
|
533
|
-
function splitSentences(text) {
|
|
534
|
-
const matches = text.match(SENTENCE_SPLIT);
|
|
535
|
-
if (!matches) return [text.trim()];
|
|
536
|
-
return matches.map((part) => part.trim()).filter(Boolean);
|
|
537
|
-
}
|
|
538
|
-
function formatCapabilitySentence(sentence) {
|
|
539
|
-
const match = CAPABILITY_SENTENCE.exec(sentence.trim());
|
|
540
|
-
if (!match) return null;
|
|
541
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
542
|
-
if (items.length < 3) return null;
|
|
543
|
-
const intro = `${match[1].trim()}:`;
|
|
544
|
-
return `${intro}
|
|
545
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
546
|
-
}
|
|
547
|
-
function formatIncludeListSentence(sentence) {
|
|
548
|
-
const match = INCLUDE_LIST_SENTENCE.exec(sentence.trim());
|
|
549
|
-
if (!match) return null;
|
|
550
|
-
const intro = match[1].trim().replace(/[,:]\s*$/, "");
|
|
551
|
-
const items = splitEnumeration(match[2] ?? "");
|
|
552
|
-
if (items.length < 2) return null;
|
|
553
|
-
return `${intro}:
|
|
554
|
-
${items.map((item) => `- ${item}`).join("\n")}`;
|
|
555
|
-
}
|
|
556
|
-
function formatReadableSentence(sentence) {
|
|
557
|
-
return formatCapabilitySentence(sentence) ?? formatIncludeListSentence(sentence) ?? sentence.trim();
|
|
558
|
-
}
|
|
559
|
-
function enhancePlainAssistantContent(content) {
|
|
560
|
-
if (!content?.trim() || looksLikeMarkdown(content)) return content;
|
|
561
|
-
const trimmed = content.trim();
|
|
562
|
-
if (trimmed.length < MIN_ENHANCE_LENGTH) return content;
|
|
563
|
-
const sentences = splitSentences(trimmed);
|
|
564
|
-
if (sentences.length === 0) return content;
|
|
565
|
-
const blocks = sentences.map(formatReadableSentence);
|
|
566
|
-
const enhanced = blocks.join("\n\n");
|
|
567
|
-
return enhanced || content;
|
|
568
|
-
}
|
|
569
|
-
function needsWideChatLayout(content) {
|
|
570
|
-
if (!content?.trim()) return false;
|
|
571
|
-
const prepared = enhancePlainAssistantContent(content);
|
|
572
|
-
return looksLikeMarkdown(prepared) || /\n\n+/.test(prepared);
|
|
573
|
-
}
|
|
574
|
-
function parseMarkdownBlocks(content) {
|
|
575
|
-
const lines = content.replace(/\r\n/g, "\n").split("\n");
|
|
576
|
-
const blocks = [];
|
|
577
|
-
let paragraph = [];
|
|
578
|
-
let bulletItems = [];
|
|
579
|
-
let orderedItems = [];
|
|
580
|
-
let codeLines = null;
|
|
581
|
-
let codeLanguage;
|
|
582
|
-
const flushParagraph = () => {
|
|
583
|
-
if (paragraph.length === 0) return;
|
|
584
|
-
blocks.push({ kind: "paragraph", text: paragraph.join("\n") });
|
|
585
|
-
paragraph = [];
|
|
586
|
-
};
|
|
587
|
-
const flushBullets = () => {
|
|
588
|
-
if (bulletItems.length === 0) return;
|
|
589
|
-
blocks.push({ kind: "bullet", items: bulletItems });
|
|
590
|
-
bulletItems = [];
|
|
591
|
-
};
|
|
592
|
-
const flushOrdered = () => {
|
|
593
|
-
if (orderedItems.length === 0) return;
|
|
594
|
-
blocks.push({ kind: "ordered", items: orderedItems });
|
|
595
|
-
orderedItems = [];
|
|
596
|
-
};
|
|
597
|
-
const flushLists = () => {
|
|
598
|
-
flushBullets();
|
|
599
|
-
flushOrdered();
|
|
600
|
-
};
|
|
601
|
-
const flushCode = () => {
|
|
602
|
-
if (codeLines === null) return;
|
|
603
|
-
blocks.push({
|
|
604
|
-
kind: "codeblock",
|
|
605
|
-
code: codeLines.join("\n"),
|
|
606
|
-
...codeLanguage ? { language: codeLanguage } : {}
|
|
607
|
-
});
|
|
608
|
-
codeLines = null;
|
|
609
|
-
codeLanguage = void 0;
|
|
610
|
-
};
|
|
611
|
-
for (const line of lines) {
|
|
612
|
-
if (codeLines !== null) {
|
|
613
|
-
if (/^\s*```\s*$/.test(line)) {
|
|
614
|
-
flushCode();
|
|
615
|
-
} else {
|
|
616
|
-
codeLines.push(line);
|
|
617
|
-
}
|
|
618
|
-
continue;
|
|
619
|
-
}
|
|
620
|
-
const fence = FENCE_LINE.exec(line);
|
|
621
|
-
if (fence) {
|
|
622
|
-
flushParagraph();
|
|
623
|
-
flushLists();
|
|
624
|
-
codeLines = [];
|
|
625
|
-
codeLanguage = fence[1] || void 0;
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
const trimmed = line.trim();
|
|
629
|
-
if (!trimmed) {
|
|
630
|
-
flushParagraph();
|
|
631
|
-
flushLists();
|
|
632
|
-
continue;
|
|
633
|
-
}
|
|
634
|
-
const heading = HEADING_LINE.exec(line);
|
|
635
|
-
if (heading) {
|
|
636
|
-
flushParagraph();
|
|
637
|
-
flushLists();
|
|
638
|
-
const level = Math.min(heading[1].length, 3);
|
|
639
|
-
blocks.push({ kind: "heading", level, text: heading[2].trim() });
|
|
640
|
-
continue;
|
|
641
|
-
}
|
|
642
|
-
const ordered = ORDERED_LINE.exec(line);
|
|
643
|
-
if (ordered) {
|
|
644
|
-
flushParagraph();
|
|
645
|
-
flushBullets();
|
|
646
|
-
orderedItems.push(ordered[2].trim());
|
|
647
|
-
continue;
|
|
648
|
-
}
|
|
649
|
-
const bullet = BULLET_LINE.exec(line);
|
|
650
|
-
if (bullet) {
|
|
651
|
-
flushParagraph();
|
|
652
|
-
flushOrdered();
|
|
653
|
-
bulletItems.push(bullet[1].trim());
|
|
654
|
-
continue;
|
|
655
|
-
}
|
|
656
|
-
flushLists();
|
|
657
|
-
paragraph.push(line);
|
|
658
|
-
}
|
|
659
|
-
flushParagraph();
|
|
660
|
-
flushLists();
|
|
661
|
-
flushCode();
|
|
662
|
-
return blocks.length > 0 ? blocks : [{ kind: "paragraph", text: content }];
|
|
663
|
-
}
|
|
664
|
-
function parseInlineMarkdown(text) {
|
|
665
|
-
if (!text) return [{ kind: "text", value: "" }];
|
|
666
|
-
const segments = [];
|
|
667
|
-
let lastIndex = 0;
|
|
668
|
-
INLINE_PATTERN.lastIndex = 0;
|
|
669
|
-
for (let match = INLINE_PATTERN.exec(text); match; match = INLINE_PATTERN.exec(text)) {
|
|
670
|
-
if (match.index > lastIndex) {
|
|
671
|
-
segments.push({ kind: "text", value: text.slice(lastIndex, match.index) });
|
|
672
|
-
}
|
|
673
|
-
if (match[1] && match[2]) {
|
|
674
|
-
segments.push({ kind: "link", value: match[1].trim(), href: match[2] });
|
|
675
|
-
} else if (match[3] || match[4]) {
|
|
676
|
-
segments.push({ kind: "bold", value: (match[3] ?? match[4]).trim() });
|
|
677
|
-
} else if (match[5]) {
|
|
678
|
-
segments.push({ kind: "code", value: match[5] });
|
|
679
|
-
} else if (match[6] || match[7]) {
|
|
680
|
-
segments.push({ kind: "italic", value: (match[6] ?? match[7]).trim() });
|
|
681
|
-
}
|
|
682
|
-
lastIndex = INLINE_PATTERN.lastIndex;
|
|
683
|
-
}
|
|
684
|
-
if (lastIndex < text.length) {
|
|
685
|
-
segments.push({ kind: "text", value: text.slice(lastIndex) });
|
|
686
|
-
}
|
|
687
|
-
return segments.length > 0 ? segments : [{ kind: "text", value: text }];
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
// src/components/ChatMarkdown.tsx
|
|
691
1220
|
function segmentKey(segment, index) {
|
|
692
1221
|
return `${segment.kind}-${index}-${segment.value.slice(0, 12)}`;
|
|
693
1222
|
}
|
|
@@ -697,17 +1226,17 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
697
1226
|
const key = segmentKey(segment, index);
|
|
698
1227
|
switch (segment.kind) {
|
|
699
1228
|
case "bold":
|
|
700
|
-
return /* @__PURE__ */
|
|
1229
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.bold] }, segment.value);
|
|
701
1230
|
case "italic":
|
|
702
|
-
return /* @__PURE__ */
|
|
1231
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { key, style: [baseStyle, styles4.italic] }, segment.value);
|
|
703
1232
|
case "code":
|
|
704
|
-
return /* @__PURE__ */
|
|
1233
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
705
1234
|
Text,
|
|
706
1235
|
{
|
|
707
1236
|
key,
|
|
708
1237
|
style: [
|
|
709
1238
|
baseStyle,
|
|
710
|
-
|
|
1239
|
+
styles4.code,
|
|
711
1240
|
{
|
|
712
1241
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.06)"),
|
|
713
1242
|
color: theme.codeColor ?? theme.color
|
|
@@ -717,14 +1246,14 @@ function renderInlineSegments(text, theme, baseStyle) {
|
|
|
717
1246
|
segment.value
|
|
718
1247
|
);
|
|
719
1248
|
case "link":
|
|
720
|
-
return /* @__PURE__ */
|
|
1249
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
721
1250
|
Text,
|
|
722
1251
|
{
|
|
723
1252
|
key,
|
|
724
1253
|
accessibilityRole: "link",
|
|
725
1254
|
style: [
|
|
726
1255
|
baseStyle,
|
|
727
|
-
|
|
1256
|
+
styles4.link,
|
|
728
1257
|
{
|
|
729
1258
|
color: theme.linkColor ?? (theme.variant === "user" ? theme.color : "#2563EB")
|
|
730
1259
|
}
|
|
@@ -751,7 +1280,7 @@ function InlineMarkdown({
|
|
|
751
1280
|
fontSize: theme.fontSize,
|
|
752
1281
|
lineHeight: theme.lineHeight
|
|
753
1282
|
};
|
|
754
|
-
return /* @__PURE__ */
|
|
1283
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseStyle }, renderInlineSegments(text, theme, baseStyle));
|
|
755
1284
|
}
|
|
756
1285
|
function ChatMarkdown({ content, theme, contentWidth }) {
|
|
757
1286
|
const prepared = enhancePlainAssistantContent(content);
|
|
@@ -761,29 +1290,29 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
761
1290
|
fontSize: theme.fontSize,
|
|
762
1291
|
lineHeight: theme.lineHeight
|
|
763
1292
|
};
|
|
764
|
-
const rootStyle = contentWidth ? [
|
|
1293
|
+
const rootStyle = contentWidth ? [styles4.root, { width: contentWidth }] : styles4.root;
|
|
765
1294
|
if (!looksLikeMarkdown(prepared)) {
|
|
766
1295
|
const paragraphs = prepared.split(/\n\n+/).map((part) => part.trim()).filter(Boolean);
|
|
767
1296
|
if (paragraphs.length > 1) {
|
|
768
|
-
return /* @__PURE__ */
|
|
1297
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: rootStyle }, paragraphs.map((paragraph, index) => /* @__PURE__ */ React8__default.createElement(View, { key: `plain-p-${index}`, style: index > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(Text, { style: baseTextStyle }, paragraph))));
|
|
769
1298
|
}
|
|
770
|
-
return /* @__PURE__ */
|
|
1299
|
+
return /* @__PURE__ */ React8__default.createElement(Text, { style: baseTextStyle }, prepared);
|
|
771
1300
|
}
|
|
772
1301
|
const blocks = parseMarkdownBlocks(prepared);
|
|
773
|
-
return /* @__PURE__ */
|
|
1302
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: rootStyle }, blocks.map((block, blockIndex) => {
|
|
774
1303
|
if (block.kind === "paragraph") {
|
|
775
|
-
return /* @__PURE__ */
|
|
1304
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `p-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(InlineMarkdown, { text: block.text, theme }));
|
|
776
1305
|
}
|
|
777
1306
|
if (block.kind === "heading") {
|
|
778
1307
|
const scale = block.level === 1 ? 1.25 : block.level === 2 ? 1.15 : 1.05;
|
|
779
1308
|
const headingSize = Math.round((theme.fontSize ?? 15) * scale);
|
|
780
|
-
return /* @__PURE__ */
|
|
1309
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `h-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__default.createElement(
|
|
781
1310
|
Text,
|
|
782
1311
|
{
|
|
783
1312
|
accessibilityRole: "header",
|
|
784
1313
|
style: [
|
|
785
1314
|
baseTextStyle,
|
|
786
|
-
|
|
1315
|
+
styles4.bold,
|
|
787
1316
|
{ fontSize: headingSize, lineHeight: Math.round(headingSize * 1.35) }
|
|
788
1317
|
]
|
|
789
1318
|
},
|
|
@@ -795,23 +1324,23 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
795
1324
|
));
|
|
796
1325
|
}
|
|
797
1326
|
if (block.kind === "codeblock") {
|
|
798
|
-
return /* @__PURE__ */
|
|
1327
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
799
1328
|
View,
|
|
800
1329
|
{
|
|
801
1330
|
key: `code-${blockIndex}`,
|
|
802
1331
|
style: [
|
|
803
|
-
|
|
804
|
-
blockIndex > 0 ?
|
|
1332
|
+
styles4.codeBlock,
|
|
1333
|
+
blockIndex > 0 ? styles4.blockGap : void 0,
|
|
805
1334
|
{
|
|
806
1335
|
backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.055)")
|
|
807
1336
|
}
|
|
808
1337
|
]
|
|
809
1338
|
},
|
|
810
|
-
/* @__PURE__ */
|
|
1339
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
811
1340
|
Text,
|
|
812
1341
|
{
|
|
813
1342
|
style: [
|
|
814
|
-
|
|
1343
|
+
styles4.code,
|
|
815
1344
|
{
|
|
816
1345
|
color: theme.codeColor ?? theme.color,
|
|
817
1346
|
fontSize: (theme.fontSize ?? 15) - 1,
|
|
@@ -824,28 +1353,28 @@ function ChatMarkdown({ content, theme, contentWidth }) {
|
|
|
824
1353
|
);
|
|
825
1354
|
}
|
|
826
1355
|
if (block.kind === "bullet") {
|
|
827
|
-
return /* @__PURE__ */
|
|
1356
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `ul-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__default.createElement(
|
|
828
1357
|
Text,
|
|
829
1358
|
{
|
|
830
1359
|
key: `ul-${blockIndex}-${itemIndex}`,
|
|
831
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1360
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
832
1361
|
},
|
|
833
1362
|
"\u2022 ",
|
|
834
1363
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
835
1364
|
)));
|
|
836
1365
|
}
|
|
837
|
-
return /* @__PURE__ */
|
|
1366
|
+
return /* @__PURE__ */ React8__default.createElement(View, { key: `ol-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__default.createElement(
|
|
838
1367
|
Text,
|
|
839
1368
|
{
|
|
840
1369
|
key: `ol-${blockIndex}-${itemIndex}`,
|
|
841
|
-
style: [baseTextStyle, itemIndex > 0 ?
|
|
1370
|
+
style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
|
|
842
1371
|
},
|
|
843
1372
|
`${itemIndex + 1}. `,
|
|
844
1373
|
renderInlineSegments(item, theme, baseTextStyle)
|
|
845
1374
|
)));
|
|
846
1375
|
}));
|
|
847
1376
|
}
|
|
848
|
-
var
|
|
1377
|
+
var styles4 = StyleSheet.create({
|
|
849
1378
|
root: {
|
|
850
1379
|
flexShrink: 1,
|
|
851
1380
|
alignSelf: "stretch"
|
|
@@ -889,7 +1418,7 @@ function AppilotsThemeProvider({
|
|
|
889
1418
|
() => mergeThemeTokens(resolveBaseTheme(mode, systemScheme), theme ?? void 0),
|
|
890
1419
|
[mode, systemScheme, theme]
|
|
891
1420
|
);
|
|
892
|
-
return /* @__PURE__ */
|
|
1421
|
+
return /* @__PURE__ */ React8__default.createElement(ThemeContext.Provider, { value: tokens }, children);
|
|
893
1422
|
}
|
|
894
1423
|
function useAppilotsTheme() {
|
|
895
1424
|
return useContext(ThemeContext);
|
|
@@ -982,177 +1511,6 @@ var appilotsTheme = {
|
|
|
982
1511
|
fromTailwind: appilotsThemeFromTailwind
|
|
983
1512
|
};
|
|
984
1513
|
|
|
985
|
-
// src/i18n/bundles/pt-BR.ts
|
|
986
|
-
var ptBR = {
|
|
987
|
-
chatTitle: "Assistente Appilots",
|
|
988
|
-
clearButton: "Limpar",
|
|
989
|
-
inputPlaceholder: "Digite uma mensagem...",
|
|
990
|
-
emptyTitle: "Como posso ajudar?",
|
|
991
|
-
emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
|
|
992
|
-
thinking: "Pensando...",
|
|
993
|
-
statusAnalyzing: "Analisando a tela...",
|
|
994
|
-
statusWaitingApp: "Aguardando o app responder...",
|
|
995
|
-
statusAdjusting: "Ajustando o plano...",
|
|
996
|
-
poweredBy: "Powered by Appilots",
|
|
997
|
-
approve: "Aprovar",
|
|
998
|
-
reject: "Rejeitar",
|
|
999
|
-
cancelledByUser: "Cancelado pelo usu\xE1rio",
|
|
1000
|
-
confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
|
|
1001
|
-
confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
|
|
1002
|
-
confirmMessage: 'Tem certeza que deseja "{action}"?',
|
|
1003
|
-
confirmDestructiveApprove: "Sim, executar",
|
|
1004
|
-
confirmApprove: "Confirmar",
|
|
1005
|
-
confirmCancel: "Cancelar",
|
|
1006
|
-
confirmThisAction: "esta a\xE7\xE3o",
|
|
1007
|
-
unknownAction: "A\xE7\xE3o desconhecida",
|
|
1008
|
-
somethingWentWrong: "Algo deu errado",
|
|
1009
|
-
openChatA11y: "Abrir chat do assistente",
|
|
1010
|
-
closeChatA11y: "Fechar chat do assistente",
|
|
1011
|
-
stopGeneratingA11y: "Parar gera\xE7\xE3o",
|
|
1012
|
-
talkToHumanA11y: "Falar com um atendente humano",
|
|
1013
|
-
humanAgentLabel: "Atendente",
|
|
1014
|
-
escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
|
|
1015
|
-
escalationConnected: "Um atendente entrou na conversa.",
|
|
1016
|
-
escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
|
|
1017
|
-
escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
|
|
1018
|
-
escalationOfferChip: "Falar com um atendente",
|
|
1019
|
-
escalationPendingBanner: "Aguardando um atendente...",
|
|
1020
|
-
escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente"
|
|
1021
|
-
};
|
|
1022
|
-
|
|
1023
|
-
// src/i18n/bundles/en.ts
|
|
1024
|
-
var en = {
|
|
1025
|
-
chatTitle: "Appilots Assistant",
|
|
1026
|
-
clearButton: "Clear",
|
|
1027
|
-
inputPlaceholder: "Type a message...",
|
|
1028
|
-
emptyTitle: "How can I help?",
|
|
1029
|
-
emptySubtitle: "I navigate, fill forms, and run actions in this app.",
|
|
1030
|
-
thinking: "Thinking...",
|
|
1031
|
-
statusAnalyzing: "Reading the screen...",
|
|
1032
|
-
statusWaitingApp: "Waiting for the app...",
|
|
1033
|
-
statusAdjusting: "Adjusting the plan...",
|
|
1034
|
-
poweredBy: "Powered by Appilots",
|
|
1035
|
-
approve: "Approve",
|
|
1036
|
-
reject: "Reject",
|
|
1037
|
-
cancelledByUser: "Cancelled by user",
|
|
1038
|
-
confirmDestructiveTitle: "Destructive action",
|
|
1039
|
-
confirmTitle: "Confirmation needed",
|
|
1040
|
-
confirmMessage: 'Are you sure you want to "{action}"?',
|
|
1041
|
-
confirmDestructiveApprove: "Yes, do it",
|
|
1042
|
-
confirmApprove: "Confirm",
|
|
1043
|
-
confirmCancel: "Cancel",
|
|
1044
|
-
confirmThisAction: "this action",
|
|
1045
|
-
unknownAction: "Unknown action",
|
|
1046
|
-
somethingWentWrong: "Something went wrong",
|
|
1047
|
-
openChatA11y: "Open assistant chat",
|
|
1048
|
-
closeChatA11y: "Close assistant chat",
|
|
1049
|
-
stopGeneratingA11y: "Stop generating",
|
|
1050
|
-
talkToHumanA11y: "Talk to a human agent",
|
|
1051
|
-
humanAgentLabel: "Agent",
|
|
1052
|
-
escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
|
|
1053
|
-
escalationConnected: "A human agent joined the conversation.",
|
|
1054
|
-
escalationResolved: "The human handoff has ended. I'm back to help you here.",
|
|
1055
|
-
escalationOffer: "If you prefer, I can bring in a person to help.",
|
|
1056
|
-
escalationOfferChip: "Talk to a human",
|
|
1057
|
-
escalationPendingBanner: "Waiting for a human agent...",
|
|
1058
|
-
escalationActiveBanner: "You're talking to a human agent"
|
|
1059
|
-
};
|
|
1060
|
-
|
|
1061
|
-
// src/i18n/bundles/es.ts
|
|
1062
|
-
var es = {
|
|
1063
|
-
chatTitle: "Asistente Appilots",
|
|
1064
|
-
clearButton: "Limpiar",
|
|
1065
|
-
inputPlaceholder: "Escribe un mensaje...",
|
|
1066
|
-
emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
|
|
1067
|
-
emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
|
|
1068
|
-
thinking: "Pensando...",
|
|
1069
|
-
statusAnalyzing: "Analizando la pantalla...",
|
|
1070
|
-
statusWaitingApp: "Esperando a la app...",
|
|
1071
|
-
statusAdjusting: "Ajustando el plan...",
|
|
1072
|
-
poweredBy: "Hecho con Appilots",
|
|
1073
|
-
approve: "Aprobar",
|
|
1074
|
-
reject: "Rechazar",
|
|
1075
|
-
cancelledByUser: "Cancelado por el usuario",
|
|
1076
|
-
confirmDestructiveTitle: "Acci\xF3n destructiva",
|
|
1077
|
-
confirmTitle: "Confirmaci\xF3n necesaria",
|
|
1078
|
-
confirmMessage: '\xBFSeguro que quieres "{action}"?',
|
|
1079
|
-
confirmDestructiveApprove: "S\xED, ejecutar",
|
|
1080
|
-
confirmApprove: "Confirmar",
|
|
1081
|
-
confirmCancel: "Cancelar",
|
|
1082
|
-
confirmThisAction: "esta acci\xF3n",
|
|
1083
|
-
unknownAction: "Acci\xF3n desconocida",
|
|
1084
|
-
somethingWentWrong: "Algo sali\xF3 mal",
|
|
1085
|
-
openChatA11y: "Abrir chat del asistente",
|
|
1086
|
-
closeChatA11y: "Cerrar chat del asistente",
|
|
1087
|
-
stopGeneratingA11y: "Detener generaci\xF3n",
|
|
1088
|
-
talkToHumanA11y: "Hablar con un agente humano",
|
|
1089
|
-
humanAgentLabel: "Agente",
|
|
1090
|
-
escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
|
|
1091
|
-
escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
|
|
1092
|
-
escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
|
|
1093
|
-
escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
|
|
1094
|
-
escalationOfferChip: "Hablar con un agente",
|
|
1095
|
-
escalationPendingBanner: "Esperando a un agente...",
|
|
1096
|
-
escalationActiveBanner: "Est\xE1s hablando con un agente humano"
|
|
1097
|
-
};
|
|
1098
|
-
var BUNDLES = {
|
|
1099
|
-
"pt-BR": ptBR,
|
|
1100
|
-
en,
|
|
1101
|
-
es
|
|
1102
|
-
};
|
|
1103
|
-
var DEFAULT_LOCALE = "en";
|
|
1104
|
-
function detectDeviceLocale() {
|
|
1105
|
-
try {
|
|
1106
|
-
let raw;
|
|
1107
|
-
if (Platform.OS === "ios") {
|
|
1108
|
-
const settings = NativeModules?.SettingsManager?.settings;
|
|
1109
|
-
raw = settings?.AppleLocale || (Array.isArray(settings?.AppleLanguages) ? settings?.AppleLanguages?.[0] : void 0);
|
|
1110
|
-
} else if (Platform.OS === "android") {
|
|
1111
|
-
raw = NativeModules?.I18nManager?.localeIdentifier;
|
|
1112
|
-
}
|
|
1113
|
-
if (!raw || typeof raw !== "string") return null;
|
|
1114
|
-
const lower = raw.toLowerCase().replace("_", "-");
|
|
1115
|
-
if (lower.startsWith("pt")) return "pt-BR";
|
|
1116
|
-
if (lower.startsWith("es")) return "es";
|
|
1117
|
-
if (lower.startsWith("en")) return "en";
|
|
1118
|
-
return null;
|
|
1119
|
-
} catch {
|
|
1120
|
-
return null;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
function resolveLocale(prop) {
|
|
1124
|
-
if (prop && BUNDLES[prop]) return prop;
|
|
1125
|
-
const detected = detectDeviceLocale();
|
|
1126
|
-
if (detected && BUNDLES[detected]) return detected;
|
|
1127
|
-
return DEFAULT_LOCALE;
|
|
1128
|
-
}
|
|
1129
|
-
var I18nContext = createContext(null);
|
|
1130
|
-
function AppilotsI18nProvider({
|
|
1131
|
-
locale,
|
|
1132
|
-
overrides,
|
|
1133
|
-
children
|
|
1134
|
-
}) {
|
|
1135
|
-
const value = useMemo(() => {
|
|
1136
|
-
const resolved = resolveLocale(locale ?? null);
|
|
1137
|
-
const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
|
|
1138
|
-
return {
|
|
1139
|
-
locale: resolved,
|
|
1140
|
-
strings: merged,
|
|
1141
|
-
t: (key) => merged[key]
|
|
1142
|
-
};
|
|
1143
|
-
}, [locale, overrides]);
|
|
1144
|
-
return /* @__PURE__ */ React7__default.createElement(I18nContext.Provider, { value }, children);
|
|
1145
|
-
}
|
|
1146
|
-
function useAppilotsI18n() {
|
|
1147
|
-
const ctx = useContext(I18nContext);
|
|
1148
|
-
if (ctx) return ctx;
|
|
1149
|
-
return {
|
|
1150
|
-
locale: DEFAULT_LOCALE,
|
|
1151
|
-
strings: BUNDLES[DEFAULT_LOCALE],
|
|
1152
|
-
t: (key) => BUNDLES[DEFAULT_LOCALE][key]
|
|
1153
|
-
};
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
1514
|
// src/components/AppilotsChat.tsx
|
|
1157
1515
|
function translateLegacyTheme(legacy) {
|
|
1158
1516
|
const out = {};
|
|
@@ -1180,34 +1538,42 @@ function isImageSource(value) {
|
|
|
1180
1538
|
return typeof value === "number" || /^https?:\/\//i.test(value.trim());
|
|
1181
1539
|
}
|
|
1182
1540
|
var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get("window");
|
|
1541
|
+
var A11Y_FOCUS_DELAY_MS = 500;
|
|
1183
1542
|
var CHAT_HORIZONTAL_PADDING = 16;
|
|
1184
1543
|
var BUBBLE_HORIZONTAL_PADDING = 14;
|
|
1185
1544
|
var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
|
|
1186
|
-
var
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
};
|
|
1545
|
+
var MIN_TOUCH_TARGET2 = 44;
|
|
1546
|
+
var LARGE_TEXT_FONT_SCALE = 1.6;
|
|
1547
|
+
var INPUT_MAX_HEIGHT = 120;
|
|
1190
1548
|
function AppilotsChat(props) {
|
|
1191
1549
|
const { degraded } = useAppilotsContext();
|
|
1192
1550
|
if (degraded) return null;
|
|
1193
|
-
return /* @__PURE__ */
|
|
1551
|
+
return /* @__PURE__ */ React8__default.createElement(AppilotsErrorBoundary, { surface: "chat", fallback: null }, /* @__PURE__ */ React8__default.createElement(AppilotsChatSurface, { ...props }));
|
|
1194
1552
|
}
|
|
1195
1553
|
function AppilotsChatSurface(props) {
|
|
1554
|
+
const [conversationLocale, setConversationLocale] = useState(null);
|
|
1196
1555
|
const { remotePersonalization } = useAppilotsContext();
|
|
1197
1556
|
const themeProp = useMemo(() => {
|
|
1198
1557
|
if (!props.theme) return void 0;
|
|
1199
1558
|
return isLegacyTheme(props.theme) ? translateLegacyTheme(props.theme) : props.theme;
|
|
1200
1559
|
}, [props.theme]);
|
|
1201
|
-
return /* @__PURE__ */
|
|
1560
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1202
1561
|
AppilotsThemeProvider,
|
|
1203
1562
|
{
|
|
1204
1563
|
theme: resolveTheme(themeProp, remotePersonalization),
|
|
1205
1564
|
mode: resolveThemeMode(props.themeMode, remotePersonalization)
|
|
1206
1565
|
},
|
|
1207
|
-
/* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1567
|
+
AppilotsI18nProvider,
|
|
1568
|
+
{
|
|
1569
|
+
locale: conversationLocale ?? resolveLocaleProp(props.locale, remotePersonalization)
|
|
1570
|
+
},
|
|
1571
|
+
/* @__PURE__ */ React8__default.createElement(AppilotsChatInner, { ...props, onReplyLocaleChange: setConversationLocale })
|
|
1572
|
+
)
|
|
1208
1573
|
);
|
|
1209
1574
|
}
|
|
1210
1575
|
function AppilotsChatInner({
|
|
1576
|
+
onReplyLocaleChange,
|
|
1211
1577
|
visible: controlledVisible,
|
|
1212
1578
|
onClose,
|
|
1213
1579
|
placeholder,
|
|
@@ -1223,14 +1589,22 @@ function AppilotsChatInner({
|
|
|
1223
1589
|
triggerButton = "default",
|
|
1224
1590
|
triggerIcon,
|
|
1225
1591
|
triggerButtonColor: triggerButtonColorProp,
|
|
1226
|
-
triggerButtonImage: triggerButtonImageProp
|
|
1592
|
+
triggerButtonImage: triggerButtonImageProp,
|
|
1593
|
+
experience: experienceProp,
|
|
1594
|
+
speech: speechProp
|
|
1227
1595
|
}) {
|
|
1228
1596
|
const theme = useAppilotsTheme();
|
|
1229
|
-
const { strings, t } = useAppilotsI18n();
|
|
1597
|
+
const { strings, t, locale: resolvedLocale } = useAppilotsI18n();
|
|
1230
1598
|
const {
|
|
1231
1599
|
messages,
|
|
1600
|
+
mission,
|
|
1601
|
+
pauseMission,
|
|
1602
|
+
resumeMission,
|
|
1603
|
+
cancelMission,
|
|
1604
|
+
replyLocale,
|
|
1232
1605
|
isLoading,
|
|
1233
1606
|
loadingStatusKey,
|
|
1607
|
+
hasStartedActing,
|
|
1234
1608
|
sendMessage,
|
|
1235
1609
|
cancelMessage,
|
|
1236
1610
|
clearMessages,
|
|
@@ -1245,6 +1619,9 @@ function AppilotsChatInner({
|
|
|
1245
1619
|
offer: t("escalationOffer")
|
|
1246
1620
|
}
|
|
1247
1621
|
});
|
|
1622
|
+
useEffect(() => {
|
|
1623
|
+
onReplyLocaleChange(replyLocale);
|
|
1624
|
+
}, [replyLocale, onReplyLocaleChange]);
|
|
1248
1625
|
const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = useAppilotsActions({ autoExecute });
|
|
1249
1626
|
const { emit, remotePersonalization } = useAppilotsContext();
|
|
1250
1627
|
const {
|
|
@@ -1270,18 +1647,87 @@ function AppilotsChatInner({
|
|
|
1270
1647
|
);
|
|
1271
1648
|
const allActions = [...pendingActions, ...executingActions, ...completedActions];
|
|
1272
1649
|
const timeline = buildChatTimeline(messages, allActions);
|
|
1273
|
-
const lastAssistantMessageId =
|
|
1650
|
+
const lastAssistantMessageId = React8__default.useMemo(() => {
|
|
1274
1651
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1275
1652
|
if (messages[i].role === "assistant") return messages[i].id;
|
|
1276
1653
|
}
|
|
1277
1654
|
return void 0;
|
|
1278
1655
|
}, [messages]);
|
|
1279
1656
|
const insets = useSafeAreaInsetsOrDefault();
|
|
1657
|
+
const { fontScale } = useWindowDimensions();
|
|
1280
1658
|
const [internalVisible, setInternalVisible] = useState(mode === "inline");
|
|
1281
1659
|
const [inputText, setInputText] = useState("");
|
|
1282
1660
|
const flatListRef = useRef(null);
|
|
1283
1661
|
const slideAnim = useRef(new Animated.Value(SCREEN_HEIGHT)).current;
|
|
1284
|
-
const
|
|
1662
|
+
const wantsSheet = mode === "inline" ? true : controlledVisible !== void 0 ? controlledVisible : internalVisible;
|
|
1663
|
+
const speechHost = isSpeechHost(speechProp) ? speechProp : null;
|
|
1664
|
+
const hasGeometry = useSyncExternalStore(
|
|
1665
|
+
subscribeGeometryHost,
|
|
1666
|
+
() => geometryAvailability() !== "unavailable",
|
|
1667
|
+
() => false
|
|
1668
|
+
);
|
|
1669
|
+
const capabilities = useMemo(
|
|
1670
|
+
() => ({ geometry: hasGeometry, speech: speechHost !== null }),
|
|
1671
|
+
[hasGeometry, speechHost]
|
|
1672
|
+
);
|
|
1673
|
+
const { experience, downgrades } = useMemo(
|
|
1674
|
+
() => resolveExperience(experienceProp, capabilities),
|
|
1675
|
+
[experienceProp, capabilities]
|
|
1676
|
+
);
|
|
1677
|
+
const presence = mode === "inline" ? "sheet" : experience.presence;
|
|
1678
|
+
useEffect(() => {
|
|
1679
|
+
if (!__DEV__ || downgrades.length === 0) return;
|
|
1680
|
+
if (!isGeometryResolved()) return;
|
|
1681
|
+
for (const line of formatDowngrades(downgrades)) {
|
|
1682
|
+
console.warn(line);
|
|
1683
|
+
}
|
|
1684
|
+
}, [downgrades, hasGeometry]);
|
|
1685
|
+
const [unreadResult, setUnreadResult] = useState(false);
|
|
1686
|
+
const [explicitlyOpened, setExplicitlyOpened] = useState(false);
|
|
1687
|
+
const requireApproval = useCallback(
|
|
1688
|
+
(action) => {
|
|
1689
|
+
if (action.status !== "pending") return false;
|
|
1690
|
+
if (action.type === "confirm") return true;
|
|
1691
|
+
return !autoExecute;
|
|
1692
|
+
},
|
|
1693
|
+
[autoExecute]
|
|
1694
|
+
);
|
|
1695
|
+
const awaitingApproval = pendingActions.some((action) => requireApproval(action));
|
|
1696
|
+
const awaitingUser = awaitingApproval || escalation?.status === "pending" || escalation?.status === "active";
|
|
1697
|
+
const busy = isLoading || executingActions.length > 0;
|
|
1698
|
+
const stillWorkingSeconds = useStillWorking(busy && !awaitingUser, strings.stillWorking);
|
|
1699
|
+
const acting = busy && hasStartedActing;
|
|
1700
|
+
useChatAnnouncements({
|
|
1701
|
+
messages,
|
|
1702
|
+
actions: allActions,
|
|
1703
|
+
awaitingApproval,
|
|
1704
|
+
acting,
|
|
1705
|
+
locale: resolvedLocale,
|
|
1706
|
+
strings
|
|
1707
|
+
});
|
|
1708
|
+
const hostModalOpen = useHostModalOpen(
|
|
1709
|
+
usesPill(presence) && (busy || wantsSheet || unreadResult)
|
|
1710
|
+
);
|
|
1711
|
+
const surface = resolveSurface(presence, {
|
|
1712
|
+
busy,
|
|
1713
|
+
acting,
|
|
1714
|
+
awaitingUser,
|
|
1715
|
+
open: wantsSheet,
|
|
1716
|
+
unread: unreadResult,
|
|
1717
|
+
hostModalOpen,
|
|
1718
|
+
explicitlyOpened
|
|
1719
|
+
});
|
|
1720
|
+
const isVisible = mode === "inline" ? true : surface === "sheet";
|
|
1721
|
+
const spotlight = useSpotlight(experience.spotlight !== "off");
|
|
1722
|
+
useEffect(() => {
|
|
1723
|
+
setSpotlightMode(experience.spotlight);
|
|
1724
|
+
return () => setSpotlightMode("off");
|
|
1725
|
+
}, [experience.spotlight]);
|
|
1726
|
+
const { label: pillLabel, state: pillState } = surface === "pill" ? resolvePillStatus(allActions, busy, {
|
|
1727
|
+
working: strings.pillWorking,
|
|
1728
|
+
done: strings.pillDone,
|
|
1729
|
+
locale: resolvedLocale
|
|
1730
|
+
}) : { label: "", state: "pending" };
|
|
1285
1731
|
const showSuggestedPrompts = shouldShowSuggestedPrompts({
|
|
1286
1732
|
isVisible,
|
|
1287
1733
|
messageCount: messages.length,
|
|
@@ -1292,14 +1738,38 @@ function AppilotsChatInner({
|
|
|
1292
1738
|
limit: 3
|
|
1293
1739
|
});
|
|
1294
1740
|
const openChat = useCallback(() => {
|
|
1741
|
+
setExplicitlyOpened(true);
|
|
1295
1742
|
setInternalVisible(true);
|
|
1296
1743
|
emit({ type: "chat:open", timestamp: Date.now(), data: {} });
|
|
1297
1744
|
}, [emit]);
|
|
1298
1745
|
const closeChat = useCallback(() => {
|
|
1746
|
+
setExplicitlyOpened(false);
|
|
1299
1747
|
setInternalVisible(false);
|
|
1300
1748
|
onClose?.();
|
|
1301
1749
|
emit({ type: "chat:close", timestamp: Date.now(), data: {} });
|
|
1302
1750
|
}, [onClose, emit]);
|
|
1751
|
+
useEffect(() => {
|
|
1752
|
+
if (acting) setExplicitlyOpened(false);
|
|
1753
|
+
if (presence === "hidden" && acting) setInternalVisible(false);
|
|
1754
|
+
}, [presence, acting]);
|
|
1755
|
+
const wasActingRef = useRef(false);
|
|
1756
|
+
useEffect(() => {
|
|
1757
|
+
if (!usesPill(presence)) {
|
|
1758
|
+
wasActingRef.current = acting;
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
if (acting) {
|
|
1762
|
+
wasActingRef.current = true;
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
if (!wasActingRef.current) return;
|
|
1766
|
+
wasActingRef.current = false;
|
|
1767
|
+
if (shouldReopenOnTurnEnd(presence)) setInternalVisible(true);
|
|
1768
|
+
else setUnreadResult(true);
|
|
1769
|
+
}, [acting, presence]);
|
|
1770
|
+
useEffect(() => {
|
|
1771
|
+
if (surface === "sheet") setUnreadResult(false);
|
|
1772
|
+
}, [surface]);
|
|
1303
1773
|
useEffect(() => {
|
|
1304
1774
|
if (mode === "inline") return;
|
|
1305
1775
|
Animated.spring(slideAnim, {
|
|
@@ -1309,11 +1779,30 @@ function AppilotsChatInner({
|
|
|
1309
1779
|
friction: 11
|
|
1310
1780
|
}).start();
|
|
1311
1781
|
}, [isVisible, slideAnim, mode]);
|
|
1782
|
+
const titleRef = useRef(null);
|
|
1783
|
+
const launcherRef = useRef(null);
|
|
1784
|
+
const pillRef = useRef(null);
|
|
1785
|
+
const wasVisibleRef = useRef(isVisible);
|
|
1786
|
+
useEffect(() => {
|
|
1787
|
+
if (mode === "inline" || wasVisibleRef.current === isVisible) return;
|
|
1788
|
+
wasVisibleRef.current = isVisible;
|
|
1789
|
+
const timer = setTimeout(() => {
|
|
1790
|
+
const target = isVisible ? titleRef.current : pillRef.current ?? launcherRef.current;
|
|
1791
|
+
if (target) AccessibilityInfo.sendAccessibilityEvent(target, "focus");
|
|
1792
|
+
}, A11Y_FOCUS_DELAY_MS);
|
|
1793
|
+
return () => clearTimeout(timer);
|
|
1794
|
+
}, [isVisible, mode]);
|
|
1312
1795
|
useEffect(() => {
|
|
1313
1796
|
if (messages.length > 0) {
|
|
1314
1797
|
setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
|
|
1315
1798
|
}
|
|
1316
1799
|
}, [messages.length]);
|
|
1800
|
+
const voiceEnabled = experience.input.includes("voice");
|
|
1801
|
+
const voice = useVoiceInput({
|
|
1802
|
+
host: voiceEnabled ? speechHost : null,
|
|
1803
|
+
locale: resolvedLocale,
|
|
1804
|
+
onTranscript: sendMessage
|
|
1805
|
+
});
|
|
1317
1806
|
const handleSend = useCallback(() => {
|
|
1318
1807
|
if (!inputText.trim()) return;
|
|
1319
1808
|
sendMessage(inputText.trim());
|
|
@@ -1323,11 +1812,11 @@ function AppilotsChatInner({
|
|
|
1323
1812
|
({ item }) => {
|
|
1324
1813
|
if (item.role === "system") {
|
|
1325
1814
|
const isOffer = item.metadata?.escalationOffer === true;
|
|
1326
|
-
return /* @__PURE__ */
|
|
1815
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.systemMessageContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1327
1816
|
Text,
|
|
1328
1817
|
{
|
|
1329
1818
|
style: [
|
|
1330
|
-
|
|
1819
|
+
styles5.systemMessageText,
|
|
1331
1820
|
{
|
|
1332
1821
|
color: theme.colors.textSecondary,
|
|
1333
1822
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1336,13 +1825,13 @@ function AppilotsChatInner({
|
|
|
1336
1825
|
]
|
|
1337
1826
|
},
|
|
1338
1827
|
item.content
|
|
1339
|
-
), isOffer && !escalation && /* @__PURE__ */
|
|
1828
|
+
), isOffer && !escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1340
1829
|
TouchableOpacity,
|
|
1341
1830
|
{
|
|
1342
1831
|
...APPILOTS_SKIP_PROPS,
|
|
1343
1832
|
style: [
|
|
1344
|
-
|
|
1345
|
-
|
|
1833
|
+
styles5.chip,
|
|
1834
|
+
styles5.escalationOfferChip,
|
|
1346
1835
|
{
|
|
1347
1836
|
backgroundColor: theme.colors.surface,
|
|
1348
1837
|
borderColor: theme.colors.border,
|
|
@@ -1355,12 +1844,12 @@ function AppilotsChatInner({
|
|
|
1355
1844
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1356
1845
|
testID: "escalation-offer-chip"
|
|
1357
1846
|
},
|
|
1358
|
-
/* @__PURE__ */
|
|
1359
|
-
/* @__PURE__ */
|
|
1847
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
|
|
1848
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1360
1849
|
Text,
|
|
1361
1850
|
{
|
|
1362
1851
|
style: [
|
|
1363
|
-
|
|
1852
|
+
styles5.chipText,
|
|
1364
1853
|
{
|
|
1365
1854
|
color: theme.colors.text,
|
|
1366
1855
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1376,11 +1865,11 @@ function AppilotsChatInner({
|
|
|
1376
1865
|
const isHumanAgent = item.role === "human_agent";
|
|
1377
1866
|
const useWideAssistantLayout = !isUser && needsWideChatLayout(item.content);
|
|
1378
1867
|
if (isHumanAgent) {
|
|
1379
|
-
return /* @__PURE__ */
|
|
1868
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.humanAgentContainer, testID: "human-agent-message" }, /* @__PURE__ */ React8__default.createElement(View, { style: styles5.humanAgentLabelRow }, /* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 11, color: theme.colors.secondary }), /* @__PURE__ */ React8__default.createElement(
|
|
1380
1869
|
Text,
|
|
1381
1870
|
{
|
|
1382
1871
|
style: [
|
|
1383
|
-
|
|
1872
|
+
styles5.humanAgentLabel,
|
|
1384
1873
|
{
|
|
1385
1874
|
color: theme.colors.textSecondary,
|
|
1386
1875
|
fontFamily: theme.typography.fontFamily
|
|
@@ -1388,17 +1877,17 @@ function AppilotsChatInner({
|
|
|
1388
1877
|
]
|
|
1389
1878
|
},
|
|
1390
1879
|
escalation?.operatorName ?? strings.humanAgentLabel
|
|
1391
|
-
)), /* @__PURE__ */
|
|
1880
|
+
)), /* @__PURE__ */ React8__default.createElement(
|
|
1392
1881
|
View,
|
|
1393
1882
|
{
|
|
1394
1883
|
accessibilityLabel: item.content,
|
|
1395
1884
|
style: [
|
|
1396
|
-
|
|
1397
|
-
|
|
1885
|
+
styles5.messageBubble,
|
|
1886
|
+
styles5.assistantBubble,
|
|
1398
1887
|
{ backgroundColor: theme.colors.surface }
|
|
1399
1888
|
]
|
|
1400
1889
|
},
|
|
1401
|
-
/* @__PURE__ */
|
|
1890
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1402
1891
|
ChatMarkdown,
|
|
1403
1892
|
{
|
|
1404
1893
|
content: item.content,
|
|
@@ -1413,21 +1902,21 @@ function AppilotsChatInner({
|
|
|
1413
1902
|
)
|
|
1414
1903
|
));
|
|
1415
1904
|
}
|
|
1416
|
-
return /* @__PURE__ */
|
|
1905
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1417
1906
|
View,
|
|
1418
1907
|
{
|
|
1419
1908
|
testID: isUser ? void 0 : item.id === lastAssistantMessageId ? "assistant-last-message" : "assistant-message",
|
|
1420
1909
|
accessibilityLabel: isUser ? void 0 : item.content,
|
|
1421
1910
|
style: [
|
|
1422
|
-
|
|
1423
|
-
isUser ? [
|
|
1424
|
-
|
|
1425
|
-
useWideAssistantLayout &&
|
|
1911
|
+
styles5.messageBubble,
|
|
1912
|
+
isUser ? [styles5.userBubble, { backgroundColor: theme.colors.primary }] : [
|
|
1913
|
+
styles5.assistantBubble,
|
|
1914
|
+
useWideAssistantLayout && styles5.assistantBubbleWide,
|
|
1426
1915
|
{ backgroundColor: theme.colors.surface }
|
|
1427
1916
|
]
|
|
1428
1917
|
]
|
|
1429
1918
|
},
|
|
1430
|
-
/* @__PURE__ */
|
|
1919
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1431
1920
|
ChatMarkdown,
|
|
1432
1921
|
{
|
|
1433
1922
|
content: item.content,
|
|
@@ -1445,19 +1934,16 @@ function AppilotsChatInner({
|
|
|
1445
1934
|
},
|
|
1446
1935
|
[theme, lastAssistantMessageId, escalation, requestHuman, strings]
|
|
1447
1936
|
);
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
return !autoExecute;
|
|
1453
|
-
},
|
|
1454
|
-
[autoExecute]
|
|
1455
|
-
);
|
|
1937
|
+
const composerRef = useRef(null);
|
|
1938
|
+
const returnFocusToComposer = useCallback(() => {
|
|
1939
|
+
if (composerRef.current) AccessibilityInfo.sendAccessibilityEvent(composerRef.current, "focus");
|
|
1940
|
+
}, []);
|
|
1456
1941
|
const renderBreadcrumb = useCallback(
|
|
1457
|
-
(actions) => /* @__PURE__ */
|
|
1942
|
+
(actions) => /* @__PURE__ */ React8__default.createElement(
|
|
1458
1943
|
ActionBreadcrumb,
|
|
1459
1944
|
{
|
|
1460
1945
|
actions,
|
|
1946
|
+
locale: resolvedLocale,
|
|
1461
1947
|
primaryColor: theme.colors.primary,
|
|
1462
1948
|
textColor: theme.colors.text,
|
|
1463
1949
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1468,7 +1954,8 @@ function AppilotsChatInner({
|
|
|
1468
1954
|
confirmDestructiveApprove: strings.confirmDestructiveApprove,
|
|
1469
1955
|
confirmApprove: strings.confirmApprove,
|
|
1470
1956
|
confirmCancel: strings.confirmCancel,
|
|
1471
|
-
confirmThisAction: strings.confirmThisAction
|
|
1957
|
+
confirmThisAction: strings.confirmThisAction,
|
|
1958
|
+
confirmExpired: strings.confirmExpired
|
|
1472
1959
|
},
|
|
1473
1960
|
palette: {
|
|
1474
1961
|
textSecondary: theme.colors.textSecondary,
|
|
@@ -1480,7 +1967,8 @@ function AppilotsChatInner({
|
|
|
1480
1967
|
},
|
|
1481
1968
|
requireApprovalFor: requireApproval,
|
|
1482
1969
|
onApprove: approveAction,
|
|
1483
|
-
onReject: rejectAction
|
|
1970
|
+
onReject: rejectAction,
|
|
1971
|
+
onConfirmCardGone: returnFocusToComposer
|
|
1484
1972
|
}
|
|
1485
1973
|
),
|
|
1486
1974
|
[
|
|
@@ -1493,9 +1981,12 @@ function AppilotsChatInner({
|
|
|
1493
1981
|
theme.colors.warning,
|
|
1494
1982
|
theme.colors.error,
|
|
1495
1983
|
theme.typography.fontFamily,
|
|
1984
|
+
strings,
|
|
1985
|
+
resolvedLocale,
|
|
1496
1986
|
requireApproval,
|
|
1497
1987
|
approveAction,
|
|
1498
|
-
rejectAction
|
|
1988
|
+
rejectAction,
|
|
1989
|
+
returnFocusToComposer
|
|
1499
1990
|
]
|
|
1500
1991
|
);
|
|
1501
1992
|
const resolvedHeaderTitle = resolvedTitle ?? t("chatTitle");
|
|
@@ -1505,17 +1996,17 @@ function AppilotsChatInner({
|
|
|
1505
1996
|
const showEmptySubtitle = resolvedEmptySubtitle.length > 0 && !(showSuggestedPrompts && suggestedPrompts.length > 0);
|
|
1506
1997
|
const renderAvatar = () => {
|
|
1507
1998
|
if (!assistantAvatar) {
|
|
1508
|
-
return /* @__PURE__ */
|
|
1999
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: [styles5.headerDot, { backgroundColor: theme.colors.primary }] });
|
|
1509
2000
|
}
|
|
1510
2001
|
if (typeof assistantAvatar === "string") {
|
|
1511
|
-
return /* @__PURE__ */
|
|
2002
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: { uri: assistantAvatar }, style: styles5.headerAvatar });
|
|
1512
2003
|
}
|
|
1513
2004
|
if (typeof assistantAvatar === "number") {
|
|
1514
|
-
return /* @__PURE__ */
|
|
2005
|
+
return /* @__PURE__ */ React8__default.createElement(Image, { source: assistantAvatar, style: styles5.headerAvatar });
|
|
1515
2006
|
}
|
|
1516
|
-
return /* @__PURE__ */
|
|
2007
|
+
return /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerAvatarSlot }, assistantAvatar);
|
|
1517
2008
|
};
|
|
1518
|
-
const showTrigger = mode === "bubble" &&
|
|
2009
|
+
const showTrigger = mode === "bubble" && surface === "none" && experience.entry.includes("fab") && controlledVisible === void 0 && triggerButton !== "none";
|
|
1519
2010
|
const fabPositionStyle = (() => {
|
|
1520
2011
|
switch (position) {
|
|
1521
2012
|
case "bottom-left":
|
|
@@ -1529,15 +2020,16 @@ function AppilotsChatInner({
|
|
|
1529
2020
|
return { bottom: 24, right: 24 };
|
|
1530
2021
|
}
|
|
1531
2022
|
})();
|
|
1532
|
-
const chatSurface = /* @__PURE__ */
|
|
2023
|
+
const chatSurface = /* @__PURE__ */ React8__default.createElement(
|
|
1533
2024
|
View,
|
|
1534
2025
|
{
|
|
1535
2026
|
...APPILOTS_SKIP_PROPS,
|
|
1536
2027
|
style: [
|
|
1537
|
-
|
|
1538
|
-
mode === "fullscreen" &&
|
|
1539
|
-
mode === "sidebar" &&
|
|
1540
|
-
mode === "inline" &&
|
|
2028
|
+
styles5.chatContainer,
|
|
2029
|
+
mode === "fullscreen" && styles5.chatContainerFullscreen,
|
|
2030
|
+
mode === "sidebar" && styles5.chatContainerSidebar,
|
|
2031
|
+
mode === "inline" && styles5.chatContainerInline,
|
|
2032
|
+
mode === "bubble" && fontScale >= LARGE_TEXT_FONT_SCALE && styles5.chatContainerFullscreen,
|
|
1541
2033
|
{
|
|
1542
2034
|
backgroundColor: theme.colors.background,
|
|
1543
2035
|
borderTopLeftRadius: theme.radii.lg,
|
|
@@ -1545,11 +2037,13 @@ function AppilotsChatInner({
|
|
|
1545
2037
|
}
|
|
1546
2038
|
]
|
|
1547
2039
|
},
|
|
1548
|
-
/* @__PURE__ */
|
|
2040
|
+
/* @__PURE__ */ React8__default.createElement(View, { style: [styles5.header, { borderBottomColor: theme.colors.border }] }, /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerLeft }, renderAvatar(), /* @__PURE__ */ React8__default.createElement(
|
|
1549
2041
|
Text,
|
|
1550
2042
|
{
|
|
2043
|
+
ref: titleRef,
|
|
2044
|
+
accessibilityRole: "header",
|
|
1551
2045
|
style: [
|
|
1552
|
-
|
|
2046
|
+
styles5.headerTitle,
|
|
1553
2047
|
{
|
|
1554
2048
|
color: theme.colors.text,
|
|
1555
2049
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1558,50 +2052,50 @@ function AppilotsChatInner({
|
|
|
1558
2052
|
]
|
|
1559
2053
|
},
|
|
1560
2054
|
resolvedHeaderTitle
|
|
1561
|
-
)), /* @__PURE__ */
|
|
2055
|
+
)), /* @__PURE__ */ React8__default.createElement(View, { style: styles5.headerActions }, /* @__PURE__ */ React8__default.createElement(
|
|
1562
2056
|
TouchableOpacity,
|
|
1563
2057
|
{
|
|
1564
2058
|
...APPILOTS_SKIP_PROPS,
|
|
1565
2059
|
onPress: () => requestHuman("user_requested"),
|
|
1566
|
-
style:
|
|
2060
|
+
style: styles5.headerButton,
|
|
1567
2061
|
accessibilityRole: "button",
|
|
1568
2062
|
accessibilityLabel: strings.talkToHumanA11y,
|
|
1569
2063
|
testID: "escalation-header-button"
|
|
1570
2064
|
},
|
|
1571
|
-
/* @__PURE__ */
|
|
2065
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1572
2066
|
HeadsetIcon,
|
|
1573
2067
|
{
|
|
1574
2068
|
size: 16,
|
|
1575
2069
|
color: escalation ? theme.colors.primary : theme.colors.textSecondary
|
|
1576
2070
|
}
|
|
1577
2071
|
)
|
|
1578
|
-
), /* @__PURE__ */
|
|
2072
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
1579
2073
|
TouchableOpacity,
|
|
1580
2074
|
{
|
|
1581
2075
|
...APPILOTS_SKIP_PROPS,
|
|
1582
2076
|
onPress: clearMessages,
|
|
1583
|
-
style:
|
|
2077
|
+
style: styles5.headerButton,
|
|
1584
2078
|
accessibilityRole: "button",
|
|
1585
2079
|
testID: "assistant-clear"
|
|
1586
2080
|
},
|
|
1587
|
-
/* @__PURE__ */
|
|
1588
|
-
), mode !== "inline" && /* @__PURE__ */
|
|
2081
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles5.headerButtonText, { color: theme.colors.textSecondary }] }, strings.clearButton)
|
|
2082
|
+
), mode !== "inline" && /* @__PURE__ */ React8__default.createElement(
|
|
1589
2083
|
TouchableOpacity,
|
|
1590
2084
|
{
|
|
1591
2085
|
...APPILOTS_SKIP_PROPS,
|
|
1592
2086
|
onPress: closeChat,
|
|
1593
|
-
style:
|
|
2087
|
+
style: styles5.closeButton,
|
|
1594
2088
|
accessibilityRole: "button",
|
|
1595
2089
|
accessibilityLabel: strings.closeChatA11y,
|
|
1596
2090
|
testID: "assistant-close"
|
|
1597
2091
|
},
|
|
1598
|
-
/* @__PURE__ */
|
|
2092
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: [styles5.closeButtonText, { color: theme.colors.text }] }, "\u2715")
|
|
1599
2093
|
))),
|
|
1600
|
-
escalation && /* @__PURE__ */
|
|
2094
|
+
escalation && /* @__PURE__ */ React8__default.createElement(
|
|
1601
2095
|
View,
|
|
1602
2096
|
{
|
|
1603
2097
|
style: [
|
|
1604
|
-
|
|
2098
|
+
styles5.escalationBanner,
|
|
1605
2099
|
{
|
|
1606
2100
|
borderBottomColor: theme.colors.border,
|
|
1607
2101
|
backgroundColor: theme.colors.primary + "0d"
|
|
@@ -1609,12 +2103,12 @@ function AppilotsChatInner({
|
|
|
1609
2103
|
],
|
|
1610
2104
|
testID: "escalation-banner"
|
|
1611
2105
|
},
|
|
1612
|
-
/* @__PURE__ */
|
|
1613
|
-
/* @__PURE__ */
|
|
2106
|
+
/* @__PURE__ */ React8__default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
|
|
2107
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1614
2108
|
Text,
|
|
1615
2109
|
{
|
|
1616
2110
|
style: [
|
|
1617
|
-
|
|
2111
|
+
styles5.escalationBannerText,
|
|
1618
2112
|
{
|
|
1619
2113
|
color: theme.colors.textSecondary,
|
|
1620
2114
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1625,10 +2119,11 @@ function AppilotsChatInner({
|
|
|
1625
2119
|
escalation.status === "pending" ? strings.escalationPendingBanner : strings.escalationActiveBanner
|
|
1626
2120
|
)
|
|
1627
2121
|
),
|
|
1628
|
-
/* @__PURE__ */
|
|
2122
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1629
2123
|
FlatList,
|
|
1630
2124
|
{
|
|
1631
2125
|
...APPILOTS_SKIP_PROPS,
|
|
2126
|
+
testID: "assistant-transcript",
|
|
1632
2127
|
ref: flatListRef,
|
|
1633
2128
|
data: timeline,
|
|
1634
2129
|
keyExtractor: (item) => item.type === "message" ? item.data.id : item.key,
|
|
@@ -1641,48 +2136,47 @@ function AppilotsChatInner({
|
|
|
1641
2136
|
}
|
|
1642
2137
|
return null;
|
|
1643
2138
|
},
|
|
1644
|
-
contentContainerStyle:
|
|
1645
|
-
ListEmptyComponent: /* @__PURE__ */
|
|
2139
|
+
contentContainerStyle: styles5.messageList,
|
|
2140
|
+
ListEmptyComponent: /* @__PURE__ */ React8__default.createElement(View, { style: styles5.emptyState }, emptyStateIcon && isImageSource(emptyStateIcon) ? /* @__PURE__ */ React8__default.createElement(
|
|
1646
2141
|
Image,
|
|
1647
2142
|
{
|
|
1648
2143
|
source: typeof emptyStateIcon === "string" ? { uri: emptyStateIcon } : emptyStateIcon,
|
|
1649
|
-
style:
|
|
2144
|
+
style: styles5.emptyIconImage,
|
|
1650
2145
|
resizeMode: "contain"
|
|
1651
2146
|
}
|
|
1652
|
-
) : /* @__PURE__ */
|
|
2147
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1653
2148
|
View,
|
|
1654
2149
|
{
|
|
1655
|
-
style: [
|
|
2150
|
+
style: [styles5.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
|
|
1656
2151
|
},
|
|
1657
|
-
emptyStateIcon ? /* @__PURE__ */
|
|
1658
|
-
), /* @__PURE__ */
|
|
2152
|
+
emptyStateIcon ? /* @__PURE__ */ React8__default.createElement(Text, { style: styles5.emptyIconEmoji }, emptyStateIcon) : /* @__PURE__ */ React8__default.createElement(ChatIcon, { size: 30, color: theme.colors.primary })
|
|
2153
|
+
), /* @__PURE__ */ React8__default.createElement(
|
|
1659
2154
|
Text,
|
|
1660
2155
|
{
|
|
1661
2156
|
style: [
|
|
1662
|
-
|
|
2157
|
+
styles5.emptyTitle,
|
|
1663
2158
|
{ color: theme.colors.text, fontFamily: theme.typography.fontFamily }
|
|
1664
2159
|
]
|
|
1665
2160
|
},
|
|
1666
2161
|
resolvedEmptyTitle
|
|
1667
|
-
), showEmptySubtitle && /* @__PURE__ */
|
|
2162
|
+
), showEmptySubtitle && /* @__PURE__ */ React8__default.createElement(
|
|
1668
2163
|
Text,
|
|
1669
2164
|
{
|
|
1670
2165
|
style: [
|
|
1671
|
-
|
|
2166
|
+
styles5.emptySubtitle,
|
|
1672
2167
|
{
|
|
1673
2168
|
color: theme.colors.textSecondary,
|
|
1674
2169
|
fontFamily: theme.typography.fontFamily
|
|
1675
2170
|
}
|
|
1676
|
-
]
|
|
1677
|
-
numberOfLines: 2
|
|
2171
|
+
]
|
|
1678
2172
|
},
|
|
1679
2173
|
resolvedEmptySubtitle
|
|
1680
|
-
), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */
|
|
2174
|
+
), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.chipsContainer, testID: "assistant-suggested-prompts" }, suggestedPrompts.map((prompt) => /* @__PURE__ */ React8__default.createElement(
|
|
1681
2175
|
TouchableOpacity,
|
|
1682
2176
|
{
|
|
1683
2177
|
key: `${prompt.source}:${prompt.text}`,
|
|
1684
2178
|
style: [
|
|
1685
|
-
|
|
2179
|
+
styles5.chip,
|
|
1686
2180
|
{
|
|
1687
2181
|
backgroundColor: theme.colors.surface,
|
|
1688
2182
|
borderColor: theme.colors.border,
|
|
@@ -1693,67 +2187,101 @@ function AppilotsChatInner({
|
|
|
1693
2187
|
activeOpacity: 0.7,
|
|
1694
2188
|
accessibilityLabel: `Suggested prompt: ${prompt.text}`
|
|
1695
2189
|
},
|
|
1696
|
-
/* @__PURE__ */
|
|
2190
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1697
2191
|
Text,
|
|
1698
2192
|
{
|
|
1699
2193
|
style: [
|
|
1700
|
-
|
|
2194
|
+
styles5.chipText,
|
|
1701
2195
|
{
|
|
1702
2196
|
color: theme.colors.buttonText,
|
|
1703
2197
|
fontFamily: theme.typography.fontFamily,
|
|
1704
2198
|
fontSize: theme.typography.fontSizeSm
|
|
1705
2199
|
}
|
|
1706
|
-
]
|
|
1707
|
-
numberOfLines: 1
|
|
2200
|
+
]
|
|
1708
2201
|
},
|
|
1709
2202
|
prompt.text
|
|
1710
2203
|
)
|
|
1711
2204
|
)))),
|
|
1712
|
-
ListFooterComponent: isLoading ? /* @__PURE__ */
|
|
2205
|
+
ListFooterComponent: isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
1713
2206
|
View,
|
|
1714
2207
|
{
|
|
1715
2208
|
style: [
|
|
1716
|
-
|
|
1717
|
-
|
|
2209
|
+
styles5.messageBubble,
|
|
2210
|
+
styles5.assistantBubble,
|
|
1718
2211
|
{ backgroundColor: theme.colors.surface }
|
|
1719
2212
|
]
|
|
1720
2213
|
},
|
|
1721
|
-
/* @__PURE__ */
|
|
2214
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1722
2215
|
Text,
|
|
1723
2216
|
{
|
|
1724
2217
|
style: [
|
|
1725
|
-
|
|
2218
|
+
styles5.messageText,
|
|
1726
2219
|
{ color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
|
|
1727
2220
|
]
|
|
1728
2221
|
},
|
|
1729
|
-
strings[loadingStatusKey] ?? strings.thinking
|
|
2222
|
+
stillWorkingSeconds ? strings.stillWorking.replace("{seconds}", String(stillWorkingSeconds)) : strings[loadingStatusKey] ?? strings.thinking
|
|
1730
2223
|
)
|
|
1731
2224
|
) : null
|
|
1732
2225
|
}
|
|
1733
2226
|
),
|
|
1734
|
-
/* @__PURE__ */
|
|
2227
|
+
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: styles5.missionButtons }, mission.status === "running" ? /* @__PURE__ */ React8__default.createElement(
|
|
2228
|
+
TouchableOpacity,
|
|
2229
|
+
{
|
|
2230
|
+
onPress: () => void pauseMission(),
|
|
2231
|
+
testID: "appilots-mission-pause",
|
|
2232
|
+
style: styles5.missionButton,
|
|
2233
|
+
accessibilityRole: "button"
|
|
2234
|
+
},
|
|
2235
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionPause)
|
|
2236
|
+
) : mission.status !== "awaiting_approval" ? /* @__PURE__ */ React8__default.createElement(
|
|
2237
|
+
TouchableOpacity,
|
|
2238
|
+
{
|
|
2239
|
+
onPress: () => void resumeMission(),
|
|
2240
|
+
disabled: isLoading,
|
|
2241
|
+
testID: "appilots-mission-resume",
|
|
2242
|
+
style: styles5.missionButton,
|
|
2243
|
+
accessibilityRole: "button"
|
|
2244
|
+
},
|
|
2245
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionResume)
|
|
2246
|
+
) : null, /* @__PURE__ */ React8__default.createElement(
|
|
2247
|
+
TouchableOpacity,
|
|
2248
|
+
{
|
|
2249
|
+
onPress: () => void cancelMission(),
|
|
2250
|
+
testID: "appilots-mission-cancel",
|
|
2251
|
+
style: styles5.missionButton,
|
|
2252
|
+
accessibilityRole: "button"
|
|
2253
|
+
},
|
|
2254
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: { color: theme.colors.text } }, strings.missionCancel)
|
|
2255
|
+
))),
|
|
2256
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1735
2257
|
View,
|
|
1736
2258
|
{
|
|
1737
2259
|
style: [
|
|
1738
|
-
|
|
2260
|
+
styles5.inputContainer,
|
|
1739
2261
|
{
|
|
1740
2262
|
borderTopColor: theme.colors.border,
|
|
1741
2263
|
paddingBottom: Math.max(insets.bottom, 10)
|
|
1742
2264
|
}
|
|
1743
2265
|
]
|
|
1744
2266
|
},
|
|
1745
|
-
/* @__PURE__ */
|
|
2267
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
1746
2268
|
TextInput,
|
|
1747
2269
|
{
|
|
2270
|
+
ref: composerRef,
|
|
1748
2271
|
style: [
|
|
1749
|
-
|
|
2272
|
+
styles5.input,
|
|
1750
2273
|
{
|
|
1751
2274
|
backgroundColor: theme.colors.surface,
|
|
1752
2275
|
color: theme.colors.text,
|
|
1753
2276
|
borderRadius: theme.radii.md,
|
|
1754
2277
|
fontFamily: theme.typography.fontFamily,
|
|
1755
2278
|
fontSize: theme.typography.fontSizeBase,
|
|
1756
|
-
lineHeight: theme.typography.fontSizeBase * 1.35
|
|
2279
|
+
lineHeight: theme.typography.fontSizeBase * 1.35,
|
|
2280
|
+
// The 120pt cap is ~5 lines at default size and barely one at
|
|
2281
|
+
// iOS AX5, where even the placeholder was cut. It grows with
|
|
2282
|
+
// the text, but never past a quarter of the screen, so the
|
|
2283
|
+
// keyboard still leaves room for the transcript.
|
|
2284
|
+
maxHeight: Math.min(INPUT_MAX_HEIGHT * fontScale, SCREEN_HEIGHT * 0.25)
|
|
1757
2285
|
}
|
|
1758
2286
|
],
|
|
1759
2287
|
placeholder: resolvedPlaceholder,
|
|
@@ -1763,16 +2291,35 @@ function AppilotsChatInner({
|
|
|
1763
2291
|
multiline: true,
|
|
1764
2292
|
blurOnSubmit: false,
|
|
1765
2293
|
scrollEnabled: true,
|
|
1766
|
-
editable: !isLoading,
|
|
2294
|
+
editable: !isLoading && (!mission || ["completed", "cancelled"].includes(mission.status)),
|
|
1767
2295
|
testID: "assistant-input",
|
|
1768
2296
|
__appilotsInternal: true
|
|
1769
2297
|
}
|
|
1770
2298
|
),
|
|
1771
|
-
isLoading ? /* @__PURE__ */
|
|
2299
|
+
voiceEnabled && !isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
1772
2300
|
TouchableOpacity,
|
|
1773
2301
|
{
|
|
1774
2302
|
style: [
|
|
1775
|
-
|
|
2303
|
+
styles5.sendButton,
|
|
2304
|
+
{
|
|
2305
|
+
backgroundColor: voice.state === "listening" || voice.state === "starting" ? theme.colors.error : theme.colors.primary + "40",
|
|
2306
|
+
borderRadius: theme.radii.md
|
|
2307
|
+
}
|
|
2308
|
+
],
|
|
2309
|
+
onPressIn: voice.start,
|
|
2310
|
+
onPressOut: voice.stop,
|
|
2311
|
+
accessibilityRole: "button",
|
|
2312
|
+
accessibilityLabel: voice.state === "listening" ? strings.micStopA11y : strings.micStartA11y,
|
|
2313
|
+
testID: "appilots-mic-button",
|
|
2314
|
+
activeOpacity: 0.7
|
|
2315
|
+
},
|
|
2316
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u25CF")
|
|
2317
|
+
) : null,
|
|
2318
|
+
isLoading ? /* @__PURE__ */ React8__default.createElement(
|
|
2319
|
+
TouchableOpacity,
|
|
2320
|
+
{
|
|
2321
|
+
style: [
|
|
2322
|
+
styles5.sendButton,
|
|
1776
2323
|
{
|
|
1777
2324
|
backgroundColor: theme.colors.primary,
|
|
1778
2325
|
borderRadius: theme.radii.md
|
|
@@ -1784,31 +2331,31 @@ function AppilotsChatInner({
|
|
|
1784
2331
|
testID: "appilots-stop-button",
|
|
1785
2332
|
activeOpacity: 0.7
|
|
1786
2333
|
},
|
|
1787
|
-
/* @__PURE__ */
|
|
1788
|
-
) : /* @__PURE__ */
|
|
2334
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u25A0")
|
|
2335
|
+
) : /* @__PURE__ */ React8__default.createElement(
|
|
1789
2336
|
TouchableOpacity,
|
|
1790
2337
|
{
|
|
1791
2338
|
style: [
|
|
1792
|
-
|
|
2339
|
+
styles5.sendButton,
|
|
1793
2340
|
{
|
|
1794
2341
|
backgroundColor: inputText.trim() ? theme.colors.primary : theme.colors.primary + "40",
|
|
1795
2342
|
borderRadius: theme.radii.md
|
|
1796
2343
|
}
|
|
1797
2344
|
],
|
|
1798
2345
|
onPress: handleSend,
|
|
1799
|
-
disabled: !inputText.trim(),
|
|
2346
|
+
disabled: !inputText.trim() || !!(mission && !["completed", "cancelled"].includes(mission.status)),
|
|
1800
2347
|
activeOpacity: 0.7,
|
|
1801
2348
|
accessibilityRole: "button",
|
|
1802
2349
|
testID: "assistant-send"
|
|
1803
2350
|
},
|
|
1804
|
-
/* @__PURE__ */
|
|
2351
|
+
/* @__PURE__ */ React8__default.createElement(Text, { style: styles5.sendButtonText }, "\u2191")
|
|
1805
2352
|
)
|
|
1806
2353
|
),
|
|
1807
|
-
poweredByVisible && /* @__PURE__ */
|
|
2354
|
+
poweredByVisible && /* @__PURE__ */ React8__default.createElement(View, { style: styles5.poweredByContainer }, /* @__PURE__ */ React8__default.createElement(
|
|
1808
2355
|
Text,
|
|
1809
2356
|
{
|
|
1810
2357
|
style: [
|
|
1811
|
-
|
|
2358
|
+
styles5.poweredByText,
|
|
1812
2359
|
{
|
|
1813
2360
|
color: theme.colors.textSecondary,
|
|
1814
2361
|
fontFamily: theme.typography.fontFamily,
|
|
@@ -1824,11 +2371,12 @@ function AppilotsChatInner({
|
|
|
1824
2371
|
}
|
|
1825
2372
|
const renderTrigger = () => {
|
|
1826
2373
|
if (triggerButton === "none") return null;
|
|
1827
|
-
if (triggerButton !== "default" &&
|
|
1828
|
-
return /* @__PURE__ */
|
|
2374
|
+
if (triggerButton !== "default" && React8__default.isValidElement(triggerButton)) {
|
|
2375
|
+
return /* @__PURE__ */ React8__default.createElement(View, { ...APPILOTS_SKIP_PROPS, style: [styles5.fabWrapper, fabPositionStyle] }, /* @__PURE__ */ React8__default.createElement(
|
|
1829
2376
|
TouchableOpacity,
|
|
1830
2377
|
{
|
|
1831
2378
|
...APPILOTS_SKIP_PROPS,
|
|
2379
|
+
ref: launcherRef,
|
|
1832
2380
|
onPress: openChat,
|
|
1833
2381
|
activeOpacity: 0.8,
|
|
1834
2382
|
accessibilityRole: "button",
|
|
@@ -1838,12 +2386,13 @@ function AppilotsChatInner({
|
|
|
1838
2386
|
triggerButton
|
|
1839
2387
|
));
|
|
1840
2388
|
}
|
|
1841
|
-
return /* @__PURE__ */
|
|
2389
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
1842
2390
|
TouchableOpacity,
|
|
1843
2391
|
{
|
|
1844
2392
|
...APPILOTS_SKIP_PROPS,
|
|
2393
|
+
ref: launcherRef,
|
|
1845
2394
|
style: [
|
|
1846
|
-
|
|
2395
|
+
styles5.fab,
|
|
1847
2396
|
fabPositionStyle,
|
|
1848
2397
|
{ backgroundColor: triggerButtonColor ?? theme.colors.primary }
|
|
1849
2398
|
],
|
|
@@ -1853,55 +2402,116 @@ function AppilotsChatInner({
|
|
|
1853
2402
|
accessibilityLabel: strings.openChatA11y,
|
|
1854
2403
|
testID: "assistant-launcher"
|
|
1855
2404
|
},
|
|
1856
|
-
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */
|
|
2405
|
+
triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React8__default.createElement(
|
|
1857
2406
|
Image,
|
|
1858
2407
|
{
|
|
1859
2408
|
source: typeof triggerButtonImage === "string" ? { uri: triggerButtonImage } : triggerButtonImage,
|
|
1860
|
-
style:
|
|
2409
|
+
style: styles5.fabImage,
|
|
1861
2410
|
resizeMode: "contain"
|
|
1862
2411
|
}
|
|
1863
|
-
) : /* @__PURE__ */
|
|
2412
|
+
) : /* @__PURE__ */ React8__default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
|
|
1864
2413
|
);
|
|
1865
2414
|
};
|
|
1866
|
-
return /* @__PURE__ */
|
|
1867
|
-
|
|
2415
|
+
return /* @__PURE__ */ React8__default.createElement(React8__default.Fragment, null, showTrigger && renderTrigger(), spotlight && experience.spotlight !== "off" ? /* @__PURE__ */ React8__default.createElement(
|
|
2416
|
+
SpotlightOverlay,
|
|
2417
|
+
{
|
|
2418
|
+
rect: spotlight.rect,
|
|
2419
|
+
seq: spotlight.seq,
|
|
2420
|
+
label: spotlight.label,
|
|
2421
|
+
color: theme.colors.primary,
|
|
2422
|
+
captionBackground: theme.colors.surface,
|
|
2423
|
+
captionColor: theme.colors.text,
|
|
2424
|
+
fontFamily: theme.typography.fontFamily,
|
|
2425
|
+
window: { width: SCREEN_WIDTH, height: SCREEN_HEIGHT }
|
|
2426
|
+
}
|
|
2427
|
+
) : null, surface === "pill" && /* @__PURE__ */ React8__default.createElement(
|
|
2428
|
+
AgentPill,
|
|
2429
|
+
{
|
|
2430
|
+
label: mission && !["completed", "cancelled"].includes(mission.status) ? mission.progressText : pillLabel,
|
|
2431
|
+
state: pillState,
|
|
2432
|
+
position,
|
|
2433
|
+
insets,
|
|
2434
|
+
fontFamily: theme.typography.fontFamily,
|
|
2435
|
+
colors: {
|
|
2436
|
+
surface: theme.colors.surface,
|
|
2437
|
+
text: theme.colors.text,
|
|
2438
|
+
textSecondary: theme.colors.textSecondary,
|
|
2439
|
+
primary: theme.colors.primary,
|
|
2440
|
+
border: theme.colors.border,
|
|
2441
|
+
success: theme.colors.success,
|
|
2442
|
+
error: theme.colors.error
|
|
2443
|
+
},
|
|
2444
|
+
strings: { expandA11y: strings.pillExpandA11y, stopA11y: strings.pillStopA11y },
|
|
2445
|
+
onExpand: openChat,
|
|
2446
|
+
expandRef: pillRef,
|
|
2447
|
+
onStop: busy ? cancelMessage : void 0
|
|
2448
|
+
}
|
|
2449
|
+
), /* @__PURE__ */ React8__default.createElement(SheetHost, { useModal: presence === "sheet", visible: isVisible, onRequestClose: closeChat }, /* @__PURE__ */ React8__default.createElement(
|
|
2450
|
+
Animated.View,
|
|
1868
2451
|
{
|
|
1869
2452
|
...APPILOTS_SKIP_PROPS,
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
2453
|
+
pointerEvents: presence === "sheet" ? "auto" : "box-none",
|
|
2454
|
+
onAccessibilityEscape: closeChat,
|
|
2455
|
+
style: [
|
|
2456
|
+
mode === "fullscreen" ? styles5.modalContainerFullscreen : styles5.modalContainer,
|
|
2457
|
+
mode === "sidebar" && styles5.modalContainerSidebar,
|
|
2458
|
+
presence !== "sheet" && styles5.sheetContainerNoScrim,
|
|
2459
|
+
// Keeps the sheet out of the status bar / notch. It is padding
|
|
2460
|
+
// and not a margin so the scrim still covers the full screen.
|
|
2461
|
+
// Only reachable now that the sheet can grow to the top edge:
|
|
2462
|
+
// `fullscreen` and `sidebar` always could, and `bubble` does
|
|
2463
|
+
// whenever the keyboard shrinks it — without this, the header
|
|
2464
|
+
// renders under the clock.
|
|
2465
|
+
{ paddingTop: insets.top },
|
|
2466
|
+
{ transform: [{ translateY: slideAnim }] }
|
|
2467
|
+
]
|
|
1874
2468
|
},
|
|
1875
|
-
/* @__PURE__ */
|
|
1876
|
-
|
|
2469
|
+
/* @__PURE__ */ React8__default.createElement(
|
|
2470
|
+
KeyboardAvoidingView,
|
|
1877
2471
|
{
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
mode === "sidebar" && styles3.modalContainerSidebar,
|
|
1882
|
-
// Keeps the sheet out of the status bar / notch. It is padding
|
|
1883
|
-
// and not a margin so the scrim still covers the full screen.
|
|
1884
|
-
// Only reachable now that the sheet can grow to the top edge:
|
|
1885
|
-
// `fullscreen` and `sidebar` always could, and `bubble` does
|
|
1886
|
-
// whenever the keyboard shrinks it — without this, the header
|
|
1887
|
-
// renders under the clock.
|
|
1888
|
-
{ paddingTop: insets.top },
|
|
1889
|
-
{ transform: [{ translateY: slideAnim }] }
|
|
1890
|
-
]
|
|
2472
|
+
style: styles5.keyboardView,
|
|
2473
|
+
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
2474
|
+
keyboardVerticalOffset: 0
|
|
1891
2475
|
},
|
|
1892
|
-
|
|
1893
|
-
KeyboardAvoidingView,
|
|
1894
|
-
{
|
|
1895
|
-
style: styles3.keyboardView,
|
|
1896
|
-
behavior: Platform.OS === "ios" ? "padding" : "height",
|
|
1897
|
-
keyboardVerticalOffset: 0
|
|
1898
|
-
},
|
|
1899
|
-
chatSurface
|
|
1900
|
-
)
|
|
2476
|
+
chatSurface
|
|
1901
2477
|
)
|
|
1902
|
-
));
|
|
2478
|
+
)));
|
|
1903
2479
|
}
|
|
1904
|
-
|
|
2480
|
+
function SheetHost({
|
|
2481
|
+
useModal,
|
|
2482
|
+
visible,
|
|
2483
|
+
onRequestClose,
|
|
2484
|
+
children
|
|
2485
|
+
}) {
|
|
2486
|
+
if (useModal) {
|
|
2487
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2488
|
+
Modal,
|
|
2489
|
+
{
|
|
2490
|
+
...APPILOTS_SKIP_PROPS,
|
|
2491
|
+
visible,
|
|
2492
|
+
transparent: true,
|
|
2493
|
+
animationType: "none",
|
|
2494
|
+
onRequestClose
|
|
2495
|
+
},
|
|
2496
|
+
children
|
|
2497
|
+
);
|
|
2498
|
+
}
|
|
2499
|
+
if (!visible) return null;
|
|
2500
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2501
|
+
View,
|
|
2502
|
+
{
|
|
2503
|
+
...APPILOTS_SKIP_PROPS,
|
|
2504
|
+
pointerEvents: "box-none",
|
|
2505
|
+
accessibilityViewIsModal: true,
|
|
2506
|
+
style: [StyleSheet.absoluteFill, styles5.sheetOverlay]
|
|
2507
|
+
},
|
|
2508
|
+
children
|
|
2509
|
+
);
|
|
2510
|
+
}
|
|
2511
|
+
var styles5 = StyleSheet.create({
|
|
2512
|
+
// An explicitly opened chat must not mount underneath a sibling portal.
|
|
2513
|
+
// Automatic expansion is separately deferred while the host modal is open.
|
|
2514
|
+
sheetOverlay: { zIndex: 1e3, elevation: 7 },
|
|
1905
2515
|
fab: {
|
|
1906
2516
|
position: "absolute",
|
|
1907
2517
|
width: 56,
|
|
@@ -1944,6 +2554,12 @@ var styles3 = StyleSheet.create({
|
|
|
1944
2554
|
flexDirection: "row",
|
|
1945
2555
|
justifyContent: "flex-end"
|
|
1946
2556
|
},
|
|
2557
|
+
// Non-modal presences drop the scrim entirely: dimming the app is
|
|
2558
|
+
// the opposite of the point, and a painted full-screen surface is
|
|
2559
|
+
// touch-opaque no matter what pointerEvents the parent asks for.
|
|
2560
|
+
sheetContainerNoScrim: {
|
|
2561
|
+
backgroundColor: "transparent"
|
|
2562
|
+
},
|
|
1947
2563
|
keyboardView: {
|
|
1948
2564
|
flex: 1,
|
|
1949
2565
|
justifyContent: "flex-end"
|
|
@@ -1985,8 +2601,13 @@ var styles3 = StyleSheet.create({
|
|
|
1985
2601
|
maxHeight: "100%",
|
|
1986
2602
|
flex: 1
|
|
1987
2603
|
},
|
|
2604
|
+
// Wraps instead of squeezing: at large text sizes the title alone is
|
|
2605
|
+
// wider than the row, and without the wrap it pushed Clear and ✕ off the
|
|
2606
|
+
// right edge — the chat could not be closed (measured at iOS AX5).
|
|
1988
2607
|
header: {
|
|
1989
2608
|
flexDirection: "row",
|
|
2609
|
+
flexWrap: "wrap",
|
|
2610
|
+
rowGap: 4,
|
|
1990
2611
|
alignItems: "center",
|
|
1991
2612
|
justifyContent: "space-between",
|
|
1992
2613
|
paddingHorizontal: 16,
|
|
@@ -1996,7 +2617,8 @@ var styles3 = StyleSheet.create({
|
|
|
1996
2617
|
headerLeft: {
|
|
1997
2618
|
flexDirection: "row",
|
|
1998
2619
|
alignItems: "center",
|
|
1999
|
-
gap: 8
|
|
2620
|
+
gap: 8,
|
|
2621
|
+
flexShrink: 1
|
|
2000
2622
|
},
|
|
2001
2623
|
headerDot: {
|
|
2002
2624
|
width: 8,
|
|
@@ -2015,24 +2637,30 @@ var styles3 = StyleSheet.create({
|
|
|
2015
2637
|
justifyContent: "center"
|
|
2016
2638
|
},
|
|
2017
2639
|
headerTitle: {
|
|
2018
|
-
fontWeight: "600"
|
|
2640
|
+
fontWeight: "600",
|
|
2641
|
+
flexShrink: 1
|
|
2019
2642
|
},
|
|
2020
2643
|
headerActions: {
|
|
2021
2644
|
flexDirection: "row",
|
|
2022
2645
|
alignItems: "center",
|
|
2023
|
-
gap:
|
|
2646
|
+
gap: 4,
|
|
2647
|
+
// Stays right-aligned when the header wraps it onto its own line.
|
|
2648
|
+
marginLeft: "auto"
|
|
2024
2649
|
},
|
|
2025
2650
|
headerButton: {
|
|
2651
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2652
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2026
2653
|
paddingHorizontal: 8,
|
|
2027
|
-
|
|
2654
|
+
alignItems: "center",
|
|
2655
|
+
justifyContent: "center"
|
|
2028
2656
|
},
|
|
2029
2657
|
headerButtonText: {
|
|
2030
2658
|
fontSize: 13
|
|
2031
2659
|
},
|
|
2032
2660
|
closeButton: {
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
borderRadius:
|
|
2661
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2662
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2663
|
+
borderRadius: MIN_TOUCH_TARGET2 / 2,
|
|
2036
2664
|
alignItems: "center",
|
|
2037
2665
|
justifyContent: "center"
|
|
2038
2666
|
},
|
|
@@ -2114,6 +2742,8 @@ var styles3 = StyleSheet.create({
|
|
|
2114
2742
|
maxWidth: 320
|
|
2115
2743
|
},
|
|
2116
2744
|
chip: {
|
|
2745
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2746
|
+
justifyContent: "center",
|
|
2117
2747
|
paddingHorizontal: 16,
|
|
2118
2748
|
paddingVertical: 10,
|
|
2119
2749
|
borderWidth: 1,
|
|
@@ -2176,16 +2806,16 @@ var styles3 = StyleSheet.create({
|
|
|
2176
2806
|
},
|
|
2177
2807
|
input: {
|
|
2178
2808
|
flex: 1,
|
|
2179
|
-
minHeight:
|
|
2180
|
-
maxHeight:
|
|
2809
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2810
|
+
maxHeight: INPUT_MAX_HEIGHT,
|
|
2181
2811
|
paddingHorizontal: 16,
|
|
2182
2812
|
paddingTop: Platform.OS === "ios" ? 9 : 8,
|
|
2183
2813
|
paddingBottom: Platform.OS === "ios" ? 9 : 8,
|
|
2184
2814
|
textAlignVertical: "top"
|
|
2185
2815
|
},
|
|
2186
2816
|
sendButton: {
|
|
2187
|
-
|
|
2188
|
-
|
|
2817
|
+
minWidth: MIN_TOUCH_TARGET2,
|
|
2818
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2189
2819
|
alignItems: "center",
|
|
2190
2820
|
justifyContent: "center"
|
|
2191
2821
|
},
|
|
@@ -2194,6 +2824,15 @@ var styles3 = StyleSheet.create({
|
|
|
2194
2824
|
fontSize: 18,
|
|
2195
2825
|
fontWeight: "700"
|
|
2196
2826
|
},
|
|
2827
|
+
missionButtons: {
|
|
2828
|
+
flexDirection: "row",
|
|
2829
|
+
flexWrap: "wrap",
|
|
2830
|
+
columnGap: 12
|
|
2831
|
+
},
|
|
2832
|
+
missionButton: {
|
|
2833
|
+
minHeight: MIN_TOUCH_TARGET2,
|
|
2834
|
+
justifyContent: "center"
|
|
2835
|
+
},
|
|
2197
2836
|
poweredByContainer: {
|
|
2198
2837
|
alignItems: "center",
|
|
2199
2838
|
paddingVertical: 4
|
|
@@ -2208,6 +2847,11 @@ function ConfirmDialog(_props = {}) {
|
|
|
2208
2847
|
return null;
|
|
2209
2848
|
}
|
|
2210
2849
|
|
|
2850
|
+
// src/auto/appilotsListTotal.ts
|
|
2851
|
+
function appilotsListTotal(total) {
|
|
2852
|
+
return { appilotsTotalItemCount: total };
|
|
2853
|
+
}
|
|
2854
|
+
|
|
2211
2855
|
// src/hoc/canHoldRef.ts
|
|
2212
2856
|
var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
2213
2857
|
var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
|
|
@@ -2234,12 +2878,19 @@ function canHoldRef(type) {
|
|
|
2234
2878
|
}
|
|
2235
2879
|
}
|
|
2236
2880
|
|
|
2881
|
+
// src/hoc/withDeclaredIdentity.ts
|
|
2882
|
+
function withDeclaredIdentity(props, declaredId, enabled) {
|
|
2883
|
+
if (!enabled || !declaredId) return props;
|
|
2884
|
+
if (props.testID != null) return props;
|
|
2885
|
+
return { ...props, testID: declaredId };
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2237
2888
|
// src/hoc/createAppilotsInput.tsx
|
|
2238
2889
|
function normalizeId(label) {
|
|
2239
2890
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2240
2891
|
}
|
|
2241
2892
|
function createAppilotsInput(WrappedComponent) {
|
|
2242
|
-
const AppilotsInput =
|
|
2893
|
+
const AppilotsInput = React8__default.forwardRef((props, ref) => {
|
|
2243
2894
|
const {
|
|
2244
2895
|
appilotsId,
|
|
2245
2896
|
appilotsScreen,
|
|
@@ -2294,10 +2945,14 @@ function createAppilotsInput(WrappedComponent) {
|
|
|
2294
2945
|
},
|
|
2295
2946
|
[ref]
|
|
2296
2947
|
);
|
|
2297
|
-
return /* @__PURE__ */
|
|
2948
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2298
2949
|
WrappedComponent,
|
|
2299
2950
|
{
|
|
2300
|
-
...
|
|
2951
|
+
...withDeclaredIdentity(
|
|
2952
|
+
{ label, value, onChangeText, ...rest },
|
|
2953
|
+
fieldId,
|
|
2954
|
+
appilotsEnabled
|
|
2955
|
+
),
|
|
2301
2956
|
...canHoldRef(WrappedComponent) ? { ref: mergedRef } : {}
|
|
2302
2957
|
}
|
|
2303
2958
|
);
|
|
@@ -2309,7 +2964,7 @@ function normalizeId2(label) {
|
|
|
2309
2964
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2310
2965
|
}
|
|
2311
2966
|
function createAppilotsButton(WrappedComponent) {
|
|
2312
|
-
const AppilotsButton =
|
|
2967
|
+
const AppilotsButton = React8__default.forwardRef((props, ref) => {
|
|
2313
2968
|
const {
|
|
2314
2969
|
appilotsId,
|
|
2315
2970
|
appilotsScreen,
|
|
@@ -2335,10 +2990,10 @@ function createAppilotsButton(WrappedComponent) {
|
|
|
2335
2990
|
componentRegistry.unregister(targetId);
|
|
2336
2991
|
};
|
|
2337
2992
|
}, [targetId, appilotsEnabled, press, title, appilotsScreen]);
|
|
2338
|
-
return /* @__PURE__ */
|
|
2993
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2339
2994
|
WrappedComponent,
|
|
2340
2995
|
{
|
|
2341
|
-
...{ title, onPress, ...rest },
|
|
2996
|
+
...withDeclaredIdentity({ title, onPress, ...rest }, targetId, appilotsEnabled),
|
|
2342
2997
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2343
2998
|
}
|
|
2344
2999
|
);
|
|
@@ -2350,7 +3005,7 @@ function normalizeId3(label) {
|
|
|
2350
3005
|
return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
|
|
2351
3006
|
}
|
|
2352
3007
|
function createAppilotsSwitch(WrappedComponent) {
|
|
2353
|
-
const AppilotsSwitch =
|
|
3008
|
+
const AppilotsSwitch = React8__default.forwardRef((props, ref) => {
|
|
2354
3009
|
const {
|
|
2355
3010
|
appilotsId,
|
|
2356
3011
|
appilotsScreen,
|
|
@@ -2381,10 +3036,14 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2381
3036
|
componentRegistry.unregister(toggleId);
|
|
2382
3037
|
};
|
|
2383
3038
|
}, [toggleId, appilotsEnabled, getValue, setValue, label, appilotsScreen]);
|
|
2384
|
-
return /* @__PURE__ */
|
|
3039
|
+
return /* @__PURE__ */ React8__default.createElement(
|
|
2385
3040
|
WrappedComponent,
|
|
2386
3041
|
{
|
|
2387
|
-
...
|
|
3042
|
+
...withDeclaredIdentity(
|
|
3043
|
+
{ label, value, onValueChange, ...rest },
|
|
3044
|
+
toggleId,
|
|
3045
|
+
appilotsEnabled
|
|
3046
|
+
),
|
|
2388
3047
|
...canHoldRef(WrappedComponent) ? { ref } : {}
|
|
2389
3048
|
}
|
|
2390
3049
|
);
|
|
@@ -2393,4 +3052,4 @@ function createAppilotsSwitch(WrappedComponent) {
|
|
|
2393
3052
|
return AppilotsSwitch;
|
|
2394
3053
|
}
|
|
2395
3054
|
|
|
2396
|
-
export { ActionBreadcrumb,
|
|
3055
|
+
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 };
|