@appilots/sdk 0.11.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunk5UVMNKPT_js = require('./chunk-5UVMNKPT.js');
4
- var chunkUFMTRGML_js = require('./chunk-UFMTRGML.js');
5
- var chunkSUMIABJK_js = require('./chunk-SUMIABJK.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: chunkSUMIABJK_js.defaultLightTheme.colors.primary,
51
- text: chunkSUMIABJK_js.defaultLightTheme.colors.text,
52
- textSecondary: chunkSUMIABJK_js.defaultLightTheme.colors.textSecondary,
53
- surface: chunkSUMIABJK_js.defaultLightTheme.colors.surface,
54
- border: chunkSUMIABJK_js.defaultLightTheme.colors.border,
55
- success: chunkSUMIABJK_js.defaultLightTheme.colors.success,
56
- warning: chunkSUMIABJK_js.defaultLightTheme.colors.warning,
57
- error: chunkSUMIABJK_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 } = chunkSUMIABJK_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,22 +253,22 @@ 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),
@@ -237,8 +277,8 @@ function RegularBreadcrumbRow({
237
277
  accessibilityLabel: "Rejeitar a\xE7\xE3o",
238
278
  testID: "assistant-action-reject"
239
279
  },
240
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles.rejectBtnText, { color: palette.error }] }, "Rejeitar")
241
- ), /* @__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(
242
282
  reactNative.TouchableOpacity,
243
283
  {
244
284
  onPress: () => onApprove(action.id),
@@ -247,7 +287,7 @@ function RegularBreadcrumbRow({
247
287
  accessibilityLabel: "Aprovar a\xE7\xE3o",
248
288
  testID: "assistant-action-approve"
249
289
  },
250
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles.approveBtnText }, "Aprovar")
290
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles.approveBtnText }, "Aprovar")
251
291
  )));
252
292
  }
253
293
  function ConfirmCard({
@@ -272,7 +312,7 @@ function ConfirmCard({
272
312
  cancelBackground,
273
313
  cancelTextColor
274
314
  } = deriveConfirmCardContent(action, palette, confirmStrings);
275
- return /* @__PURE__ */ React7__namespace.default.createElement(
315
+ return /* @__PURE__ */ React8__namespace.default.createElement(
276
316
  reactNative.View,
277
317
  {
278
318
  style: [
@@ -281,7 +321,7 @@ function ConfirmCard({
281
321
  ],
282
322
  testID: "assistant-confirm-card"
283
323
  },
284
- /* @__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(
285
325
  reactNative.Text,
286
326
  {
287
327
  style: [
@@ -291,8 +331,8 @@ function ConfirmCard({
291
331
  },
292
332
  title
293
333
  )),
294
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.message, { color: messageColor, fontFamily }] }, message),
295
- /* @__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(
296
336
  reactNative.TouchableOpacity,
297
337
  {
298
338
  onPress: () => onReject?.(action.id),
@@ -301,8 +341,8 @@ function ConfirmCard({
301
341
  accessibilityLabel: cancelLabel,
302
342
  testID: "assistant-confirm-reject"
303
343
  },
304
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [confirmCardStyles.cancelText, { color: cancelTextColor, fontFamily }] }, cancelLabel)
305
- ), /* @__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(
306
346
  reactNative.TouchableOpacity,
307
347
  {
308
348
  onPress: () => onApprove?.(action.id),
@@ -315,7 +355,7 @@ function ConfirmCard({
315
355
  accessibilityLabel: confirmLabel,
316
356
  testID: "assistant-confirm-approve"
317
357
  },
318
- /* @__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)
319
359
  ))
320
360
  );
321
361
  }
@@ -380,7 +420,7 @@ function StateIcon({
380
420
  tone,
381
421
  primaryColor
382
422
  }) {
383
- 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)));
384
424
  }
385
425
  var styles = reactNative.StyleSheet.create({
386
426
  container: {
@@ -471,7 +511,7 @@ function resolvePersonalization(props, remote) {
471
511
  };
472
512
  }
473
513
  function ChatIcon({ size = 24, color = "#ffffff" }) {
474
- 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(
475
515
  Svg.Path,
476
516
  {
477
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",
@@ -479,8 +519,438 @@ function ChatIcon({ size = 24, color = "#ffffff" }) {
479
519
  }
480
520
  ));
481
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
+ }
482
952
  function HeadsetIcon({ size = 18, color = "#ffffff" }) {
483
- 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(
484
954
  Svg.Path,
485
955
  {
486
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",
@@ -521,215 +991,26 @@ function buildChatTimeline(messages, actions) {
521
991
  }
522
992
  return timeline;
523
993
  }
524
-
525
- // src/components/markdownContent.ts
526
- var ORDERED_LINE = /^\s*(\d+)\.\s+(.+)$/;
527
- var BULLET_LINE = /^\s*[-*•]\s+(.+)$/;
528
- var HEADING_LINE = /^\s*(#{1,6})\s+(.+)$/;
529
- var FENCE_LINE = /^\s*```\s*([A-Za-z0-9+#_-]*)\s*$/;
530
- var INLINE_PATTERN = /\[([^\]\n]+)\]\((https?:\/\/[^\s)]+)\)|\*\*(.+?)\*\*|__(.+?)__|`([^`]+)`|\*(.+?)\*|_(.+?)_/g;
531
- var MIN_ENHANCE_LENGTH = 80;
532
- var SENTENCE_SPLIT = /[^.!?]+[.!?]+(?=\s+[A-ZÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛÃÕÇÑ¿¡"“]|$)|[^.!?]+$/g;
533
- 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;
534
- var INCLUDE_LIST_SENTENCE = /^(.+?)\s+(?:incluem|inclui|include|includes|incluye|incluyen|such as|for example|par exemple|por exemplo)\s+(.+?)\.?\s*$/i;
535
- function looksLikeMarkdown(content) {
536
- if (!content) return false;
537
- 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);
538
- }
539
- function splitEnumeration(text) {
540
- const trimmed = text.trim().replace(/\.\s*$/, "");
541
- if (!trimmed) return [];
542
- const commaParts = trimmed.split(",").map((part) => part.trim()).filter(Boolean);
543
- if (commaParts.length <= 1) {
544
- const conjParts = trimmed.split(/\s+(?:e|and|y|ou|or)\s+/i).map((part) => part.trim());
545
- return conjParts.filter(Boolean);
546
- }
547
- const last = commaParts[commaParts.length - 1];
548
- const conjMatch = last.match(/^(.+?)\s+(?:e|and|y|ou|or)\s+(.+)$/i);
549
- if (conjMatch) {
550
- commaParts[commaParts.length - 1] = conjMatch[1].trim();
551
- commaParts.push(conjMatch[2].trim());
552
- }
553
- return commaParts.filter(Boolean);
554
- }
555
- function splitSentences(text) {
556
- const matches = text.match(SENTENCE_SPLIT);
557
- if (!matches) return [text.trim()];
558
- return matches.map((part) => part.trim()).filter(Boolean);
559
- }
560
- function formatCapabilitySentence(sentence) {
561
- const match = CAPABILITY_SENTENCE.exec(sentence.trim());
562
- if (!match) return null;
563
- const items = splitEnumeration(match[2] ?? "");
564
- if (items.length < 3) return null;
565
- const intro = `${match[1].trim()}:`;
566
- return `${intro}
567
- ${items.map((item) => `- ${item}`).join("\n")}`;
568
- }
569
- function formatIncludeListSentence(sentence) {
570
- const match = INCLUDE_LIST_SENTENCE.exec(sentence.trim());
571
- if (!match) return null;
572
- const intro = match[1].trim().replace(/[,:]\s*$/, "");
573
- const items = splitEnumeration(match[2] ?? "");
574
- if (items.length < 2) return null;
575
- return `${intro}:
576
- ${items.map((item) => `- ${item}`).join("\n")}`;
577
- }
578
- function formatReadableSentence(sentence) {
579
- return formatCapabilitySentence(sentence) ?? formatIncludeListSentence(sentence) ?? sentence.trim();
580
- }
581
- function enhancePlainAssistantContent(content) {
582
- if (!content?.trim() || looksLikeMarkdown(content)) return content;
583
- const trimmed = content.trim();
584
- if (trimmed.length < MIN_ENHANCE_LENGTH) return content;
585
- const sentences = splitSentences(trimmed);
586
- if (sentences.length === 0) return content;
587
- const blocks = sentences.map(formatReadableSentence);
588
- const enhanced = blocks.join("\n\n");
589
- return enhanced || content;
590
- }
591
- function needsWideChatLayout(content) {
592
- if (!content?.trim()) return false;
593
- const prepared = enhancePlainAssistantContent(content);
594
- return looksLikeMarkdown(prepared) || /\n\n+/.test(prepared);
595
- }
596
- function parseMarkdownBlocks(content) {
597
- const lines = content.replace(/\r\n/g, "\n").split("\n");
598
- const blocks = [];
599
- let paragraph = [];
600
- let bulletItems = [];
601
- let orderedItems = [];
602
- let codeLines = null;
603
- let codeLanguage;
604
- const flushParagraph = () => {
605
- if (paragraph.length === 0) return;
606
- blocks.push({ kind: "paragraph", text: paragraph.join("\n") });
607
- paragraph = [];
608
- };
609
- const flushBullets = () => {
610
- if (bulletItems.length === 0) return;
611
- blocks.push({ kind: "bullet", items: bulletItems });
612
- bulletItems = [];
613
- };
614
- const flushOrdered = () => {
615
- if (orderedItems.length === 0) return;
616
- blocks.push({ kind: "ordered", items: orderedItems });
617
- orderedItems = [];
618
- };
619
- const flushLists = () => {
620
- flushBullets();
621
- flushOrdered();
622
- };
623
- const flushCode = () => {
624
- if (codeLines === null) return;
625
- blocks.push({
626
- kind: "codeblock",
627
- code: codeLines.join("\n"),
628
- ...codeLanguage ? { language: codeLanguage } : {}
629
- });
630
- codeLines = null;
631
- codeLanguage = void 0;
632
- };
633
- for (const line of lines) {
634
- if (codeLines !== null) {
635
- if (/^\s*```\s*$/.test(line)) {
636
- flushCode();
637
- } else {
638
- codeLines.push(line);
639
- }
640
- continue;
641
- }
642
- const fence = FENCE_LINE.exec(line);
643
- if (fence) {
644
- flushParagraph();
645
- flushLists();
646
- codeLines = [];
647
- codeLanguage = fence[1] || void 0;
648
- continue;
649
- }
650
- const trimmed = line.trim();
651
- if (!trimmed) {
652
- flushParagraph();
653
- flushLists();
654
- continue;
655
- }
656
- const heading = HEADING_LINE.exec(line);
657
- if (heading) {
658
- flushParagraph();
659
- flushLists();
660
- const level = Math.min(heading[1].length, 3);
661
- blocks.push({ kind: "heading", level, text: heading[2].trim() });
662
- continue;
663
- }
664
- const ordered = ORDERED_LINE.exec(line);
665
- if (ordered) {
666
- flushParagraph();
667
- flushBullets();
668
- orderedItems.push(ordered[2].trim());
669
- continue;
670
- }
671
- const bullet = BULLET_LINE.exec(line);
672
- if (bullet) {
673
- flushParagraph();
674
- flushOrdered();
675
- bulletItems.push(bullet[1].trim());
676
- continue;
677
- }
678
- flushLists();
679
- paragraph.push(line);
680
- }
681
- flushParagraph();
682
- flushLists();
683
- flushCode();
684
- return blocks.length > 0 ? blocks : [{ kind: "paragraph", text: content }];
685
- }
686
- function parseInlineMarkdown(text) {
687
- if (!text) return [{ kind: "text", value: "" }];
688
- const segments = [];
689
- let lastIndex = 0;
690
- INLINE_PATTERN.lastIndex = 0;
691
- for (let match = INLINE_PATTERN.exec(text); match; match = INLINE_PATTERN.exec(text)) {
692
- if (match.index > lastIndex) {
693
- segments.push({ kind: "text", value: text.slice(lastIndex, match.index) });
694
- }
695
- if (match[1] && match[2]) {
696
- segments.push({ kind: "link", value: match[1].trim(), href: match[2] });
697
- } else if (match[3] || match[4]) {
698
- segments.push({ kind: "bold", value: (match[3] ?? match[4]).trim() });
699
- } else if (match[5]) {
700
- segments.push({ kind: "code", value: match[5] });
701
- } else if (match[6] || match[7]) {
702
- segments.push({ kind: "italic", value: (match[6] ?? match[7]).trim() });
703
- }
704
- lastIndex = INLINE_PATTERN.lastIndex;
705
- }
706
- if (lastIndex < text.length) {
707
- segments.push({ kind: "text", value: text.slice(lastIndex) });
708
- }
709
- return segments.length > 0 ? segments : [{ kind: "text", value: text }];
710
- }
711
-
712
- // src/components/ChatMarkdown.tsx
713
994
  function segmentKey(segment, index) {
714
995
  return `${segment.kind}-${index}-${segment.value.slice(0, 12)}`;
715
996
  }
716
997
  function renderInlineSegments(text, theme, baseStyle) {
717
- const segments = parseInlineMarkdown(text);
998
+ const segments = chunkUZ2D4BVX_js.parseInlineMarkdown(text);
718
999
  return segments.map((segment, index) => {
719
1000
  const key = segmentKey(segment, index);
720
1001
  switch (segment.kind) {
721
1002
  case "bold":
722
- 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);
723
1004
  case "italic":
724
- 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);
725
1006
  case "code":
726
- return /* @__PURE__ */ React7__namespace.default.createElement(
1007
+ return /* @__PURE__ */ React8__namespace.default.createElement(
727
1008
  reactNative.Text,
728
1009
  {
729
1010
  key,
730
1011
  style: [
731
1012
  baseStyle,
732
- styles2.code,
1013
+ styles4.code,
733
1014
  {
734
1015
  backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.22)" : "rgba(0,0,0,0.06)"),
735
1016
  color: theme.codeColor ?? theme.color
@@ -739,14 +1020,14 @@ function renderInlineSegments(text, theme, baseStyle) {
739
1020
  segment.value
740
1021
  );
741
1022
  case "link":
742
- return /* @__PURE__ */ React7__namespace.default.createElement(
1023
+ return /* @__PURE__ */ React8__namespace.default.createElement(
743
1024
  reactNative.Text,
744
1025
  {
745
1026
  key,
746
1027
  accessibilityRole: "link",
747
1028
  style: [
748
1029
  baseStyle,
749
- styles2.link,
1030
+ styles4.link,
750
1031
  {
751
1032
  color: theme.linkColor ?? (theme.variant === "user" ? theme.color : "#2563EB")
752
1033
  }
@@ -773,39 +1054,39 @@ function InlineMarkdown({
773
1054
  fontSize: theme.fontSize,
774
1055
  lineHeight: theme.lineHeight
775
1056
  };
776
- 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));
777
1058
  }
778
1059
  function ChatMarkdown({ content, theme, contentWidth }) {
779
- const prepared = enhancePlainAssistantContent(content);
1060
+ const prepared = chunkUZ2D4BVX_js.enhancePlainAssistantContent(content);
780
1061
  const baseTextStyle = {
781
1062
  color: theme.color,
782
1063
  fontFamily: theme.fontFamily,
783
1064
  fontSize: theme.fontSize,
784
1065
  lineHeight: theme.lineHeight
785
1066
  };
786
- const rootStyle = contentWidth ? [styles2.root, { width: contentWidth }] : styles2.root;
787
- if (!looksLikeMarkdown(prepared)) {
1067
+ const rootStyle = contentWidth ? [styles4.root, { width: contentWidth }] : styles4.root;
1068
+ if (!chunkUZ2D4BVX_js.looksLikeMarkdown(prepared)) {
788
1069
  const paragraphs = prepared.split(/\n\n+/).map((part) => part.trim()).filter(Boolean);
789
1070
  if (paragraphs.length > 1) {
790
- 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))));
791
1072
  }
792
- return /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, prepared);
1073
+ return /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: baseTextStyle }, prepared);
793
1074
  }
794
- const blocks = parseMarkdownBlocks(prepared);
795
- 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) => {
796
1077
  if (block.kind === "paragraph") {
797
- 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 }));
798
1079
  }
799
1080
  if (block.kind === "heading") {
800
1081
  const scale = block.level === 1 ? 1.25 : block.level === 2 ? 1.15 : 1.05;
801
1082
  const headingSize = Math.round((theme.fontSize ?? 15) * scale);
802
- 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(
803
1084
  reactNative.Text,
804
1085
  {
805
1086
  accessibilityRole: "header",
806
1087
  style: [
807
1088
  baseTextStyle,
808
- styles2.bold,
1089
+ styles4.bold,
809
1090
  { fontSize: headingSize, lineHeight: Math.round(headingSize * 1.35) }
810
1091
  ]
811
1092
  },
@@ -817,23 +1098,23 @@ function ChatMarkdown({ content, theme, contentWidth }) {
817
1098
  ));
818
1099
  }
819
1100
  if (block.kind === "codeblock") {
820
- return /* @__PURE__ */ React7__namespace.default.createElement(
1101
+ return /* @__PURE__ */ React8__namespace.default.createElement(
821
1102
  reactNative.View,
822
1103
  {
823
1104
  key: `code-${blockIndex}`,
824
1105
  style: [
825
- styles2.codeBlock,
826
- blockIndex > 0 ? styles2.blockGap : void 0,
1106
+ styles4.codeBlock,
1107
+ blockIndex > 0 ? styles4.blockGap : void 0,
827
1108
  {
828
1109
  backgroundColor: theme.codeBackground ?? (theme.variant === "user" ? "rgba(255,255,255,0.18)" : "rgba(0,0,0,0.055)")
829
1110
  }
830
1111
  ]
831
1112
  },
832
- /* @__PURE__ */ React7__namespace.default.createElement(
1113
+ /* @__PURE__ */ React8__namespace.default.createElement(
833
1114
  reactNative.Text,
834
1115
  {
835
1116
  style: [
836
- styles2.code,
1117
+ styles4.code,
837
1118
  {
838
1119
  color: theme.codeColor ?? theme.color,
839
1120
  fontSize: (theme.fontSize ?? 15) - 1,
@@ -846,28 +1127,28 @@ function ChatMarkdown({ content, theme, contentWidth }) {
846
1127
  );
847
1128
  }
848
1129
  if (block.kind === "bullet") {
849
- 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(
850
1131
  reactNative.Text,
851
1132
  {
852
1133
  key: `ul-${blockIndex}-${itemIndex}`,
853
- style: [baseTextStyle, itemIndex > 0 ? styles2.listItemGap : void 0]
1134
+ style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
854
1135
  },
855
1136
  "\u2022 ",
856
1137
  renderInlineSegments(item, theme, baseTextStyle)
857
1138
  )));
858
1139
  }
859
- 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(
860
1141
  reactNative.Text,
861
1142
  {
862
1143
  key: `ol-${blockIndex}-${itemIndex}`,
863
- style: [baseTextStyle, itemIndex > 0 ? styles2.listItemGap : void 0]
1144
+ style: [baseTextStyle, itemIndex > 0 ? styles4.listItemGap : void 0]
864
1145
  },
865
1146
  `${itemIndex + 1}. `,
866
1147
  renderInlineSegments(item, theme, baseTextStyle)
867
1148
  )));
868
1149
  }));
869
1150
  }
870
- var styles2 = reactNative.StyleSheet.create({
1151
+ var styles4 = reactNative.StyleSheet.create({
871
1152
  root: {
872
1153
  flexShrink: 1,
873
1154
  alignSelf: "stretch"
@@ -900,21 +1181,21 @@ var styles2 = reactNative.StyleSheet.create({
900
1181
  textDecorationLine: "underline"
901
1182
  }
902
1183
  });
903
- var ThemeContext = React7.createContext(chunkSUMIABJK_js.defaultLightTheme);
1184
+ var ThemeContext = React8.createContext(chunkUZ2D4BVX_js.defaultLightTheme);
904
1185
  function AppilotsThemeProvider({
905
1186
  theme,
906
1187
  mode = "auto",
907
1188
  children
908
1189
  }) {
909
1190
  const systemScheme = reactNative.useColorScheme();
910
- const tokens = React7.useMemo(
911
- () => chunkSUMIABJK_js.mergeThemeTokens(chunkSUMIABJK_js.resolveBaseTheme(mode, systemScheme), theme ?? void 0),
1191
+ const tokens = React8.useMemo(
1192
+ () => chunkUZ2D4BVX_js.mergeThemeTokens(chunkUZ2D4BVX_js.resolveBaseTheme(mode, systemScheme), theme ?? void 0),
912
1193
  [mode, systemScheme, theme]
913
1194
  );
914
- return /* @__PURE__ */ React7__namespace.default.createElement(ThemeContext.Provider, { value: tokens }, children);
1195
+ return /* @__PURE__ */ React8__namespace.default.createElement(ThemeContext.Provider, { value: tokens }, children);
915
1196
  }
916
1197
  function useAppilotsTheme() {
917
- return React7.useContext(ThemeContext);
1198
+ return React8.useContext(ThemeContext);
918
1199
  }
919
1200
 
920
1201
  // src/theme/tailwindBridge.ts
@@ -1004,177 +1285,6 @@ var appilotsTheme = {
1004
1285
  fromTailwind: appilotsThemeFromTailwind
1005
1286
  };
1006
1287
 
1007
- // src/i18n/bundles/pt-BR.ts
1008
- var ptBR = {
1009
- chatTitle: "Assistente Appilots",
1010
- clearButton: "Limpar",
1011
- inputPlaceholder: "Digite uma mensagem...",
1012
- emptyTitle: "Como posso ajudar?",
1013
- emptySubtitle: "Navego, preencho formul\xE1rios e executo a\xE7\xF5es neste app.",
1014
- thinking: "Pensando...",
1015
- statusAnalyzing: "Analisando a tela...",
1016
- statusWaitingApp: "Aguardando o app responder...",
1017
- statusAdjusting: "Ajustando o plano...",
1018
- poweredBy: "Powered by Appilots",
1019
- approve: "Aprovar",
1020
- reject: "Rejeitar",
1021
- cancelledByUser: "Cancelado pelo usu\xE1rio",
1022
- confirmDestructiveTitle: "A\xE7\xE3o destrutiva",
1023
- confirmTitle: "Confirma\xE7\xE3o necess\xE1ria",
1024
- confirmMessage: 'Tem certeza que deseja "{action}"?',
1025
- confirmDestructiveApprove: "Sim, executar",
1026
- confirmApprove: "Confirmar",
1027
- confirmCancel: "Cancelar",
1028
- confirmThisAction: "esta a\xE7\xE3o",
1029
- unknownAction: "A\xE7\xE3o desconhecida",
1030
- somethingWentWrong: "Algo deu errado",
1031
- openChatA11y: "Abrir chat do assistente",
1032
- closeChatA11y: "Fechar chat do assistente",
1033
- stopGeneratingA11y: "Parar gera\xE7\xE3o",
1034
- talkToHumanA11y: "Falar com um atendente humano",
1035
- humanAgentLabel: "Atendente",
1036
- escalationRequested: "Certo! Chamei um atendente humano. Voc\xEA pode continuar usando o app normalmente enquanto isso.",
1037
- escalationConnected: "Um atendente entrou na conversa.",
1038
- escalationResolved: "O atendimento humano foi encerrado. Voltei a te ajudar por aqui.",
1039
- escalationOffer: "Se preferir, posso chamar uma pessoa para ajudar.",
1040
- escalationOfferChip: "Falar com um atendente",
1041
- escalationPendingBanner: "Aguardando um atendente...",
1042
- escalationActiveBanner: "Voc\xEA est\xE1 falando com um atendente"
1043
- };
1044
-
1045
- // src/i18n/bundles/en.ts
1046
- var en = {
1047
- chatTitle: "Appilots Assistant",
1048
- clearButton: "Clear",
1049
- inputPlaceholder: "Type a message...",
1050
- emptyTitle: "How can I help?",
1051
- emptySubtitle: "I navigate, fill forms, and run actions in this app.",
1052
- thinking: "Thinking...",
1053
- statusAnalyzing: "Reading the screen...",
1054
- statusWaitingApp: "Waiting for the app...",
1055
- statusAdjusting: "Adjusting the plan...",
1056
- poweredBy: "Powered by Appilots",
1057
- approve: "Approve",
1058
- reject: "Reject",
1059
- cancelledByUser: "Cancelled by user",
1060
- confirmDestructiveTitle: "Destructive action",
1061
- confirmTitle: "Confirmation needed",
1062
- confirmMessage: 'Are you sure you want to "{action}"?',
1063
- confirmDestructiveApprove: "Yes, do it",
1064
- confirmApprove: "Confirm",
1065
- confirmCancel: "Cancel",
1066
- confirmThisAction: "this action",
1067
- unknownAction: "Unknown action",
1068
- somethingWentWrong: "Something went wrong",
1069
- openChatA11y: "Open assistant chat",
1070
- closeChatA11y: "Close assistant chat",
1071
- stopGeneratingA11y: "Stop generating",
1072
- talkToHumanA11y: "Talk to a human agent",
1073
- humanAgentLabel: "Agent",
1074
- escalationRequested: "Done! I've called a human agent. You can keep using the app normally in the meantime.",
1075
- escalationConnected: "A human agent joined the conversation.",
1076
- escalationResolved: "The human handoff has ended. I'm back to help you here.",
1077
- escalationOffer: "If you prefer, I can bring in a person to help.",
1078
- escalationOfferChip: "Talk to a human",
1079
- escalationPendingBanner: "Waiting for a human agent...",
1080
- escalationActiveBanner: "You're talking to a human agent"
1081
- };
1082
-
1083
- // src/i18n/bundles/es.ts
1084
- var es = {
1085
- chatTitle: "Asistente Appilots",
1086
- clearButton: "Limpiar",
1087
- inputPlaceholder: "Escribe un mensaje...",
1088
- emptyTitle: "\xBFEn qu\xE9 puedo ayudarte?",
1089
- emptySubtitle: "Navego, relleno formularios y ejecuto acciones en esta app.",
1090
- thinking: "Pensando...",
1091
- statusAnalyzing: "Analizando la pantalla...",
1092
- statusWaitingApp: "Esperando a la app...",
1093
- statusAdjusting: "Ajustando el plan...",
1094
- poweredBy: "Hecho con Appilots",
1095
- approve: "Aprobar",
1096
- reject: "Rechazar",
1097
- cancelledByUser: "Cancelado por el usuario",
1098
- confirmDestructiveTitle: "Acci\xF3n destructiva",
1099
- confirmTitle: "Confirmaci\xF3n necesaria",
1100
- confirmMessage: '\xBFSeguro que quieres "{action}"?',
1101
- confirmDestructiveApprove: "S\xED, ejecutar",
1102
- confirmApprove: "Confirmar",
1103
- confirmCancel: "Cancelar",
1104
- confirmThisAction: "esta acci\xF3n",
1105
- unknownAction: "Acci\xF3n desconocida",
1106
- somethingWentWrong: "Algo sali\xF3 mal",
1107
- openChatA11y: "Abrir chat del asistente",
1108
- closeChatA11y: "Cerrar chat del asistente",
1109
- stopGeneratingA11y: "Detener generaci\xF3n",
1110
- talkToHumanA11y: "Hablar con un agente humano",
1111
- humanAgentLabel: "Agente",
1112
- escalationRequested: "\xA1Listo! Llam\xE9 a un agente humano. Mientras tanto puedes seguir usando la app con normalidad.",
1113
- escalationConnected: "Un agente humano se uni\xF3 a la conversaci\xF3n.",
1114
- escalationResolved: "La atenci\xF3n humana termin\xF3. Vuelvo a ayudarte por aqu\xED.",
1115
- escalationOffer: "Si prefieres, puedo llamar a una persona para ayudarte.",
1116
- escalationOfferChip: "Hablar con un agente",
1117
- escalationPendingBanner: "Esperando a un agente...",
1118
- escalationActiveBanner: "Est\xE1s hablando con un agente humano"
1119
- };
1120
- var BUNDLES = {
1121
- "pt-BR": ptBR,
1122
- en,
1123
- es
1124
- };
1125
- var DEFAULT_LOCALE = "en";
1126
- function detectDeviceLocale() {
1127
- try {
1128
- let raw;
1129
- if (reactNative.Platform.OS === "ios") {
1130
- const settings = reactNative.NativeModules?.SettingsManager?.settings;
1131
- raw = settings?.AppleLocale || (Array.isArray(settings?.AppleLanguages) ? settings?.AppleLanguages?.[0] : void 0);
1132
- } else if (reactNative.Platform.OS === "android") {
1133
- raw = reactNative.NativeModules?.I18nManager?.localeIdentifier;
1134
- }
1135
- if (!raw || typeof raw !== "string") return null;
1136
- const lower = raw.toLowerCase().replace("_", "-");
1137
- if (lower.startsWith("pt")) return "pt-BR";
1138
- if (lower.startsWith("es")) return "es";
1139
- if (lower.startsWith("en")) return "en";
1140
- return null;
1141
- } catch {
1142
- return null;
1143
- }
1144
- }
1145
- function resolveLocale(prop) {
1146
- if (prop && BUNDLES[prop]) return prop;
1147
- const detected = detectDeviceLocale();
1148
- if (detected && BUNDLES[detected]) return detected;
1149
- return DEFAULT_LOCALE;
1150
- }
1151
- var I18nContext = React7.createContext(null);
1152
- function AppilotsI18nProvider({
1153
- locale,
1154
- overrides,
1155
- children
1156
- }) {
1157
- const value = React7.useMemo(() => {
1158
- const resolved = resolveLocale(locale ?? null);
1159
- const merged = overrides ? { ...BUNDLES[resolved], ...overrides } : BUNDLES[resolved];
1160
- return {
1161
- locale: resolved,
1162
- strings: merged,
1163
- t: (key) => merged[key]
1164
- };
1165
- }, [locale, overrides]);
1166
- return /* @__PURE__ */ React7__namespace.default.createElement(I18nContext.Provider, { value }, children);
1167
- }
1168
- function useAppilotsI18n() {
1169
- const ctx = React7.useContext(I18nContext);
1170
- if (ctx) return ctx;
1171
- return {
1172
- locale: DEFAULT_LOCALE,
1173
- strings: BUNDLES[DEFAULT_LOCALE],
1174
- t: (key) => BUNDLES[DEFAULT_LOCALE][key]
1175
- };
1176
- }
1177
-
1178
1288
  // src/components/AppilotsChat.tsx
1179
1289
  function translateLegacyTheme(legacy) {
1180
1290
  const out = {};
@@ -1205,31 +1315,35 @@ var { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = reactNative.Dimensions.get(
1205
1315
  var CHAT_HORIZONTAL_PADDING = 16;
1206
1316
  var BUBBLE_HORIZONTAL_PADDING = 14;
1207
1317
  var ASSISTANT_CONTENT_WIDTH = SCREEN_WIDTH - CHAT_HORIZONTAL_PADDING * 2 - BUBBLE_HORIZONTAL_PADDING * 2;
1208
- var APPILOTS_SKIP_PROPS = {
1209
- __appilotsSkip: true,
1210
- __appilotsInternal: true
1211
- };
1212
1318
  function AppilotsChat(props) {
1213
- const { degraded } = chunkSUMIABJK_js.useAppilotsContext();
1319
+ const { degraded } = chunkUZ2D4BVX_js.useAppilotsContext();
1214
1320
  if (degraded) return null;
1215
- return /* @__PURE__ */ React7__namespace.default.createElement(chunkSUMIABJK_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 }));
1216
1322
  }
1217
1323
  function AppilotsChatSurface(props) {
1218
- const { remotePersonalization } = chunkSUMIABJK_js.useAppilotsContext();
1219
- const themeProp = React7.useMemo(() => {
1324
+ const [conversationLocale, setConversationLocale] = React8.useState(null);
1325
+ const { remotePersonalization } = chunkUZ2D4BVX_js.useAppilotsContext();
1326
+ const themeProp = React8.useMemo(() => {
1220
1327
  if (!props.theme) return void 0;
1221
1328
  return isLegacyTheme(props.theme) ? translateLegacyTheme(props.theme) : props.theme;
1222
1329
  }, [props.theme]);
1223
- return /* @__PURE__ */ React7__namespace.default.createElement(
1330
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1224
1331
  AppilotsThemeProvider,
1225
1332
  {
1226
1333
  theme: resolveTheme(themeProp, remotePersonalization),
1227
1334
  mode: resolveThemeMode(props.themeMode, remotePersonalization)
1228
1335
  },
1229
- /* @__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
+ )
1230
1343
  );
1231
1344
  }
1232
1345
  function AppilotsChatInner({
1346
+ onReplyLocaleChange,
1233
1347
  visible: controlledVisible,
1234
1348
  onClose,
1235
1349
  placeholder,
@@ -1245,20 +1359,28 @@ function AppilotsChatInner({
1245
1359
  triggerButton = "default",
1246
1360
  triggerIcon,
1247
1361
  triggerButtonColor: triggerButtonColorProp,
1248
- triggerButtonImage: triggerButtonImageProp
1362
+ triggerButtonImage: triggerButtonImageProp,
1363
+ experience: experienceProp,
1364
+ speech: speechProp
1249
1365
  }) {
1250
1366
  const theme = useAppilotsTheme();
1251
- const { strings, t } = useAppilotsI18n();
1367
+ const { strings, t, locale: resolvedLocale } = chunkAJDHZRBN_js.useAppilotsI18n();
1252
1368
  const {
1253
1369
  messages,
1370
+ mission,
1371
+ pauseMission,
1372
+ resumeMission,
1373
+ cancelMission,
1374
+ replyLocale,
1254
1375
  isLoading,
1255
1376
  loadingStatusKey,
1377
+ hasStartedActing,
1256
1378
  sendMessage,
1257
1379
  cancelMessage,
1258
1380
  clearMessages,
1259
1381
  escalation,
1260
1382
  requestHuman
1261
- } = chunkUFMTRGML_js.useAppilotsChat({
1383
+ } = chunkAJDHZRBN_js.useAppilotsChat({
1262
1384
  errorPrefix: t("somethingWentWrong"),
1263
1385
  escalationStrings: {
1264
1386
  requested: t("escalationRequested"),
@@ -1267,8 +1389,11 @@ function AppilotsChatInner({
1267
1389
  offer: t("escalationOffer")
1268
1390
  }
1269
1391
  });
1270
- const { pendingActions, executingActions, completedActions, approveAction, rejectAction } = chunkUFMTRGML_js.useAppilotsActions({ autoExecute });
1271
- const { emit, remotePersonalization } = chunkSUMIABJK_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();
1272
1397
  const {
1273
1398
  headerTitle: resolvedTitle,
1274
1399
  assistantAvatar,
@@ -1292,37 +1417,119 @@ function AppilotsChatInner({
1292
1417
  );
1293
1418
  const allActions = [...pendingActions, ...executingActions, ...completedActions];
1294
1419
  const timeline = buildChatTimeline(messages, allActions);
1295
- const lastAssistantMessageId = React7__namespace.default.useMemo(() => {
1420
+ const lastAssistantMessageId = React8__namespace.default.useMemo(() => {
1296
1421
  for (let i = messages.length - 1; i >= 0; i--) {
1297
1422
  if (messages[i].role === "assistant") return messages[i].id;
1298
1423
  }
1299
1424
  return void 0;
1300
1425
  }, [messages]);
1301
1426
  const insets = useSafeAreaInsetsOrDefault();
1302
- const [internalVisible, setInternalVisible] = React7.useState(mode === "inline");
1303
- const [inputText, setInputText] = React7.useState("");
1304
- const flatListRef = React7.useRef(null);
1305
- const slideAnim = React7.useRef(new reactNative.Animated.Value(SCREEN_HEIGHT)).current;
1306
- const isVisible = mode === "inline" ? true : controlledVisible !== void 0 ? controlledVisible : internalVisible;
1307
- const showSuggestedPrompts = chunkUFMTRGML_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({
1308
1491
  isVisible,
1309
1492
  messageCount: messages.length,
1310
1493
  inputText
1311
1494
  });
1312
- const { prompts: suggestedPrompts } = chunkUFMTRGML_js.useSuggestedPrompts({
1495
+ const { prompts: suggestedPrompts } = chunkAJDHZRBN_js.useSuggestedPrompts({
1313
1496
  enabled: showSuggestedPrompts,
1314
1497
  limit: 3
1315
1498
  });
1316
- const openChat = React7.useCallback(() => {
1499
+ const openChat = React8.useCallback(() => {
1500
+ setExplicitlyOpened(true);
1317
1501
  setInternalVisible(true);
1318
1502
  emit({ type: "chat:open", timestamp: Date.now(), data: {} });
1319
1503
  }, [emit]);
1320
- const closeChat = React7.useCallback(() => {
1504
+ const closeChat = React8.useCallback(() => {
1505
+ setExplicitlyOpened(false);
1321
1506
  setInternalVisible(false);
1322
1507
  onClose?.();
1323
1508
  emit({ type: "chat:close", timestamp: Date.now(), data: {} });
1324
1509
  }, [onClose, emit]);
1325
- 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(() => {
1326
1533
  if (mode === "inline") return;
1327
1534
  reactNative.Animated.spring(slideAnim, {
1328
1535
  toValue: isVisible ? 0 : SCREEN_HEIGHT,
@@ -1331,25 +1538,31 @@ function AppilotsChatInner({
1331
1538
  friction: 11
1332
1539
  }).start();
1333
1540
  }, [isVisible, slideAnim, mode]);
1334
- React7.useEffect(() => {
1541
+ React8.useEffect(() => {
1335
1542
  if (messages.length > 0) {
1336
1543
  setTimeout(() => flatListRef.current?.scrollToEnd({ animated: true }), 100);
1337
1544
  }
1338
1545
  }, [messages.length]);
1339
- 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(() => {
1340
1553
  if (!inputText.trim()) return;
1341
1554
  sendMessage(inputText.trim());
1342
1555
  setInputText("");
1343
1556
  }, [inputText, sendMessage]);
1344
- const renderMessage = React7.useCallback(
1557
+ const renderMessage = React8.useCallback(
1345
1558
  ({ item }) => {
1346
1559
  if (item.role === "system") {
1347
1560
  const isOffer = item.metadata?.escalationOffer === true;
1348
- 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(
1349
1562
  reactNative.Text,
1350
1563
  {
1351
1564
  style: [
1352
- styles3.systemMessageText,
1565
+ styles5.systemMessageText,
1353
1566
  {
1354
1567
  color: theme.colors.textSecondary,
1355
1568
  fontFamily: theme.typography.fontFamily,
@@ -1358,13 +1571,13 @@ function AppilotsChatInner({
1358
1571
  ]
1359
1572
  },
1360
1573
  item.content
1361
- ), isOffer && !escalation && /* @__PURE__ */ React7__namespace.default.createElement(
1574
+ ), isOffer && !escalation && /* @__PURE__ */ React8__namespace.default.createElement(
1362
1575
  reactNative.TouchableOpacity,
1363
1576
  {
1364
1577
  ...APPILOTS_SKIP_PROPS,
1365
1578
  style: [
1366
- styles3.chip,
1367
- styles3.escalationOfferChip,
1579
+ styles5.chip,
1580
+ styles5.escalationOfferChip,
1368
1581
  {
1369
1582
  backgroundColor: theme.colors.surface,
1370
1583
  borderColor: theme.colors.border,
@@ -1377,12 +1590,12 @@ function AppilotsChatInner({
1377
1590
  accessibilityLabel: strings.talkToHumanA11y,
1378
1591
  testID: "escalation-offer-chip"
1379
1592
  },
1380
- /* @__PURE__ */ React7__namespace.default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
1381
- /* @__PURE__ */ React7__namespace.default.createElement(
1593
+ /* @__PURE__ */ React8__namespace.default.createElement(HeadsetIcon, { size: 14, color: theme.colors.textSecondary }),
1594
+ /* @__PURE__ */ React8__namespace.default.createElement(
1382
1595
  reactNative.Text,
1383
1596
  {
1384
1597
  style: [
1385
- styles3.chipText,
1598
+ styles5.chipText,
1386
1599
  {
1387
1600
  color: theme.colors.text,
1388
1601
  fontFamily: theme.typography.fontFamily,
@@ -1396,13 +1609,13 @@ function AppilotsChatInner({
1396
1609
  }
1397
1610
  const isUser = item.role === "user";
1398
1611
  const isHumanAgent = item.role === "human_agent";
1399
- const useWideAssistantLayout = !isUser && needsWideChatLayout(item.content);
1612
+ const useWideAssistantLayout = !isUser && chunkUZ2D4BVX_js.needsWideChatLayout(item.content);
1400
1613
  if (isHumanAgent) {
1401
- 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(
1402
1615
  reactNative.Text,
1403
1616
  {
1404
1617
  style: [
1405
- styles3.humanAgentLabel,
1618
+ styles5.humanAgentLabel,
1406
1619
  {
1407
1620
  color: theme.colors.textSecondary,
1408
1621
  fontFamily: theme.typography.fontFamily
@@ -1410,17 +1623,17 @@ function AppilotsChatInner({
1410
1623
  ]
1411
1624
  },
1412
1625
  escalation?.operatorName ?? strings.humanAgentLabel
1413
- )), /* @__PURE__ */ React7__namespace.default.createElement(
1626
+ )), /* @__PURE__ */ React8__namespace.default.createElement(
1414
1627
  reactNative.View,
1415
1628
  {
1416
1629
  accessibilityLabel: item.content,
1417
1630
  style: [
1418
- styles3.messageBubble,
1419
- styles3.assistantBubble,
1631
+ styles5.messageBubble,
1632
+ styles5.assistantBubble,
1420
1633
  { backgroundColor: theme.colors.surface }
1421
1634
  ]
1422
1635
  },
1423
- /* @__PURE__ */ React7__namespace.default.createElement(
1636
+ /* @__PURE__ */ React8__namespace.default.createElement(
1424
1637
  ChatMarkdown,
1425
1638
  {
1426
1639
  content: item.content,
@@ -1435,21 +1648,21 @@ function AppilotsChatInner({
1435
1648
  )
1436
1649
  ));
1437
1650
  }
1438
- return /* @__PURE__ */ React7__namespace.default.createElement(
1651
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1439
1652
  reactNative.View,
1440
1653
  {
1441
1654
  testID: isUser ? void 0 : item.id === lastAssistantMessageId ? "assistant-last-message" : "assistant-message",
1442
1655
  accessibilityLabel: isUser ? void 0 : item.content,
1443
1656
  style: [
1444
- styles3.messageBubble,
1445
- isUser ? [styles3.userBubble, { backgroundColor: theme.colors.primary }] : [
1446
- styles3.assistantBubble,
1447
- useWideAssistantLayout && styles3.assistantBubbleWide,
1657
+ styles5.messageBubble,
1658
+ isUser ? [styles5.userBubble, { backgroundColor: theme.colors.primary }] : [
1659
+ styles5.assistantBubble,
1660
+ useWideAssistantLayout && styles5.assistantBubbleWide,
1448
1661
  { backgroundColor: theme.colors.surface }
1449
1662
  ]
1450
1663
  ]
1451
1664
  },
1452
- /* @__PURE__ */ React7__namespace.default.createElement(
1665
+ /* @__PURE__ */ React8__namespace.default.createElement(
1453
1666
  ChatMarkdown,
1454
1667
  {
1455
1668
  content: item.content,
@@ -1467,19 +1680,12 @@ function AppilotsChatInner({
1467
1680
  },
1468
1681
  [theme, lastAssistantMessageId, escalation, requestHuman, strings]
1469
1682
  );
1470
- const requireApproval = React7.useCallback(
1471
- (action) => {
1472
- if (action.status !== "pending") return false;
1473
- if (action.type === "confirm") return true;
1474
- return !autoExecute;
1475
- },
1476
- [autoExecute]
1477
- );
1478
- const renderBreadcrumb = React7.useCallback(
1479
- (actions) => /* @__PURE__ */ React7__namespace.default.createElement(
1683
+ const renderBreadcrumb = React8.useCallback(
1684
+ (actions) => /* @__PURE__ */ React8__namespace.default.createElement(
1480
1685
  ActionBreadcrumb,
1481
1686
  {
1482
1687
  actions,
1688
+ locale: resolvedLocale,
1483
1689
  primaryColor: theme.colors.primary,
1484
1690
  textColor: theme.colors.text,
1485
1691
  fontFamily: theme.typography.fontFamily,
@@ -1515,6 +1721,8 @@ function AppilotsChatInner({
1515
1721
  theme.colors.warning,
1516
1722
  theme.colors.error,
1517
1723
  theme.typography.fontFamily,
1724
+ strings,
1725
+ resolvedLocale,
1518
1726
  requireApproval,
1519
1727
  approveAction,
1520
1728
  rejectAction
@@ -1527,17 +1735,17 @@ function AppilotsChatInner({
1527
1735
  const showEmptySubtitle = resolvedEmptySubtitle.length > 0 && !(showSuggestedPrompts && suggestedPrompts.length > 0);
1528
1736
  const renderAvatar = () => {
1529
1737
  if (!assistantAvatar) {
1530
- 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 }] });
1531
1739
  }
1532
1740
  if (typeof assistantAvatar === "string") {
1533
- 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 });
1534
1742
  }
1535
1743
  if (typeof assistantAvatar === "number") {
1536
- 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 });
1537
1745
  }
1538
- 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);
1539
1747
  };
1540
- 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";
1541
1749
  const fabPositionStyle = (() => {
1542
1750
  switch (position) {
1543
1751
  case "bottom-left":
@@ -1551,15 +1759,15 @@ function AppilotsChatInner({
1551
1759
  return { bottom: 24, right: 24 };
1552
1760
  }
1553
1761
  })();
1554
- const chatSurface = /* @__PURE__ */ React7__namespace.default.createElement(
1762
+ const chatSurface = /* @__PURE__ */ React8__namespace.default.createElement(
1555
1763
  reactNative.View,
1556
1764
  {
1557
1765
  ...APPILOTS_SKIP_PROPS,
1558
1766
  style: [
1559
- styles3.chatContainer,
1560
- mode === "fullscreen" && styles3.chatContainerFullscreen,
1561
- mode === "sidebar" && styles3.chatContainerSidebar,
1562
- mode === "inline" && styles3.chatContainerInline,
1767
+ styles5.chatContainer,
1768
+ mode === "fullscreen" && styles5.chatContainerFullscreen,
1769
+ mode === "sidebar" && styles5.chatContainerSidebar,
1770
+ mode === "inline" && styles5.chatContainerInline,
1563
1771
  {
1564
1772
  backgroundColor: theme.colors.background,
1565
1773
  borderTopLeftRadius: theme.radii.lg,
@@ -1567,11 +1775,11 @@ function AppilotsChatInner({
1567
1775
  }
1568
1776
  ]
1569
1777
  },
1570
- /* @__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(
1571
1779
  reactNative.Text,
1572
1780
  {
1573
1781
  style: [
1574
- styles3.headerTitle,
1782
+ styles5.headerTitle,
1575
1783
  {
1576
1784
  color: theme.colors.text,
1577
1785
  fontFamily: theme.typography.fontFamily,
@@ -1580,50 +1788,50 @@ function AppilotsChatInner({
1580
1788
  ]
1581
1789
  },
1582
1790
  resolvedHeaderTitle
1583
- )), /* @__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(
1584
1792
  reactNative.TouchableOpacity,
1585
1793
  {
1586
1794
  ...APPILOTS_SKIP_PROPS,
1587
1795
  onPress: () => requestHuman("user_requested"),
1588
- style: styles3.headerButton,
1796
+ style: styles5.headerButton,
1589
1797
  accessibilityRole: "button",
1590
1798
  accessibilityLabel: strings.talkToHumanA11y,
1591
1799
  testID: "escalation-header-button"
1592
1800
  },
1593
- /* @__PURE__ */ React7__namespace.default.createElement(
1801
+ /* @__PURE__ */ React8__namespace.default.createElement(
1594
1802
  HeadsetIcon,
1595
1803
  {
1596
1804
  size: 16,
1597
1805
  color: escalation ? theme.colors.primary : theme.colors.textSecondary
1598
1806
  }
1599
1807
  )
1600
- ), /* @__PURE__ */ React7__namespace.default.createElement(
1808
+ ), /* @__PURE__ */ React8__namespace.default.createElement(
1601
1809
  reactNative.TouchableOpacity,
1602
1810
  {
1603
1811
  ...APPILOTS_SKIP_PROPS,
1604
1812
  onPress: clearMessages,
1605
- style: styles3.headerButton,
1813
+ style: styles5.headerButton,
1606
1814
  accessibilityRole: "button",
1607
1815
  testID: "assistant-clear"
1608
1816
  },
1609
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: [styles3.headerButtonText, { color: theme.colors.textSecondary }] }, strings.clearButton)
1610
- ), 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(
1611
1819
  reactNative.TouchableOpacity,
1612
1820
  {
1613
1821
  ...APPILOTS_SKIP_PROPS,
1614
1822
  onPress: closeChat,
1615
- style: styles3.closeButton,
1823
+ style: styles5.closeButton,
1616
1824
  accessibilityRole: "button",
1617
1825
  accessibilityLabel: strings.closeChatA11y,
1618
1826
  testID: "assistant-close"
1619
1827
  },
1620
- /* @__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")
1621
1829
  ))),
1622
- escalation && /* @__PURE__ */ React7__namespace.default.createElement(
1830
+ escalation && /* @__PURE__ */ React8__namespace.default.createElement(
1623
1831
  reactNative.View,
1624
1832
  {
1625
1833
  style: [
1626
- styles3.escalationBanner,
1834
+ styles5.escalationBanner,
1627
1835
  {
1628
1836
  borderBottomColor: theme.colors.border,
1629
1837
  backgroundColor: theme.colors.primary + "0d"
@@ -1631,12 +1839,12 @@ function AppilotsChatInner({
1631
1839
  ],
1632
1840
  testID: "escalation-banner"
1633
1841
  },
1634
- /* @__PURE__ */ React7__namespace.default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
1635
- /* @__PURE__ */ React7__namespace.default.createElement(
1842
+ /* @__PURE__ */ React8__namespace.default.createElement(HeadsetIcon, { size: 12, color: theme.colors.primary }),
1843
+ /* @__PURE__ */ React8__namespace.default.createElement(
1636
1844
  reactNative.Text,
1637
1845
  {
1638
1846
  style: [
1639
- styles3.escalationBannerText,
1847
+ styles5.escalationBannerText,
1640
1848
  {
1641
1849
  color: theme.colors.textSecondary,
1642
1850
  fontFamily: theme.typography.fontFamily,
@@ -1647,10 +1855,11 @@ function AppilotsChatInner({
1647
1855
  escalation.status === "pending" ? strings.escalationPendingBanner : strings.escalationActiveBanner
1648
1856
  )
1649
1857
  ),
1650
- /* @__PURE__ */ React7__namespace.default.createElement(
1858
+ /* @__PURE__ */ React8__namespace.default.createElement(
1651
1859
  reactNative.FlatList,
1652
1860
  {
1653
1861
  ...APPILOTS_SKIP_PROPS,
1862
+ testID: "assistant-transcript",
1654
1863
  ref: flatListRef,
1655
1864
  data: timeline,
1656
1865
  keyExtractor: (item) => item.type === "message" ? item.data.id : item.key,
@@ -1663,34 +1872,34 @@ function AppilotsChatInner({
1663
1872
  }
1664
1873
  return null;
1665
1874
  },
1666
- contentContainerStyle: styles3.messageList,
1667
- 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(
1668
1877
  reactNative.Image,
1669
1878
  {
1670
1879
  source: typeof emptyStateIcon === "string" ? { uri: emptyStateIcon } : emptyStateIcon,
1671
- style: styles3.emptyIconImage,
1880
+ style: styles5.emptyIconImage,
1672
1881
  resizeMode: "contain"
1673
1882
  }
1674
- ) : /* @__PURE__ */ React7__namespace.default.createElement(
1883
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(
1675
1884
  reactNative.View,
1676
1885
  {
1677
- style: [styles3.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
1886
+ style: [styles5.emptyIconBadge, { backgroundColor: theme.colors.primary + "14" }]
1678
1887
  },
1679
- emptyStateIcon ? /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.emptyIconEmoji }, emptyStateIcon) : /* @__PURE__ */ React7__namespace.default.createElement(ChatIcon, { size: 30, color: theme.colors.primary })
1680
- ), /* @__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(
1681
1890
  reactNative.Text,
1682
1891
  {
1683
1892
  style: [
1684
- styles3.emptyTitle,
1893
+ styles5.emptyTitle,
1685
1894
  { color: theme.colors.text, fontFamily: theme.typography.fontFamily }
1686
1895
  ]
1687
1896
  },
1688
1897
  resolvedEmptyTitle
1689
- ), showEmptySubtitle && /* @__PURE__ */ React7__namespace.default.createElement(
1898
+ ), showEmptySubtitle && /* @__PURE__ */ React8__namespace.default.createElement(
1690
1899
  reactNative.Text,
1691
1900
  {
1692
1901
  style: [
1693
- styles3.emptySubtitle,
1902
+ styles5.emptySubtitle,
1694
1903
  {
1695
1904
  color: theme.colors.textSecondary,
1696
1905
  fontFamily: theme.typography.fontFamily
@@ -1699,12 +1908,12 @@ function AppilotsChatInner({
1699
1908
  numberOfLines: 2
1700
1909
  },
1701
1910
  resolvedEmptySubtitle
1702
- ), showSuggestedPrompts && suggestedPrompts.length > 0 && /* @__PURE__ */ React7__namespace.default.createElement(reactNative.View, { style: styles3.chipsContainer, testID: "assistant-suggested-prompts" }, 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(
1703
1912
  reactNative.TouchableOpacity,
1704
1913
  {
1705
1914
  key: `${prompt.source}:${prompt.text}`,
1706
1915
  style: [
1707
- styles3.chip,
1916
+ styles5.chip,
1708
1917
  {
1709
1918
  backgroundColor: theme.colors.surface,
1710
1919
  borderColor: theme.colors.border,
@@ -1715,11 +1924,11 @@ function AppilotsChatInner({
1715
1924
  activeOpacity: 0.7,
1716
1925
  accessibilityLabel: `Suggested prompt: ${prompt.text}`
1717
1926
  },
1718
- /* @__PURE__ */ React7__namespace.default.createElement(
1927
+ /* @__PURE__ */ React8__namespace.default.createElement(
1719
1928
  reactNative.Text,
1720
1929
  {
1721
1930
  style: [
1722
- styles3.chipText,
1931
+ styles5.chipText,
1723
1932
  {
1724
1933
  color: theme.colors.buttonText,
1725
1934
  fontFamily: theme.typography.fontFamily,
@@ -1731,20 +1940,20 @@ function AppilotsChatInner({
1731
1940
  prompt.text
1732
1941
  )
1733
1942
  )))),
1734
- ListFooterComponent: isLoading ? /* @__PURE__ */ React7__namespace.default.createElement(
1943
+ ListFooterComponent: isLoading ? /* @__PURE__ */ React8__namespace.default.createElement(
1735
1944
  reactNative.View,
1736
1945
  {
1737
1946
  style: [
1738
- styles3.messageBubble,
1739
- styles3.assistantBubble,
1947
+ styles5.messageBubble,
1948
+ styles5.assistantBubble,
1740
1949
  { backgroundColor: theme.colors.surface }
1741
1950
  ]
1742
1951
  },
1743
- /* @__PURE__ */ React7__namespace.default.createElement(
1952
+ /* @__PURE__ */ React8__namespace.default.createElement(
1744
1953
  reactNative.Text,
1745
1954
  {
1746
1955
  style: [
1747
- styles3.messageText,
1956
+ styles5.messageText,
1748
1957
  { color: theme.colors.textSecondary, fontFamily: theme.typography.fontFamily }
1749
1958
  ]
1750
1959
  },
@@ -1753,22 +1962,48 @@ function AppilotsChatInner({
1753
1962
  ) : null
1754
1963
  }
1755
1964
  ),
1756
- /* @__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(
1757
1992
  reactNative.View,
1758
1993
  {
1759
1994
  style: [
1760
- styles3.inputContainer,
1995
+ styles5.inputContainer,
1761
1996
  {
1762
1997
  borderTopColor: theme.colors.border,
1763
1998
  paddingBottom: Math.max(insets.bottom, 10)
1764
1999
  }
1765
2000
  ]
1766
2001
  },
1767
- /* @__PURE__ */ React7__namespace.default.createElement(
2002
+ /* @__PURE__ */ React8__namespace.default.createElement(
1768
2003
  reactNative.TextInput,
1769
2004
  {
1770
2005
  style: [
1771
- styles3.input,
2006
+ styles5.input,
1772
2007
  {
1773
2008
  backgroundColor: theme.colors.surface,
1774
2009
  color: theme.colors.text,
@@ -1785,16 +2020,35 @@ function AppilotsChatInner({
1785
2020
  multiline: true,
1786
2021
  blurOnSubmit: false,
1787
2022
  scrollEnabled: true,
1788
- editable: !isLoading,
2023
+ editable: !isLoading && (!mission || ["completed", "cancelled"].includes(mission.status)),
1789
2024
  testID: "assistant-input",
1790
2025
  __appilotsInternal: true
1791
2026
  }
1792
2027
  ),
1793
- isLoading ? /* @__PURE__ */ React7__namespace.default.createElement(
2028
+ voiceEnabled && !isLoading ? /* @__PURE__ */ React8__namespace.default.createElement(
1794
2029
  reactNative.TouchableOpacity,
1795
2030
  {
1796
2031
  style: [
1797
- 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,
1798
2052
  {
1799
2053
  backgroundColor: theme.colors.primary,
1800
2054
  borderRadius: theme.radii.md
@@ -1806,31 +2060,31 @@ function AppilotsChatInner({
1806
2060
  testID: "appilots-stop-button",
1807
2061
  activeOpacity: 0.7
1808
2062
  },
1809
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.sendButtonText }, "\u25A0")
1810
- ) : /* @__PURE__ */ React7__namespace.default.createElement(
2063
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.sendButtonText }, "\u25A0")
2064
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(
1811
2065
  reactNative.TouchableOpacity,
1812
2066
  {
1813
2067
  style: [
1814
- styles3.sendButton,
2068
+ styles5.sendButton,
1815
2069
  {
1816
2070
  backgroundColor: inputText.trim() ? theme.colors.primary : theme.colors.primary + "40",
1817
2071
  borderRadius: theme.radii.md
1818
2072
  }
1819
2073
  ],
1820
2074
  onPress: handleSend,
1821
- disabled: !inputText.trim(),
2075
+ disabled: !inputText.trim() || !!(mission && !["completed", "cancelled"].includes(mission.status)),
1822
2076
  activeOpacity: 0.7,
1823
2077
  accessibilityRole: "button",
1824
2078
  testID: "assistant-send"
1825
2079
  },
1826
- /* @__PURE__ */ React7__namespace.default.createElement(reactNative.Text, { style: styles3.sendButtonText }, "\u2191")
2080
+ /* @__PURE__ */ React8__namespace.default.createElement(reactNative.Text, { style: styles5.sendButtonText }, "\u2191")
1827
2081
  )
1828
2082
  ),
1829
- 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(
1830
2084
  reactNative.Text,
1831
2085
  {
1832
2086
  style: [
1833
- styles3.poweredByText,
2087
+ styles5.poweredByText,
1834
2088
  {
1835
2089
  color: theme.colors.textSecondary,
1836
2090
  fontFamily: theme.typography.fontFamily,
@@ -1846,8 +2100,8 @@ function AppilotsChatInner({
1846
2100
  }
1847
2101
  const renderTrigger = () => {
1848
2102
  if (triggerButton === "none") return null;
1849
- if (triggerButton !== "default" && React7__namespace.default.isValidElement(triggerButton)) {
1850
- 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(
1851
2105
  reactNative.TouchableOpacity,
1852
2106
  {
1853
2107
  ...APPILOTS_SKIP_PROPS,
@@ -1860,12 +2114,12 @@ function AppilotsChatInner({
1860
2114
  triggerButton
1861
2115
  ));
1862
2116
  }
1863
- return /* @__PURE__ */ React7__namespace.default.createElement(
2117
+ return /* @__PURE__ */ React8__namespace.default.createElement(
1864
2118
  reactNative.TouchableOpacity,
1865
2119
  {
1866
2120
  ...APPILOTS_SKIP_PROPS,
1867
2121
  style: [
1868
- styles3.fab,
2122
+ styles5.fab,
1869
2123
  fabPositionStyle,
1870
2124
  { backgroundColor: triggerButtonColor ?? theme.colors.primary }
1871
2125
  ],
@@ -1875,55 +2129,113 @@ function AppilotsChatInner({
1875
2129
  accessibilityLabel: strings.openChatA11y,
1876
2130
  testID: "assistant-launcher"
1877
2131
  },
1878
- triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React7__namespace.default.createElement(
2132
+ triggerIcon ?? (triggerButtonImage ? /* @__PURE__ */ React8__namespace.default.createElement(
1879
2133
  reactNative.Image,
1880
2134
  {
1881
2135
  source: typeof triggerButtonImage === "string" ? { uri: triggerButtonImage } : triggerButtonImage,
1882
- style: styles3.fabImage,
2136
+ style: styles5.fabImage,
1883
2137
  resizeMode: "contain"
1884
2138
  }
1885
- ) : /* @__PURE__ */ React7__namespace.default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
2139
+ ) : /* @__PURE__ */ React8__namespace.default.createElement(ChatIcon, { size: 26, color: "#ffffff" }))
1886
2140
  );
1887
2141
  };
1888
- return /* @__PURE__ */ React7__namespace.default.createElement(React7__namespace.default.Fragment, null, showTrigger && renderTrigger(), /* @__PURE__ */ React7__namespace.default.createElement(
1889
- 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,
1890
2177
  {
1891
2178
  ...APPILOTS_SKIP_PROPS,
1892
- visible: isVisible,
1893
- transparent: true,
1894
- animationType: "none",
1895
- 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
+ ]
1896
2193
  },
1897
- /* @__PURE__ */ React7__namespace.default.createElement(
1898
- reactNative.Animated.View,
2194
+ /* @__PURE__ */ React8__namespace.default.createElement(
2195
+ reactNative.KeyboardAvoidingView,
1899
2196
  {
1900
- ...APPILOTS_SKIP_PROPS,
1901
- style: [
1902
- mode === "fullscreen" ? styles3.modalContainerFullscreen : styles3.modalContainer,
1903
- mode === "sidebar" && styles3.modalContainerSidebar,
1904
- // Keeps the sheet out of the status bar / notch. It is padding
1905
- // and not a margin so the scrim still covers the full screen.
1906
- // Only reachable now that the sheet can grow to the top edge:
1907
- // `fullscreen` and `sidebar` always could, and `bubble` does
1908
- // whenever the keyboard shrinks it — without this, the header
1909
- // renders under the clock.
1910
- { paddingTop: insets.top },
1911
- { transform: [{ translateY: slideAnim }] }
1912
- ]
2197
+ style: styles5.keyboardView,
2198
+ behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
2199
+ keyboardVerticalOffset: 0
1913
2200
  },
1914
- /* @__PURE__ */ React7__namespace.default.createElement(
1915
- reactNative.KeyboardAvoidingView,
1916
- {
1917
- style: styles3.keyboardView,
1918
- behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
1919
- keyboardVerticalOffset: 0
1920
- },
1921
- chatSurface
1922
- )
2201
+ chatSurface
1923
2202
  )
1924
- ));
2203
+ )));
1925
2204
  }
1926
- 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 },
1927
2239
  fab: {
1928
2240
  position: "absolute",
1929
2241
  width: 56,
@@ -1966,6 +2278,12 @@ var styles3 = reactNative.StyleSheet.create({
1966
2278
  flexDirection: "row",
1967
2279
  justifyContent: "flex-end"
1968
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
+ },
1969
2287
  keyboardView: {
1970
2288
  flex: 1,
1971
2289
  justifyContent: "flex-end"
@@ -2230,6 +2548,11 @@ function ConfirmDialog(_props = {}) {
2230
2548
  return null;
2231
2549
  }
2232
2550
 
2551
+ // src/auto/appilotsListTotal.ts
2552
+ function appilotsListTotal(total) {
2553
+ return { appilotsTotalItemCount: total };
2554
+ }
2555
+
2233
2556
  // src/hoc/canHoldRef.ts
2234
2557
  var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
2235
2558
  var MEMO = /* @__PURE__ */ Symbol.for("react.memo");
@@ -2256,12 +2579,19 @@ function canHoldRef(type) {
2256
2579
  }
2257
2580
  }
2258
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
+
2259
2589
  // src/hoc/createAppilotsInput.tsx
2260
2590
  function normalizeId(label) {
2261
2591
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2262
2592
  }
2263
2593
  function createAppilotsInput(WrappedComponent) {
2264
- const AppilotsInput = React7__namespace.default.forwardRef((props, ref) => {
2594
+ const AppilotsInput = React8__namespace.default.forwardRef((props, ref) => {
2265
2595
  const {
2266
2596
  appilotsId,
2267
2597
  appilotsScreen,
@@ -2273,17 +2603,17 @@ function createAppilotsInput(WrappedComponent) {
2273
2603
  ...rest
2274
2604
  } = props;
2275
2605
  const fieldId = appilotsId || (label ? normalizeId(label) : null);
2276
- const valueRef = React7.useRef(value ?? "");
2277
- const onChangeRef = React7.useRef(onChangeText);
2278
- const innerRef = React7.useRef(null);
2606
+ const valueRef = React8.useRef(value ?? "");
2607
+ const onChangeRef = React8.useRef(onChangeText);
2608
+ const innerRef = React8.useRef(null);
2279
2609
  valueRef.current = value ?? "";
2280
2610
  onChangeRef.current = onChangeText;
2281
- const getValue = React7.useCallback(() => valueRef.current, []);
2282
- const setValue = React7.useCallback((v) => onChangeRef.current?.(v), []);
2283
- 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(() => {
2284
2614
  innerRef.current?.focus?.();
2285
2615
  }, []);
2286
- React7.useEffect(() => {
2616
+ React8.useEffect(() => {
2287
2617
  if (!fieldId || !appilotsEnabled) return;
2288
2618
  const entry = {
2289
2619
  kind: "field",
@@ -2294,9 +2624,9 @@ function createAppilotsInput(WrappedComponent) {
2294
2624
  label: label ?? fieldId,
2295
2625
  screen: appilotsScreen
2296
2626
  };
2297
- chunkSUMIABJK_js.componentRegistry.register(fieldId, entry);
2627
+ chunkUZ2D4BVX_js.componentRegistry.register(fieldId, entry);
2298
2628
  return () => {
2299
- chunkSUMIABJK_js.componentRegistry.unregister(fieldId);
2629
+ chunkUZ2D4BVX_js.componentRegistry.unregister(fieldId);
2300
2630
  };
2301
2631
  }, [
2302
2632
  fieldId,
@@ -2308,7 +2638,7 @@ function createAppilotsInput(WrappedComponent) {
2308
2638
  label,
2309
2639
  appilotsScreen
2310
2640
  ]);
2311
- const mergedRef = React7.useCallback(
2641
+ const mergedRef = React8.useCallback(
2312
2642
  (instance) => {
2313
2643
  innerRef.current = instance;
2314
2644
  if (typeof ref === "function") ref(instance);
@@ -2316,10 +2646,14 @@ function createAppilotsInput(WrappedComponent) {
2316
2646
  },
2317
2647
  [ref]
2318
2648
  );
2319
- return /* @__PURE__ */ React7__namespace.default.createElement(
2649
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2320
2650
  WrappedComponent,
2321
2651
  {
2322
- ...{ label, value, onChangeText, ...rest },
2652
+ ...withDeclaredIdentity(
2653
+ { label, value, onChangeText, ...rest },
2654
+ fieldId,
2655
+ appilotsEnabled
2656
+ ),
2323
2657
  ...canHoldRef(WrappedComponent) ? { ref: mergedRef } : {}
2324
2658
  }
2325
2659
  );
@@ -2331,7 +2665,7 @@ function normalizeId2(label) {
2331
2665
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2332
2666
  }
2333
2667
  function createAppilotsButton(WrappedComponent) {
2334
- const AppilotsButton = React7__namespace.default.forwardRef((props, ref) => {
2668
+ const AppilotsButton = React8__namespace.default.forwardRef((props, ref) => {
2335
2669
  const {
2336
2670
  appilotsId,
2337
2671
  appilotsScreen,
@@ -2341,10 +2675,10 @@ function createAppilotsButton(WrappedComponent) {
2341
2675
  ...rest
2342
2676
  } = props;
2343
2677
  const targetId = appilotsId || (title ? normalizeId2(title) : null);
2344
- const onPressRef = React7.useRef(onPress);
2678
+ const onPressRef = React8.useRef(onPress);
2345
2679
  onPressRef.current = onPress;
2346
- const press = React7.useCallback(() => onPressRef.current?.(), []);
2347
- React7.useEffect(() => {
2680
+ const press = React8.useCallback(() => onPressRef.current?.(), []);
2681
+ React8.useEffect(() => {
2348
2682
  if (!targetId || !appilotsEnabled) return;
2349
2683
  const entry = {
2350
2684
  kind: "target",
@@ -2352,15 +2686,15 @@ function createAppilotsButton(WrappedComponent) {
2352
2686
  label: title ?? targetId,
2353
2687
  screen: appilotsScreen
2354
2688
  };
2355
- chunkSUMIABJK_js.componentRegistry.register(targetId, entry);
2689
+ chunkUZ2D4BVX_js.componentRegistry.register(targetId, entry);
2356
2690
  return () => {
2357
- chunkSUMIABJK_js.componentRegistry.unregister(targetId);
2691
+ chunkUZ2D4BVX_js.componentRegistry.unregister(targetId);
2358
2692
  };
2359
2693
  }, [targetId, appilotsEnabled, press, title, appilotsScreen]);
2360
- return /* @__PURE__ */ React7__namespace.default.createElement(
2694
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2361
2695
  WrappedComponent,
2362
2696
  {
2363
- ...{ title, onPress, ...rest },
2697
+ ...withDeclaredIdentity({ title, onPress, ...rest }, targetId, appilotsEnabled),
2364
2698
  ...canHoldRef(WrappedComponent) ? { ref } : {}
2365
2699
  }
2366
2700
  );
@@ -2372,7 +2706,7 @@ function normalizeId3(label) {
2372
2706
  return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase());
2373
2707
  }
2374
2708
  function createAppilotsSwitch(WrappedComponent) {
2375
- const AppilotsSwitch = React7__namespace.default.forwardRef((props, ref) => {
2709
+ const AppilotsSwitch = React8__namespace.default.forwardRef((props, ref) => {
2376
2710
  const {
2377
2711
  appilotsId,
2378
2712
  appilotsScreen,
@@ -2383,13 +2717,13 @@ function createAppilotsSwitch(WrappedComponent) {
2383
2717
  ...rest
2384
2718
  } = props;
2385
2719
  const toggleId = appilotsId || (label ? normalizeId3(label) : null);
2386
- const valueRef = React7.useRef(value ?? false);
2387
- const onChangeRef = React7.useRef(onValueChange);
2720
+ const valueRef = React8.useRef(value ?? false);
2721
+ const onChangeRef = React8.useRef(onValueChange);
2388
2722
  valueRef.current = value ?? false;
2389
2723
  onChangeRef.current = onValueChange;
2390
- const getValue = React7.useCallback(() => valueRef.current, []);
2391
- const setValue = React7.useCallback((v) => onChangeRef.current?.(v), []);
2392
- React7.useEffect(() => {
2724
+ const getValue = React8.useCallback(() => valueRef.current, []);
2725
+ const setValue = React8.useCallback((v) => onChangeRef.current?.(v), []);
2726
+ React8.useEffect(() => {
2393
2727
  if (!toggleId || !appilotsEnabled) return;
2394
2728
  const entry = {
2395
2729
  kind: "toggle",
@@ -2398,15 +2732,19 @@ function createAppilotsSwitch(WrappedComponent) {
2398
2732
  label: label ?? toggleId,
2399
2733
  screen: appilotsScreen
2400
2734
  };
2401
- chunkSUMIABJK_js.componentRegistry.register(toggleId, entry);
2735
+ chunkUZ2D4BVX_js.componentRegistry.register(toggleId, entry);
2402
2736
  return () => {
2403
- chunkSUMIABJK_js.componentRegistry.unregister(toggleId);
2737
+ chunkUZ2D4BVX_js.componentRegistry.unregister(toggleId);
2404
2738
  };
2405
2739
  }, [toggleId, appilotsEnabled, getValue, setValue, label, appilotsScreen]);
2406
- return /* @__PURE__ */ React7__namespace.default.createElement(
2740
+ return /* @__PURE__ */ React8__namespace.default.createElement(
2407
2741
  WrappedComponent,
2408
2742
  {
2409
- ...{ label, value, onValueChange, ...rest },
2743
+ ...withDeclaredIdentity(
2744
+ { label, value, onValueChange, ...rest },
2745
+ toggleId,
2746
+ appilotsEnabled
2747
+ ),
2410
2748
  ...canHoldRef(WrappedComponent) ? { ref } : {}
2411
2749
  }
2412
2750
  );
@@ -2417,193 +2755,252 @@ function createAppilotsSwitch(WrappedComponent) {
2417
2755
 
2418
2756
  Object.defineProperty(exports, "AppilotsNavigationContainer", {
2419
2757
  enumerable: true,
2420
- get: function () { return chunk5UVMNKPT_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; }
2421
2771
  });
2422
2772
  Object.defineProperty(exports, "appilotsSelfCheck", {
2423
2773
  enumerable: true,
2424
- get: function () { return chunkUFMTRGML_js.appilotsSelfCheck; }
2774
+ get: function () { return chunkAJDHZRBN_js.appilotsSelfCheck; }
2425
2775
  });
2426
2776
  Object.defineProperty(exports, "captureSnapshot", {
2427
2777
  enumerable: true,
2428
- get: function () { return chunkUFMTRGML_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; }
2429
2783
  });
2430
2784
  Object.defineProperty(exports, "executeAction", {
2431
2785
  enumerable: true,
2432
- get: function () { return chunkUFMTRGML_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; }
2433
2819
  });
2434
2820
  Object.defineProperty(exports, "useAppilots", {
2435
2821
  enumerable: true,
2436
- get: function () { return chunkUFMTRGML_js.useAppilots; }
2822
+ get: function () { return chunkAJDHZRBN_js.useAppilots; }
2437
2823
  });
2438
2824
  Object.defineProperty(exports, "useAppilotsActions", {
2439
2825
  enumerable: true,
2440
- get: function () { return chunkUFMTRGML_js.useAppilotsActions; }
2826
+ get: function () { return chunkAJDHZRBN_js.useAppilotsActions; }
2441
2827
  });
2442
2828
  Object.defineProperty(exports, "useAppilotsChat", {
2443
2829
  enumerable: true,
2444
- get: function () { return chunkUFMTRGML_js.useAppilotsChat; }
2830
+ get: function () { return chunkAJDHZRBN_js.useAppilotsChat; }
2445
2831
  });
2446
2832
  Object.defineProperty(exports, "useAppilotsField", {
2447
2833
  enumerable: true,
2448
- get: function () { return chunkUFMTRGML_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; }
2449
2839
  });
2450
2840
  Object.defineProperty(exports, "useAppilotsNavigation", {
2451
2841
  enumerable: true,
2452
- get: function () { return chunkUFMTRGML_js.useAppilotsNavigation; }
2842
+ get: function () { return chunkAJDHZRBN_js.useAppilotsNavigation; }
2453
2843
  });
2454
2844
  Object.defineProperty(exports, "useAppilotsSlider", {
2455
2845
  enumerable: true,
2456
- get: function () { return chunkUFMTRGML_js.useAppilotsSlider; }
2846
+ get: function () { return chunkAJDHZRBN_js.useAppilotsSlider; }
2457
2847
  });
2458
2848
  Object.defineProperty(exports, "useAppilotsTarget", {
2459
2849
  enumerable: true,
2460
- get: function () { return chunkUFMTRGML_js.useAppilotsTarget; }
2850
+ get: function () { return chunkAJDHZRBN_js.useAppilotsTarget; }
2461
2851
  });
2462
2852
  Object.defineProperty(exports, "useAppilotsToggle", {
2463
2853
  enumerable: true,
2464
- get: function () { return chunkUFMTRGML_js.useAppilotsToggle; }
2854
+ get: function () { return chunkAJDHZRBN_js.useAppilotsToggle; }
2465
2855
  });
2466
2856
  Object.defineProperty(exports, "useSuggestedPrompts", {
2467
2857
  enumerable: true,
2468
- get: function () { return chunkUFMTRGML_js.useSuggestedPrompts; }
2858
+ get: function () { return chunkAJDHZRBN_js.useSuggestedPrompts; }
2469
2859
  });
2470
2860
  Object.defineProperty(exports, "AppilotsClient", {
2471
2861
  enumerable: true,
2472
- get: function () { return chunkSUMIABJK_js.AppilotsClient; }
2862
+ get: function () { return chunkUZ2D4BVX_js.AppilotsClient; }
2473
2863
  });
2474
2864
  Object.defineProperty(exports, "AppilotsProvider", {
2475
2865
  enumerable: true,
2476
- get: function () { return chunkSUMIABJK_js.AppilotsProvider; }
2866
+ get: function () { return chunkUZ2D4BVX_js.AppilotsProvider; }
2477
2867
  });
2478
2868
  Object.defineProperty(exports, "AppilotsRegistryProvider", {
2479
2869
  enumerable: true,
2480
- get: function () { return chunkSUMIABJK_js.AppilotsRegistryProvider; }
2870
+ get: function () { return chunkUZ2D4BVX_js.AppilotsRegistryProvider; }
2481
2871
  });
2482
2872
  Object.defineProperty(exports, "RateLimitedError", {
2483
2873
  enumerable: true,
2484
- get: function () { return chunkSUMIABJK_js.RateLimitedError; }
2874
+ get: function () { return chunkUZ2D4BVX_js.RateLimitedError; }
2485
2875
  });
2486
2876
  Object.defineProperty(exports, "SDK_VERSION", {
2487
2877
  enumerable: true,
2488
- get: function () { return chunkSUMIABJK_js.SDK_VERSION; }
2878
+ get: function () { return chunkUZ2D4BVX_js.SDK_VERSION; }
2489
2879
  });
2490
2880
  Object.defineProperty(exports, "_patchJsxRuntimes", {
2491
2881
  enumerable: true,
2492
- get: function () { return chunkSUMIABJK_js._patchJsxRuntimes; }
2882
+ get: function () { return chunkUZ2D4BVX_js._patchJsxRuntimes; }
2493
2883
  });
2494
2884
  Object.defineProperty(exports, "clearAppilotsDebugTraces", {
2495
2885
  enumerable: true,
2496
- get: function () { return chunkSUMIABJK_js.clearAppilotsDebugTraces; }
2886
+ get: function () { return chunkUZ2D4BVX_js.clearAppilotsDebugTraces; }
2497
2887
  });
2498
2888
  Object.defineProperty(exports, "componentRegistry", {
2499
2889
  enumerable: true,
2500
- get: function () { return chunkSUMIABJK_js.componentRegistry; }
2890
+ get: function () { return chunkUZ2D4BVX_js.componentRegistry; }
2501
2891
  });
2502
2892
  Object.defineProperty(exports, "createComponentRegistry", {
2503
2893
  enumerable: true,
2504
- get: function () { return chunkSUMIABJK_js.createComponentRegistry; }
2894
+ get: function () { return chunkUZ2D4BVX_js.createComponentRegistry; }
2505
2895
  });
2506
2896
  Object.defineProperty(exports, "createElementRegistry", {
2507
2897
  enumerable: true,
2508
- get: function () { return chunkSUMIABJK_js.createElementRegistry; }
2898
+ get: function () { return chunkUZ2D4BVX_js.createElementRegistry; }
2509
2899
  });
2510
2900
  Object.defineProperty(exports, "createListRegistry", {
2511
2901
  enumerable: true,
2512
- get: function () { return chunkSUMIABJK_js.createListRegistry; }
2902
+ get: function () { return chunkUZ2D4BVX_js.createListRegistry; }
2513
2903
  });
2514
2904
  Object.defineProperty(exports, "defaultDarkTheme", {
2515
2905
  enumerable: true,
2516
- get: function () { return chunkSUMIABJK_js.defaultDarkTheme; }
2906
+ get: function () { return chunkUZ2D4BVX_js.defaultDarkTheme; }
2517
2907
  });
2518
2908
  Object.defineProperty(exports, "defaultLightTheme", {
2519
2909
  enumerable: true,
2520
- get: function () { return chunkSUMIABJK_js.defaultLightTheme; }
2910
+ get: function () { return chunkUZ2D4BVX_js.defaultLightTheme; }
2521
2911
  });
2522
2912
  Object.defineProperty(exports, "describeAction", {
2523
2913
  enumerable: true,
2524
- get: function () { return chunkSUMIABJK_js.describeAction; }
2914
+ get: function () { return chunkUZ2D4BVX_js.describeAction; }
2525
2915
  });
2526
2916
  Object.defineProperty(exports, "elementRegistry", {
2527
2917
  enumerable: true,
2528
- get: function () { return chunkSUMIABJK_js.elementRegistry; }
2918
+ get: function () { return chunkUZ2D4BVX_js.elementRegistry; }
2529
2919
  });
2530
2920
  Object.defineProperty(exports, "enableAppilotsAutoTracking", {
2531
2921
  enumerable: true,
2532
- get: function () { return chunkSUMIABJK_js.enableAppilotsAutoTracking; }
2922
+ get: function () { return chunkUZ2D4BVX_js.enableAppilotsAutoTracking; }
2533
2923
  });
2534
2924
  Object.defineProperty(exports, "getAppilotsDebugTraces", {
2535
2925
  enumerable: true,
2536
- get: function () { return chunkSUMIABJK_js.getAppilotsDebugTraces; }
2926
+ get: function () { return chunkUZ2D4BVX_js.getAppilotsDebugTraces; }
2537
2927
  });
2538
2928
  Object.defineProperty(exports, "getAutoTrackingState", {
2539
2929
  enumerable: true,
2540
- get: function () { return chunkSUMIABJK_js.getAutoTrackingState; }
2930
+ get: function () { return chunkUZ2D4BVX_js.getAutoTrackingState; }
2541
2931
  });
2542
2932
  Object.defineProperty(exports, "getGlobalConfig", {
2543
2933
  enumerable: true,
2544
- get: function () { return chunkSUMIABJK_js.getGlobalConfig; }
2934
+ get: function () { return chunkUZ2D4BVX_js.getGlobalConfig; }
2545
2935
  });
2546
2936
  Object.defineProperty(exports, "getIntrospectionDiagnostics", {
2547
2937
  enumerable: true,
2548
- get: function () { return chunkSUMIABJK_js.getIntrospectionDiagnostics; }
2938
+ get: function () { return chunkUZ2D4BVX_js.getIntrospectionDiagnostics; }
2549
2939
  });
2550
2940
  Object.defineProperty(exports, "humanizeError", {
2551
2941
  enumerable: true,
2552
- get: function () { return chunkSUMIABJK_js.humanizeError; }
2942
+ get: function () { return chunkUZ2D4BVX_js.humanizeError; }
2553
2943
  });
2554
2944
  Object.defineProperty(exports, "initAppilots", {
2555
2945
  enumerable: true,
2556
- get: function () { return chunkSUMIABJK_js.initAppilots; }
2946
+ get: function () { return chunkUZ2D4BVX_js.initAppilots; }
2557
2947
  });
2558
2948
  Object.defineProperty(exports, "isAutoTrackingEnabled", {
2559
2949
  enumerable: true,
2560
- get: function () { return chunkSUMIABJK_js.isAutoTrackingEnabled; }
2950
+ get: function () { return chunkUZ2D4BVX_js.isAutoTrackingEnabled; }
2561
2951
  });
2562
2952
  Object.defineProperty(exports, "listRegistry", {
2563
2953
  enumerable: true,
2564
- get: function () { return chunkSUMIABJK_js.listRegistry; }
2954
+ get: function () { return chunkUZ2D4BVX_js.listRegistry; }
2565
2955
  });
2566
2956
  Object.defineProperty(exports, "mergeThemeTokens", {
2567
2957
  enumerable: true,
2568
- get: function () { return chunkSUMIABJK_js.mergeThemeTokens; }
2958
+ get: function () { return chunkUZ2D4BVX_js.mergeThemeTokens; }
2569
2959
  });
2570
2960
  Object.defineProperty(exports, "recordAppilotsDebugTrace", {
2571
2961
  enumerable: true,
2572
- get: function () { return chunkSUMIABJK_js.recordAppilotsDebugTrace; }
2962
+ get: function () { return chunkUZ2D4BVX_js.recordAppilotsDebugTrace; }
2573
2963
  });
2574
2964
  Object.defineProperty(exports, "registerScreen", {
2575
2965
  enumerable: true,
2576
- get: function () { return chunkSUMIABJK_js.registerScreen; }
2966
+ get: function () { return chunkUZ2D4BVX_js.registerScreen; }
2577
2967
  });
2578
2968
  Object.defineProperty(exports, "setCurrentScreen", {
2579
2969
  enumerable: true,
2580
- get: function () { return chunkSUMIABJK_js.setCurrentScreen; }
2970
+ get: function () { return chunkUZ2D4BVX_js.setCurrentScreen; }
2581
2971
  });
2582
2972
  Object.defineProperty(exports, "subscribeAppilotsDebugTraces", {
2583
2973
  enumerable: true,
2584
- get: function () { return chunkSUMIABJK_js.subscribeAppilotsDebugTraces; }
2974
+ get: function () { return chunkUZ2D4BVX_js.subscribeAppilotsDebugTraces; }
2585
2975
  });
2586
2976
  Object.defineProperty(exports, "useAppilotsContext", {
2587
2977
  enumerable: true,
2588
- get: function () { return chunkSUMIABJK_js.useAppilotsContext; }
2978
+ get: function () { return chunkUZ2D4BVX_js.useAppilotsContext; }
2589
2979
  });
2590
2980
  Object.defineProperty(exports, "useResolvedRegistry", {
2591
2981
  enumerable: true,
2592
- get: function () { return chunkSUMIABJK_js.useResolvedRegistry; }
2982
+ get: function () { return chunkUZ2D4BVX_js.useResolvedRegistry; }
2593
2983
  });
2594
2984
  exports.ActionBreadcrumb = ActionBreadcrumb;
2985
+ exports.AgentPill = AgentPill;
2595
2986
  exports.AppilotsChat = AppilotsChat;
2596
- exports.AppilotsI18nProvider = AppilotsI18nProvider;
2597
2987
  exports.AppilotsThemeProvider = AppilotsThemeProvider;
2598
2988
  exports.ChatIcon = ChatIcon;
2599
2989
  exports.ConfirmDialog = ConfirmDialog;
2990
+ exports.DEFAULT_EXPERIENCE = DEFAULT_EXPERIENCE;
2600
2991
  exports.HeadsetIcon = HeadsetIcon;
2992
+ exports.SpotlightOverlay = SpotlightOverlay;
2993
+ exports.appilotsListTotal = appilotsListTotal;
2601
2994
  exports.appilotsTheme = appilotsTheme;
2602
2995
  exports.appilotsThemeFromTailwind = appilotsThemeFromTailwind;
2603
2996
  exports.createAppilotsButton = createAppilotsButton;
2604
2997
  exports.createAppilotsInput = createAppilotsInput;
2605
2998
  exports.createAppilotsSwitch = createAppilotsSwitch;
2606
- exports.detectDeviceLocale = detectDeviceLocale;
2607
- exports.resolveLocale = resolveLocale;
2608
- exports.useAppilotsI18n = useAppilotsI18n;
2999
+ exports.formatDowngrades = formatDowngrades;
3000
+ exports.resolveExperience = resolveExperience;
3001
+ exports.resolvePillStatus = resolvePillStatus;
3002
+ exports.resolveSurface = resolveSurface;
3003
+ exports.shouldReopenOnTurnEnd = shouldReopenOnTurnEnd;
2609
3004
  exports.useAppilotsTheme = useAppilotsTheme;
3005
+ exports.useSpotlight = useSpotlight;
3006
+ exports.usesPill = usesPill;