@appilots/sdk 0.11.1 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkDRXUBLGY_js = require('./chunk-DRXUBLGY.js');
4
- var chunkX4MPSZL3_js = require('./chunk-X4MPSZL3.js');
5
- var chunkKZ2BLMS4_js = require('./chunk-KZ2BLMS4.js');
6
- var React7 = require('react');
3
+ var chunkALJGKORS_js = require('./chunk-ALJGKORS.js');
4
+ var chunkAJDHZRBN_js = require('./chunk-AJDHZRBN.js');
5
+ var chunkUZ2D4BVX_js = require('./chunk-UZ2D4BVX.js');
6
+ var React8 = require('react');
7
7
  var reactNative = require('react-native');
8
8
  var reactNativeSafeAreaContext = require('react-native-safe-area-context');
9
9
  var Svg = require('react-native-svg');
@@ -28,13 +28,13 @@ function _interopNamespace(e) {
28
28
  return Object.freeze(n);
29
29
  }
30
30
 
31
- var React7__namespace = /*#__PURE__*/_interopNamespace(React7);
31
+ var React8__namespace = /*#__PURE__*/_interopNamespace(React8);
32
32
  var Svg__default = /*#__PURE__*/_interopDefault(Svg);
33
33
 
34
34
  var NO_INSETS = { top: 0, right: 0, bottom: 0, left: 0 };
35
35
  var _warned = false;
36
36
  function useSafeAreaInsetsOrDefault() {
37
- const insets = React7.useContext(reactNativeSafeAreaContext.SafeAreaInsetsContext);
37
+ const insets = React8.useContext(reactNativeSafeAreaContext.SafeAreaInsetsContext);
38
38
  if (insets) return insets;
39
39
  if (!_warned) {
40
40
  _warned = true;
@@ -44,17 +44,54 @@ function useSafeAreaInsetsOrDefault() {
44
44
  }
45
45
  return NO_INSETS;
46
46
  }
47
+ function probeHostModalOpen() {
48
+ const stack = [chunkUZ2D4BVX_js.getFiberRoot()];
49
+ const seen = /* @__PURE__ */ new Set();
50
+ while (stack.length) {
51
+ const node = stack.pop();
52
+ if (!node || seen.has(node)) continue;
53
+ seen.add(node);
54
+ if (node.sibling) stack.push(node.sibling);
55
+ if (chunkUZ2D4BVX_js.shouldSkipSubtree(node)) continue;
56
+ if (chunkUZ2D4BVX_js.isModalFiber(node) && node.child) return true;
57
+ if (node.child) stack.push(node.child);
58
+ }
59
+ return false;
60
+ }
61
+ function useHostModalOpen(enabled) {
62
+ const [open, setOpen] = React8.useState(false);
63
+ React8.useEffect(() => {
64
+ if (!enabled) {
65
+ setOpen(false);
66
+ return;
67
+ }
68
+ let closedSince;
69
+ const sample = () => {
70
+ if (probeHostModalOpen()) {
71
+ closedSince = void 0;
72
+ setOpen(true);
73
+ } else {
74
+ closedSince ??= Date.now();
75
+ if (Date.now() - closedSince >= 300) setOpen(false);
76
+ }
77
+ };
78
+ sample();
79
+ const timer = setInterval(sample, 150);
80
+ return () => clearInterval(timer);
81
+ }, [enabled]);
82
+ return enabled && open;
83
+ }
47
84
 
48
85
  // src/components/breadcrumbPresentation.ts
49
86
  var DEFAULT_BREADCRUMB_PALETTE = {
50
- primary: chunkKZ2BLMS4_js.defaultLightTheme.colors.primary,
51
- text: chunkKZ2BLMS4_js.defaultLightTheme.colors.text,
52
- textSecondary: chunkKZ2BLMS4_js.defaultLightTheme.colors.textSecondary,
53
- surface: chunkKZ2BLMS4_js.defaultLightTheme.colors.surface,
54
- border: chunkKZ2BLMS4_js.defaultLightTheme.colors.border,
55
- success: chunkKZ2BLMS4_js.defaultLightTheme.colors.success,
56
- warning: chunkKZ2BLMS4_js.defaultLightTheme.colors.warning,
57
- error: chunkKZ2BLMS4_js.defaultLightTheme.colors.error
87
+ primary: chunkUZ2D4BVX_js.defaultLightTheme.colors.primary,
88
+ text: chunkUZ2D4BVX_js.defaultLightTheme.colors.text,
89
+ textSecondary: chunkUZ2D4BVX_js.defaultLightTheme.colors.textSecondary,
90
+ surface: chunkUZ2D4BVX_js.defaultLightTheme.colors.surface,
91
+ border: chunkUZ2D4BVX_js.defaultLightTheme.colors.border,
92
+ success: chunkUZ2D4BVX_js.defaultLightTheme.colors.success,
93
+ warning: chunkUZ2D4BVX_js.defaultLightTheme.colors.warning,
94
+ error: chunkUZ2D4BVX_js.defaultLightTheme.colors.error
58
95
  };
59
96
  var KNOWN_TINTS = {
60
97
  [DEFAULT_BREADCRUMB_PALETTE.primary.toUpperCase()]: "#EEF2FF",
@@ -136,6 +173,7 @@ function ActionBreadcrumb({
136
173
  fontFamily,
137
174
  palette,
138
175
  confirmStrings,
176
+ locale,
139
177
  requireApprovalFor,
140
178
  onApprove,
141
179
  onReject
@@ -147,7 +185,7 @@ function ActionBreadcrumb({
147
185
  primary: primaryColor,
148
186
  text: textColor
149
187
  };
150
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles.container }, actions.map((action) => /* @__PURE__ */ React7__namespace.default.createElement(
188
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles.container }, actions.map((action) => /* @__PURE__ */ React8__namespace.default.createElement(
151
189
  BreadcrumbRow,
152
190
  {
153
191
  key: action.id,
@@ -157,6 +195,7 @@ function ActionBreadcrumb({
157
195
  fontFamily,
158
196
  palette: resolvedPalette,
159
197
  confirmStrings,
198
+ locale,
160
199
  needsApproval: requireApprovalFor?.(action) ?? false,
161
200
  onApprove,
162
201
  onReject
@@ -166,7 +205,7 @@ function ActionBreadcrumb({
166
205
  function BreadcrumbRow(props) {
167
206
  const { action, needsApproval } = props;
168
207
  if (action.type === "confirm" && action.status === "pending" && needsApproval) {
169
- return /* @__PURE__ */ React7__namespace.default.createElement(
208
+ return /* @__PURE__ */ React8__namespace.default.createElement(
170
209
  ConfirmCard,
171
210
  {
172
211
  action,
@@ -178,7 +217,7 @@ function BreadcrumbRow(props) {
178
217
  }
179
218
  );
180
219
  }
181
- return /* @__PURE__ */ React7__namespace.default.createElement(RegularBreadcrumbRow, { ...props });
220
+ return /* @__PURE__ */ React8__namespace.default.createElement(RegularBreadcrumbRow, { ...props });
182
221
  }
183
222
  function RegularBreadcrumbRow({
184
223
  action,
@@ -186,23 +225,24 @@ function RegularBreadcrumbRow({
186
225
  textColor,
187
226
  fontFamily,
188
227
  palette,
228
+ locale,
189
229
  needsApproval,
190
230
  onApprove,
191
231
  onReject
192
232
  }) {
193
- const { label, state } = chunkKZ2BLMS4_js.describeAction(action);
233
+ const { label, state } = chunkUZ2D4BVX_js.describeAction(action, locale);
194
234
  const tone = deriveStateTone(palette)[state];
195
- const fade = React7.useRef(new reactNative.Animated.Value(0)).current;
196
- const pulse = React7.useRef(new reactNative.Animated.Value(1)).current;
197
- const lastState = React7.useRef(state);
198
- React7.useEffect(() => {
235
+ const fade = React8.useRef(new reactNative.Animated.Value(0)).current;
236
+ const pulse = React8.useRef(new reactNative.Animated.Value(1)).current;
237
+ const lastState = React8.useRef(state);
238
+ React8.useEffect(() => {
199
239
  reactNative.Animated.timing(fade, {
200
240
  toValue: 1,
201
241
  duration: 180,
202
242
  useNativeDriver: true
203
243
  }).start();
204
244
  }, [fade]);
205
- React7.useEffect(() => {
245
+ React8.useEffect(() => {
206
246
  if (lastState.current === state) return;
207
247
  lastState.current = state;
208
248
  pulse.setValue(0.4);
@@ -213,39 +253,41 @@ function RegularBreadcrumbRow({
213
253
  }).start();
214
254
  }, [state, pulse]);
215
255
  const isDestructive = isDestructiveAction(action);
216
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React7__namespace.default.createElement(
256
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Animated.View, { style: [styles.row, { opacity: fade }] }, /* @__PURE__ */ React8__namespace.default.createElement(
217
257
  reactNative.Animated.View,
218
258
  {
219
259
  style: { opacity: pulse, flexDirection: "row", alignItems: "flex-start", flex: 1 }
220
260
  },
221
- /* @__PURE__ */ React7__namespace.default.createElement(StateIcon, { state, tone, primaryColor }),
222
- /* @__PURE__ */ React7__namespace.default.createElement(
261
+ /* @__PURE__ */ React8__namespace.default.createElement(StateIcon, { state, tone, primaryColor }),
262
+ /* @__PURE__ */ React8__namespace.default.createElement(
223
263
  reactNative.Text,
224
264
  {
225
265
  style: [styles.label, { color: state === "failed" ? tone.color : textColor, fontFamily }],
226
266
  accessibilityLabel: `${state}: ${label}`
227
267
  },
228
268
  label,
229
- isDestructive && /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
269
+ isDestructive && /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [styles.destructiveTag, { color: palette.error }] }, " \u26A0 destrutiva")
230
270
  )
231
- ), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles.approvalButtons }, /* @__PURE__ */ React7__namespace.default.createElement(
271
+ ), needsApproval && action.status === "pending" && onApprove && onReject && /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles.approvalButtons }, /* @__PURE__ */ React8__namespace.default.createElement(
232
272
  reactNative.TouchableOpacity,
233
273
  {
234
274
  onPress: () => onReject(action.id),
235
275
  style: [styles.btn, { backgroundColor: deriveStateTone(palette).failed.iconBg }],
236
276
  activeOpacity: 0.7,
237
- accessibilityLabel: "Rejeitar a\xE7\xE3o"
277
+ accessibilityLabel: "Rejeitar a\xE7\xE3o",
278
+ testID: "assistant-action-reject"
238
279
  },
239
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
240
- ), /* @__PURE__ */ React7__namespace.default.createElement(
280
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
281
+ ), /* @__PURE__ */ React8__namespace.default.createElement(
241
282
  reactNative.TouchableOpacity,
242
283
  {
243
284
  onPress: () => onApprove(action.id),
244
285
  style: [styles.btn, styles.approveBtn, { backgroundColor: primaryColor }],
245
286
  activeOpacity: 0.7,
246
- accessibilityLabel: "Aprovar a\xE7\xE3o"
287
+ accessibilityLabel: "Aprovar a\xE7\xE3o",
288
+ testID: "assistant-action-approve"
247
289
  },
248
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles.approveBtnText }, "Aprovar")
290
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles.approveBtnText }, "Aprovar")
249
291
  )));
250
292
  }
251
293
  function ConfirmCard({
@@ -270,7 +312,7 @@ function ConfirmCard({
270
312
  cancelBackground,
271
313
  cancelTextColor
272
314
  } = deriveConfirmCardContent(action, palette, confirmStrings);
273
- return /* @__PURE__ */ React7__namespace.default.createElement(
315
+ return /* @__PURE__ */ React8__namespace.default.createElement(
274
316
  reactNative.View,
275
317
  {
276
318
  style: [
@@ -279,7 +321,7 @@ function ConfirmCard({
279
321
  ],
280
322
  testID: "assistant-confirm-card"
281
323
  },
282
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: confirmCardStyles.headerRow }, /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.glyph, { color: actionColor }] }, glyph), /* @__PURE__ */ React7__namespace.default.createElement(
324
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: confirmCardStyles.headerRow }, /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.glyph, { color: actionColor }] }, glyph), /* @__PURE__ */ React8__namespace.default.createElement(
283
325
  reactNative.Text,
284
326
  {
285
327
  style: [
@@ -289,18 +331,18 @@ function ConfirmCard({
289
331
  },
290
332
  title
291
333
  )),
292
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message),
293
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React7__namespace.default.createElement(
334
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message),
335
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: confirmCardStyles.buttons }, /* @__PURE__ */ React8__namespace.default.createElement(
294
336
  reactNative.TouchableOpacity,
295
337
  {
296
338
  onPress: () => onReject?.(action.id),
297
339
  style: [confirmCardStyles.btn, { backgroundColor: cancelBackground }],
298
340
  activeOpacity: 0.7,
299
- accessibilityLabel: "Cancelar",
341
+ accessibilityLabel: cancelLabel,
300
342
  testID: "assistant-confirm-reject"
301
343
  },
302
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
303
- ), /* @__PURE__ */ React7__namespace.default.createElement(
344
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
345
+ ), /* @__PURE__ */ React8__namespace.default.createElement(
304
346
  reactNative.TouchableOpacity,
305
347
  {
306
348
  onPress: () => onApprove?.(action.id),
@@ -310,10 +352,10 @@ function ConfirmCard({
310
352
  { backgroundColor: actionColor }
311
353
  ],
312
354
  activeOpacity: 0.7,
313
- accessibilityLabel: "Confirmar",
355
+ accessibilityLabel: confirmLabel,
314
356
  testID: "assistant-confirm-approve"
315
357
  },
316
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
358
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.confirmText, { fontFamily }] }, confirmLabel)
317
359
  ))
318
360
  );
319
361
  }
@@ -378,7 +420,7 @@ function StateIcon({
378
420
  tone,
379
421
  primaryColor
380
422
  }) {
381
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React7__namespace.default.createElement(reactNative.ActivityIndicator, { size: "small", color: primaryColor }) : /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles.iconGlyph, { color: tone.color }] }, iconGlyphFor(state)));
423
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: [styles.iconCircle, { backgroundColor: tone.iconBg }] }, state === "running" ? /* @__PURE__ */ React8__namespace.default.createElement(reactNative.ActivityIndicator, { size: "small", color: primaryColor }) : /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [styles.iconGlyph, { color: tone.color }] }, iconGlyphFor(state)));
382
424
  }
383
425
  var styles = reactNative.StyleSheet.create({
384
426
  container: {
@@ -469,7 +511,7 @@ function resolvePersonalization(props, remote) {
469
511
  };
470
512
  }
471
513
  function ChatIcon({ size = 24, color = "#ffffff" }) {
472
- return /* @__PURE__ */ React7__namespace.createElement(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React7__namespace.createElement(
514
+ return /* @__PURE__ */ React8__namespace.createElement(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8__namespace.createElement(
473
515
  Svg.Path,
474
516
  {
475
517
  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",
@@ -477,8 +519,438 @@ function ChatIcon({ size = 24, color = "#ffffff" }) {
477
519
  }
478
520
  ));
479
521
  }
522
+
523
+ // src/components/internalProps.ts
524
+ var APPILOTS_SKIP_PROPS = {
525
+ __appilotsSkip: true,
526
+ __appilotsInternal: true
527
+ };
528
+
529
+ // src/components/AgentPill.tsx
530
+ function toneFor(state, colors) {
531
+ switch (state) {
532
+ case "success":
533
+ return colors.success;
534
+ case "failed":
535
+ return colors.error;
536
+ default:
537
+ return colors.primary;
538
+ }
539
+ }
540
+ function AgentPill({
541
+ label,
542
+ state,
543
+ onExpand,
544
+ onStop,
545
+ position,
546
+ insets,
547
+ colors,
548
+ fontFamily,
549
+ strings
550
+ }) {
551
+ const atTop = position === "top-left" || position === "top-right";
552
+ const enter = React8.useRef(new reactNative.Animated.Value(0)).current;
553
+ React8.useEffect(() => {
554
+ reactNative.Animated.spring(enter, {
555
+ toValue: 1,
556
+ useNativeDriver: true,
557
+ tension: 70,
558
+ friction: 12
559
+ }).start();
560
+ }, [enter]);
561
+ const translateY = enter.interpolate({
562
+ inputRange: [0, 1],
563
+ outputRange: [atTop ? -80 : 80, 0]
564
+ });
565
+ const running = state === "running" || state === "pending";
566
+ return /* @__PURE__ */ React8__namespace.default.createElement(
567
+ reactNative.Animated.View,
568
+ {
569
+ ...APPILOTS_SKIP_PROPS,
570
+ pointerEvents: "box-none",
571
+ style: [
572
+ styles2.wrapper,
573
+ atTop ? { top: insets.top + 8 } : { bottom: insets.bottom + 8 },
574
+ { opacity: enter, transform: [{ translateY }] }
575
+ ]
576
+ },
577
+ /* @__PURE__ */ React8__namespace.default.createElement(
578
+ reactNative.TouchableOpacity,
579
+ {
580
+ ...APPILOTS_SKIP_PROPS,
581
+ testID: "appilots-agent-pill",
582
+ accessibilityRole: "button",
583
+ accessibilityLabel: strings.expandA11y,
584
+ activeOpacity: 0.85,
585
+ onPress: onExpand,
586
+ style: [styles2.pill, { backgroundColor: colors.surface, borderColor: colors.border }]
587
+ },
588
+ running ? /* @__PURE__ */ React8__namespace.default.createElement(reactNative.ActivityIndicator, { size: "small", color: toneFor(state, colors) }) : /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: [styles2.dot, { backgroundColor: toneFor(state, colors) }] }),
589
+ /* @__PURE__ */ React8__namespace.default.createElement(
590
+ reactNative.Text,
591
+ {
592
+ testID: "appilots-agent-pill-label",
593
+ numberOfLines: 1,
594
+ style: [styles2.label, { color: colors.text, fontFamily }]
595
+ },
596
+ label
597
+ ),
598
+ onStop ? /* @__PURE__ */ React8__namespace.default.createElement(
599
+ reactNative.TouchableOpacity,
600
+ {
601
+ ...APPILOTS_SKIP_PROPS,
602
+ testID: "appilots-agent-pill-stop",
603
+ accessibilityRole: "button",
604
+ accessibilityLabel: strings.stopA11y,
605
+ onPress: onStop,
606
+ hitSlop: { top: 12, bottom: 12, left: 12, right: 12 },
607
+ style: [styles2.stop, { borderColor: colors.border }]
608
+ },
609
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: [styles2.stopGlyph, { backgroundColor: colors.textSecondary }] })
610
+ ) : null
611
+ )
612
+ );
613
+ }
614
+ var styles2 = reactNative.StyleSheet.create({
615
+ // `box-none` above + `position: absolute` here is what lets touches
616
+ // outside the pill itself reach the app underneath.
617
+ wrapper: {
618
+ position: "absolute",
619
+ left: 12,
620
+ right: 12,
621
+ zIndex: 999,
622
+ alignItems: "center"
623
+ },
624
+ pill: {
625
+ flexDirection: "row",
626
+ alignItems: "center",
627
+ gap: 10,
628
+ maxWidth: "100%",
629
+ paddingLeft: 14,
630
+ paddingRight: 8,
631
+ paddingVertical: 10,
632
+ borderRadius: 24,
633
+ borderWidth: reactNative.StyleSheet.hairlineWidth,
634
+ shadowColor: "#000",
635
+ shadowOffset: { width: 0, height: 2 },
636
+ shadowOpacity: 0.18,
637
+ shadowRadius: 8,
638
+ elevation: 8
639
+ },
640
+ dot: { width: 8, height: 8, borderRadius: 4 },
641
+ label: { flexShrink: 1, fontSize: 14, fontWeight: "500" },
642
+ stop: {
643
+ width: 26,
644
+ height: 26,
645
+ borderRadius: 13,
646
+ borderWidth: reactNative.StyleSheet.hairlineWidth,
647
+ alignItems: "center",
648
+ justifyContent: "center"
649
+ },
650
+ stopGlyph: { width: 9, height: 9, borderRadius: 1.5 }
651
+ });
652
+ var PADDING = 6;
653
+ var CAPTION_HEIGHT = 28;
654
+ var CAPTION_GAP = 8;
655
+ function SpotlightOverlay({
656
+ rect,
657
+ seq,
658
+ label,
659
+ color,
660
+ captionBackground,
661
+ captionColor,
662
+ fontFamily,
663
+ window: win
664
+ }) {
665
+ const pulse = React8.useRef(new reactNative.Animated.Value(0)).current;
666
+ React8.useEffect(() => {
667
+ pulse.setValue(0);
668
+ reactNative.Animated.timing(pulse, {
669
+ toValue: 1,
670
+ duration: 220,
671
+ useNativeDriver: true
672
+ }).start();
673
+ }, [seq, pulse]);
674
+ if (!chunkUZ2D4BVX_js.isRectOnScreen(rect, win)) return null;
675
+ const frame = {
676
+ left: rect.x - PADDING,
677
+ top: rect.y - PADDING,
678
+ width: rect.width + PADDING * 2,
679
+ height: rect.height + PADDING * 2
680
+ };
681
+ const above = frame.top - CAPTION_GAP - CAPTION_HEIGHT >= 0;
682
+ const captionTop = above ? frame.top - CAPTION_GAP - CAPTION_HEIGHT : frame.top + frame.height + CAPTION_GAP;
683
+ const captionFits = captionTop + CAPTION_HEIGHT <= win.height;
684
+ return /* @__PURE__ */ React8__namespace.default.createElement(
685
+ reactNative.View,
686
+ {
687
+ ...APPILOTS_SKIP_PROPS,
688
+ pointerEvents: "none",
689
+ style: reactNative.StyleSheet.absoluteFill,
690
+ testID: "appilots-spotlight"
691
+ },
692
+ /* @__PURE__ */ React8__namespace.default.createElement(
693
+ reactNative.Animated.View,
694
+ {
695
+ ...APPILOTS_SKIP_PROPS,
696
+ pointerEvents: "none",
697
+ style: [
698
+ styles3.ring,
699
+ frame,
700
+ { borderColor: color },
701
+ {
702
+ opacity: pulse,
703
+ // Settles inward: the ring arrives slightly large and snaps
704
+ // to the control, which reads as "this one" rather than as a
705
+ // box that was always there.
706
+ transform: [
707
+ {
708
+ scale: pulse.interpolate({ inputRange: [0, 1], outputRange: [1.08, 1] })
709
+ }
710
+ ]
711
+ }
712
+ ]
713
+ }
714
+ ),
715
+ label && captionFits ? /* @__PURE__ */ React8__namespace.default.createElement(
716
+ reactNative.Animated.View,
717
+ {
718
+ ...APPILOTS_SKIP_PROPS,
719
+ pointerEvents: "none",
720
+ style: [
721
+ styles3.caption,
722
+ {
723
+ top: captionTop,
724
+ // Clamped so a control at either edge does not push the
725
+ // caption off screen.
726
+ left: Math.max(8, Math.min(frame.left, win.width - 8)),
727
+ maxWidth: win.width - 16,
728
+ backgroundColor: captionBackground,
729
+ opacity: pulse
730
+ }
731
+ ]
732
+ },
733
+ /* @__PURE__ */ React8__namespace.default.createElement(
734
+ reactNative.Text,
735
+ {
736
+ testID: "appilots-spotlight-label",
737
+ numberOfLines: 1,
738
+ style: [styles3.captionText, { color: captionColor, fontFamily }]
739
+ },
740
+ label
741
+ )
742
+ ) : null
743
+ );
744
+ }
745
+ var styles3 = reactNative.StyleSheet.create({
746
+ ring: {
747
+ position: "absolute",
748
+ borderWidth: 2.5,
749
+ borderRadius: 10
750
+ },
751
+ caption: {
752
+ position: "absolute",
753
+ height: CAPTION_HEIGHT,
754
+ justifyContent: "center",
755
+ paddingHorizontal: 10,
756
+ borderRadius: 8
757
+ },
758
+ captionText: { fontSize: 13, fontWeight: "500" }
759
+ });
760
+ var NEVER = () => () => {
761
+ };
762
+ var NULL_TARGET = () => null;
763
+ function useSpotlight(enabled) {
764
+ const subscribe = React8.useCallback(
765
+ (onChange) => enabled ? chunkAJDHZRBN_js.subscribeSpotlight(onChange) : NEVER(),
766
+ [enabled]
767
+ );
768
+ return React8.useSyncExternalStore(subscribe, enabled ? chunkAJDHZRBN_js.getSpotlightTarget : NULL_TARGET, NULL_TARGET);
769
+ }
770
+
771
+ // src/components/pillStatus.ts
772
+ function resolvePillStatus(actions, busy, strings) {
773
+ for (let i = actions.length - 1; i >= 0; i--) {
774
+ const action = actions[i];
775
+ if (action.status === "executing") return chunkUZ2D4BVX_js.describeAction(action, strings.locale);
776
+ }
777
+ if (!busy) {
778
+ for (let i = actions.length - 1; i >= 0; i--) {
779
+ const action = actions[i];
780
+ if (action.status === "completed" || action.status === "failed") {
781
+ return chunkUZ2D4BVX_js.describeAction(action, strings.locale);
782
+ }
783
+ }
784
+ return { label: strings.done, state: "success" };
785
+ }
786
+ return { label: strings.working, state: "running" };
787
+ }
788
+
789
+ // src/components/speech.ts
790
+ function isSpeechHost(value) {
791
+ if (!value || typeof value !== "object") return false;
792
+ const candidate = value;
793
+ return typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.cancel === "function";
794
+ }
795
+ function useVoiceInput({
796
+ host,
797
+ locale,
798
+ onTranscript
799
+ }) {
800
+ const [state, setState] = React8.useState("idle");
801
+ const [partial, setPartial] = React8.useState("");
802
+ const mounted = React8.useRef(true);
803
+ React8.useEffect(() => {
804
+ mounted.current = true;
805
+ return () => {
806
+ mounted.current = false;
807
+ };
808
+ }, []);
809
+ const onTranscriptRef = React8.useRef(onTranscript);
810
+ onTranscriptRef.current = onTranscript;
811
+ const stateRef = React8.useRef("idle");
812
+ stateRef.current = state;
813
+ React8.useEffect(() => {
814
+ return () => {
815
+ if (stateRef.current === "listening" || stateRef.current === "starting") {
816
+ void host?.cancel().catch(() => {
817
+ });
818
+ }
819
+ };
820
+ }, [host]);
821
+ const start = React8.useCallback(() => {
822
+ if (!host) return;
823
+ if (state !== "idle" && state !== "error") return;
824
+ setState("starting");
825
+ setPartial("");
826
+ host.start({ locale }).then(() => {
827
+ if (!mounted.current) return;
828
+ setState("listening");
829
+ }).catch((err) => {
830
+ chunkUZ2D4BVX_js.appilotsDebugWarn("useVoiceInput: start failed", err);
831
+ if (!mounted.current) return;
832
+ setState("error");
833
+ });
834
+ }, [host, locale, state]);
835
+ const stop = React8.useCallback(() => {
836
+ if (!host) return;
837
+ if (state !== "listening" && state !== "starting") return;
838
+ setState("stopping");
839
+ host.stop().then((text) => {
840
+ if (!mounted.current) return;
841
+ setState("idle");
842
+ setPartial("");
843
+ const trimmed = text?.trim();
844
+ if (trimmed) onTranscriptRef.current(trimmed);
845
+ }).catch((err) => {
846
+ chunkUZ2D4BVX_js.appilotsDebugWarn("useVoiceInput: stop failed", err);
847
+ if (!mounted.current) return;
848
+ setState("error");
849
+ setPartial("");
850
+ });
851
+ }, [host, state]);
852
+ const cancel = React8.useCallback(() => {
853
+ if (!host) return;
854
+ setPartial("");
855
+ setState("idle");
856
+ void host.cancel().catch((err) => chunkUZ2D4BVX_js.appilotsDebugWarn("useVoiceInput: cancel failed", err));
857
+ }, [host]);
858
+ React8.useEffect(() => {
859
+ if (!host?.onPartial) return;
860
+ if (state !== "listening") return;
861
+ const dispose = host.onPartial((text) => {
862
+ if (mounted.current) setPartial(text);
863
+ });
864
+ return dispose;
865
+ }, [host, state]);
866
+ return { state, partial, start, stop, cancel };
867
+ }
868
+
869
+ // src/components/experience.ts
870
+ var DEFAULT_EXPERIENCE = {
871
+ presence: "sheet",
872
+ spotlight: "off",
873
+ control: "agent",
874
+ entry: ["fab"],
875
+ input: ["text"]
876
+ };
877
+ function uniq(values) {
878
+ return values.filter((value, index) => values.indexOf(value) === index);
879
+ }
880
+ function resolveExperience(requested, caps) {
881
+ const downgrades = [];
882
+ let presence = requested?.presence ?? DEFAULT_EXPERIENCE.presence;
883
+ let spotlight = requested?.spotlight ?? DEFAULT_EXPERIENCE.spotlight;
884
+ const control = requested?.control ?? DEFAULT_EXPERIENCE.control;
885
+ const entry = uniq(requested?.entry ?? DEFAULT_EXPERIENCE.entry);
886
+ let input = uniq(requested?.input ?? DEFAULT_EXPERIENCE.input);
887
+ if (spotlight !== "off" && !caps.geometry) {
888
+ downgrades.push({
889
+ field: "spotlight",
890
+ from: spotlight,
891
+ to: "off",
892
+ reason: 'spotlight needs Fabric window geometry, which this app cannot report. Enable the new React Native architecture, or set spotlight:"off" to silence this.'
893
+ });
894
+ spotlight = "off";
895
+ }
896
+ if (spotlight !== "off" && presence === "sheet") {
897
+ downgrades.push({
898
+ field: "presence",
899
+ from: "sheet",
900
+ to: "pill",
901
+ reason: 'spotlight draws on the app, which the sheet covers. Set presence:"pill" or "hidden" explicitly to silence this.'
902
+ });
903
+ presence = "pill";
904
+ }
905
+ if (control === "shared" && presence === "sheet") {
906
+ downgrades.push({
907
+ field: "presence",
908
+ from: "sheet",
909
+ to: "pill",
910
+ 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.'
911
+ });
912
+ presence = "pill";
913
+ }
914
+ if (input.includes("voice") && !caps.speech) {
915
+ downgrades.push({
916
+ field: "input",
917
+ from: input.join("+"),
918
+ to: input.filter((mode) => mode !== "voice").join("+") || "text",
919
+ reason: 'input:"voice" needs a SpeechHost passed to <AppilotsChat speech={...} />. The SDK ships no speech engine of its own \u2014 see docs/experience.md.'
920
+ });
921
+ input = input.filter((mode) => mode !== "voice");
922
+ }
923
+ if (input.length === 0) input = ["text"];
924
+ return {
925
+ experience: { presence, spotlight, control, entry, input },
926
+ downgrades
927
+ };
928
+ }
929
+ function formatDowngrades(downgrades) {
930
+ return downgrades.map(
931
+ (d) => `[appilots] experience.${d.field}: "${d.from}" -> "${d.to}". ${d.reason}`
932
+ );
933
+ }
934
+
935
+ // src/components/presence.ts
936
+ function resolveSurface(presence, activity) {
937
+ if (presence === "sheet") return activity.open ? "sheet" : "none";
938
+ if (activity.awaitingUser) return "sheet";
939
+ if (activity.busy && (activity.acting || !activity.open)) return "pill";
940
+ if (activity.hostModalOpen && !activity.explicitlyOpened && (activity.open || activity.unread))
941
+ return "pill";
942
+ if (activity.open) return "sheet";
943
+ if (activity.unread) return "pill";
944
+ return "none";
945
+ }
946
+ function shouldReopenOnTurnEnd(presence) {
947
+ return presence === "pill";
948
+ }
949
+ function usesPill(presence) {
950
+ return presence !== "sheet";
951
+ }
480
952
  function HeadsetIcon({ size = 18, color = "#ffffff" }) {
481
- return /* @__PURE__ */ React7__namespace.createElement(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React7__namespace.createElement(
953
+ return /* @__PURE__ */ React8__namespace.createElement(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none" }, /* @__PURE__ */ React8__namespace.createElement(
482
954
  Svg.Path,
483
955
  {
484
956
  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",
@@ -519,215 +991,26 @@ function buildChatTimeline(messages, actions) {
519
991
  }
520
992
  return timeline;
521
993
  }
522
-
523
- // src/components/markdownContent.ts
524
- var ORDERED_LINE = /^\s*(\d+)\.\s+(.+)$/;
525
- var BULLET_LINE = /^\s*[-*•]\s+(.+)$/;
526
- var HEADING_LINE = /^\s*(#{1,6})\s+(.+)$/;
527
- var FENCE_LINE = /^\s*```\s*([A-Za-z0-9+#_-]*)\s*$/;
528
- var INLINE_PATTERN = /\[([^\]\n]+)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|__(.+?)__|`([^`]+)`|\*(.+?)\*|_(.+?)_/g;
529
- var MIN_ENHANCE_LENGTH = 80;
530
- var SENTENCE_SPLIT = /[^.!?]+[.!?]+(?=\s+[A-ZÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕÇÑ¿¡"“]|$)|[^.!?]+$/g;
531
- 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;
532
- var INCLUDE_LIST_SENTENCE = /^(.+?)\s+(?:incluem|inclui|include|includes|incluye|incluyen|such as|for example|par exemple|por exemplo)\s+(.+?)\.?\s*$/i;
533
- function looksLikeMarkdown(content) {
534
- if (!content) return false;
535
- 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);
536
- }
537
- function splitEnumeration(text) {
538
- const trimmed = text.trim().replace(/\.\s*$/, "");
539
- if (!trimmed) return [];
540
- const commaParts = trimmed.split(",").map((part) => part.trim()).filter(Boolean);
541
- if (commaParts.length <= 1) {
542
- const conjParts = trimmed.split(/\s+(?:e|and|y|ou|or)\s+/i).map((part) => part.trim());
543
- return conjParts.filter(Boolean);
544
- }
545
- const last = commaParts[commaParts.length - 1];
546
- const conjMatch = last.match(/^(.+?)\s+(?:e|and|y|ou|or)\s+(.+)$/i);
547
- if (conjMatch) {
548
- commaParts[commaParts.length - 1] = conjMatch[1].trim();
549
- commaParts.push(conjMatch[2].trim());
550
- }
551
- return commaParts.filter(Boolean);
552
- }
553
- function splitSentences(text) {
554
- const matches = text.match(SENTENCE_SPLIT);
555
- if (!matches) return [text.trim()];
556
- return matches.map((part) => part.trim()).filter(Boolean);
557
- }
558
- function formatCapabilitySentence(sentence) {
559
- const match = CAPABILITY_SENTENCE.exec(sentence.trim());
560
- if (!match) return null;
561
- const items = splitEnumeration(match[2] ?? "");
562
- if (items.length < 3) return null;
563
- const intro = `${match[1].trim()}:`;
564
- return `${intro}
565
- ${items.map((item) => `- ${item}`).join("\n")}`;
566
- }
567
- function formatIncludeListSentence(sentence) {
568
- const match = INCLUDE_LIST_SENTENCE.exec(sentence.trim());
569
- if (!match) return null;
570
- const intro = match[1].trim().replace(/[,:]\s*$/, "");
571
- const items = splitEnumeration(match[2] ?? "");
572
- if (items.length < 2) return null;
573
- return `${intro}:
574
- ${items.map((item) => `- ${item}`).join("\n")}`;
575
- }
576
- function formatReadableSentence(sentence) {
577
- return formatCapabilitySentence(sentence) ?? formatIncludeListSentence(sentence) ?? sentence.trim();
578
- }
579
- function enhancePlainAssistantContent(content) {
580
- if (!content?.trim() || looksLikeMarkdown(content)) return content;
581
- const trimmed = content.trim();
582
- if (trimmed.length < MIN_ENHANCE_LENGTH) return content;
583
- const sentences = splitSentences(trimmed);
584
- if (sentences.length === 0) return content;
585
- const blocks = sentences.map(formatReadableSentence);
586
- const enhanced = blocks.join("\n\n");
587
- return enhanced || content;
588
- }
589
- function needsWideChatLayout(content) {
590
- if (!content?.trim()) return false;
591
- const prepared = enhancePlainAssistantContent(content);
592
- return looksLikeMarkdown(prepared) || /\n\n+/.test(prepared);
593
- }
594
- function parseMarkdownBlocks(content) {
595
- const lines = content.replace(/\r\n/g, "\n").split("\n");
596
- const blocks = [];
597
- let paragraph = [];
598
- let bulletItems = [];
599
- let orderedItems = [];
600
- let codeLines = null;
601
- let codeLanguage;
602
- const flushParagraph = () => {
603
- if (paragraph.length === 0) return;
604
- blocks.push({ kind: "paragraph", text: paragraph.join("\n") });
605
- paragraph = [];
606
- };
607
- const flushBullets = () => {
608
- if (bulletItems.length === 0) return;
609
- blocks.push({ kind: "bullet", items: bulletItems });
610
- bulletItems = [];
611
- };
612
- const flushOrdered = () => {
613
- if (orderedItems.length === 0) return;
614
- blocks.push({ kind: "ordered", items: orderedItems });
615
- orderedItems = [];
616
- };
617
- const flushLists = () => {
618
- flushBullets();
619
- flushOrdered();
620
- };
621
- const flushCode = () => {
622
- if (codeLines === null) return;
623
- blocks.push({
624
- kind: "codeblock",
625
- code: codeLines.join("\n"),
626
- ...codeLanguage ? { language: codeLanguage } : {}
627
- });
628
- codeLines = null;
629
- codeLanguage = void 0;
630
- };
631
- for (const line of lines) {
632
- if (codeLines !== null) {
633
- if (/^\s*```\s*$/.test(line)) {
634
- flushCode();
635
- } else {
636
- codeLines.push(line);
637
- }
638
- continue;
639
- }
640
- const fence = FENCE_LINE.exec(line);
641
- if (fence) {
642
- flushParagraph();
643
- flushLists();
644
- codeLines = [];
645
- codeLanguage = fence[1] || void 0;
646
- continue;
647
- }
648
- const trimmed = line.trim();
649
- if (!trimmed) {
650
- flushParagraph();
651
- flushLists();
652
- continue;
653
- }
654
- const heading = HEADING_LINE.exec(line);
655
- if (heading) {
656
- flushParagraph();
657
- flushLists();
658
- const level = Math.min(heading[1].length, 3);
659
- blocks.push({ kind: "heading", level, text: heading[2].trim() });
660
- continue;
661
- }
662
- const ordered = ORDERED_LINE.exec(line);
663
- if (ordered) {
664
- flushParagraph();
665
- flushBullets();
666
- orderedItems.push(ordered[2].trim());
667
- continue;
668
- }
669
- const bullet = BULLET_LINE.exec(line);
670
- if (bullet) {
671
- flushParagraph();
672
- flushOrdered();
673
- bulletItems.push(bullet[1].trim());
674
- continue;
675
- }
676
- flushLists();
677
- paragraph.push(line);
678
- }
679
- flushParagraph();
680
- flushLists();
681
- flushCode();
682
- return blocks.length > 0 ? blocks : [{ kind: "paragraph", text: content }];
683
- }
684
- function parseInlineMarkdown(text) {
685
- if (!text) return [{ kind: "text", value: "" }];
686
- const segments = [];
687
- let lastIndex = 0;
688
- INLINE_PATTERN.lastIndex = 0;
689
- for (let match = INLINE_PATTERN.exec(text); match; match = INLINE_PATTERN.exec(text)) {
690
- if (match.index > lastIndex) {
691
- segments.push({ kind: "text", value: text.slice(lastIndex, match.index) });
692
- }
693
- if (match[1] && match[2]) {
694
- segments.push({ kind: "link", value: match[1].trim(), href: match[2] });
695
- } else if (match[3] || match[4]) {
696
- segments.push({ kind: "bold", value: (match[3] ?? match[4]).trim() });
697
- } else if (match[5]) {
698
- segments.push({ kind: "code", value: match[5] });
699
- } else if (match[6] || match[7]) {
700
- segments.push({ kind: "italic", value: (match[6] ?? match[7]).trim() });
701
- }
702
- lastIndex = INLINE_PATTERN.lastIndex;
703
- }
704
- if (lastIndex < text.length) {
705
- segments.push({ kind: "text", value: text.slice(lastIndex) });
706
- }
707
- return segments.length > 0 ? segments : [{ kind: "text", value: text }];
708
- }
709
-
710
- // src/components/ChatMarkdown.tsx
711
994
  function segmentKey(segment, index) {
712
995
  return `${segment.kind}-${index}-${segment.value.slice(0, 12)}`;
713
996
  }
714
997
  function renderInlineSegments(text, theme, baseStyle) {
715
- const segments = parseInlineMarkdown(text);
998
+ const segments = chunkUZ2D4BVX_js.parseInlineMarkdown(text);
716
999
  return segments.map((segment, index) => {
717
1000
  const key = segmentKey(segment, index);
718
1001
  switch (segment.kind) {
719
1002
  case "bold":
720
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { key, style: [baseStyle, styles2.bold] }, segment.value);
1003
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { key, style: [baseStyle, styles4.bold] }, segment.value);
721
1004
  case "italic":
722
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { key, style: [baseStyle, styles2.italic] }, segment.value);
1005
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { key, style: [baseStyle, styles4.italic] }, segment.value);
723
1006
  case "code":
724
- return /* @__PURE__ */ React7__namespace.default.createElement(
1007
+ return /* @__PURE__ */ React8__namespace.default.createElement(
725
1008
  reactNative.Text,
726
1009
  {
727
1010
  key,
728
1011
  style: [
729
1012
  baseStyle,
730
- styles2.code,
1013
+ styles4.code,
731
1014
  {
732
1015
  backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.06)"),
733
1016
  color: theme.codeColor ?? theme.color
@@ -737,14 +1020,14 @@ function renderInlineSegments(text, theme, baseStyle) {
737
1020
  segment.value
738
1021
  );
739
1022
  case "link":
740
- return /* @__PURE__ */ React7__namespace.default.createElement(
1023
+ return /* @__PURE__ */ React8__namespace.default.createElement(
741
1024
  reactNative.Text,
742
1025
  {
743
1026
  key,
744
1027
  accessibilityRole: "link",
745
1028
  style: [
746
1029
  baseStyle,
747
- styles2.link,
1030
+ styles4.link,
748
1031
  {
749
1032
  color: theme.linkColor ?? (theme.variant === "user" ? theme.color : "#2563EB")
750
1033
  }
@@ -771,39 +1054,39 @@ function InlineMarkdown({
771
1054
  fontSize: theme.fontSize,
772
1055
  lineHeight: theme.lineHeight
773
1056
  };
774
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: baseStyle }, renderInlineSegments(text, theme, baseStyle));
1057
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: baseStyle }, renderInlineSegments(text, theme, baseStyle));
775
1058
  }
776
1059
  function ChatMarkdown({ content, theme, contentWidth }) {
777
- const prepared = enhancePlainAssistantContent(content);
1060
+ const prepared = chunkUZ2D4BVX_js.enhancePlainAssistantContent(content);
778
1061
  const baseTextStyle = {
779
1062
  color: theme.color,
780
1063
  fontFamily: theme.fontFamily,
781
1064
  fontSize: theme.fontSize,
782
1065
  lineHeight: theme.lineHeight
783
1066
  };
784
- const rootStyle = contentWidth ? [styles2.root, { width: contentWidth }] : styles2.root;
785
- if (!looksLikeMarkdown(prepared)) {
1067
+ const rootStyle = contentWidth ? [styles4.root, { width: contentWidth }] : styles4.root;
1068
+ if (!chunkUZ2D4BVX_js.looksLikeMarkdown(prepared)) {
786
1069
  const paragraphs = prepared.split(/\n\n+/).map((part) => part.trim()).filter(Boolean);
787
1070
  if (paragraphs.length > 1) {
788
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: rootStyle }, paragraphs.map((paragraph, index) => /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { key: `plain-p-${index}`, style: index > 0 ? styles2.blockGap : void 0 }, /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, paragraph))));
1071
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: rootStyle }, paragraphs.map((paragraph, index) => /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { key: `plain-p-${index}`, style: index > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, paragraph))));
789
1072
  }
790
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, prepared);
1073
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, prepared);
791
1074
  }
792
- const blocks = parseMarkdownBlocks(prepared);
793
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: rootStyle }, blocks.map((block, blockIndex) => {
1075
+ const blocks = chunkUZ2D4BVX_js.parseMarkdownBlocks(prepared);
1076
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: rootStyle }, blocks.map((block, blockIndex) => {
794
1077
  if (block.kind === "paragraph") {
795
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { key: `p-${blockIndex}`, style: blockIndex > 0 ? styles2.blockGap : void 0 }, /* @__PURE__ */ React7__namespace.default.createElement(InlineMarkdown, { text: block.text, theme }));
1078
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { key: `p-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__namespace.default.createElement(InlineMarkdown, { text: block.text, theme }));
796
1079
  }
797
1080
  if (block.kind === "heading") {
798
1081
  const scale = block.level === 1 ? 1.25 : block.level === 2 ? 1.15 : 1.05;
799
1082
  const headingSize = Math.round((theme.fontSize ?? 15) * scale);
800
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { key: `h-${blockIndex}`, style: blockIndex > 0 ? styles2.blockGap : void 0 }, /* @__PURE__ */ React7__namespace.default.createElement(
1083
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { key: `h-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, /* @__PURE__ */ React8__namespace.default.createElement(
801
1084
  reactNative.Text,
802
1085
  {
803
1086
  accessibilityRole: "header",
804
1087
  style: [
805
1088
  baseTextStyle,
806
- styles2.bold,
1089
+ styles4.bold,
807
1090
  { fontSize: headingSize, lineHeight: Math.round(headingSize * 1.35) }
808
1091
  ]
809
1092
  },
@@ -815,23 +1098,23 @@ function ChatMarkdown({ content, theme, contentWidth }) {
815
1098
  ));
816
1099
  }
817
1100
  if (block.kind === "codeblock") {
818
- return /* @__PURE__ */ React7__namespace.default.createElement(
1101
+ return /* @__PURE__ */ React8__namespace.default.createElement(
819
1102
  reactNative.View,
820
1103
  {
821
1104
  key: `code-${blockIndex}`,
822
1105
  style: [
823
- styles2.codeBlock,
824
- blockIndex > 0 ? styles2.blockGap : void 0,
1106
+ styles4.codeBlock,
1107
+ blockIndex > 0 ? styles4.blockGap : void 0,
825
1108
  {
826
1109
  backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.055)")
827
1110
  }
828
1111
  ]
829
1112
  },
830
- /* @__PURE__ */ React7__namespace.default.createElement(
1113
+ /* @__PURE__ */ React8__namespace.default.createElement(
831
1114
  reactNative.Text,
832
1115
  {
833
1116
  style: [
834
- styles2.code,
1117
+ styles4.code,
835
1118
  {
836
1119
  color: theme.codeColor ?? theme.color,
837
1120
  fontSize: (theme.fontSize ?? 15) - 1,
@@ -844,28 +1127,28 @@ function ChatMarkdown({ content, theme, contentWidth }) {
844
1127
  );
845
1128
  }
846
1129
  if (block.kind === "bullet") {
847
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { key: `ul-${blockIndex}`, style: blockIndex > 0 ? styles2.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React7__namespace.default.createElement(
1130
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { key: `ul-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__namespace.default.createElement(
848
1131
  reactNative.Text,
849
1132
  {
850
1133
  key: `ul-${blockIndex}-${itemIndex}`,
851
- style: [baseTextStyle, itemIndex > 0 ? styles2.listItemGap : void 0]
1134
+ style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
852
1135
  },
853
1136
  "\u2022 ",
854
1137
  renderInlineSegments(item, theme, baseTextStyle)
855
1138
  )));
856
1139
  }
857
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { key: `ol-${blockIndex}`, style: blockIndex > 0 ? styles2.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React7__namespace.default.createElement(
1140
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { key: `ol-${blockIndex}`, style: blockIndex > 0 ? styles4.blockGap : void 0 }, block.items.map((item, itemIndex) => /* @__PURE__ */ React8__namespace.default.createElement(
858
1141
  reactNative.Text,
859
1142
  {
860
1143
  key: `ol-${blockIndex}-${itemIndex}`,
861
- style: [baseTextStyle, itemIndex > 0 ? styles2.listItemGap : void 0]
1144
+ style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
862
1145
  },
863
1146
  `${itemIndex + 1}. `,
864
1147
  renderInlineSegments(item, theme, baseTextStyle)
865
1148
  )));
866
1149
  }));
867
1150
  }
868
- var styles2 = reactNative.StyleSheet.create({
1151
+ var styles4 = reactNative.StyleSheet.create({
869
1152
  root: {
870
1153
  flexShrink: 1,
871
1154
  alignSelf: "stretch"
@@ -898,21 +1181,21 @@ var styles2 = reactNative.StyleSheet.create({
898
1181
  textDecorationLine: "underline"
899
1182
  }
900
1183
  });
901
- var ThemeContext = React7.createContext(chunkKZ2BLMS4_js.defaultLightTheme);
1184
+ var ThemeContext = React8.createContext(chunkUZ2D4BVX_js.defaultLightTheme);
902
1185
  function AppilotsThemeProvider({
903
1186
  theme,
904
1187
  mode = "auto",
905
1188
  children
906
1189
  }) {
907
1190
  const systemScheme = reactNative.useColorScheme();
908
- const tokens = React7.useMemo(
909
- () => chunkKZ2BLMS4_js.mergeThemeTokens(chunkKZ2BLMS4_js.resolveBaseTheme(mode, systemScheme), theme ?? void 0),
1191
+ const tokens = React8.useMemo(
1192
+ () => chunkUZ2D4BVX_js.mergeThemeTokens(chunkUZ2D4BVX_js.resolveBaseTheme(mode, systemScheme), theme ?? void 0),
910
1193
  [mode, systemScheme, theme]
911
1194
  );
912
- return /* @__PURE__ */ React7__namespace.default.createElement(ThemeContext.Provider, { value: tokens }, children);
1195
+ return /* @__PURE__ */ React8__namespace.default.createElement(ThemeContext.Provider, { value: tokens }, children);
913
1196
  }
914
1197
  function useAppilotsTheme() {
915
- return React7.useContext(ThemeContext);
1198
+ return React8.useContext(ThemeContext);
916
1199
  }
917
1200
 
918
1201
  // src/theme/tailwindBridge.ts
@@ -1002,177 +1285,6 @@ var appilotsTheme = {
1002
1285
  fromTailwind: appilotsThemeFromTailwind
1003
1286
  };
1004
1287
 
1005
- // src/i18n/bundles/pt-BR.ts
1006
- var ptBR = {
1007
- chatTitle: "Assistente Appilots",
1008
- clearButton: "Limpar",
1009
- inputPlaceholder: "Digite uma mensagem...",
1010
- emptyTitle: "Como posso ajudar?",
1011
- emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
1012
- thinking: "Pensando...",
1013
- statusAnalyzing: "Analisando a tela...",
1014
- statusWaitingApp: "Aguardando o app responder...",
1015
- statusAdjusting: "Ajustando o plano...",
1016
- poweredBy: "Powered by Appilots",
1017
- approve: "Aprovar",
1018
- reject: "Rejeitar",
1019
- cancelledByUser: "Cancelado pelo usu\xE1rio",
1020
- confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
1021
- confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
1022
- confirmMessage: 'Tem certeza que deseja "{action}"?',
1023
- confirmDestructiveApprove: "Sim, executar",
1024
- confirmApprove: "Confirmar",
1025
- confirmCancel: "Cancelar",
1026
- confirmThisAction: "esta a\xE7\xE3o",
1027
- unknownAction: "A\xE7\xE3o desconhecida",
1028
- somethingWentWrong: "Algo deu errado",
1029
- openChatA11y: "Abrir chat do assistente",
1030
- closeChatA11y: "Fechar chat do assistente",
1031
- stopGeneratingA11y: "Parar gera\xE7\xE3o",
1032
- talkToHumanA11y: "Falar com um atendente humano",
1033
- humanAgentLabel: "Atendente",
1034
- escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
1035
- escalationConnected: "Um atendente entrou na conversa.",
1036
- escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
1037
- escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
1038
- escalationOfferChip: "Falar com um atendente",
1039
- escalationPendingBanner: "Aguardando um atendente...",
1040
- escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente"
1041
- };
1042
-
1043
- // src/i18n/bundles/en.ts
1044
- var en = {
1045
- chatTitle: "Appilots Assistant",
1046
- clearButton: "Clear",
1047
- inputPlaceholder: "Type a message...",
1048
- emptyTitle: "How can I help?",
1049
- emptySubtitle: "I navigate, fill forms, and run actions in this app.",
1050
- thinking: "Thinking...",
1051
- statusAnalyzing: "Reading the screen...",
1052
- statusWaitingApp: "Waiting for the app...",
1053
- statusAdjusting: "Adjusting the plan...",
1054
- poweredBy: "Powered by Appilots",
1055
- approve: "Approve",
1056
- reject: "Reject",
1057
- cancelledByUser: "Cancelled by user",
1058
- confirmDestructiveTitle: "Destructive action",
1059
- confirmTitle: "Confirmation needed",
1060
- confirmMessage: 'Are you sure you want to "{action}"?',
1061
- confirmDestructiveApprove: "Yes, do it",
1062
- confirmApprove: "Confirm",
1063
- confirmCancel: "Cancel",
1064
- confirmThisAction: "this action",
1065
- unknownAction: "Unknown action",
1066
- somethingWentWrong: "Something went wrong",
1067
- openChatA11y: "Open assistant chat",
1068
- closeChatA11y: "Close assistant chat",
1069
- stopGeneratingA11y: "Stop generating",
1070
- talkToHumanA11y: "Talk to a human agent",
1071
- humanAgentLabel: "Agent",
1072
- escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
1073
- escalationConnected: "A human agent joined the conversation.",
1074
- escalationResolved: "The human handoff has ended. I'm back to help you here.",
1075
- escalationOffer: "If you prefer, I can bring in a person to help.",
1076
- escalationOfferChip: "Talk to a human",
1077
- escalationPendingBanner: "Waiting for a human agent...",
1078
- escalationActiveBanner: "You're talking to a human agent"
1079
- };
1080
-
1081
- // src/i18n/bundles/es.ts
1082
- var es = {
1083
- chatTitle: "Asistente Appilots",
1084
- clearButton: "Limpiar",
1085
- inputPlaceholder: "Escribe un mensaje...",
1086
- emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
1087
- emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
1088
- thinking: "Pensando...",
1089
- statusAnalyzing: "Analizando la pantalla...",
1090
- statusWaitingApp: "Esperando a la app...",
1091
- statusAdjusting: "Ajustando el plan...",
1092
- poweredBy: "Hecho con Appilots",
1093
- approve: "Aprobar",
1094
- reject: "Rechazar",
1095
- cancelledByUser: "Cancelado por el usuario",
1096
- confirmDestructiveTitle: "Acci\xF3n destructiva",
1097
- confirmTitle: "Confirmaci\xF3n necesaria",
1098
- confirmMessage: '\xBFSeguro que quieres "{action}"?',
1099
- confirmDestructiveApprove: "S\xED, ejecutar",
1100
- confirmApprove: "Confirmar",
1101
- confirmCancel: "Cancelar",
1102
- confirmThisAction: "esta acci\xF3n",
1103
- unknownAction: "Acci\xF3n desconocida",
1104
- somethingWentWrong: "Algo sali\xF3 mal",
1105
- openChatA11y: "Abrir chat del asistente",
1106
- closeChatA11y: "Cerrar chat del asistente",
1107
- stopGeneratingA11y: "Detener generaci\xF3n",
1108
- talkToHumanA11y: "Hablar con un agente humano",
1109
- humanAgentLabel: "Agente",
1110
- escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
1111
- escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
1112
- escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
1113
- escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
1114
- escalationOfferChip: "Hablar con un agente",
1115
- escalationPendingBanner: "Esperando a un agente...",
1116
- escalationActiveBanner: "Est\xE1s hablando con un agente humano"
1117
- };
1118
- var BUNDLES = {
1119
- "pt-BR": ptBR,
1120
- en,
1121
- es
1122
- };
1123
- var DEFAULT_LOCALE = "en";
1124
- function detectDeviceLocale() {
1125
- try {
1126
- let raw;
1127
- if (reactNative.Platform.OS === "ios") {
1128
- const settings = reactNative.NativeModules?.SettingsManager?.settings;
1129
- raw = settings?.AppleLocale || (Array.isArray(settings?.AppleLanguages) ? settings?.AppleLanguages?.[0] : void 0);
1130
- } else if (reactNative.Platform.OS === "android") {
1131
- raw = reactNative.NativeModules?.I18nManager?.localeIdentifier;
1132
- }
1133
- if (!raw || typeof raw !== "string") return null;
1134
- const lower = raw.toLowerCase().replace("_", "-");
1135
- if (lower.startsWith("pt")) return "pt-BR";
1136
- if (lower.startsWith("es")) return "es";
1137
- if (lower.startsWith("en")) return "en";
1138
- return null;
1139
- } catch {
1140
- return null;
1141
- }
1142
- }
1143
- function resolveLocale(prop) {
1144
- if (prop && BUNDLES[prop]) return prop;
1145
- const detected = detectDeviceLocale();
1146
- if (detected && BUNDLES[detected]) return detected;
1147
- return DEFAULT_LOCALE;
1148
- }
1149
- var I18nContext = React7.createContext(null);
1150
- function AppilotsI18nProvider({
1151
- locale,
1152
- overrides,
1153
- children
1154
- }) {
1155
- const value = React7.useMemo(() => {
1156
- const resolved = resolveLocale(locale ?? null);
1157
- const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
1158
- return {
1159
- locale: resolved,
1160
- strings: merged,
1161
- t: (key) => merged[key]
1162
- };
1163
- }, [locale, overrides]);
1164
- return /* @__PURE__ */ React7__namespace.default.createElement(I18nContext.Provider, { value }, children);
1165
- }
1166
- function useAppilotsI18n() {
1167
- const ctx = React7.useContext(I18nContext);
1168
- if (ctx) return ctx;
1169
- return {
1170
- locale: DEFAULT_LOCALE,
1171
- strings: BUNDLES[DEFAULT_LOCALE],
1172
- t: (key) => BUNDLES[DEFAULT_LOCALE][key]
1173
- };
1174
- }
1175
-
1176
1288
  // src/components/AppilotsChat.tsx
1177
1289
  function translateLegacyTheme(legacy) {
1178
1290
  const out = {};
@@ -1203,31 +1315,35 @@ var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = reactNative.Dimensions.get(
1203
1315
  var CHAT_HORIZONTAL_PADDING = 16;
1204
1316
  var BUBBLE_HORIZONTAL_PADDING = 14;
1205
1317
  var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
1206
- var APPILOTS_SKIP_PROPS = {
1207
- __appilotsSkip: true,
1208
- __appilotsInternal: true
1209
- };
1210
1318
  function AppilotsChat(props) {
1211
- const { degraded } = chunkKZ2BLMS4_js.useAppilotsContext();
1319
+ const { degraded } = chunkUZ2D4BVX_js.useAppilotsContext();
1212
1320
  if (degraded) return null;
1213
- return /* @__PURE__ */ React7__namespace.default.createElement(chunkKZ2BLMS4_js.AppilotsErrorBoundary, { surface: "chat", fallback: null }, /* @__PURE__ */ React7__namespace.default.createElement(AppilotsChatSurface, { ...props }));
1321
+ return /* @__PURE__ */ React8__namespace.default.createElement(chunkUZ2D4BVX_js.AppilotsErrorBoundary, { surface: "chat", fallback: null }, /* @__PURE__ */ React8__namespace.default.createElement(AppilotsChatSurface, { ...props }));
1214
1322
  }
1215
1323
  function AppilotsChatSurface(props) {
1216
- const { remotePersonalization } = chunkKZ2BLMS4_js.useAppilotsContext();
1217
- const themeProp = React7.useMemo(() => {
1324
+ const [conversationLocale, setConversationLocale] = React8.useState(null);
1325
+ const { remotePersonalization } = chunkUZ2D4BVX_js.useAppilotsContext();
1326
+ const themeProp = React8.useMemo(() => {
1218
1327
  if (!props.theme) return void 0;
1219
1328
  return isLegacyTheme(props.theme) ? translateLegacyTheme(props.theme) : props.theme;
1220
1329
  }, [props.theme]);
1221
- return /* @__PURE__ */ React7__namespace.default.createElement(
1330
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1222
1331
  AppilotsThemeProvider,
1223
1332
  {
1224
1333
  theme: resolveTheme(themeProp, remotePersonalization),
1225
1334
  mode: resolveThemeMode(props.themeMode, remotePersonalization)
1226
1335
  },
1227
- /* @__PURE__ */ React7__namespace.default.createElement(AppilotsI18nProvider, { locale: resolveLocaleProp(props.locale, remotePersonalization) }, /* @__PURE__ */ React7__namespace.default.createElement(AppilotsChatInner, { ...props }))
1336
+ /* @__PURE__ */ React8__namespace.default.createElement(
1337
+ chunkAJDHZRBN_js.AppilotsI18nProvider,
1338
+ {
1339
+ locale: conversationLocale ?? resolveLocaleProp(props.locale, remotePersonalization)
1340
+ },
1341
+ /* @__PURE__ */ React8__namespace.default.createElement(AppilotsChatInner, { ...props, onReplyLocaleChange: setConversationLocale })
1342
+ )
1228
1343
  );
1229
1344
  }
1230
1345
  function AppilotsChatInner({
1346
+ onReplyLocaleChange,
1231
1347
  visible: controlledVisible,
1232
1348
  onClose,
1233
1349
  placeholder,
@@ -1243,20 +1359,28 @@ function AppilotsChatInner({
1243
1359
  triggerButton = "default",
1244
1360
  triggerIcon,
1245
1361
  triggerButtonColor: triggerButtonColorProp,
1246
- triggerButtonImage: triggerButtonImageProp
1362
+ triggerButtonImage: triggerButtonImageProp,
1363
+ experience: experienceProp,
1364
+ speech: speechProp
1247
1365
  }) {
1248
1366
  const theme = useAppilotsTheme();
1249
- const { strings, t } = useAppilotsI18n();
1367
+ const { strings, t, locale: resolvedLocale } = chunkAJDHZRBN_js.useAppilotsI18n();
1250
1368
  const {
1251
1369
  messages,
1370
+ mission,
1371
+ pauseMission,
1372
+ resumeMission,
1373
+ cancelMission,
1374
+ replyLocale,
1252
1375
  isLoading,
1253
1376
  loadingStatusKey,
1377
+ hasStartedActing,
1254
1378
  sendMessage,
1255
1379
  cancelMessage,
1256
1380
  clearMessages,
1257
1381
  escalation,
1258
1382
  requestHuman
1259
- } = chunkX4MPSZL3_js.useAppilotsChat({
1383
+ } = chunkAJDHZRBN_js.useAppilotsChat({
1260
1384
  errorPrefix: t("somethingWentWrong"),
1261
1385
  escalationStrings: {
1262
1386
  requested: t("escalationRequested"),
@@ -1265,8 +1389,11 @@ function AppilotsChatInner({
1265
1389
  offer: t("escalationOffer")
1266
1390
  }
1267
1391
  });
1268
- const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = chunkX4MPSZL3_js.useAppilotsActions({ autoExecute });
1269
- const { emit, remotePersonalization } = chunkKZ2BLMS4_js.useAppilotsContext();
1392
+ React8.useEffect(() => {
1393
+ onReplyLocaleChange(replyLocale);
1394
+ }, [replyLocale, onReplyLocaleChange]);
1395
+ const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = chunkAJDHZRBN_js.useAppilotsActions({ autoExecute });
1396
+ const { emit, remotePersonalization } = chunkUZ2D4BVX_js.useAppilotsContext();
1270
1397
  const {
1271
1398
  headerTitle: resolvedTitle,
1272
1399
  assistantAvatar,
@@ -1290,37 +1417,119 @@ function AppilotsChatInner({
1290
1417
  );
1291
1418
  const allActions = [...pendingActions, ...executingActions, ...completedActions];
1292
1419
  const timeline = buildChatTimeline(messages, allActions);
1293
- const lastAssistantMessageId = React7__namespace.default.useMemo(() => {
1420
+ const lastAssistantMessageId = React8__namespace.default.useMemo(() => {
1294
1421
  for (let i = messages.length - 1; i >= 0; i--) {
1295
1422
  if (messages[i].role === "assistant") return messages[i].id;
1296
1423
  }
1297
1424
  return void 0;
1298
1425
  }, [messages]);
1299
1426
  const insets = useSafeAreaInsetsOrDefault();
1300
- const [internalVisible, setInternalVisible] = React7.useState(mode === "inline");
1301
- const [inputText, setInputText] = React7.useState("");
1302
- const flatListRef = React7.useRef(null);
1303
- const slideAnim = React7.useRef(new reactNative.Animated.Value(SCREEN_HEIGHT)).current;
1304
- const isVisible = mode === "inline" ? true : controlledVisible !== void 0 ? controlledVisible : internalVisible;
1305
- const showSuggestedPrompts = chunkX4MPSZL3_js.shouldShowSuggestedPrompts({
1427
+ const [internalVisible, setInternalVisible] = React8.useState(mode === "inline");
1428
+ const [inputText, setInputText] = React8.useState("");
1429
+ const flatListRef = React8.useRef(null);
1430
+ const slideAnim = React8.useRef(new reactNative.Animated.Value(SCREEN_HEIGHT)).current;
1431
+ const wantsSheet = mode === "inline" ? true : controlledVisible !== void 0 ? controlledVisible : internalVisible;
1432
+ const speechHost = isSpeechHost(speechProp) ? speechProp : null;
1433
+ const hasGeometry = React8.useSyncExternalStore(
1434
+ chunkUZ2D4BVX_js.subscribeGeometryHost,
1435
+ () => chunkUZ2D4BVX_js.geometryAvailability() !== "unavailable",
1436
+ () => false
1437
+ );
1438
+ const capabilities = React8.useMemo(
1439
+ () => ({ geometry: hasGeometry, speech: speechHost !== null }),
1440
+ [hasGeometry, speechHost]
1441
+ );
1442
+ const { experience, downgrades } = React8.useMemo(
1443
+ () => resolveExperience(experienceProp, capabilities),
1444
+ [experienceProp, capabilities]
1445
+ );
1446
+ const presence = mode === "inline" ? "sheet" : experience.presence;
1447
+ React8.useEffect(() => {
1448
+ if (!__DEV__ || downgrades.length === 0) return;
1449
+ if (!chunkUZ2D4BVX_js.isGeometryResolved()) return;
1450
+ for (const line of formatDowngrades(downgrades)) {
1451
+ console.warn(line);
1452
+ }
1453
+ }, [downgrades, hasGeometry]);
1454
+ const [unreadResult, setUnreadResult] = React8.useState(false);
1455
+ const [explicitlyOpened, setExplicitlyOpened] = React8.useState(false);
1456
+ const requireApproval = React8.useCallback(
1457
+ (action) => {
1458
+ if (action.status !== "pending") return false;
1459
+ if (action.type === "confirm") return true;
1460
+ return !autoExecute;
1461
+ },
1462
+ [autoExecute]
1463
+ );
1464
+ const awaitingUser = pendingActions.some((action) => requireApproval(action)) || escalation?.status === "pending" || escalation?.status === "active";
1465
+ const busy = isLoading || executingActions.length > 0;
1466
+ const acting = busy && hasStartedActing;
1467
+ const hostModalOpen = useHostModalOpen(
1468
+ usesPill(presence) && (busy || wantsSheet || unreadResult)
1469
+ );
1470
+ const surface = resolveSurface(presence, {
1471
+ busy,
1472
+ acting,
1473
+ awaitingUser,
1474
+ open: wantsSheet,
1475
+ unread: unreadResult,
1476
+ hostModalOpen,
1477
+ explicitlyOpened
1478
+ });
1479
+ const isVisible = mode === "inline" ? true : surface === "sheet";
1480
+ const spotlight = useSpotlight(experience.spotlight !== "off");
1481
+ React8.useEffect(() => {
1482
+ chunkAJDHZRBN_js.setSpotlightMode(experience.spotlight);
1483
+ return () => chunkAJDHZRBN_js.setSpotlightMode("off");
1484
+ }, [experience.spotlight]);
1485
+ const { label: pillLabel, state: pillState } = surface === "pill" ? resolvePillStatus(allActions, busy, {
1486
+ working: strings.pillWorking,
1487
+ done: strings.pillDone,
1488
+ locale: resolvedLocale
1489
+ }) : { label: "", state: "pending" };
1490
+ const showSuggestedPrompts = chunkAJDHZRBN_js.shouldShowSuggestedPrompts({
1306
1491
  isVisible,
1307
1492
  messageCount: messages.length,
1308
1493
  inputText
1309
1494
  });
1310
- const { prompts: suggestedPrompts } = chunkX4MPSZL3_js.useSuggestedPrompts({
1495
+ const { prompts: suggestedPrompts } = chunkAJDHZRBN_js.useSuggestedPrompts({
1311
1496
  enabled: showSuggestedPrompts,
1312
1497
  limit: 3
1313
1498
  });
1314
- const openChat = React7.useCallback(() => {
1499
+ const openChat = React8.useCallback(() => {
1500
+ setExplicitlyOpened(true);
1315
1501
  setInternalVisible(true);
1316
1502
  emit({ type: "chat:open", timestamp: Date.now(), data: {} });
1317
1503
  }, [emit]);
1318
- const closeChat = React7.useCallback(() => {
1504
+ const closeChat = React8.useCallback(() => {
1505
+ setExplicitlyOpened(false);
1319
1506
  setInternalVisible(false);
1320
1507
  onClose?.();
1321
1508
  emit({ type: "chat:close", timestamp: Date.now(), data: {} });
1322
1509
  }, [onClose, emit]);
1323
- React7.useEffect(() => {
1510
+ React8.useEffect(() => {
1511
+ if (acting) setExplicitlyOpened(false);
1512
+ if (presence === "hidden" && acting) setInternalVisible(false);
1513
+ }, [presence, acting]);
1514
+ const wasActingRef = React8.useRef(false);
1515
+ React8.useEffect(() => {
1516
+ if (!usesPill(presence)) {
1517
+ wasActingRef.current = acting;
1518
+ return;
1519
+ }
1520
+ if (acting) {
1521
+ wasActingRef.current = true;
1522
+ return;
1523
+ }
1524
+ if (!wasActingRef.current) return;
1525
+ wasActingRef.current = false;
1526
+ if (shouldReopenOnTurnEnd(presence)) setInternalVisible(true);
1527
+ else setUnreadResult(true);
1528
+ }, [acting, presence]);
1529
+ React8.useEffect(() => {
1530
+ if (surface === "sheet") setUnreadResult(false);
1531
+ }, [surface]);
1532
+ React8.useEffect(() => {
1324
1533
  if (mode === "inline") return;
1325
1534
  reactNative.Animated.spring(slideAnim, {
1326
1535
  toValue: isVisible ? 0 : SCREEN_HEIGHT,
@@ -1329,25 +1538,31 @@ function AppilotsChatInner({
1329
1538
  friction: 11
1330
1539
  }).start();
1331
1540
  }, [isVisible, slideAnim, mode]);
1332
- React7.useEffect(() => {
1541
+ React8.useEffect(() => {
1333
1542
  if (messages.length > 0) {
1334
1543
  setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
1335
1544
  }
1336
1545
  }, [messages.length]);
1337
- const handleSend = React7.useCallback(() => {
1546
+ const voiceEnabled = experience.input.includes("voice");
1547
+ const voice = useVoiceInput({
1548
+ host: voiceEnabled ? speechHost : null,
1549
+ locale: resolvedLocale,
1550
+ onTranscript: sendMessage
1551
+ });
1552
+ const handleSend = React8.useCallback(() => {
1338
1553
  if (!inputText.trim()) return;
1339
1554
  sendMessage(inputText.trim());
1340
1555
  setInputText("");
1341
1556
  }, [inputText, sendMessage]);
1342
- const renderMessage = React7.useCallback(
1557
+ const renderMessage = React8.useCallback(
1343
1558
  ({ item }) => {
1344
1559
  if (item.role === "system") {
1345
1560
  const isOffer = item.metadata?.escalationOffer === true;
1346
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.systemMessageContainer }, /* @__PURE__ */ React7__namespace.default.createElement(
1561
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.systemMessageContainer }, /* @__PURE__ */ React8__namespace.default.createElement(
1347
1562
  reactNative.Text,
1348
1563
  {
1349
1564
  style: [
1350
- styles3.systemMessageText,
1565
+ styles5.systemMessageText,
1351
1566
  {
1352
1567
  color: theme.colors.textSecondary,
1353
1568
  fontFamily: theme.typography.fontFamily,
@@ -1356,13 +1571,13 @@ function AppilotsChatInner({
1356
1571
  ]
1357
1572
  },
1358
1573
  item.content
1359
- ), isOffer && !escalation && /* @__PURE__ */ React7__namespace.default.createElement(
1574
+ ), isOffer && !escalation && /* @__PURE__ */ React8__namespace.default.createElement(
1360
1575
  reactNative.TouchableOpacity,
1361
1576
  {
1362
1577
  ...APPILOTS_SKIP_PROPS,
1363
1578
  style: [
1364
- styles3.chip,
1365
- styles3.escalationOfferChip,
1579
+ styles5.chip,
1580
+ styles5.escalationOfferChip,
1366
1581
  {
1367
1582
  backgroundColor: theme.colors.surface,
1368
1583
  borderColor: theme.colors.border,
@@ -1375,12 +1590,12 @@ function AppilotsChatInner({
1375
1590
  accessibilityLabel: strings.talkToHumanA11y,
1376
1591
  testID: "escalation-offer-chip"
1377
1592
  },
1378
- /* @__PURE__ */ React7__namespace.default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
1379
- /* @__PURE__ */ React7__namespace.default.createElement(
1593
+ /* @__PURE__ */ React8__namespace.default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
1594
+ /* @__PURE__ */ React8__namespace.default.createElement(
1380
1595
  reactNative.Text,
1381
1596
  {
1382
1597
  style: [
1383
- styles3.chipText,
1598
+ styles5.chipText,
1384
1599
  {
1385
1600
  color: theme.colors.text,
1386
1601
  fontFamily: theme.typography.fontFamily,
@@ -1394,13 +1609,13 @@ function AppilotsChatInner({
1394
1609
  }
1395
1610
  const isUser = item.role === "user";
1396
1611
  const isHumanAgent = item.role === "human_agent";
1397
- const useWideAssistantLayout = !isUser && needsWideChatLayout(item.content);
1612
+ const useWideAssistantLayout = !isUser && chunkUZ2D4BVX_js.needsWideChatLayout(item.content);
1398
1613
  if (isHumanAgent) {
1399
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.humanAgentContainer, testID: "human-agent-message" }, /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.humanAgentLabelRow }, /* @__PURE__ */ React7__namespace.default.createElement(HeadsetIcon, { size: 11, color: theme.colors.secondary }), /* @__PURE__ */ React7__namespace.default.createElement(
1614
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.humanAgentContainer, testID: "human-agent-message" }, /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.humanAgentLabelRow }, /* @__PURE__ */ React8__namespace.default.createElement(HeadsetIcon, { size: 11, color: theme.colors.secondary }), /* @__PURE__ */ React8__namespace.default.createElement(
1400
1615
  reactNative.Text,
1401
1616
  {
1402
1617
  style: [
1403
- styles3.humanAgentLabel,
1618
+ styles5.humanAgentLabel,
1404
1619
  {
1405
1620
  color: theme.colors.textSecondary,
1406
1621
  fontFamily: theme.typography.fontFamily
@@ -1408,17 +1623,17 @@ function AppilotsChatInner({
1408
1623
  ]
1409
1624
  },
1410
1625
  escalation?.operatorName ?? strings.humanAgentLabel
1411
- )), /* @__PURE__ */ React7__namespace.default.createElement(
1626
+ )), /* @__PURE__ */ React8__namespace.default.createElement(
1412
1627
  reactNative.View,
1413
1628
  {
1414
1629
  accessibilityLabel: item.content,
1415
1630
  style: [
1416
- styles3.messageBubble,
1417
- styles3.assistantBubble,
1631
+ styles5.messageBubble,
1632
+ styles5.assistantBubble,
1418
1633
  { backgroundColor: theme.colors.surface }
1419
1634
  ]
1420
1635
  },
1421
- /* @__PURE__ */ React7__namespace.default.createElement(
1636
+ /* @__PURE__ */ React8__namespace.default.createElement(
1422
1637
  ChatMarkdown,
1423
1638
  {
1424
1639
  content: item.content,
@@ -1433,21 +1648,21 @@ function AppilotsChatInner({
1433
1648
  )
1434
1649
  ));
1435
1650
  }
1436
- return /* @__PURE__ */ React7__namespace.default.createElement(
1651
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1437
1652
  reactNative.View,
1438
1653
  {
1439
1654
  testID: isUser ? void 0 : item.id === lastAssistantMessageId ? "assistant-last-message" : "assistant-message",
1440
1655
  accessibilityLabel: isUser ? void 0 : item.content,
1441
1656
  style: [
1442
- styles3.messageBubble,
1443
- isUser ? [styles3.userBubble, { backgroundColor: theme.colors.primary }] : [
1444
- styles3.assistantBubble,
1445
- useWideAssistantLayout && styles3.assistantBubbleWide,
1657
+ styles5.messageBubble,
1658
+ isUser ? [styles5.userBubble, { backgroundColor: theme.colors.primary }] : [
1659
+ styles5.assistantBubble,
1660
+ useWideAssistantLayout && styles5.assistantBubbleWide,
1446
1661
  { backgroundColor: theme.colors.surface }
1447
1662
  ]
1448
1663
  ]
1449
1664
  },
1450
- /* @__PURE__ */ React7__namespace.default.createElement(
1665
+ /* @__PURE__ */ React8__namespace.default.createElement(
1451
1666
  ChatMarkdown,
1452
1667
  {
1453
1668
  content: item.content,
@@ -1465,19 +1680,12 @@ function AppilotsChatInner({
1465
1680
  },
1466
1681
  [theme, lastAssistantMessageId, escalation, requestHuman, strings]
1467
1682
  );
1468
- const requireApproval = React7.useCallback(
1469
- (action) => {
1470
- if (action.status !== "pending") return false;
1471
- if (action.type === "confirm") return true;
1472
- return !autoExecute;
1473
- },
1474
- [autoExecute]
1475
- );
1476
- const renderBreadcrumb = React7.useCallback(
1477
- (actions) => /* @__PURE__ */ React7__namespace.default.createElement(
1683
+ const renderBreadcrumb = React8.useCallback(
1684
+ (actions) => /* @__PURE__ */ React8__namespace.default.createElement(
1478
1685
  ActionBreadcrumb,
1479
1686
  {
1480
1687
  actions,
1688
+ locale: resolvedLocale,
1481
1689
  primaryColor: theme.colors.primary,
1482
1690
  textColor: theme.colors.text,
1483
1691
  fontFamily: theme.typography.fontFamily,
@@ -1513,6 +1721,8 @@ function AppilotsChatInner({
1513
1721
  theme.colors.warning,
1514
1722
  theme.colors.error,
1515
1723
  theme.typography.fontFamily,
1724
+ strings,
1725
+ resolvedLocale,
1516
1726
  requireApproval,
1517
1727
  approveAction,
1518
1728
  rejectAction
@@ -1525,17 +1735,17 @@ function AppilotsChatInner({
1525
1735
  const showEmptySubtitle = resolvedEmptySubtitle.length > 0 && !(showSuggestedPrompts && suggestedPrompts.length > 0);
1526
1736
  const renderAvatar = () => {
1527
1737
  if (!assistantAvatar) {
1528
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: [styles3.headerDot, { backgroundColor: theme.colors.primary }] });
1738
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: [styles5.headerDot, { backgroundColor: theme.colors.primary }] });
1529
1739
  }
1530
1740
  if (typeof assistantAvatar === "string") {
1531
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Image, { source: { uri: assistantAvatar }, style: styles3.headerAvatar });
1741
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Image, { source: { uri: assistantAvatar }, style: styles5.headerAvatar });
1532
1742
  }
1533
1743
  if (typeof assistantAvatar === "number") {
1534
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Image, { source: assistantAvatar, style: styles3.headerAvatar });
1744
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Image, { source: assistantAvatar, style: styles5.headerAvatar });
1535
1745
  }
1536
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.headerAvatarSlot }, assistantAvatar);
1746
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.headerAvatarSlot }, assistantAvatar);
1537
1747
  };
1538
- const showTrigger = mode === "bubble" && !isVisible && controlledVisible === void 0 && triggerButton !== "none";
1748
+ const showTrigger = mode === "bubble" && surface === "none" && experience.entry.includes("fab") && controlledVisible === void 0 && triggerButton !== "none";
1539
1749
  const fabPositionStyle = (() => {
1540
1750
  switch (position) {
1541
1751
  case "bottom-left":
@@ -1549,15 +1759,15 @@ function AppilotsChatInner({
1549
1759
  return { bottom: 24, right: 24 };
1550
1760
  }
1551
1761
  })();
1552
- const chatSurface = /* @__PURE__ */ React7__namespace.default.createElement(
1762
+ const chatSurface = /* @__PURE__ */ React8__namespace.default.createElement(
1553
1763
  reactNative.View,
1554
1764
  {
1555
1765
  ...APPILOTS_SKIP_PROPS,
1556
1766
  style: [
1557
- styles3.chatContainer,
1558
- mode === "fullscreen" && styles3.chatContainerFullscreen,
1559
- mode === "sidebar" && styles3.chatContainerSidebar,
1560
- mode === "inline" && styles3.chatContainerInline,
1767
+ styles5.chatContainer,
1768
+ mode === "fullscreen" && styles5.chatContainerFullscreen,
1769
+ mode === "sidebar" && styles5.chatContainerSidebar,
1770
+ mode === "inline" && styles5.chatContainerInline,
1561
1771
  {
1562
1772
  backgroundColor: theme.colors.background,
1563
1773
  borderTopLeftRadius: theme.radii.lg,
@@ -1565,11 +1775,11 @@ function AppilotsChatInner({
1565
1775
  }
1566
1776
  ]
1567
1777
  },
1568
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: [styles3.header, { borderBottomColor: theme.colors.border }] }, /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.headerLeft }, renderAvatar(), /* @__PURE__ */ React7__namespace.default.createElement(
1778
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: [styles5.header, { borderBottomColor: theme.colors.border }] }, /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.headerLeft }, renderAvatar(), /* @__PURE__ */ React8__namespace.default.createElement(
1569
1779
  reactNative.Text,
1570
1780
  {
1571
1781
  style: [
1572
- styles3.headerTitle,
1782
+ styles5.headerTitle,
1573
1783
  {
1574
1784
  color: theme.colors.text,
1575
1785
  fontFamily: theme.typography.fontFamily,
@@ -1578,46 +1788,50 @@ function AppilotsChatInner({
1578
1788
  ]
1579
1789
  },
1580
1790
  resolvedHeaderTitle
1581
- )), /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.headerActions }, /* @__PURE__ */ React7__namespace.default.createElement(
1791
+ )), /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.headerActions }, /* @__PURE__ */ React8__namespace.default.createElement(
1582
1792
  reactNative.TouchableOpacity,
1583
1793
  {
1584
1794
  ...APPILOTS_SKIP_PROPS,
1585
1795
  onPress: () => requestHuman("user_requested"),
1586
- style: styles3.headerButton,
1796
+ style: styles5.headerButton,
1587
1797
  accessibilityRole: "button",
1588
1798
  accessibilityLabel: strings.talkToHumanA11y,
1589
1799
  testID: "escalation-header-button"
1590
1800
  },
1591
- /* @__PURE__ */ React7__namespace.default.createElement(
1801
+ /* @__PURE__ */ React8__namespace.default.createElement(
1592
1802
  HeadsetIcon,
1593
1803
  {
1594
1804
  size: 16,
1595
1805
  color: escalation ? theme.colors.primary : theme.colors.textSecondary
1596
1806
  }
1597
1807
  )
1598
- ), /* @__PURE__ */ React7__namespace.default.createElement(
1808
+ ), /* @__PURE__ */ React8__namespace.default.createElement(
1599
1809
  reactNative.TouchableOpacity,
1600
1810
  {
1601
1811
  ...APPILOTS_SKIP_PROPS,
1602
1812
  onPress: clearMessages,
1603
- style: styles3.headerButton
1813
+ style: styles5.headerButton,
1814
+ accessibilityRole: "button",
1815
+ testID: "assistant-clear"
1604
1816
  },
1605
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles3.headerButtonText, { color: theme.colors.textSecondary }] }, strings.clearButton)
1606
- ), mode !== "inline" && /* @__PURE__ */ React7__namespace.default.createElement(
1817
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [styles5.headerButtonText, { color: theme.colors.textSecondary }] }, strings.clearButton)
1818
+ ), mode !== "inline" && /* @__PURE__ */ React8__namespace.default.createElement(
1607
1819
  reactNative.TouchableOpacity,
1608
1820
  {
1609
1821
  ...APPILOTS_SKIP_PROPS,
1610
1822
  onPress: closeChat,
1611
- style: styles3.closeButton,
1612
- accessibilityLabel: strings.closeChatA11y
1823
+ style: styles5.closeButton,
1824
+ accessibilityRole: "button",
1825
+ accessibilityLabel: strings.closeChatA11y,
1826
+ testID: "assistant-close"
1613
1827
  },
1614
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles3.closeButtonText, { color: theme.colors.text }] }, "\u2715")
1828
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: [styles5.closeButtonText, { color: theme.colors.text }] }, "\u2715")
1615
1829
  ))),
1616
- escalation && /* @__PURE__ */ React7__namespace.default.createElement(
1830
+ escalation && /* @__PURE__ */ React8__namespace.default.createElement(
1617
1831
  reactNative.View,
1618
1832
  {
1619
1833
  style: [
1620
- styles3.escalationBanner,
1834
+ styles5.escalationBanner,
1621
1835
  {
1622
1836
  borderBottomColor: theme.colors.border,
1623
1837
  backgroundColor: theme.colors.primary + "0d"
@@ -1625,12 +1839,12 @@ function AppilotsChatInner({
1625
1839
  ],
1626
1840
  testID: "escalation-banner"
1627
1841
  },
1628
- /* @__PURE__ */ React7__namespace.default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
1629
- /* @__PURE__ */ React7__namespace.default.createElement(
1842
+ /* @__PURE__ */ React8__namespace.default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
1843
+ /* @__PURE__ */ React8__namespace.default.createElement(
1630
1844
  reactNative.Text,
1631
1845
  {
1632
1846
  style: [
1633
- styles3.escalationBannerText,
1847
+ styles5.escalationBannerText,
1634
1848
  {
1635
1849
  color: theme.colors.textSecondary,
1636
1850
  fontFamily: theme.typography.fontFamily,
@@ -1641,10 +1855,11 @@ function AppilotsChatInner({
1641
1855
  escalation.status === "pending" ? strings.escalationPendingBanner : strings.escalationActiveBanner
1642
1856
  )
1643
1857
  ),
1644
- /* @__PURE__ */ React7__namespace.default.createElement(
1858
+ /* @__PURE__ */ React8__namespace.default.createElement(
1645
1859
  reactNative.FlatList,
1646
1860
  {
1647
1861
  ...APPILOTS_SKIP_PROPS,
1862
+ testID: "assistant-transcript",
1648
1863
  ref: flatListRef,
1649
1864
  data: timeline,
1650
1865
  keyExtractor: (item) => item.type === "message" ? item.data.id : item.key,
@@ -1657,34 +1872,34 @@ function AppilotsChatInner({
1657
1872
  }
1658
1873
  return null;
1659
1874
  },
1660
- contentContainerStyle: styles3.messageList,
1661
- ListEmptyComponent: /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.emptyState }, emptyStateIcon && isImageSource(emptyStateIcon) ? /* @__PURE__ */ React7__namespace.default.createElement(
1875
+ contentContainerStyle: styles5.messageList,
1876
+ ListEmptyComponent: /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.emptyState }, emptyStateIcon && isImageSource(emptyStateIcon) ? /* @__PURE__ */ React8__namespace.default.createElement(
1662
1877
  reactNative.Image,
1663
1878
  {
1664
1879
  source: typeof emptyStateIcon === "string" ? { uri: emptyStateIcon } : emptyStateIcon,
1665
- style: styles3.emptyIconImage,
1880
+ style: styles5.emptyIconImage,
1666
1881
  resizeMode: "contain"
1667
1882
  }
1668
- ) : /* @__PURE__ */ React7__namespace.default.createElement(
1883
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(
1669
1884
  reactNative.View,
1670
1885
  {
1671
- style: [styles3.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
1886
+ style: [styles5.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
1672
1887
  },
1673
- emptyStateIcon ? /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.emptyIconEmoji }, emptyStateIcon) : /* @__PURE__ */ React7__namespace.default.createElement(ChatIcon, { size: 30, color: theme.colors.primary })
1674
- ), /* @__PURE__ */ React7__namespace.default.createElement(
1888
+ emptyStateIcon ? /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.emptyIconEmoji }, emptyStateIcon) : /* @__PURE__ */ React8__namespace.default.createElement(ChatIcon, { size: 30, color: theme.colors.primary })
1889
+ ), /* @__PURE__ */ React8__namespace.default.createElement(
1675
1890
  reactNative.Text,
1676
1891
  {
1677
1892
  style: [
1678
- styles3.emptyTitle,
1893
+ styles5.emptyTitle,
1679
1894
  { color: theme.colors.text, fontFamily: theme.typography.fontFamily }
1680
1895
  ]
1681
1896
  },
1682
1897
  resolvedEmptyTitle
1683
- ), showEmptySubtitle && /* @__PURE__ */ React7__namespace.default.createElement(
1898
+ ), showEmptySubtitle && /* @__PURE__ */ React8__namespace.default.createElement(
1684
1899
  reactNative.Text,
1685
1900
  {
1686
1901
  style: [
1687
- styles3.emptySubtitle,
1902
+ styles5.emptySubtitle,
1688
1903
  {
1689
1904
  color: theme.colors.textSecondary,
1690
1905
  fontFamily: theme.typography.fontFamily
@@ -1693,12 +1908,12 @@ function AppilotsChatInner({
1693
1908
  numberOfLines: 2
1694
1909
  },
1695
1910
  resolvedEmptySubtitle
1696
- ), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.chipsContainer }, suggestedPrompts.map((prompt) => /* @__PURE__ */ React7__namespace.default.createElement(
1911
+ ), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.chipsContainer, testID: "assistant-suggested-prompts" }, suggestedPrompts.map((prompt) => /* @__PURE__ */ React8__namespace.default.createElement(
1697
1912
  reactNative.TouchableOpacity,
1698
1913
  {
1699
1914
  key: `${prompt.source}:${prompt.text}`,
1700
1915
  style: [
1701
- styles3.chip,
1916
+ styles5.chip,
1702
1917
  {
1703
1918
  backgroundColor: theme.colors.surface,
1704
1919
  borderColor: theme.colors.border,
@@ -1709,11 +1924,11 @@ function AppilotsChatInner({
1709
1924
  activeOpacity: 0.7,
1710
1925
  accessibilityLabel: `Suggested prompt: ${prompt.text}`
1711
1926
  },
1712
- /* @__PURE__ */ React7__namespace.default.createElement(
1927
+ /* @__PURE__ */ React8__namespace.default.createElement(
1713
1928
  reactNative.Text,
1714
1929
  {
1715
1930
  style: [
1716
- styles3.chipText,
1931
+ styles5.chipText,
1717
1932
  {
1718
1933
  color: theme.colors.buttonText,
1719
1934
  fontFamily: theme.typography.fontFamily,
@@ -1725,20 +1940,20 @@ function AppilotsChatInner({
1725
1940
  prompt.text
1726
1941
  )
1727
1942
  )))),
1728
- ListFooterComponent: isLoading ? /* @__PURE__ */ React7__namespace.default.createElement(
1943
+ ListFooterComponent: isLoading ? /* @__PURE__ */ React8__namespace.default.createElement(
1729
1944
  reactNative.View,
1730
1945
  {
1731
1946
  style: [
1732
- styles3.messageBubble,
1733
- styles3.assistantBubble,
1947
+ styles5.messageBubble,
1948
+ styles5.assistantBubble,
1734
1949
  { backgroundColor: theme.colors.surface }
1735
1950
  ]
1736
1951
  },
1737
- /* @__PURE__ */ React7__namespace.default.createElement(
1952
+ /* @__PURE__ */ React8__namespace.default.createElement(
1738
1953
  reactNative.Text,
1739
1954
  {
1740
1955
  style: [
1741
- styles3.messageText,
1956
+ styles5.messageText,
1742
1957
  { color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
1743
1958
  ]
1744
1959
  },
@@ -1747,22 +1962,48 @@ function AppilotsChatInner({
1747
1962
  ) : null
1748
1963
  }
1749
1964
  ),
1750
- /* @__PURE__ */ React7__namespace.default.createElement(
1965
+ mission && !["completed", "cancelled"].includes(mission.status) && /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: { padding: 12, gap: 8 }, testID: "appilots-mission-controls" }, /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: { color: theme.colors.text }, testID: "appilots-mission-progress" }, mission.progressText, mission.status === "paused" ? ` \xB7 ${strings.missionPaused}` : ""), /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: { flexDirection: "row", gap: 12 } }, mission.status === "running" ? /* @__PURE__ */ React8__namespace.default.createElement(
1966
+ reactNative.TouchableOpacity,
1967
+ {
1968
+ onPress: () => void pauseMission(),
1969
+ testID: "appilots-mission-pause",
1970
+ accessibilityRole: "button"
1971
+ },
1972
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: { color: theme.colors.text } }, strings.missionPause)
1973
+ ) : mission.status !== "awaiting_approval" ? /* @__PURE__ */ React8__namespace.default.createElement(
1974
+ reactNative.TouchableOpacity,
1975
+ {
1976
+ onPress: () => void resumeMission(),
1977
+ disabled: isLoading,
1978
+ testID: "appilots-mission-resume",
1979
+ accessibilityRole: "button"
1980
+ },
1981
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: { color: theme.colors.text } }, strings.missionResume)
1982
+ ) : null, /* @__PURE__ */ React8__namespace.default.createElement(
1983
+ reactNative.TouchableOpacity,
1984
+ {
1985
+ onPress: () => void cancelMission(),
1986
+ testID: "appilots-mission-cancel",
1987
+ accessibilityRole: "button"
1988
+ },
1989
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: { color: theme.colors.text } }, strings.missionCancel)
1990
+ ))),
1991
+ /* @__PURE__ */ React8__namespace.default.createElement(
1751
1992
  reactNative.View,
1752
1993
  {
1753
1994
  style: [
1754
- styles3.inputContainer,
1995
+ styles5.inputContainer,
1755
1996
  {
1756
1997
  borderTopColor: theme.colors.border,
1757
1998
  paddingBottom: Math.max(insets.bottom, 10)
1758
1999
  }
1759
2000
  ]
1760
2001
  },
1761
- /* @__PURE__ */ React7__namespace.default.createElement(
2002
+ /* @__PURE__ */ React8__namespace.default.createElement(
1762
2003
  reactNative.TextInput,
1763
2004
  {
1764
2005
  style: [
1765
- styles3.input,
2006
+ styles5.input,
1766
2007
  {
1767
2008
  backgroundColor: theme.colors.surface,
1768
2009
  color: theme.colors.text,
@@ -1779,16 +2020,35 @@ function AppilotsChatInner({
1779
2020
  multiline: true,
1780
2021
  blurOnSubmit: false,
1781
2022
  scrollEnabled: true,
1782
- editable: !isLoading,
2023
+ editable: !isLoading && (!mission || ["completed", "cancelled"].includes(mission.status)),
1783
2024
  testID: "assistant-input",
1784
2025
  __appilotsInternal: true
1785
2026
  }
1786
2027
  ),
1787
- isLoading ? /* @__PURE__ */ React7__namespace.default.createElement(
2028
+ voiceEnabled && !isLoading ? /* @__PURE__ */ React8__namespace.default.createElement(
1788
2029
  reactNative.TouchableOpacity,
1789
2030
  {
1790
2031
  style: [
1791
- styles3.sendButton,
2032
+ styles5.sendButton,
2033
+ {
2034
+ backgroundColor: voice.state === "listening" || voice.state === "starting" ? theme.colors.error : theme.colors.primary + "40",
2035
+ borderRadius: theme.radii.md
2036
+ }
2037
+ ],
2038
+ onPressIn: voice.start,
2039
+ onPressOut: voice.stop,
2040
+ accessibilityRole: "button",
2041
+ accessibilityLabel: voice.state === "listening" ? strings.micStopA11y : strings.micStartA11y,
2042
+ testID: "appilots-mic-button",
2043
+ activeOpacity: 0.7
2044
+ },
2045
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.sendButtonText }, "\u25CF")
2046
+ ) : null,
2047
+ isLoading ? /* @__PURE__ */ React8__namespace.default.createElement(
2048
+ reactNative.TouchableOpacity,
2049
+ {
2050
+ style: [
2051
+ styles5.sendButton,
1792
2052
  {
1793
2053
  backgroundColor: theme.colors.primary,
1794
2054
  borderRadius: theme.radii.md
@@ -1800,31 +2060,31 @@ function AppilotsChatInner({
1800
2060
  testID: "appilots-stop-button",
1801
2061
  activeOpacity: 0.7
1802
2062
  },
1803
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.sendButtonText }, "\u25A0")
1804
- ) : /* @__PURE__ */ React7__namespace.default.createElement(
2063
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.sendButtonText }, "\u25A0")
2064
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(
1805
2065
  reactNative.TouchableOpacity,
1806
2066
  {
1807
2067
  style: [
1808
- styles3.sendButton,
2068
+ styles5.sendButton,
1809
2069
  {
1810
2070
  backgroundColor: inputText.trim() ? theme.colors.primary : theme.colors.primary + "40",
1811
2071
  borderRadius: theme.radii.md
1812
2072
  }
1813
2073
  ],
1814
2074
  onPress: handleSend,
1815
- disabled: !inputText.trim(),
2075
+ disabled: !inputText.trim() || !!(mission && !["completed", "cancelled"].includes(mission.status)),
1816
2076
  activeOpacity: 0.7,
1817
2077
  accessibilityRole: "button",
1818
2078
  testID: "assistant-send"
1819
2079
  },
1820
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.sendButtonText }, "\u2191")
2080
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.sendButtonText }, "\u2191")
1821
2081
  )
1822
2082
  ),
1823
- poweredByVisible && /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.poweredByContainer }, /* @__PURE__ */ React7__namespace.default.createElement(
2083
+ poweredByVisible && /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { style: styles5.poweredByContainer }, /* @__PURE__ */ React8__namespace.default.createElement(
1824
2084
  reactNative.Text,
1825
2085
  {
1826
2086
  style: [
1827
- styles3.poweredByText,
2087
+ styles5.poweredByText,
1828
2088
  {
1829
2089
  color: theme.colors.textSecondary,
1830
2090
  fontFamily: theme.typography.fontFamily,
@@ -1840,8 +2100,8 @@ function AppilotsChatInner({
1840
2100
  }
1841
2101
  const renderTrigger = () => {
1842
2102
  if (triggerButton === "none") return null;
1843
- if (triggerButton !== "default" && React7__namespace.default.isValidElement(triggerButton)) {
1844
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { ...APPILOTS_SKIP_PROPS, style: [styles3.fabWrapper, fabPositionStyle] }, /* @__PURE__ */ React7__namespace.default.createElement(
2103
+ if (triggerButton !== "default" && React8__namespace.default.isValidElement(triggerButton)) {
2104
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.View, { ...APPILOTS_SKIP_PROPS, style: [styles5.fabWrapper, fabPositionStyle] }, /* @__PURE__ */ React8__namespace.default.createElement(
1845
2105
  reactNative.TouchableOpacity,
1846
2106
  {
1847
2107
  ...APPILOTS_SKIP_PROPS,
@@ -1854,12 +2114,12 @@ function AppilotsChatInner({
1854
2114
  triggerButton
1855
2115
  ));
1856
2116
  }
1857
- return /* @__PURE__ */ React7__namespace.default.createElement(
2117
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1858
2118
  reactNative.TouchableOpacity,
1859
2119
  {
1860
2120
  ...APPILOTS_SKIP_PROPS,
1861
2121
  style: [
1862
- styles3.fab,
2122
+ styles5.fab,
1863
2123
  fabPositionStyle,
1864
2124
  { backgroundColor: triggerButtonColor ?? theme.colors.primary }
1865
2125
  ],
@@ -1869,48 +2129,113 @@ function AppilotsChatInner({
1869
2129
  accessibilityLabel: strings.openChatA11y,
1870
2130
  testID: "assistant-launcher"
1871
2131
  },
1872
- triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React7__namespace.default.createElement(
2132
+ triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React8__namespace.default.createElement(
1873
2133
  reactNative.Image,
1874
2134
  {
1875
2135
  source: typeof triggerButtonImage === "string" ? { uri: triggerButtonImage } : triggerButtonImage,
1876
- style: styles3.fabImage,
2136
+ style: styles5.fabImage,
1877
2137
  resizeMode: "contain"
1878
2138
  }
1879
- ) : /* @__PURE__ */ React7__namespace.default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
2139
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
1880
2140
  );
1881
2141
  };
1882
- return /* @__PURE__ */ React7__namespace.default.createElement(React7__namespace.default.Fragment, null, showTrigger && renderTrigger(), /* @__PURE__ */ React7__namespace.default.createElement(
1883
- reactNative.Modal,
2142
+ return /* @__PURE__ */ React8__namespace.default.createElement(React8__namespace.default.Fragment, null, showTrigger && renderTrigger(), spotlight && experience.spotlight !== "off" ? /* @__PURE__ */ React8__namespace.default.createElement(
2143
+ SpotlightOverlay,
2144
+ {
2145
+ rect: spotlight.rect,
2146
+ seq: spotlight.seq,
2147
+ label: spotlight.label,
2148
+ color: theme.colors.primary,
2149
+ captionBackground: theme.colors.surface,
2150
+ captionColor: theme.colors.text,
2151
+ fontFamily: theme.typography.fontFamily,
2152
+ window: { width: SCREEN_WIDTH, height: SCREEN_HEIGHT }
2153
+ }
2154
+ ) : null, surface === "pill" && /* @__PURE__ */ React8__namespace.default.createElement(
2155
+ AgentPill,
2156
+ {
2157
+ label: mission && !["completed", "cancelled"].includes(mission.status) ? mission.progressText : pillLabel,
2158
+ state: pillState,
2159
+ position,
2160
+ insets,
2161
+ fontFamily: theme.typography.fontFamily,
2162
+ colors: {
2163
+ surface: theme.colors.surface,
2164
+ text: theme.colors.text,
2165
+ textSecondary: theme.colors.textSecondary,
2166
+ primary: theme.colors.primary,
2167
+ border: theme.colors.border,
2168
+ success: theme.colors.success,
2169
+ error: theme.colors.error
2170
+ },
2171
+ strings: { expandA11y: strings.pillExpandA11y, stopA11y: strings.pillStopA11y },
2172
+ onExpand: openChat,
2173
+ onStop: busy ? cancelMessage : void 0
2174
+ }
2175
+ ), /* @__PURE__ */ React8__namespace.default.createElement(SheetHost, { useModal: presence === "sheet", visible: isVisible, onRequestClose: closeChat }, /* @__PURE__ */ React8__namespace.default.createElement(
2176
+ reactNative.Animated.View,
1884
2177
  {
1885
2178
  ...APPILOTS_SKIP_PROPS,
1886
- visible: isVisible,
1887
- transparent: true,
1888
- animationType: "none",
1889
- onRequestClose: closeChat
2179
+ pointerEvents: presence === "sheet" ? "auto" : "box-none",
2180
+ style: [
2181
+ mode === "fullscreen" ? styles5.modalContainerFullscreen : styles5.modalContainer,
2182
+ mode === "sidebar" && styles5.modalContainerSidebar,
2183
+ presence !== "sheet" && styles5.sheetContainerNoScrim,
2184
+ // Keeps the sheet out of the status bar / notch. It is padding
2185
+ // and not a margin so the scrim still covers the full screen.
2186
+ // Only reachable now that the sheet can grow to the top edge:
2187
+ // `fullscreen` and `sidebar` always could, and `bubble` does
2188
+ // whenever the keyboard shrinks it — without this, the header
2189
+ // renders under the clock.
2190
+ { paddingTop: insets.top },
2191
+ { transform: [{ translateY: slideAnim }] }
2192
+ ]
1890
2193
  },
1891
- /* @__PURE__ */ React7__namespace.default.createElement(
1892
- reactNative.Animated.View,
2194
+ /* @__PURE__ */ React8__namespace.default.createElement(
2195
+ reactNative.KeyboardAvoidingView,
1893
2196
  {
1894
- ...APPILOTS_SKIP_PROPS,
1895
- style: [
1896
- mode === "fullscreen" ? styles3.modalContainerFullscreen : styles3.modalContainer,
1897
- mode === "sidebar" && styles3.modalContainerSidebar,
1898
- { transform: [{ translateY: slideAnim }] }
1899
- ]
2197
+ style: styles5.keyboardView,
2198
+ behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
2199
+ keyboardVerticalOffset: 0
1900
2200
  },
1901
- /* @__PURE__ */ React7__namespace.default.createElement(
1902
- reactNative.KeyboardAvoidingView,
1903
- {
1904
- style: styles3.keyboardView,
1905
- behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
1906
- keyboardVerticalOffset: 0
1907
- },
1908
- chatSurface
1909
- )
2201
+ chatSurface
1910
2202
  )
1911
- ));
2203
+ )));
1912
2204
  }
1913
- var styles3 = reactNative.StyleSheet.create({
2205
+ function SheetHost({
2206
+ useModal,
2207
+ visible,
2208
+ onRequestClose,
2209
+ children
2210
+ }) {
2211
+ if (useModal) {
2212
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2213
+ reactNative.Modal,
2214
+ {
2215
+ ...APPILOTS_SKIP_PROPS,
2216
+ visible,
2217
+ transparent: true,
2218
+ animationType: "none",
2219
+ onRequestClose
2220
+ },
2221
+ children
2222
+ );
2223
+ }
2224
+ if (!visible) return null;
2225
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2226
+ reactNative.View,
2227
+ {
2228
+ ...APPILOTS_SKIP_PROPS,
2229
+ pointerEvents: "box-none",
2230
+ style: [reactNative.StyleSheet.absoluteFill, styles5.sheetOverlay]
2231
+ },
2232
+ children
2233
+ );
2234
+ }
2235
+ var styles5 = reactNative.StyleSheet.create({
2236
+ // An explicitly opened chat must not mount underneath a sibling portal.
2237
+ // Automatic expansion is separately deferred while the host modal is open.
2238
+ sheetOverlay: { zIndex: 1e3, elevation: 7 },
1914
2239
  fab: {
1915
2240
  position: "absolute",
1916
2241
  width: 56,
@@ -1953,12 +2278,31 @@ var styles3 = reactNative.StyleSheet.create({
1953
2278
  flexDirection: "row",
1954
2279
  justifyContent: "flex-end"
1955
2280
  },
2281
+ // Non-modal presences drop the scrim entirely: dimming the app is
2282
+ // the opposite of the point, and a painted full-screen surface is
2283
+ // touch-opaque no matter what pointerEvents the parent asks for.
2284
+ sheetContainerNoScrim: {
2285
+ backgroundColor: "transparent"
2286
+ },
1956
2287
  keyboardView: {
1957
2288
  flex: 1,
1958
2289
  justifyContent: "flex-end"
1959
2290
  },
2291
+ // The sheet has to be able to SHRINK, so its size is a maximum and not
2292
+ // a height. `keyboardView` is a KeyboardAvoidingView on `padding`
2293
+ // (`height` on Android): when the keyboard opens, the space left for
2294
+ // this child drops by the keyboard's height. A fixed `height` ignores
2295
+ // that — the sheet keeps its full size, the parent's
2296
+ // `justifyContent: 'flex-end'` pins it to the bottom, and it overflows
2297
+ // off the TOP, carrying the header away with it. Measured on a
2298
+ // third-party app at 0.75 × 812pt against a ~336pt keyboard: focusing
2299
+ // the input put the entire header off screen, close button included,
2300
+ // and nothing could dismiss the chat. `flex: 1` + `maxHeight` keeps the
2301
+ // same size with the keyboard down and shrinks instead of overflowing
2302
+ // with it up.
1960
2303
  chatContainer: {
1961
- height: SCREEN_HEIGHT * 0.75,
2304
+ flex: 1,
2305
+ maxHeight: SCREEN_HEIGHT * 0.75,
1962
2306
  shadowColor: "#000",
1963
2307
  shadowOffset: { width: 0, height: -3 },
1964
2308
  shadowOpacity: 0.1,
@@ -1966,15 +2310,19 @@ var styles3 = reactNative.StyleSheet.create({
1966
2310
  elevation: 10
1967
2311
  },
1968
2312
  chatContainerFullscreen: {
1969
- height: SCREEN_HEIGHT
2313
+ maxHeight: SCREEN_HEIGHT
1970
2314
  },
1971
2315
  chatContainerSidebar: {
1972
- height: SCREEN_HEIGHT,
2316
+ maxHeight: SCREEN_HEIGHT,
1973
2317
  width: SCREEN_WIDTH > 600 ? SCREEN_WIDTH * 0.4 : SCREEN_WIDTH
1974
2318
  },
2319
+ // Inline renders in place with no modal and no KeyboardAvoidingView, so
2320
+ // it fills its host instead — the 75% cap above would shrink it to
2321
+ // three quarters of whatever the integrator sized the slot.
1975
2322
  chatContainerInline: {
1976
2323
  height: "100%",
1977
2324
  width: "100%",
2325
+ maxHeight: "100%",
1978
2326
  flex: 1
1979
2327
  },
1980
2328
  header: {
@@ -2200,6 +2548,11 @@ function ConfirmDialog(_props = {}) {
2200
2548
  return null;
2201
2549
  }
2202
2550
 
2551
+ // src/auto/appilotsListTotal.ts
2552
+ function appilotsListTotal(total) {
2553
+ return { appilotsTotalItemCount: total };
2554
+ }
2555
+
2203
2556
  // src/hoc/canHoldRef.ts
2204
2557
  var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
2205
2558
  var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
@@ -2226,12 +2579,19 @@ function canHoldRef(type) {
2226
2579
  }
2227
2580
  }
2228
2581
 
2582
+ // src/hoc/withDeclaredIdentity.ts
2583
+ function withDeclaredIdentity(props, declaredId, enabled) {
2584
+ if (!enabled || !declaredId) return props;
2585
+ if (props.testID != null) return props;
2586
+ return { ...props, testID: declaredId };
2587
+ }
2588
+
2229
2589
  // src/hoc/createAppilotsInput.tsx
2230
2590
  function normalizeId(label) {
2231
2591
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2232
2592
  }
2233
2593
  function createAppilotsInput(WrappedComponent) {
2234
- const AppilotsInput = React7__namespace.default.forwardRef((props, ref) => {
2594
+ const AppilotsInput = React8__namespace.default.forwardRef((props, ref) => {
2235
2595
  const {
2236
2596
  appilotsId,
2237
2597
  appilotsScreen,
@@ -2243,17 +2603,17 @@ function createAppilotsInput(WrappedComponent) {
2243
2603
  ...rest
2244
2604
  } = props;
2245
2605
  const fieldId = appilotsId || (label ? normalizeId(label) : null);
2246
- const valueRef = React7.useRef(value ?? "");
2247
- const onChangeRef = React7.useRef(onChangeText);
2248
- const innerRef = React7.useRef(null);
2606
+ const valueRef = React8.useRef(value ?? "");
2607
+ const onChangeRef = React8.useRef(onChangeText);
2608
+ const innerRef = React8.useRef(null);
2249
2609
  valueRef.current = value ?? "";
2250
2610
  onChangeRef.current = onChangeText;
2251
- const getValue = React7.useCallback(() => valueRef.current, []);
2252
- const setValue = React7.useCallback((v) => onChangeRef.current?.(v), []);
2253
- const focus = React7.useCallback(() => {
2611
+ const getValue = React8.useCallback(() => valueRef.current, []);
2612
+ const setValue = React8.useCallback((v) => onChangeRef.current?.(v), []);
2613
+ const focus = React8.useCallback(() => {
2254
2614
  innerRef.current?.focus?.();
2255
2615
  }, []);
2256
- React7.useEffect(() => {
2616
+ React8.useEffect(() => {
2257
2617
  if (!fieldId || !appilotsEnabled) return;
2258
2618
  const entry = {
2259
2619
  kind: "field",
@@ -2264,9 +2624,9 @@ function createAppilotsInput(WrappedComponent) {
2264
2624
  label: label ?? fieldId,
2265
2625
  screen: appilotsScreen
2266
2626
  };
2267
- chunkKZ2BLMS4_js.componentRegistry.register(fieldId, entry);
2627
+ chunkUZ2D4BVX_js.componentRegistry.register(fieldId, entry);
2268
2628
  return () => {
2269
- chunkKZ2BLMS4_js.componentRegistry.unregister(fieldId);
2629
+ chunkUZ2D4BVX_js.componentRegistry.unregister(fieldId);
2270
2630
  };
2271
2631
  }, [
2272
2632
  fieldId,
@@ -2278,7 +2638,7 @@ function createAppilotsInput(WrappedComponent) {
2278
2638
  label,
2279
2639
  appilotsScreen
2280
2640
  ]);
2281
- const mergedRef = React7.useCallback(
2641
+ const mergedRef = React8.useCallback(
2282
2642
  (instance) => {
2283
2643
  innerRef.current = instance;
2284
2644
  if (typeof ref === "function") ref(instance);
@@ -2286,10 +2646,14 @@ function createAppilotsInput(WrappedComponent) {
2286
2646
  },
2287
2647
  [ref]
2288
2648
  );
2289
- return /* @__PURE__ */ React7__namespace.default.createElement(
2649
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2290
2650
  WrappedComponent,
2291
2651
  {
2292
- ...{ label, value, onChangeText, ...rest },
2652
+ ...withDeclaredIdentity(
2653
+ { label, value, onChangeText, ...rest },
2654
+ fieldId,
2655
+ appilotsEnabled
2656
+ ),
2293
2657
  ...canHoldRef(WrappedComponent) ? { ref: mergedRef } : {}
2294
2658
  }
2295
2659
  );
@@ -2301,7 +2665,7 @@ function normalizeId2(label) {
2301
2665
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2302
2666
  }
2303
2667
  function createAppilotsButton(WrappedComponent) {
2304
- const AppilotsButton = React7__namespace.default.forwardRef((props, ref) => {
2668
+ const AppilotsButton = React8__namespace.default.forwardRef((props, ref) => {
2305
2669
  const {
2306
2670
  appilotsId,
2307
2671
  appilotsScreen,
@@ -2311,10 +2675,10 @@ function createAppilotsButton(WrappedComponent) {
2311
2675
  ...rest
2312
2676
  } = props;
2313
2677
  const targetId = appilotsId || (title ? normalizeId2(title) : null);
2314
- const onPressRef = React7.useRef(onPress);
2678
+ const onPressRef = React8.useRef(onPress);
2315
2679
  onPressRef.current = onPress;
2316
- const press = React7.useCallback(() => onPressRef.current?.(), []);
2317
- React7.useEffect(() => {
2680
+ const press = React8.useCallback(() => onPressRef.current?.(), []);
2681
+ React8.useEffect(() => {
2318
2682
  if (!targetId || !appilotsEnabled) return;
2319
2683
  const entry = {
2320
2684
  kind: "target",
@@ -2322,15 +2686,15 @@ function createAppilotsButton(WrappedComponent) {
2322
2686
  label: title ?? targetId,
2323
2687
  screen: appilotsScreen
2324
2688
  };
2325
- chunkKZ2BLMS4_js.componentRegistry.register(targetId, entry);
2689
+ chunkUZ2D4BVX_js.componentRegistry.register(targetId, entry);
2326
2690
  return () => {
2327
- chunkKZ2BLMS4_js.componentRegistry.unregister(targetId);
2691
+ chunkUZ2D4BVX_js.componentRegistry.unregister(targetId);
2328
2692
  };
2329
2693
  }, [targetId, appilotsEnabled, press, title, appilotsScreen]);
2330
- return /* @__PURE__ */ React7__namespace.default.createElement(
2694
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2331
2695
  WrappedComponent,
2332
2696
  {
2333
- ...{ title, onPress, ...rest },
2697
+ ...withDeclaredIdentity({ title, onPress, ...rest }, targetId, appilotsEnabled),
2334
2698
  ...canHoldRef(WrappedComponent) ? { ref } : {}
2335
2699
  }
2336
2700
  );
@@ -2342,7 +2706,7 @@ function normalizeId3(label) {
2342
2706
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2343
2707
  }
2344
2708
  function createAppilotsSwitch(WrappedComponent) {
2345
- const AppilotsSwitch = React7__namespace.default.forwardRef((props, ref) => {
2709
+ const AppilotsSwitch = React8__namespace.default.forwardRef((props, ref) => {
2346
2710
  const {
2347
2711
  appilotsId,
2348
2712
  appilotsScreen,
@@ -2353,13 +2717,13 @@ function createAppilotsSwitch(WrappedComponent) {
2353
2717
  ...rest
2354
2718
  } = props;
2355
2719
  const toggleId = appilotsId || (label ? normalizeId3(label) : null);
2356
- const valueRef = React7.useRef(value ?? false);
2357
- const onChangeRef = React7.useRef(onValueChange);
2720
+ const valueRef = React8.useRef(value ?? false);
2721
+ const onChangeRef = React8.useRef(onValueChange);
2358
2722
  valueRef.current = value ?? false;
2359
2723
  onChangeRef.current = onValueChange;
2360
- const getValue = React7.useCallback(() => valueRef.current, []);
2361
- const setValue = React7.useCallback((v) => onChangeRef.current?.(v), []);
2362
- React7.useEffect(() => {
2724
+ const getValue = React8.useCallback(() => valueRef.current, []);
2725
+ const setValue = React8.useCallback((v) => onChangeRef.current?.(v), []);
2726
+ React8.useEffect(() => {
2363
2727
  if (!toggleId || !appilotsEnabled) return;
2364
2728
  const entry = {
2365
2729
  kind: "toggle",
@@ -2368,15 +2732,19 @@ function createAppilotsSwitch(WrappedComponent) {
2368
2732
  label: label ?? toggleId,
2369
2733
  screen: appilotsScreen
2370
2734
  };
2371
- chunkKZ2BLMS4_js.componentRegistry.register(toggleId, entry);
2735
+ chunkUZ2D4BVX_js.componentRegistry.register(toggleId, entry);
2372
2736
  return () => {
2373
- chunkKZ2BLMS4_js.componentRegistry.unregister(toggleId);
2737
+ chunkUZ2D4BVX_js.componentRegistry.unregister(toggleId);
2374
2738
  };
2375
2739
  }, [toggleId, appilotsEnabled, getValue, setValue, label, appilotsScreen]);
2376
- return /* @__PURE__ */ React7__namespace.default.createElement(
2740
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2377
2741
  WrappedComponent,
2378
2742
  {
2379
- ...{ label, value, onValueChange, ...rest },
2743
+ ...withDeclaredIdentity(
2744
+ { label, value, onValueChange, ...rest },
2745
+ toggleId,
2746
+ appilotsEnabled
2747
+ ),
2380
2748
  ...canHoldRef(WrappedComponent) ? { ref } : {}
2381
2749
  }
2382
2750
  );
@@ -2387,193 +2755,252 @@ function createAppilotsSwitch(WrappedComponent) {
2387
2755
 
2388
2756
  Object.defineProperty(exports, "AppilotsNavigationContainer", {
2389
2757
  enumerable: true,
2390
- get: function () { return chunkDRXUBLGY_js.AppilotsNavigationContainer; }
2758
+ get: function () { return chunkALJGKORS_js.AppilotsNavigationContainer; }
2759
+ });
2760
+ Object.defineProperty(exports, "AppilotsI18nProvider", {
2761
+ enumerable: true,
2762
+ get: function () { return chunkAJDHZRBN_js.AppilotsI18nProvider; }
2763
+ });
2764
+ Object.defineProperty(exports, "REVEAL_MARGIN", {
2765
+ enumerable: true,
2766
+ get: function () { return chunkAJDHZRBN_js.REVEAL_MARGIN; }
2767
+ });
2768
+ Object.defineProperty(exports, "SPOTLIGHT_TTL_MS", {
2769
+ enumerable: true,
2770
+ get: function () { return chunkAJDHZRBN_js.SPOTLIGHT_TTL_MS; }
2391
2771
  });
2392
2772
  Object.defineProperty(exports, "appilotsSelfCheck", {
2393
2773
  enumerable: true,
2394
- get: function () { return chunkX4MPSZL3_js.appilotsSelfCheck; }
2774
+ get: function () { return chunkAJDHZRBN_js.appilotsSelfCheck; }
2395
2775
  });
2396
2776
  Object.defineProperty(exports, "captureSnapshot", {
2397
2777
  enumerable: true,
2398
- get: function () { return chunkX4MPSZL3_js.captureSnapshot; }
2778
+ get: function () { return chunkAJDHZRBN_js.captureSnapshot; }
2779
+ });
2780
+ Object.defineProperty(exports, "detectDeviceLocale", {
2781
+ enumerable: true,
2782
+ get: function () { return chunkAJDHZRBN_js.detectDeviceLocale; }
2399
2783
  });
2400
2784
  Object.defineProperty(exports, "executeAction", {
2401
2785
  enumerable: true,
2402
- get: function () { return chunkX4MPSZL3_js.executeAction; }
2786
+ get: function () { return chunkAJDHZRBN_js.executeAction; }
2787
+ });
2788
+ Object.defineProperty(exports, "getSpotlightMode", {
2789
+ enumerable: true,
2790
+ get: function () { return chunkAJDHZRBN_js.getSpotlightMode; }
2791
+ });
2792
+ Object.defineProperty(exports, "getSpotlightTarget", {
2793
+ enumerable: true,
2794
+ get: function () { return chunkAJDHZRBN_js.getSpotlightTarget; }
2795
+ });
2796
+ Object.defineProperty(exports, "offsetToReveal", {
2797
+ enumerable: true,
2798
+ get: function () { return chunkAJDHZRBN_js.offsetToReveal; }
2799
+ });
2800
+ Object.defineProperty(exports, "resolveLocale", {
2801
+ enumerable: true,
2802
+ get: function () { return chunkAJDHZRBN_js.resolveLocale; }
2803
+ });
2804
+ Object.defineProperty(exports, "revealTarget", {
2805
+ enumerable: true,
2806
+ get: function () { return chunkAJDHZRBN_js.revealTarget; }
2807
+ });
2808
+ Object.defineProperty(exports, "setSpotlightMode", {
2809
+ enumerable: true,
2810
+ get: function () { return chunkAJDHZRBN_js.setSpotlightMode; }
2811
+ });
2812
+ Object.defineProperty(exports, "setSpotlightTarget", {
2813
+ enumerable: true,
2814
+ get: function () { return chunkAJDHZRBN_js.setSpotlightTarget; }
2815
+ });
2816
+ Object.defineProperty(exports, "subscribeSpotlight", {
2817
+ enumerable: true,
2818
+ get: function () { return chunkAJDHZRBN_js.subscribeSpotlight; }
2403
2819
  });
2404
2820
  Object.defineProperty(exports, "useAppilots", {
2405
2821
  enumerable: true,
2406
- get: function () { return chunkX4MPSZL3_js.useAppilots; }
2822
+ get: function () { return chunkAJDHZRBN_js.useAppilots; }
2407
2823
  });
2408
2824
  Object.defineProperty(exports, "useAppilotsActions", {
2409
2825
  enumerable: true,
2410
- get: function () { return chunkX4MPSZL3_js.useAppilotsActions; }
2826
+ get: function () { return chunkAJDHZRBN_js.useAppilotsActions; }
2411
2827
  });
2412
2828
  Object.defineProperty(exports, "useAppilotsChat", {
2413
2829
  enumerable: true,
2414
- get: function () { return chunkX4MPSZL3_js.useAppilotsChat; }
2830
+ get: function () { return chunkAJDHZRBN_js.useAppilotsChat; }
2415
2831
  });
2416
2832
  Object.defineProperty(exports, "useAppilotsField", {
2417
2833
  enumerable: true,
2418
- get: function () { return chunkX4MPSZL3_js.useAppilotsField; }
2834
+ get: function () { return chunkAJDHZRBN_js.useAppilotsField; }
2835
+ });
2836
+ Object.defineProperty(exports, "useAppilotsI18n", {
2837
+ enumerable: true,
2838
+ get: function () { return chunkAJDHZRBN_js.useAppilotsI18n; }
2419
2839
  });
2420
2840
  Object.defineProperty(exports, "useAppilotsNavigation", {
2421
2841
  enumerable: true,
2422
- get: function () { return chunkX4MPSZL3_js.useAppilotsNavigation; }
2842
+ get: function () { return chunkAJDHZRBN_js.useAppilotsNavigation; }
2423
2843
  });
2424
2844
  Object.defineProperty(exports, "useAppilotsSlider", {
2425
2845
  enumerable: true,
2426
- get: function () { return chunkX4MPSZL3_js.useAppilotsSlider; }
2846
+ get: function () { return chunkAJDHZRBN_js.useAppilotsSlider; }
2427
2847
  });
2428
2848
  Object.defineProperty(exports, "useAppilotsTarget", {
2429
2849
  enumerable: true,
2430
- get: function () { return chunkX4MPSZL3_js.useAppilotsTarget; }
2850
+ get: function () { return chunkAJDHZRBN_js.useAppilotsTarget; }
2431
2851
  });
2432
2852
  Object.defineProperty(exports, "useAppilotsToggle", {
2433
2853
  enumerable: true,
2434
- get: function () { return chunkX4MPSZL3_js.useAppilotsToggle; }
2854
+ get: function () { return chunkAJDHZRBN_js.useAppilotsToggle; }
2435
2855
  });
2436
2856
  Object.defineProperty(exports, "useSuggestedPrompts", {
2437
2857
  enumerable: true,
2438
- get: function () { return chunkX4MPSZL3_js.useSuggestedPrompts; }
2858
+ get: function () { return chunkAJDHZRBN_js.useSuggestedPrompts; }
2439
2859
  });
2440
2860
  Object.defineProperty(exports, "AppilotsClient", {
2441
2861
  enumerable: true,
2442
- get: function () { return chunkKZ2BLMS4_js.AppilotsClient; }
2862
+ get: function () { return chunkUZ2D4BVX_js.AppilotsClient; }
2443
2863
  });
2444
2864
  Object.defineProperty(exports, "AppilotsProvider", {
2445
2865
  enumerable: true,
2446
- get: function () { return chunkKZ2BLMS4_js.AppilotsProvider; }
2866
+ get: function () { return chunkUZ2D4BVX_js.AppilotsProvider; }
2447
2867
  });
2448
2868
  Object.defineProperty(exports, "AppilotsRegistryProvider", {
2449
2869
  enumerable: true,
2450
- get: function () { return chunkKZ2BLMS4_js.AppilotsRegistryProvider; }
2870
+ get: function () { return chunkUZ2D4BVX_js.AppilotsRegistryProvider; }
2451
2871
  });
2452
2872
  Object.defineProperty(exports, "RateLimitedError", {
2453
2873
  enumerable: true,
2454
- get: function () { return chunkKZ2BLMS4_js.RateLimitedError; }
2874
+ get: function () { return chunkUZ2D4BVX_js.RateLimitedError; }
2455
2875
  });
2456
2876
  Object.defineProperty(exports, "SDK_VERSION", {
2457
2877
  enumerable: true,
2458
- get: function () { return chunkKZ2BLMS4_js.SDK_VERSION; }
2878
+ get: function () { return chunkUZ2D4BVX_js.SDK_VERSION; }
2459
2879
  });
2460
2880
  Object.defineProperty(exports, "_patchJsxRuntimes", {
2461
2881
  enumerable: true,
2462
- get: function () { return chunkKZ2BLMS4_js._patchJsxRuntimes; }
2882
+ get: function () { return chunkUZ2D4BVX_js._patchJsxRuntimes; }
2463
2883
  });
2464
2884
  Object.defineProperty(exports, "clearAppilotsDebugTraces", {
2465
2885
  enumerable: true,
2466
- get: function () { return chunkKZ2BLMS4_js.clearAppilotsDebugTraces; }
2886
+ get: function () { return chunkUZ2D4BVX_js.clearAppilotsDebugTraces; }
2467
2887
  });
2468
2888
  Object.defineProperty(exports, "componentRegistry", {
2469
2889
  enumerable: true,
2470
- get: function () { return chunkKZ2BLMS4_js.componentRegistry; }
2890
+ get: function () { return chunkUZ2D4BVX_js.componentRegistry; }
2471
2891
  });
2472
2892
  Object.defineProperty(exports, "createComponentRegistry", {
2473
2893
  enumerable: true,
2474
- get: function () { return chunkKZ2BLMS4_js.createComponentRegistry; }
2894
+ get: function () { return chunkUZ2D4BVX_js.createComponentRegistry; }
2475
2895
  });
2476
2896
  Object.defineProperty(exports, "createElementRegistry", {
2477
2897
  enumerable: true,
2478
- get: function () { return chunkKZ2BLMS4_js.createElementRegistry; }
2898
+ get: function () { return chunkUZ2D4BVX_js.createElementRegistry; }
2479
2899
  });
2480
2900
  Object.defineProperty(exports, "createListRegistry", {
2481
2901
  enumerable: true,
2482
- get: function () { return chunkKZ2BLMS4_js.createListRegistry; }
2902
+ get: function () { return chunkUZ2D4BVX_js.createListRegistry; }
2483
2903
  });
2484
2904
  Object.defineProperty(exports, "defaultDarkTheme", {
2485
2905
  enumerable: true,
2486
- get: function () { return chunkKZ2BLMS4_js.defaultDarkTheme; }
2906
+ get: function () { return chunkUZ2D4BVX_js.defaultDarkTheme; }
2487
2907
  });
2488
2908
  Object.defineProperty(exports, "defaultLightTheme", {
2489
2909
  enumerable: true,
2490
- get: function () { return chunkKZ2BLMS4_js.defaultLightTheme; }
2910
+ get: function () { return chunkUZ2D4BVX_js.defaultLightTheme; }
2491
2911
  });
2492
2912
  Object.defineProperty(exports, "describeAction", {
2493
2913
  enumerable: true,
2494
- get: function () { return chunkKZ2BLMS4_js.describeAction; }
2914
+ get: function () { return chunkUZ2D4BVX_js.describeAction; }
2495
2915
  });
2496
2916
  Object.defineProperty(exports, "elementRegistry", {
2497
2917
  enumerable: true,
2498
- get: function () { return chunkKZ2BLMS4_js.elementRegistry; }
2918
+ get: function () { return chunkUZ2D4BVX_js.elementRegistry; }
2499
2919
  });
2500
2920
  Object.defineProperty(exports, "enableAppilotsAutoTracking", {
2501
2921
  enumerable: true,
2502
- get: function () { return chunkKZ2BLMS4_js.enableAppilotsAutoTracking; }
2922
+ get: function () { return chunkUZ2D4BVX_js.enableAppilotsAutoTracking; }
2503
2923
  });
2504
2924
  Object.defineProperty(exports, "getAppilotsDebugTraces", {
2505
2925
  enumerable: true,
2506
- get: function () { return chunkKZ2BLMS4_js.getAppilotsDebugTraces; }
2926
+ get: function () { return chunkUZ2D4BVX_js.getAppilotsDebugTraces; }
2507
2927
  });
2508
2928
  Object.defineProperty(exports, "getAutoTrackingState", {
2509
2929
  enumerable: true,
2510
- get: function () { return chunkKZ2BLMS4_js.getAutoTrackingState; }
2930
+ get: function () { return chunkUZ2D4BVX_js.getAutoTrackingState; }
2511
2931
  });
2512
2932
  Object.defineProperty(exports, "getGlobalConfig", {
2513
2933
  enumerable: true,
2514
- get: function () { return chunkKZ2BLMS4_js.getGlobalConfig; }
2934
+ get: function () { return chunkUZ2D4BVX_js.getGlobalConfig; }
2515
2935
  });
2516
2936
  Object.defineProperty(exports, "getIntrospectionDiagnostics", {
2517
2937
  enumerable: true,
2518
- get: function () { return chunkKZ2BLMS4_js.getIntrospectionDiagnostics; }
2938
+ get: function () { return chunkUZ2D4BVX_js.getIntrospectionDiagnostics; }
2519
2939
  });
2520
2940
  Object.defineProperty(exports, "humanizeError", {
2521
2941
  enumerable: true,
2522
- get: function () { return chunkKZ2BLMS4_js.humanizeError; }
2942
+ get: function () { return chunkUZ2D4BVX_js.humanizeError; }
2523
2943
  });
2524
2944
  Object.defineProperty(exports, "initAppilots", {
2525
2945
  enumerable: true,
2526
- get: function () { return chunkKZ2BLMS4_js.initAppilots; }
2946
+ get: function () { return chunkUZ2D4BVX_js.initAppilots; }
2527
2947
  });
2528
2948
  Object.defineProperty(exports, "isAutoTrackingEnabled", {
2529
2949
  enumerable: true,
2530
- get: function () { return chunkKZ2BLMS4_js.isAutoTrackingEnabled; }
2950
+ get: function () { return chunkUZ2D4BVX_js.isAutoTrackingEnabled; }
2531
2951
  });
2532
2952
  Object.defineProperty(exports, "listRegistry", {
2533
2953
  enumerable: true,
2534
- get: function () { return chunkKZ2BLMS4_js.listRegistry; }
2954
+ get: function () { return chunkUZ2D4BVX_js.listRegistry; }
2535
2955
  });
2536
2956
  Object.defineProperty(exports, "mergeThemeTokens", {
2537
2957
  enumerable: true,
2538
- get: function () { return chunkKZ2BLMS4_js.mergeThemeTokens; }
2958
+ get: function () { return chunkUZ2D4BVX_js.mergeThemeTokens; }
2539
2959
  });
2540
2960
  Object.defineProperty(exports, "recordAppilotsDebugTrace", {
2541
2961
  enumerable: true,
2542
- get: function () { return chunkKZ2BLMS4_js.recordAppilotsDebugTrace; }
2962
+ get: function () { return chunkUZ2D4BVX_js.recordAppilotsDebugTrace; }
2543
2963
  });
2544
2964
  Object.defineProperty(exports, "registerScreen", {
2545
2965
  enumerable: true,
2546
- get: function () { return chunkKZ2BLMS4_js.registerScreen; }
2966
+ get: function () { return chunkUZ2D4BVX_js.registerScreen; }
2547
2967
  });
2548
2968
  Object.defineProperty(exports, "setCurrentScreen", {
2549
2969
  enumerable: true,
2550
- get: function () { return chunkKZ2BLMS4_js.setCurrentScreen; }
2970
+ get: function () { return chunkUZ2D4BVX_js.setCurrentScreen; }
2551
2971
  });
2552
2972
  Object.defineProperty(exports, "subscribeAppilotsDebugTraces", {
2553
2973
  enumerable: true,
2554
- get: function () { return chunkKZ2BLMS4_js.subscribeAppilotsDebugTraces; }
2974
+ get: function () { return chunkUZ2D4BVX_js.subscribeAppilotsDebugTraces; }
2555
2975
  });
2556
2976
  Object.defineProperty(exports, "useAppilotsContext", {
2557
2977
  enumerable: true,
2558
- get: function () { return chunkKZ2BLMS4_js.useAppilotsContext; }
2978
+ get: function () { return chunkUZ2D4BVX_js.useAppilotsContext; }
2559
2979
  });
2560
2980
  Object.defineProperty(exports, "useResolvedRegistry", {
2561
2981
  enumerable: true,
2562
- get: function () { return chunkKZ2BLMS4_js.useResolvedRegistry; }
2982
+ get: function () { return chunkUZ2D4BVX_js.useResolvedRegistry; }
2563
2983
  });
2564
2984
  exports.ActionBreadcrumb = ActionBreadcrumb;
2985
+ exports.AgentPill = AgentPill;
2565
2986
  exports.AppilotsChat = AppilotsChat;
2566
- exports.AppilotsI18nProvider = AppilotsI18nProvider;
2567
2987
  exports.AppilotsThemeProvider = AppilotsThemeProvider;
2568
2988
  exports.ChatIcon = ChatIcon;
2569
2989
  exports.ConfirmDialog = ConfirmDialog;
2990
+ exports.DEFAULT_EXPERIENCE = DEFAULT_EXPERIENCE;
2570
2991
  exports.HeadsetIcon = HeadsetIcon;
2992
+ exports.SpotlightOverlay = SpotlightOverlay;
2993
+ exports.appilotsListTotal = appilotsListTotal;
2571
2994
  exports.appilotsTheme = appilotsTheme;
2572
2995
  exports.appilotsThemeFromTailwind = appilotsThemeFromTailwind;
2573
2996
  exports.createAppilotsButton = createAppilotsButton;
2574
2997
  exports.createAppilotsInput = createAppilotsInput;
2575
2998
  exports.createAppilotsSwitch = createAppilotsSwitch;
2576
- exports.detectDeviceLocale = detectDeviceLocale;
2577
- exports.resolveLocale = resolveLocale;
2578
- exports.useAppilotsI18n = useAppilotsI18n;
2999
+ exports.formatDowngrades = formatDowngrades;
3000
+ exports.resolveExperience = resolveExperience;
3001
+ exports.resolvePillStatus = resolvePillStatus;
3002
+ exports.resolveSurface = resolveSurface;
3003
+ exports.shouldReopenOnTurnEnd = shouldReopenOnTurnEnd;
2579
3004
  exports.useAppilotsTheme = useAppilotsTheme;
3005
+ exports.useSpotlight = useSpotlight;
3006
+ exports.usesPill = usesPill;