@appilots/sdk 0.7.0 → 0.10.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.
@@ -1,660 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunkDZ7QRFHD_js = require('./chunk-DZ7QRFHD.js');
4
- var react = require('react');
3
+ var chunkYB77RYCC_js = require('./chunk-YB77RYCC.js');
4
+ var React = require('react');
5
5
  var reactNative = require('react-native');
6
6
 
7
- // src/introspection/walkFiber.ts
8
- function getTypeName(type) {
9
- if (!type) return null;
10
- if (typeof type === "string") return type;
11
- if (typeof type === "function") {
12
- return type.displayName ?? type.name ?? null;
13
- }
14
- if (typeof type === "object") {
15
- if (type.displayName) return type.displayName;
16
- if (type.render) {
17
- return type.render.displayName ?? type.render.name ?? null;
18
- }
19
- if (type.type) return getTypeName(type.type);
20
- }
21
- return null;
22
- }
23
- function matchesName(fiber, name) {
24
- return getTypeName(fiber.type) === name || getTypeName(fiber.elementType) === name;
25
- }
26
- function extractTextFromChildren(children) {
27
- if (children == null) return "";
28
- if (typeof children === "string") return children;
29
- if (typeof children === "number") return String(children);
30
- if (Array.isArray(children)) {
31
- return children.map((c) => extractTextFromChildren(c)).filter(Boolean).join("");
32
- }
33
- return "";
34
- }
35
- function hasMeaningfulText(text) {
36
- return !!text && /[\p{L}\p{N}]/u.test(text);
37
- }
38
- function findChildText(fiber) {
39
- const stack = [];
40
- if (fiber.child) stack.push(fiber.child);
41
- const visited = /* @__PURE__ */ new WeakSet();
42
- const texts = [];
43
- while (stack.length > 0) {
44
- const node = stack.pop();
45
- if (!node || visited.has(node)) continue;
46
- visited.add(node);
47
- if (matchesName(node, "Text")) {
48
- const text = extractTextFromChildren(node.memoizedProps?.children);
49
- const trimmed = text.trim();
50
- if (hasMeaningfulText(trimmed)) {
51
- texts.push(trimmed);
52
- if (texts.length >= 3) break;
53
- }
54
- }
55
- if (node.sibling) stack.push(node.sibling);
56
- if (node.child) stack.push(node.child);
57
- }
58
- return texts.length > 0 ? texts.join(" \xB7 ") : void 0;
59
- }
60
- var SELF_REFERENTIAL_COMPONENTS = /* @__PURE__ */ new Set([
61
- "AppilotsChat",
62
- "AppilotsChatInner",
63
- "ActionBreadcrumb",
64
- "ConfirmDialog"
65
- ]);
66
- function isAppilotsSkipMarked(props) {
67
- if (!props) return false;
68
- return props.__appilotsSkip === true || props["data-appilots-skip"] === true || props.appilotsSkip === true;
69
- }
70
- function isAppilotsSensitiveMarked(props) {
71
- if (!props) return false;
72
- return props.__appilotsSensitive === true || props["data-appilots-sensitive"] === true || props.appilotsSensitive === true;
73
- }
74
- function stringProp(props, name) {
75
- const value = props?.[name];
76
- return typeof value === "string" && value.length > 0 ? value : void 0;
77
- }
78
- function numberProp(props, name) {
79
- const value = props?.[name];
80
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
81
- }
82
- function shouldSkipSubtree(fiber) {
83
- const props = fiber.memoizedProps;
84
- if (!props) return false;
85
- const typeName = getTypeName(fiber.type) ?? getTypeName(fiber.elementType);
86
- if (typeName && SELF_REFERENTIAL_COMPONENTS.has(typeName)) return true;
87
- if (isAppilotsSkipMarked(props)) return true;
88
- if (matchesName(fiber, "Modal") && props.visible === false) return true;
89
- if (matchesName(fiber, "Screen") && props.activityState === 0) return true;
90
- const style = props.style;
91
- if (style) {
92
- const flat = Array.isArray(style) ? Object.assign({}, ...style.filter(Boolean)) : style;
93
- if (flat?.display === "none") return true;
94
- if (flat?.opacity === 0 && props.pointerEvents === "none") return true;
95
- }
96
- return false;
97
- }
98
- function inferInputType(props) {
99
- if (props.secureTextEntry || isAppilotsSensitiveMarked(props)) return "password";
100
- switch (props.keyboardType) {
101
- case "email-address":
102
- return "email";
103
- case "numeric":
104
- case "number-pad":
105
- case "decimal-pad":
106
- return "number";
107
- case "phone-pad":
108
- return "phone";
109
- default:
110
- return "text";
111
- }
112
- }
113
- function inferLabel(props) {
114
- return props.accessibilityLabel ?? props.label ?? props.placeholder ?? props.testID;
115
- }
116
- function bestId(props) {
117
- return props.testID ?? props.accessibilityLabel ?? void 0;
118
- }
119
- var ALWAYS_LIST_NAMES = /* @__PURE__ */ new Set([
120
- "FlatList",
121
- "SectionList",
122
- "VirtualizedList",
123
- // Shopify's high-perf FlatList replacement — same usage shape, same
124
- // virtualization, same per-item key.
125
- "FlashList"
126
- ]);
127
- var HEURISTIC_LIST_NAMES = /* @__PURE__ */ new Set(["ScrollView"]);
128
- var LIST_CELL_NAMES = /* @__PURE__ */ new Set([
129
- "CellRenderer",
130
- "CellRendererComponent",
131
- "VirtualizedListCellContextProvider"
132
- ]);
133
- function isAlwaysListContainer(fiber) {
134
- for (const name of ALWAYS_LIST_NAMES) {
135
- if (matchesName(fiber, name)) return true;
136
- }
137
- return false;
138
- }
139
- function isHeuristicListContainer(fiber) {
140
- for (const name of HEURISTIC_LIST_NAMES) {
141
- if (matchesName(fiber, name)) return true;
142
- }
143
- return false;
144
- }
145
- function isKnownListCell(fiber) {
146
- const typeName = getTypeName(fiber.type) ?? getTypeName(fiber.elementType);
147
- return !!typeName && LIST_CELL_NAMES.has(typeName);
148
- }
149
- function isModalFiber(fiber) {
150
- return matchesName(fiber, "Modal");
151
- }
152
- function isVisibleModalFiber(fiber) {
153
- return isModalFiber(fiber) && fiber?.memoizedProps?.visible !== false;
154
- }
155
- function collectVisibleModalFibers(container, excludeRoots = []) {
156
- const excluded = /* @__PURE__ */ new WeakSet();
157
- for (const rootFiber of excludeRoots) {
158
- if (rootFiber) excluded.add(rootFiber);
159
- }
160
- const found = [];
161
- const visited = /* @__PURE__ */ new WeakSet();
162
- const stack = [];
163
- if (container?.child) stack.push(container.child);
164
- while (stack.length > 0) {
165
- const node = stack.pop();
166
- if (!node || visited.has(node)) continue;
167
- visited.add(node);
168
- if (node.sibling) stack.push(node.sibling);
169
- if (excluded.has(node) || shouldSkipSubtree(node)) continue;
170
- if (isVisibleModalFiber(node)) {
171
- found.push(node);
172
- continue;
173
- }
174
- if (node.child) stack.push(node.child);
175
- }
176
- return found;
177
- }
178
- function isMarkedListItem(fiber, listId) {
179
- const props = fiber?.memoizedProps;
180
- if (!props || props.__appilotsListItem !== true) return false;
181
- if (!listId) return true;
182
- return props.__appilotsListId === listId;
183
- }
184
- function listIdFromProps(props) {
185
- return stringProp(props, "__appilotsListId") ?? stringProp(props, "appilotsListId");
186
- }
187
- function listMetadataFromProps(props) {
188
- const id = listIdFromProps(props);
189
- const itemCount = numberProp(props, "__appilotsItemCount");
190
- const label = stringProp(props, "__appilotsListLabel") ?? stringProp(props, "accessibilityLabel") ?? stringProp(props, "testID");
191
- const refreshing = props?.refreshing === true || props?.__appilotsRefreshing === true;
192
- const empty = props?.__appilotsEmpty === true || typeof itemCount === "number" && itemCount === 0;
193
- return {
194
- id,
195
- itemCount,
196
- refreshing,
197
- empty,
198
- label,
199
- source: id ? "auto-tracked" : void 0
200
- };
201
- }
202
- function hasRenderableContent(fiber) {
203
- const stack = [fiber];
204
- const visited = /* @__PURE__ */ new WeakSet();
205
- while (stack.length > 0) {
206
- const node = stack.pop();
207
- if (!node || visited.has(node)) continue;
208
- visited.add(node);
209
- if (shouldSkipSubtree(node) || isModalFiber(node)) continue;
210
- const props = node.memoizedProps ?? {};
211
- if (matchesName(node, "Text")) {
212
- const text = extractTextFromChildren(props.children);
213
- if (text && text.trim().length > 0) return true;
214
- }
215
- if (matchesName(node, "TextInput") || matchesName(node, "Switch")) {
216
- return true;
217
- }
218
- if (TOUCHABLE_NAMES.has(getTypeName(node.type) ?? "") || TOUCHABLE_NAMES.has(getTypeName(node.elementType) ?? "")) {
219
- return true;
220
- }
221
- if (node.sibling) stack.push(node.sibling);
222
- if (node.child) stack.push(node.child);
223
- }
224
- return false;
225
- }
226
- function findListCellsByType(container, minItems) {
227
- const cells = [];
228
- const visited = /* @__PURE__ */ new WeakSet();
229
- const stack = [];
230
- if (container?.child) stack.push(container.child);
231
- while (stack.length > 0) {
232
- const node = stack.pop();
233
- if (!node || visited.has(node)) continue;
234
- visited.add(node);
235
- if (node.sibling) stack.push(node.sibling);
236
- if (shouldSkipSubtree(node) || isModalFiber(node)) continue;
237
- if (isKnownListCell(node) && hasRenderableContent(node)) {
238
- cells.push(node);
239
- continue;
240
- }
241
- if (node.child) stack.push(node.child);
242
- }
243
- return cells.length >= minItems ? cells : null;
244
- }
245
- function findMarkedListItems(container, minItems, listId) {
246
- const items = [];
247
- const visited = /* @__PURE__ */ new WeakSet();
248
- const stack = [];
249
- if (container?.child) stack.push(container.child);
250
- while (stack.length > 0) {
251
- const node = stack.pop();
252
- if (!node || visited.has(node)) continue;
253
- visited.add(node);
254
- if (node.sibling) stack.push(node.sibling);
255
- if (shouldSkipSubtree(node) || isModalFiber(node)) continue;
256
- if (isMarkedListItem(node, listId)) {
257
- items.push(node);
258
- continue;
259
- }
260
- if (node.child) stack.push(node.child);
261
- }
262
- if (items.length < minItems) return null;
263
- items.sort((a, b) => {
264
- const ai = numberProp(a.memoizedProps, "__appilotsItemIndex");
265
- const bi = numberProp(b.memoizedProps, "__appilotsItemIndex");
266
- if (ai === void 0 && bi === void 0) return 0;
267
- if (ai === void 0) return 1;
268
- if (bi === void 0) return -1;
269
- return ai - bi;
270
- });
271
- return items;
272
- }
273
- function hasAuthoredReactKey(fiber) {
274
- const key = fiber?.key;
275
- if (key === null || key === void 0 || key === "") return false;
276
- const s = String(key);
277
- if (s.startsWith(".") && !s.startsWith(".$")) return false;
278
- return true;
279
- }
280
- function findKeyedSiblingItems(container, minItems) {
281
- if (!container) return null;
282
- let current = container;
283
- const visited = /* @__PURE__ */ new WeakSet();
284
- while (current && !visited.has(current)) {
285
- visited.add(current);
286
- const siblings = [];
287
- let cur = current.child;
288
- while (cur) {
289
- if (!isModalFiber(cur)) siblings.push(cur);
290
- cur = cur.sibling;
291
- }
292
- if (siblings.length === 0) return null;
293
- const keyed = siblings.filter(hasAuthoredReactKey);
294
- if (keyed.length >= minItems) {
295
- return keyed;
296
- }
297
- if (siblings.length > 1) {
298
- return null;
299
- }
300
- current = siblings[0];
301
- }
302
- return null;
303
- }
304
- function findListItems(container, minItems = 2, preferCells = false) {
305
- if (!container) return null;
306
- const listId = listIdFromProps(container.memoizedProps);
307
- const markedItems = findMarkedListItems(container, minItems, listId);
308
- if (markedItems) return markedItems;
309
- if (preferCells) {
310
- const cells = findListCellsByType(container, minItems);
311
- if (cells) return cells;
312
- }
313
- if (minItems <= 1) {
314
- const multiItemLevel = findKeyedSiblingItems(container, 2);
315
- if (multiItemLevel) return multiItemLevel;
316
- }
317
- return findKeyedSiblingItems(container, minItems) ?? findListCellsByType(container, minItems);
318
- }
319
- var TOUCHABLE_NAMES = /* @__PURE__ */ new Set([
320
- "TouchableOpacity",
321
- "TouchableHighlight",
322
- "TouchableWithoutFeedback",
323
- "TouchableNativeFeedback",
324
- "Pressable"
325
- ]);
326
- function hasPressHandler(fiber) {
327
- const props = fiber?.memoizedProps ?? {};
328
- return typeof props.onPress === "function" || typeof props.onPressIn === "function";
329
- }
330
- function isPressableTarget(fiber) {
331
- return TOUCHABLE_NAMES.has(getTypeName(fiber.type) ?? "") || TOUCHABLE_NAMES.has(getTypeName(fiber.elementType) ?? "") || hasPressHandler(fiber);
332
- }
333
- function walkSubtree(root, detectLists, startInModal = false) {
334
- const result = {
335
- texts: [],
336
- inputs: [],
337
- buttons: [],
338
- toggles: [],
339
- sliders: [],
340
- visitedFibers: 0,
341
- skippedHidden: 0,
342
- loading: false,
343
- modalOpen: false,
344
- lists: []
345
- };
346
- if (!root) return result;
347
- const visited = /* @__PURE__ */ new WeakSet();
348
- const stack = [];
349
- if (root.child) stack.push({ fiber: root.child, inModal: startInModal });
350
- while (stack.length > 0) {
351
- const { fiber, inModal } = stack.pop();
352
- if (!fiber || visited.has(fiber)) continue;
353
- visited.add(fiber);
354
- result.visitedFibers++;
355
- if (fiber.sibling) stack.push({ fiber: fiber.sibling, inModal });
356
- if (shouldSkipSubtree(fiber)) {
357
- result.skippedHidden++;
358
- continue;
359
- }
360
- if (detectLists) {
361
- const isAlways = isAlwaysListContainer(fiber);
362
- const isHeuristic = !isAlways && isHeuristicListContainer(fiber);
363
- if (isAlways || isHeuristic) {
364
- const minItems = isAlways ? 1 : 2;
365
- const items = findListItems(fiber, minItems, isAlways);
366
- if (items && items.length >= minItems) {
367
- const containerType = getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "List";
368
- const listIndex = result.lists.length;
369
- const itemSnapshots = items.map((itemFiber, i) => {
370
- const itemResult = walkSubtree(itemFiber, false, inModal);
371
- result.visitedFibers += itemResult.visitedFibers;
372
- result.skippedHidden += itemResult.skippedHidden;
373
- if (itemResult.loading) result.loading = true;
374
- if (itemResult.modalOpen) result.modalOpen = true;
375
- const reactKey = typeof itemFiber.key === "string" || typeof itemFiber.key === "number" ? String(itemFiber.key) : typeof itemFiber.memoizedProps?.__appilotsItemKey === "string" || typeof itemFiber.memoizedProps?.__appilotsItemKey === "number" ? String(itemFiber.memoizedProps.__appilotsItemKey) : void 0;
376
- const itemKey = typeof itemFiber.memoizedProps?.__appilotsItemKey === "string" || typeof itemFiber.memoizedProps?.__appilotsItemKey === "number" ? String(itemFiber.memoizedProps.__appilotsItemKey) : void 0;
377
- const dataIndex = numberProp(itemFiber.memoizedProps, "__appilotsItemIndex");
378
- return {
379
- index: i + 1,
380
- dataIndex,
381
- reactKey,
382
- itemKey,
383
- syntheticId: `list-${listIndex}-item-${i + 1}`,
384
- texts: dedupeStringsInternal(itemResult.texts),
385
- buttons: dedupeButtonsInternal(itemResult.buttons),
386
- inputs: dedupeInputsInternal(itemResult.inputs),
387
- toggles: dedupeTogglesInternal(itemResult.toggles)
388
- };
389
- });
390
- const meta2 = listMetadataFromProps(fiber.memoizedProps);
391
- result.lists.push({
392
- index: listIndex,
393
- id: meta2.id,
394
- containerType,
395
- source: meta2.source ?? "fiber",
396
- itemCount: meta2.itemCount,
397
- visibleItemCount: itemSnapshots.length,
398
- refreshing: meta2.refreshing,
399
- empty: meta2.empty,
400
- label: meta2.label,
401
- items: itemSnapshots
402
- });
403
- for (const modalFiber of collectVisibleModalFibers(fiber, items)) {
404
- result.modalOpen = true;
405
- if (modalFiber.child) stack.push({ fiber: modalFiber.child, inModal: true });
406
- }
407
- continue;
408
- }
409
- const meta = listMetadataFromProps(fiber.memoizedProps);
410
- if (meta.id || meta.itemCount !== void 0 || meta.refreshing || meta.empty) {
411
- const containerType = getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "List";
412
- result.lists.push({
413
- index: result.lists.length,
414
- id: meta.id,
415
- containerType,
416
- source: meta.source ?? "auto-tracked",
417
- itemCount: meta.itemCount,
418
- visibleItemCount: 0,
419
- refreshing: meta.refreshing,
420
- empty: meta.empty,
421
- label: meta.label,
422
- items: []
423
- });
424
- for (const modalFiber of collectVisibleModalFibers(fiber)) {
425
- result.modalOpen = true;
426
- if (modalFiber.child) stack.push({ fiber: modalFiber.child, inModal: true });
427
- }
428
- continue;
429
- }
430
- }
431
- }
432
- const props = fiber.memoizedProps ?? {};
433
- if (matchesName(fiber, "Text")) {
434
- const text = extractTextFromChildren(props.children);
435
- if (text && text.trim().length > 0) {
436
- result.texts.push(text.trim());
437
- }
438
- } else if (matchesName(fiber, "TextInput")) {
439
- if (props.__appilotsInternal !== true) {
440
- const isSecure = !!props.secureTextEntry || isAppilotsSensitiveMarked(props);
441
- const rawValue = typeof props.value === "string" ? props.value : void 0;
442
- const safeValue = isSecure ? rawValue && rawValue.length > 0 ? "<hidden>" : void 0 : rawValue;
443
- result.inputs.push({
444
- id: bestId(props),
445
- label: inferLabel(props),
446
- value: safeValue,
447
- placeholder: props.placeholder,
448
- editable: props.editable !== false,
449
- secure: isSecure,
450
- type: inferInputType(props),
451
- ...inModal ? { inModal: true } : {}
452
- });
453
- }
454
- } else if (props.accessibilityRole === "adjustable") {
455
- if (props.__appilotsInternal !== true) {
456
- const av = props.accessibilityValue ?? {};
457
- result.sliders.push({
458
- id: bestId(props),
459
- label: props.accessibilityLabel ?? props.testID,
460
- value: typeof av.now === "number" ? av.now : void 0,
461
- min: typeof av.min === "number" ? av.min : void 0,
462
- max: typeof av.max === "number" ? av.max : void 0,
463
- ...inModal ? { inModal: true } : {}
464
- });
465
- }
466
- } else if (isPressableTarget(fiber)) {
467
- if (props.__appilotsInternal !== true) {
468
- const label = findChildText(fiber);
469
- const selected = props.accessibilityState?.selected === true;
470
- result.buttons.push({
471
- id: bestId(props) ?? (label ? normalizeLabel(label) : void 0),
472
- label,
473
- disabled: !!props.disabled,
474
- ...selected ? { selected: true } : {},
475
- ...inModal ? { inModal: true } : {}
476
- });
477
- }
478
- } else if (matchesName(fiber, "Switch")) {
479
- result.toggles.push({
480
- id: bestId(props),
481
- label: props.accessibilityLabel ?? props.testID,
482
- value: !!props.value,
483
- ...inModal ? { inModal: true } : {}
484
- });
485
- } else if (matchesName(fiber, "ActivityIndicator")) {
486
- result.loading = true;
487
- } else if (matchesName(fiber, "Modal")) {
488
- result.modalOpen = true;
489
- if (fiber.child) stack.push({ fiber: fiber.child, inModal: true });
490
- continue;
491
- }
492
- if (fiber.child) stack.push({ fiber: fiber.child, inModal });
493
- }
494
- return result;
495
- }
496
- function walkFiber(root) {
497
- const snapshot = {
498
- route: chunkDZ7QRFHD_js.getCurrentScreen(),
499
- texts: [],
500
- inputs: [],
501
- buttons: [],
502
- toggles: [],
503
- // Sliders come from the ComponentRegistry (useAppilotsSlider) —
504
- // captureSnapshot merges them so observation only ever advertises
505
- // sliders the executor can actually set (min/max/step + setValue).
506
- sliders: [],
507
- loading: false,
508
- modalOpen: false,
509
- lists: [],
510
- choiceGroups: [],
511
- elements: [],
512
- stats: { visitedFibers: 0, skippedHidden: 0 }
513
- };
514
- if (!root) return snapshot;
515
- const sub = walkSubtree(root, true);
516
- snapshot.texts = dedupeStringsInternal(sub.texts);
517
- snapshot.inputs = dedupeInputsInternal(sub.inputs);
518
- snapshot.buttons = dedupeButtonsInternal(sub.buttons);
519
- snapshot.toggles = dedupeTogglesInternal(sub.toggles);
520
- snapshot.sliders = dedupeSliders(sub.sliders);
521
- snapshot.loading = sub.loading;
522
- snapshot.modalOpen = sub.modalOpen;
523
- snapshot.lists = sub.lists;
524
- snapshot.choiceGroups = deriveChoiceGroups(snapshot);
525
- snapshot.stats.visitedFibers = sub.visitedFibers;
526
- snapshot.stats.skippedHidden = sub.skippedHidden;
527
- return snapshot;
528
- }
529
- function dedupeButtonsInternal(buttons) {
530
- return dedupeButtons(buttons);
531
- }
532
- function dedupeInputsInternal(inputs) {
533
- return dedupeInputs(inputs);
534
- }
535
- function dedupeTogglesInternal(toggles) {
536
- return dedupeToggles(toggles);
537
- }
538
- function dedupeStringsInternal(strings) {
539
- return dedupeStrings(strings);
540
- }
541
- function isCommandLikeLabel(label) {
542
- if (!label) return true;
543
- const normalized = normalizeLabel(label);
544
- if (!normalized) return true;
545
- return /^(proximo|prox|next|continuar|continue|voltar|back|confirmar|confirm|cancelar|cancel|salvar|save|enviar|submit|ok|limpar|clear|fechar|close|adicionar|add|novo|nova|new)$/i.test(
546
- normalized
547
- );
548
- }
549
- function deriveChoiceGroups(snapshot) {
550
- const groups = [];
551
- for (const list of snapshot.lists) {
552
- const options = list.items.filter((item) => item.texts.length > 0 || item.buttons.length > 0).map((item, i) => {
553
- const texts = item.texts.length > 0 ? item.texts : item.buttons.map((b) => b.label ?? b.id ?? "").filter((text) => text.length > 0);
554
- return {
555
- index: i + 1,
556
- syntheticId: `${list.id ?? `list-${list.index}`}-choice-${i + 1}`,
557
- targetId: item.syntheticId,
558
- label: texts.slice(0, 2).join(" \xB7 "),
559
- texts,
560
- disabled: false
561
- };
562
- });
563
- if (options.length > 0) {
564
- groups.push({
565
- index: groups.length,
566
- id: list.id,
567
- label: list.label,
568
- source: "list",
569
- options
570
- });
571
- }
572
- }
573
- const buttonOptions = snapshot.buttons.filter((button) => !button.disabled).filter((button) => hasMeaningfulText(button.label ?? button.id)).filter((button) => !isCommandLikeLabel(button.label ?? button.id)).map((button, i) => {
574
- const label = button.label ?? button.id ?? "";
575
- return {
576
- index: i + 1,
577
- syntheticId: `choice-buttons-option-${i + 1}`,
578
- targetId: button.id ?? button.label,
579
- label,
580
- texts: [label],
581
- selected: !!button.selected,
582
- disabled: !!button.disabled
583
- };
584
- });
585
- if (buttonOptions.length >= 2) {
586
- groups.push({
587
- index: groups.length,
588
- id: "visible-options",
589
- label: "Visible options",
590
- source: "buttons",
591
- options: buttonOptions
592
- });
593
- }
594
- return groups;
595
- }
596
- function dedupeButtons(buttons) {
597
- const seen = /* @__PURE__ */ new Set();
598
- const out = [];
599
- for (const b of buttons) {
600
- const idTrim = b.id?.trim();
601
- const labelTrim = b.label?.trim();
602
- if (!idTrim && (!labelTrim || !/[a-z0-9]/i.test(labelTrim))) continue;
603
- const key = `${idTrim ?? ""}|${labelTrim ?? ""}|${b.disabled ? 1 : 0}|${b.inModal ? 1 : 0}|${b.selected ? 1 : 0}`;
604
- if (seen.has(key)) continue;
605
- seen.add(key);
606
- out.push(b);
607
- }
608
- return out;
609
- }
610
- function dedupeInputs(inputs) {
611
- const seen = /* @__PURE__ */ new Set();
612
- const out = [];
613
- for (const i of inputs) {
614
- const key = `${i.id ?? ""}|${i.label ?? ""}|${i.placeholder ?? ""}|${i.inModal ? 1 : 0}`;
615
- if (seen.has(key)) continue;
616
- seen.add(key);
617
- out.push(i);
618
- }
619
- return out;
620
- }
621
- function dedupeSliders(sliders) {
622
- const seen = /* @__PURE__ */ new Set();
623
- const out = [];
624
- for (const s of sliders) {
625
- const key = `${s.id ?? ""}|${s.label ?? ""}|${s.inModal ? 1 : 0}`;
626
- if (seen.has(key)) continue;
627
- seen.add(key);
628
- out.push(s);
629
- }
630
- return out;
631
- }
632
- function dedupeToggles(toggles) {
633
- const seen = /* @__PURE__ */ new Set();
634
- const out = [];
635
- for (const t of toggles) {
636
- const key = `${t.id ?? ""}|${t.label ?? ""}|${t.inModal ? 1 : 0}`;
637
- if (seen.has(key)) continue;
638
- seen.add(key);
639
- out.push(t);
640
- }
641
- return out;
642
- }
643
- function dedupeStrings(strings) {
644
- const seen = /* @__PURE__ */ new Set();
645
- const out = [];
646
- for (const s of strings) {
647
- const trimmed = s.trim();
648
- if (!trimmed) continue;
649
- if (seen.has(trimmed)) continue;
650
- seen.add(trimmed);
651
- out.push(trimmed);
652
- }
653
- return out;
654
- }
655
- function normalizeLabel(label) {
656
- return label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s]/g, "").trim().replace(/\s+(.)/g, (_, c) => c.toUpperCase()).replace(/\s+/g, "");
657
- }
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var React__default = /*#__PURE__*/_interopDefault(React);
658
10
 
659
11
  // src/introspection/captureSnapshot.ts
660
12
  function normalizeSliderKey(value) {
@@ -671,9 +23,9 @@ function fiberSliderMatches(fiber, registryId, registryLabel) {
671
23
  function reconcileSliders(snapshot) {
672
24
  const fiberSliders = snapshot.sliders;
673
25
  const out = [];
674
- for (const { id, kind } of chunkDZ7QRFHD_js.componentRegistry.snapshot()) {
26
+ for (const { id, kind } of chunkYB77RYCC_js.componentRegistry.snapshot()) {
675
27
  if (kind !== "slider") continue;
676
- const entry = chunkDZ7QRFHD_js.componentRegistry.getSlider(id);
28
+ const entry = chunkYB77RYCC_js.componentRegistry.getSlider(id);
677
29
  if (!entry) continue;
678
30
  const fiber = fiberSliders.find((s) => fiberSliderMatches(s, id, entry.label));
679
31
  const visible = !!fiber || typeof entry.screen === "string" && entry.screen === snapshot.route;
@@ -696,14 +48,38 @@ function reconcileSliders(snapshot) {
696
48
  }
697
49
  snapshot.sliders = out;
698
50
  }
51
+ function normalizeFieldKey(value) {
52
+ return (value ?? "").toLowerCase().replace(/^(input|field)[-_]/, "");
53
+ }
54
+ function canonicalizeRegisteredFields(snapshot) {
55
+ const claimed = /* @__PURE__ */ new Set();
56
+ for (const { id, kind, label } of chunkYB77RYCC_js.componentRegistry.snapshot()) {
57
+ if (kind !== "field") continue;
58
+ if (snapshot.inputs.some((input) => input.id === id)) continue;
59
+ const registryLabel = (label ?? "").toLowerCase();
60
+ const registryKey = normalizeFieldKey(id);
61
+ const candidates = snapshot.inputs.filter((input) => {
62
+ if (claimed.has(input)) return false;
63
+ const inputLabel = (input.label ?? "").toLowerCase();
64
+ if (registryLabel && inputLabel && inputLabel === registryLabel) return true;
65
+ const inputKey = normalizeFieldKey(input.id);
66
+ return !!inputKey && !!registryKey && inputKey === registryKey;
67
+ });
68
+ if (candidates.length !== 1) continue;
69
+ const match = candidates[0];
70
+ claimed.add(match);
71
+ match.id = id;
72
+ }
73
+ }
699
74
  function mergeRegisteredLists(snapshot) {
700
- const registered = chunkDZ7QRFHD_js.listRegistry.snapshot();
75
+ const registered = chunkYB77RYCC_js.listRegistry.snapshot();
701
76
  if (registered.length === 0) return;
702
77
  const byId = /* @__PURE__ */ new Map();
703
78
  for (const list of snapshot.lists) {
704
79
  if (list.id) byId.set(list.id, list);
705
80
  }
706
81
  for (const entry of registered) {
82
+ if (entry.kind === "scroll") continue;
707
83
  const metrics = entry.getScrollMetrics?.();
708
84
  const scrollFacts = metrics ? {
709
85
  scrollOffsetY: Math.max(0, Math.round(metrics.offset)),
@@ -744,15 +120,70 @@ function mergeRegisteredLists(snapshot) {
744
120
  });
745
121
  }
746
122
  }
123
+ function mergeRegisteredScrollables(snapshot) {
124
+ const registered = chunkYB77RYCC_js.listRegistry.snapshot().filter((e) => e.kind === "scroll");
125
+ if (registered.length === 0) return;
126
+ const listsById = /* @__PURE__ */ new Map();
127
+ for (const list of snapshot.lists) {
128
+ if (list.id) listsById.set(list.id, list);
129
+ }
130
+ const out = [];
131
+ for (const entry of registered) {
132
+ const metrics = entry.getScrollMetrics?.();
133
+ const facts = metrics ? {
134
+ scrollOffsetY: Math.max(0, Math.round(metrics.offset)),
135
+ canScrollUp: metrics.offset > 8,
136
+ canScrollDown: metrics.offset + metrics.visibleLength < metrics.contentLength - 8
137
+ } : void 0;
138
+ const asList = listsById.get(entry.id);
139
+ if (asList) {
140
+ if (facts) {
141
+ asList.scrollOffsetY = asList.scrollOffsetY ?? facts.scrollOffsetY;
142
+ asList.canScrollUp = asList.canScrollUp ?? facts.canScrollUp;
143
+ asList.canScrollDown = asList.canScrollDown ?? facts.canScrollDown;
144
+ }
145
+ continue;
146
+ }
147
+ out.push({
148
+ id: entry.id,
149
+ containerType: entry.component,
150
+ ...entry.label ? { label: entry.label } : {},
151
+ ...facts ?? {}
152
+ });
153
+ }
154
+ if (out.length > 0) snapshot.scrollables = out;
155
+ }
156
+ function mergeNativeDialog(snapshot) {
157
+ const dialog = chunkYB77RYCC_js.getOpenNativeDialog();
158
+ if (!dialog) return;
159
+ snapshot.nativeDialog = {
160
+ id: dialog.id,
161
+ ...dialog.title ? { title: dialog.title } : {},
162
+ ...dialog.message ? { message: dialog.message } : {},
163
+ buttons: dialog.buttons.map((b) => ({
164
+ label: b.label,
165
+ ...b.style ? { style: b.style } : {}
166
+ }))
167
+ };
168
+ snapshot.modalOpen = true;
169
+ }
170
+ var MIN_FIBERS_FOR_BLINDNESS = 200;
171
+ function recordBlindWalk() {
172
+ const walk = chunkYB77RYCC_js.getLastWalkDiagnostics();
173
+ if (!walk) return;
174
+ if (walk.visitedFibers < MIN_FIBERS_FOR_BLINDNESS) return;
175
+ if (chunkYB77RYCC_js.totalDetectorHits(walk.detectors) > 0) return;
176
+ chunkYB77RYCC_js.recordIntrospectionFailure("walk-recognized-nothing", null);
177
+ }
747
178
  function captureSnapshot() {
748
- const root = chunkDZ7QRFHD_js.getFiberRoot();
179
+ const root = chunkYB77RYCC_js.getFiberRoot();
749
180
  if (!root) {
750
- console.warn(
751
- "[Appilots] captureSnapshot: fiber root not captured yet. Ensure <AppilotsProvider> has rendered before calling this."
181
+ chunkYB77RYCC_js.appilotsDebugWarn(
182
+ "captureSnapshot: fiber root not captured yet. Ensure <AppilotsProvider> has rendered before calling this."
752
183
  );
753
- chunkDZ7QRFHD_js.recordIntrospectionFailure("never-mounted", null);
184
+ chunkYB77RYCC_js.recordIntrospectionFailure("never-mounted", null);
754
185
  return {
755
- route: chunkDZ7QRFHD_js.getCurrentScreen(),
186
+ route: chunkYB77RYCC_js.getCurrentScreen(),
756
187
  texts: [],
757
188
  inputs: [],
758
189
  buttons: [],
@@ -766,35 +197,84 @@ function captureSnapshot() {
766
197
  };
767
198
  }
768
199
  const start = Date.now();
769
- const snapshot = walkFiber(root);
770
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
200
+ const snapshot = chunkYB77RYCC_js.walkFiber(root);
201
+ recordBlindWalk();
202
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
771
203
  const deepestRoute = activePath[activePath.length - 1];
772
204
  if (deepestRoute) snapshot.route = deepestRoute;
773
205
  mergeRegisteredLists(snapshot);
206
+ mergeRegisteredScrollables(snapshot);
207
+ mergeNativeDialog(snapshot);
774
208
  reconcileSliders(snapshot);
775
- snapshot.elements = chunkDZ7QRFHD_js.deriveInteractionElements(snapshot);
776
- snapshot.choiceGroups = chunkDZ7QRFHD_js.attachElementIdsToChoiceGroups(
777
- snapshot.choiceGroups,
778
- snapshot.elements
209
+ canonicalizeRegisteredFields(snapshot);
210
+ chunkYB77RYCC_js.clampSnapshotToWireLimits(snapshot);
211
+ const entries = chunkYB77RYCC_js.deriveInteractionElements(snapshot, { rectOf: chunkYB77RYCC_js.rectForNode });
212
+ const rectById = new Map(
213
+ entries.flatMap((entry) => entry.rect ? [[entry.id, entry.rect]] : [])
214
+ );
215
+ snapshot.elements = entries.map(chunkYB77RYCC_js.toWireElement);
216
+ snapshot.choiceGroups = chunkYB77RYCC_js.attachElementIdsToChoiceGroups(snapshot.choiceGroups, snapshot.elements);
217
+ chunkYB77RYCC_js.clampSnapshotToWireLimits(snapshot);
218
+ chunkYB77RYCC_js.elementRegistry.replaceAll(
219
+ snapshot.elements.map((element) => {
220
+ const rect = rectById.get(element.id);
221
+ return rect ? { ...element, rect } : element;
222
+ })
779
223
  );
780
- chunkDZ7QRFHD_js.elementRegistry.replaceAll(snapshot.elements);
781
224
  const elapsed = Date.now() - start;
782
- const totalListItems = snapshot.lists.reduce(
783
- (acc, l) => acc + l.items.length,
784
- 0
785
- );
225
+ const totalListItems = snapshot.lists.reduce((acc, l) => acc + l.items.length, 0);
786
226
  const totalListDataItems = snapshot.lists.reduce(
787
227
  (acc, l) => acc + (typeof l.itemCount === "number" ? l.itemCount : 0),
788
228
  0
789
229
  );
790
- console.log(
791
- `[Appilots] captureSnapshot: route="${snapshot.route}" texts=${snapshot.texts.length} inputs=${snapshot.inputs.length} buttons=${snapshot.buttons.length} toggles=${snapshot.toggles.length} sliders=${snapshot.sliders.length} loading=${snapshot.loading} modal=${snapshot.modalOpen} lists=${snapshot.lists.length}(visibleItems=${totalListItems}, dataItems=${totalListDataItems}) choices=${snapshot.choiceGroups.length} elements=${snapshot.elements.length} (walked ${snapshot.stats?.visitedFibers ?? 0} fibers, skipped ${snapshot.stats?.skippedHidden ?? 0} hidden, ${elapsed}ms)`
230
+ chunkYB77RYCC_js.appilotsDebugLog(
231
+ `captureSnapshot: route="${snapshot.route}" texts=${snapshot.texts.length} inputs=${snapshot.inputs.length} buttons=${snapshot.buttons.length} toggles=${snapshot.toggles.length} sliders=${snapshot.sliders.length} loading=${snapshot.loading} modal=${snapshot.modalOpen} lists=${snapshot.lists.length}(visibleItems=${totalListItems}, dataItems=${totalListDataItems}) choices=${snapshot.choiceGroups.length} elements=${snapshot.elements.length} ` + (snapshot.truncated ? "truncated=true " : "") + `(walked ${snapshot.stats?.visitedFibers ?? 0} fibers, skipped ${snapshot.stats?.skippedHidden ?? 0} hidden, ${elapsed}ms)`
792
232
  );
793
- console.log(
794
- `[Appilots] captureSnapshot detail: lists=[${snapshot.lists.map((l) => `${l.containerType}:${l.id ?? l.label ?? "?"}(${l.items.map((it) => it.texts[0] ?? it.buttons[0]?.id ?? "?").join("|")})`).join(", ")}] inputs=[${snapshot.inputs.map((i) => i.id ?? i.label ?? "?").slice(0, 12).join(", ")}] buttons=[${snapshot.buttons.map((b) => b.id ?? b.label ?? "?").slice(0, 15).join(", ")}]`
233
+ chunkYB77RYCC_js.appilotsDebugLog(
234
+ `captureSnapshot detail: lists=[${snapshot.lists.map((l) => `${l.containerType}:${l.id ?? l.label ?? "?"}(rows=${l.items.length})`).join(", ")}] inputs=[${snapshot.inputs.map((i) => i.id ?? i.label ?? "?").slice(0, 12).join(", ")}] buttons=[${snapshot.buttons.map((b) => b.id ?? b.label ?? "?").slice(0, 15).join(", ")}]`
795
235
  );
796
236
  return snapshot;
797
237
  }
238
+ function registryCounts() {
239
+ const counts = {
240
+ fields: 0,
241
+ toggles: 0,
242
+ sliders: 0,
243
+ targets: 0,
244
+ lists: chunkYB77RYCC_js.listRegistry.snapshot().length,
245
+ elements: chunkYB77RYCC_js.elementRegistry.size
246
+ };
247
+ for (const { kind } of chunkYB77RYCC_js.componentRegistry.snapshot()) {
248
+ if (kind === "field") counts.fields++;
249
+ else if (kind === "toggle") counts.toggles++;
250
+ else if (kind === "slider") counts.sliders++;
251
+ else if (kind === "target") counts.targets++;
252
+ }
253
+ return counts;
254
+ }
255
+ function appilotsSelfCheck() {
256
+ const root = chunkYB77RYCC_js.getFiberRoot();
257
+ const start = Date.now();
258
+ if (root) chunkYB77RYCC_js.walkFiber(root);
259
+ const elapsedMs = Date.now() - start;
260
+ const walk = chunkYB77RYCC_js.getLastWalkDiagnostics();
261
+ return {
262
+ sdkVersion: chunkYB77RYCC_js.SDK_VERSION,
263
+ reactVersion: React__default.default.version ?? null,
264
+ route: chunkYB77RYCC_js.getCurrentScreen() || null,
265
+ introspection: chunkYB77RYCC_js.getIntrospectionDiagnostics(),
266
+ autoTracking: chunkYB77RYCC_js.getAutoTrackingState(),
267
+ walk: {
268
+ visitedFibers: root ? walk?.visitedFibers ?? 0 : 0,
269
+ skippedHidden: root ? walk?.skippedHidden ?? 0 : 0,
270
+ elapsedMs
271
+ },
272
+ detectors: root ? walk?.detectors ?? chunkYB77RYCC_js.emptyDetectorCounts() : chunkYB77RYCC_js.emptyDetectorCounts(),
273
+ registry: registryCounts(),
274
+ nameMangling: chunkYB77RYCC_js.getNameManglingProbe(),
275
+ geometry: { availability: chunkYB77RYCC_js.geometryAvailability(), ...chunkYB77RYCC_js.geometryStats() }
276
+ };
277
+ }
798
278
 
799
279
  // src/introspection/findInteractive.ts
800
280
  function getTypeName2(type) {
@@ -808,7 +288,7 @@ function getTypeName2(type) {
808
288
  }
809
289
  return null;
810
290
  }
811
- function matchesName2(fiber, name) {
291
+ function matchesName(fiber, name) {
812
292
  return getTypeName2(fiber.type) === name || getTypeName2(fiber.elementType) === name;
813
293
  }
814
294
  var TOUCHABLE_NAMES2 = /* @__PURE__ */ new Set([
@@ -821,33 +301,33 @@ var TOUCHABLE_NAMES2 = /* @__PURE__ */ new Set([
821
301
  function isTouchable(fiber) {
822
302
  return TOUCHABLE_NAMES2.has(getTypeName2(fiber.type) ?? "") || TOUCHABLE_NAMES2.has(getTypeName2(fiber.elementType) ?? "");
823
303
  }
824
- function hasPressHandler2(fiber) {
304
+ function hasPressHandler(fiber) {
825
305
  const props = fiber?.memoizedProps ?? {};
826
306
  return typeof props.onPress === "function" || typeof props.onPressIn === "function";
827
307
  }
828
- function isPressableTarget2(fiber) {
829
- return isTouchable(fiber) || hasPressHandler2(fiber);
308
+ function isPressableTarget(fiber) {
309
+ return isTouchable(fiber) || hasPressHandler(fiber);
830
310
  }
831
- var SELF_REFERENTIAL_COMPONENTS2 = /* @__PURE__ */ new Set([
311
+ var SELF_REFERENTIAL_COMPONENTS = /* @__PURE__ */ new Set([
832
312
  "AppilotsChat",
833
313
  "AppilotsChatInner",
834
314
  "ActionBreadcrumb",
835
315
  "ConfirmDialog"
836
316
  ]);
837
- function isAppilotsSkipMarked2(props) {
317
+ function isAppilotsSkipMarked(props) {
838
318
  if (!props) return false;
839
319
  return props.__appilotsSkip === true || props["data-appilots-skip"] === true || props.appilotsSkip === true;
840
320
  }
841
- function extractTextFromChildren2(children) {
321
+ function extractTextFromChildren(children) {
842
322
  if (children == null) return "";
843
323
  if (typeof children === "string") return children;
844
324
  if (typeof children === "number") return String(children);
845
325
  if (Array.isArray(children)) {
846
- return children.map(extractTextFromChildren2).filter(Boolean).join("");
326
+ return children.map(extractTextFromChildren).filter(Boolean).join("");
847
327
  }
848
328
  return "";
849
329
  }
850
- function findChildText2(fiber) {
330
+ function findChildText(fiber) {
851
331
  const stack = [];
852
332
  if (fiber.child) stack.push(fiber.child);
853
333
  const visited = /* @__PURE__ */ new WeakSet();
@@ -855,8 +335,8 @@ function findChildText2(fiber) {
855
335
  const node = stack.pop();
856
336
  if (!node || visited.has(node)) continue;
857
337
  visited.add(node);
858
- if (matchesName2(node, "Text")) {
859
- const text = extractTextFromChildren2(node.memoizedProps?.children);
338
+ if (matchesName(node, "Text")) {
339
+ const text = extractTextFromChildren(node.memoizedProps?.children);
860
340
  if (text && text.trim().length > 0) return text.trim();
861
341
  }
862
342
  if (node.sibling) stack.push(node.sibling);
@@ -868,10 +348,10 @@ function shouldSkipSubtree2(fiber) {
868
348
  const props = fiber.memoizedProps;
869
349
  if (!props) return false;
870
350
  const typeName = getTypeName2(fiber.type) ?? getTypeName2(fiber.elementType);
871
- if (typeName && SELF_REFERENTIAL_COMPONENTS2.has(typeName)) return true;
872
- if (isAppilotsSkipMarked2(props)) return true;
873
- if (matchesName2(fiber, "Modal") && props.visible === false) return true;
874
- if (matchesName2(fiber, "Screen") && props.activityState === 0) return true;
351
+ if (typeName && SELF_REFERENTIAL_COMPONENTS.has(typeName)) return true;
352
+ if (isAppilotsSkipMarked(props)) return true;
353
+ if (chunkYB77RYCC_js.isModalFiber(fiber) && props.visible === false) return true;
354
+ if (matchesName(fiber, "Screen") && props.activityState === 0) return true;
875
355
  const style = props.style;
876
356
  if (style) {
877
357
  const flat = Array.isArray(style) ? Object.assign({}, ...style.filter(Boolean)) : style;
@@ -880,20 +360,19 @@ function shouldSkipSubtree2(fiber) {
880
360
  }
881
361
  return false;
882
362
  }
883
- function normalize(s) {
884
- if (!s) return "";
885
- return s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
886
- }
363
+ var normalize = chunkYB77RYCC_js.foldForCompare;
887
364
  function scoreMatch(fiber, queryNorm, queryRaw) {
888
365
  const props = fiber.memoizedProps ?? {};
889
366
  const candidates = [];
890
367
  if (typeof props.testID === "string") candidates.push({ val: props.testID, weight: 100 });
891
- if (typeof props.accessibilityLabel === "string") candidates.push({ val: props.accessibilityLabel, weight: 95 });
368
+ if (typeof props.accessibilityLabel === "string")
369
+ candidates.push({ val: props.accessibilityLabel, weight: 95 });
892
370
  if (typeof props.label === "string") candidates.push({ val: props.label, weight: 90 });
893
- if (typeof props.placeholder === "string") candidates.push({ val: props.placeholder, weight: 70 });
371
+ if (typeof props.placeholder === "string")
372
+ candidates.push({ val: props.placeholder, weight: 70 });
894
373
  if (typeof props.title === "string") candidates.push({ val: props.title, weight: 85 });
895
- if (isPressableTarget2(fiber)) {
896
- const childText = findChildText2(fiber);
374
+ if (isPressableTarget(fiber)) {
375
+ const childText = findChildText(fiber);
897
376
  if (childText) candidates.push({ val: childText, weight: 80 });
898
377
  }
899
378
  let best = 0;
@@ -902,7 +381,8 @@ function scoreMatch(fiber, queryNorm, queryRaw) {
902
381
  if (!vNorm) continue;
903
382
  if (val === queryRaw) best = Math.max(best, weight + 20);
904
383
  else if (vNorm === queryNorm) best = Math.max(best, weight + 10);
905
- else if (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)) best = Math.max(best, weight - 20);
384
+ else if (queryNorm && (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)))
385
+ best = Math.max(best, weight - 20);
906
386
  }
907
387
  if (best > 0 && props.disabled === true) {
908
388
  best = Math.max(1, best - 60);
@@ -933,6 +413,12 @@ function wrapTextInput(fiber) {
933
413
  if (node && typeof node.focus === "function") {
934
414
  node.focus();
935
415
  }
416
+ },
417
+ submitFromKeyboard: () => {
418
+ const { onSubmitEditing, value } = getProps();
419
+ if (typeof onSubmitEditing !== "function") return false;
420
+ onSubmitEditing({ nativeEvent: { text: value ?? "" } });
421
+ return true;
936
422
  }
937
423
  };
938
424
  }
@@ -970,16 +456,16 @@ function wrapTouchable(fiber, label) {
970
456
  };
971
457
  }
972
458
  function findInteractiveByIdentifier(query, options = {}) {
973
- const root = chunkDZ7QRFHD_js.getFiberRoot();
459
+ const root = chunkYB77RYCC_js.getFiberRoot();
974
460
  if (!root) {
975
- console.warn("[Appilots] findInteractiveByIdentifier: fiber root not captured yet");
461
+ chunkYB77RYCC_js.appilotsDebugWarn("findInteractiveByIdentifier: fiber root not captured yet");
976
462
  return null;
977
463
  }
978
464
  const queryNorm = normalize(query);
979
465
  const queryRaw = query;
980
466
  let bestScore = 0;
981
467
  let bestHandle = null;
982
- let bestId2;
468
+ let bestId;
983
469
  const visited = /* @__PURE__ */ new WeakSet();
984
470
  const stack = [];
985
471
  if (root.child) stack.push(root.child);
@@ -990,40 +476,50 @@ function findInteractiveByIdentifier(query, options = {}) {
990
476
  if (fiber.sibling) stack.push(fiber.sibling);
991
477
  if (shouldSkipSubtree2(fiber)) continue;
992
478
  let kind = null;
993
- if (matchesName2(fiber, "TextInput")) kind = "field";
994
- else if (matchesName2(fiber, "Switch")) kind = "toggle";
995
- else if (isPressableTarget2(fiber)) kind = "target";
479
+ if (matchesName(fiber, "TextInput")) kind = "field";
480
+ else if (matchesName(fiber, "Switch")) kind = "toggle";
481
+ else if (isPressableTarget(fiber)) kind = "target";
996
482
  if (kind && (!options.kind || options.kind === kind)) {
997
483
  const score = scoreMatch(fiber, queryNorm, queryRaw);
998
484
  if (score > bestScore) {
999
485
  bestScore = score;
1000
486
  const props = fiber.memoizedProps ?? {};
1001
- bestId2 = props.testID ?? props.accessibilityLabel ?? props.placeholder ?? (kind === "target" ? findChildText2(fiber) : void 0);
487
+ bestId = props.testID ?? props.accessibilityLabel ?? props.placeholder ?? (kind === "target" ? findChildText(fiber) : void 0);
1002
488
  if (kind === "field") bestHandle = wrapTextInput(fiber);
1003
489
  else if (kind === "toggle") bestHandle = wrapSwitch(fiber);
1004
- else bestHandle = wrapTouchable(fiber, findChildText2(fiber));
490
+ else bestHandle = wrapTouchable(fiber, findChildText(fiber));
1005
491
  }
1006
492
  }
1007
493
  if (fiber.child) stack.push(fiber.child);
1008
494
  }
1009
495
  if (bestHandle) {
1010
- console.log(
1011
- `[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 kind=${bestHandle.kind} label="${bestHandle.label ?? bestId2}" score=${bestScore}`
496
+ chunkYB77RYCC_js.appilotsDebugLog(
497
+ `findInteractiveByIdentifier: query="${query}" \u2192 kind=${bestHandle.kind} label="${bestHandle.label ?? bestId}" score=${bestScore}`
1012
498
  );
1013
499
  } else {
1014
- console.log(`[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 no match`);
500
+ chunkYB77RYCC_js.appilotsDebugLog(`findInteractiveByIdentifier: query="${query}" \u2192 no match`);
1015
501
  }
1016
502
  return bestHandle;
1017
503
  }
1018
504
 
1019
505
  // src/executor/handlers/navigateHandler.ts
506
+ var _reportedMissingNavRef = false;
507
+ function reportMissingNavigationRef() {
508
+ if (_reportedMissingNavRef) return;
509
+ _reportedMissingNavRef = true;
510
+ console.error(
511
+ "[Appilots] Navigation is not wired. The SDK never received a navigation ref, so every navigate the agent attempts will fail.\n Fix: wrap your NavigationContainer with <AppilotsNavigationContainer>:\n <AppilotsProvider config={...}>\n <AppilotsNavigationContainer>\n <NavigationContainer>{/* your navigators */}</NavigationContainer>\n </AppilotsNavigationContainer>\n <AppilotsChat />\n </AppilotsProvider>\n Docs: https://docs.appilots.com/getting-started/quick-start"
512
+ );
513
+ }
1020
514
  function categorizeNavigationError(message) {
1021
515
  if (/screen named|was not handled by any navigator|no route|not found|not registered in any navigator|couldn'?t find a route|route .* (?:doesn'?t|does not) exist/i.test(
1022
516
  message
1023
517
  )) {
1024
518
  return "component-not-found";
1025
519
  }
1026
- if (/couldn'?t find a navigation object|navigator (?:is )?not (?:rendered|ready)|not been (?:mounted|rendered)/i.test(message)) {
520
+ if (/couldn'?t find a navigation object|navigator (?:is )?not (?:rendered|ready)|not been (?:mounted|rendered)/i.test(
521
+ message
522
+ )) {
1027
523
  return "screen-timeout";
1028
524
  }
1029
525
  return "unknown";
@@ -1050,7 +546,9 @@ function screenExistsAnywhere(state, screenName) {
1050
546
  function safeNavigate(nav, screenName, params, path) {
1051
547
  if (path && path.length > 0) {
1052
548
  const { root, nestedParams } = buildNestedParams(path, screenName, params);
1053
- console.log(`[Appilots] safeNavigate: using path-based navigation \u2014 root="${root}", nested=${JSON.stringify(nestedParams)}`);
549
+ chunkYB77RYCC_js.appilotsDebugLog(
550
+ `safeNavigate: using path-based navigation \u2014 root="${root}", nested=${JSON.stringify(nestedParams)}`
551
+ );
1054
552
  nav.navigate(root, nestedParams);
1055
553
  return;
1056
554
  }
@@ -1065,11 +563,17 @@ function safeNavigate(nav, screenName, params, path) {
1065
563
  `Screen "${screenName}" is not registered in any navigator. The screen may have been removed, may live inside a flow that is not currently mounted (e.g. Auth stack after login), or the MCP doc is stale.`
1066
564
  );
1067
565
  }
1068
- console.log(`[Appilots] safeNavigate: screen exists in nested navigator, attempting direct navigation to "${screenName}"`);
566
+ chunkYB77RYCC_js.appilotsDebugLog(
567
+ `safeNavigate: screen exists in nested navigator, attempting direct navigation to "${screenName}"`
568
+ );
1069
569
  nav.navigate(screenName, params);
1070
570
  }
1071
571
  function navigateHandler(payload, context) {
1072
- console.log(`[Appilots] navigateHandler called: screenName="${payload.screenName}", action="${payload.navigationAction}", params=${JSON.stringify(payload.params ?? {})}`);
572
+ chunkYB77RYCC_js.appilotsDebugLog(
573
+ // Params carry record ids and, on some screens, the user's own
574
+ // data — the count answers "were params passed?" and nothing else.
575
+ `navigateHandler called: screenName="${payload.screenName}" action="${payload.navigationAction}" params=${chunkYB77RYCC_js.describeValue(payload.params)}`
576
+ );
1073
577
  const { navigationRef, permissions } = context;
1074
578
  const nav = navigationRef.current;
1075
579
  if (!permissions.canNavigate) {
@@ -1079,14 +583,15 @@ function navigateHandler(payload, context) {
1079
583
  diagnose: { category: "unknown", screen: payload.screenName }
1080
584
  };
1081
585
  }
1082
- if (permissions.blockedScreens?.includes(payload.screenName)) {
586
+ const isGoBack = payload.navigationAction === "goBack";
587
+ if (!isGoBack && permissions.blockedScreens?.includes(payload.screenName)) {
1083
588
  return {
1084
589
  success: false,
1085
590
  error: `Navigation to "${payload.screenName}" is blocked`,
1086
591
  diagnose: { category: "unknown", screen: payload.screenName }
1087
592
  };
1088
593
  }
1089
- if (permissions.allowedScreens && permissions.allowedScreens.length > 0 && !permissions.allowedScreens.includes(payload.screenName)) {
594
+ if (!isGoBack && permissions.allowedScreens && permissions.allowedScreens.length > 0 && !permissions.allowedScreens.includes(payload.screenName)) {
1090
595
  return {
1091
596
  success: false,
1092
597
  error: `Navigation to "${payload.screenName}" is not in allowed screens`,
@@ -1094,10 +599,11 @@ function navigateHandler(payload, context) {
1094
599
  };
1095
600
  }
1096
601
  if (!nav) {
602
+ reportMissingNavigationRef();
1097
603
  return {
1098
604
  success: false,
1099
- error: "Navigation ref is not available",
1100
- diagnose: { category: "screen-timeout", screen: payload.screenName }
605
+ error: "Navigation is not wired: <AppilotsNavigationContainer> is missing, so the SDK never received the navigation ref. Wrap your <NavigationContainer> with it. This cannot be retried \u2014 it needs a change in the host app.",
606
+ diagnose: { category: "unknown", screen: payload.screenName }
1101
607
  };
1102
608
  }
1103
609
  if (!nav.isReady || typeof nav.isReady === "function" && !nav.isReady()) {
@@ -1108,7 +614,15 @@ function navigateHandler(payload, context) {
1108
614
  };
1109
615
  }
1110
616
  try {
1111
- const { screenName, params, navigationAction, path } = payload;
617
+ const { params, navigationAction, path } = payload;
618
+ if (!isGoBack && !payload.screenName) {
619
+ return {
620
+ success: false,
621
+ error: `Navigation action "${navigationAction ?? "navigate"}" requires a screenName.`,
622
+ diagnose: { category: "unknown" }
623
+ };
624
+ }
625
+ const screenName = payload.screenName;
1112
626
  switch (navigationAction) {
1113
627
  case "navigate":
1114
628
  safeNavigate(nav, screenName, params ?? {}, path);
@@ -1151,10 +665,14 @@ function navigateHandler(payload, context) {
1151
665
  diagnose: { category: "unknown", screen: payload.screenName }
1152
666
  };
1153
667
  }
1154
- console.log(`[Appilots] navigateHandler: navigation succeeded for "${payload.screenName}" (action="${payload.navigationAction}")`);
668
+ chunkYB77RYCC_js.appilotsDebugLog(
669
+ `navigateHandler: navigation succeeded for "${payload.screenName}" (action="${payload.navigationAction}")`
670
+ );
1155
671
  return { success: true };
1156
672
  } catch (err) {
1157
- console.warn(`[Appilots] navigateHandler: navigation failed for "${payload.screenName}": ${err?.message}`);
673
+ chunkYB77RYCC_js.appilotsDebugWarn(
674
+ `navigateHandler: navigation failed for "${payload.screenName}": ${err?.message}`
675
+ );
1158
676
  const msg = String(err?.message ?? "Navigation failed");
1159
677
  const category = categorizeNavigationError(msg);
1160
678
  return {
@@ -1177,7 +695,7 @@ function parseSyntheticListItemId(id) {
1177
695
  if (listIndex < 0 || itemIndex < 1) return null;
1178
696
  return { listIndex, itemIndex };
1179
697
  }
1180
- function stringProp2(props, key) {
698
+ function stringProp(props, key) {
1181
699
  const value = props?.[key];
1182
700
  if (typeof value === "string" && value.trim()) return value.trim();
1183
701
  if (typeof value === "number") return String(value);
@@ -1185,33 +703,33 @@ function stringProp2(props, key) {
1185
703
  }
1186
704
  function listIdFromContainer(container) {
1187
705
  const props = container?.memoizedProps ?? {};
1188
- return stringProp2(props, "__appilotsListId") ?? stringProp2(props, "appilotsListId") ?? stringProp2(props, "testID") ?? stringProp2(props, "accessibilityLabel");
706
+ return stringProp(props, "__appilotsListId") ?? stringProp(props, "appilotsListId") ?? stringProp(props, "testID") ?? stringProp(props, "accessibilityLabel");
1189
707
  }
1190
708
  function listLabelFromContainer(container) {
1191
709
  const props = container?.memoizedProps ?? {};
1192
- return stringProp2(props, "__appilotsListLabel") ?? stringProp2(props, "accessibilityLabel") ?? stringProp2(props, "aria-label") ?? stringProp2(props, "label");
710
+ return stringProp(props, "__appilotsListLabel") ?? stringProp(props, "accessibilityLabel") ?? stringProp(props, "aria-label") ?? stringProp(props, "label");
1193
711
  }
1194
712
  function itemKeyFromFiber(fiber) {
1195
713
  const props = fiber?.memoizedProps ?? {};
1196
- return stringProp2(props, "__appilotsItemKey") ?? (fiber?.key !== void 0 && fiber?.key !== null ? String(fiber.key) : void 0);
714
+ return stringProp(props, "__appilotsItemKey") ?? (fiber?.key !== void 0 && fiber?.key !== null ? String(fiber.key) : void 0);
1197
715
  }
1198
716
  function markedItemIndexFromFiber(fiber) {
1199
717
  const value = fiber?.memoizedProps?.__appilotsItemIndex;
1200
718
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1201
719
  }
1202
720
  function normalize2(value) {
1203
- return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "");
721
+ return chunkYB77RYCC_js.foldForCompare(String(value ?? ""));
1204
722
  }
1205
- function hasPressHandler3(fiber) {
723
+ function hasPressHandler2(fiber) {
1206
724
  const props = fiber?.memoizedProps ?? {};
1207
725
  return typeof props.onPress === "function" || typeof props.onPressIn === "function";
1208
726
  }
1209
727
  function isPressableFiber(fiber) {
1210
- const typeName = getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "";
1211
- return TOUCHABLE_NAMES.has(typeName) || hasPressHandler3(fiber);
728
+ const typeName = chunkYB77RYCC_js.getTypeName(fiber.type) ?? chunkYB77RYCC_js.getTypeName(fiber.elementType) ?? "";
729
+ return chunkYB77RYCC_js.TOUCHABLE_NAMES.has(typeName) || hasPressHandler2(fiber);
1212
730
  }
1213
731
  function findListContainers(options = {}) {
1214
- const root = chunkDZ7QRFHD_js.getFiberRoot();
732
+ const root = chunkYB77RYCC_js.getFiberRoot();
1215
733
  if (!root) return [];
1216
734
  const containers = [];
1217
735
  const visited = /* @__PURE__ */ new WeakSet();
@@ -1222,17 +740,17 @@ function findListContainers(options = {}) {
1222
740
  if (!fiber || visited.has(fiber)) continue;
1223
741
  visited.add(fiber);
1224
742
  if (fiber.sibling) stack.push(fiber.sibling);
1225
- if (shouldSkipSubtree(fiber)) continue;
1226
- if (isAlwaysListContainer(fiber) || isHeuristicListContainer(fiber)) {
1227
- const minItems = isAlwaysListContainer(fiber) || options.allowSingleHeuristic ? 1 : 2;
1228
- const items = findListItems(fiber, minItems);
743
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
744
+ if (chunkYB77RYCC_js.isAlwaysListContainer(fiber) || chunkYB77RYCC_js.isHeuristicListContainer(fiber)) {
745
+ const minItems = chunkYB77RYCC_js.isAlwaysListContainer(fiber) || options.allowSingleHeuristic ? 1 : 2;
746
+ const items = chunkYB77RYCC_js.findListItems(fiber, minItems);
1229
747
  if (items && items.length >= minItems) {
1230
748
  containers.push({
1231
749
  container: fiber,
1232
750
  items,
1233
751
  listId: listIdFromContainer(fiber),
1234
752
  listLabel: listLabelFromContainer(fiber),
1235
- containerType: getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "List"
753
+ containerType: chunkYB77RYCC_js.getTypeName(fiber.type) ?? chunkYB77RYCC_js.getTypeName(fiber.elementType) ?? "List"
1236
754
  });
1237
755
  continue;
1238
756
  }
@@ -1251,7 +769,7 @@ function findFirstTouchable(item) {
1251
769
  const { fiber, includeSibling } = stack.pop();
1252
770
  if (!fiber || visited.has(fiber)) continue;
1253
771
  visited.add(fiber);
1254
- if (shouldSkipSubtree(fiber)) continue;
772
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
1255
773
  if (isPressableFiber(fiber)) {
1256
774
  const props = fiber.memoizedProps ?? {};
1257
775
  if (typeof props.onPress === "function" || typeof props.onPressIn === "function") {
@@ -1278,7 +796,7 @@ function findTouchableFibers(item) {
1278
796
  const { fiber, includeSibling } = stack.pop();
1279
797
  if (!fiber || visited.has(fiber)) continue;
1280
798
  visited.add(fiber);
1281
- if (shouldSkipSubtree(fiber)) continue;
799
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
1282
800
  const props = fiber.memoizedProps ?? {};
1283
801
  if (isPressableFiber(fiber) && (typeof props.onPress === "function" || typeof props.onPressIn === "function")) {
1284
802
  found.push(fiber);
@@ -1322,7 +840,7 @@ function findFirstText(fiber) {
1322
840
  const node = stack.pop();
1323
841
  if (!node || visited.has(node)) continue;
1324
842
  visited.add(node);
1325
- const typeName = getTypeName(node.type) ?? getTypeName(node.elementType) ?? "";
843
+ const typeName = chunkYB77RYCC_js.getTypeName(node.type) ?? chunkYB77RYCC_js.getTypeName(node.elementType) ?? "";
1326
844
  if (typeName === "Text") {
1327
845
  const text = textFromChildren(node.memoizedProps?.children).trim();
1328
846
  if (text) return text;
@@ -1341,7 +859,7 @@ function collectTexts(fiber) {
1341
859
  const node = stack.pop();
1342
860
  if (!node || visited.has(node)) continue;
1343
861
  visited.add(node);
1344
- const typeName = getTypeName(node.type) ?? getTypeName(node.elementType) ?? "";
862
+ const typeName = chunkYB77RYCC_js.getTypeName(node.type) ?? chunkYB77RYCC_js.getTypeName(node.elementType) ?? "";
1345
863
  if (typeName === "Text") {
1346
864
  const text = textFromChildren(node.memoizedProps?.children).trim();
1347
865
  if (text) out.push(text);
@@ -1353,13 +871,10 @@ function collectTexts(fiber) {
1353
871
  }
1354
872
  function hasUsefulTouchableIdentity(fiber) {
1355
873
  const props = fiber?.memoizedProps ?? {};
1356
- if (typeof props.testID === "string" && /[a-z0-9]/i.test(props.testID)) return true;
1357
- if (typeof props.accessibilityLabel === "string" && /[a-z0-9]/i.test(props.accessibilityLabel)) {
1358
- return true;
1359
- }
1360
- if (typeof props.label === "string" && /[a-z0-9]/i.test(props.label)) return true;
1361
- const label = findFirstText(fiber);
1362
- return !!label && /[a-z0-9]/i.test(label);
874
+ if (chunkYB77RYCC_js.isReferenceable(props.testID)) return true;
875
+ if (chunkYB77RYCC_js.isReferenceable(props.accessibilityLabel)) return true;
876
+ if (chunkYB77RYCC_js.isReferenceable(props.label)) return true;
877
+ return chunkYB77RYCC_js.isReferenceable(findFirstText(fiber));
1363
878
  }
1364
879
  function describeTouchable(fiber) {
1365
880
  const props = fiber?.memoizedProps ?? {};
@@ -1370,15 +885,10 @@ function describeTouchable(fiber) {
1370
885
  }
1371
886
  function touchableLooksDestructive(fiber) {
1372
887
  const descriptor = describeTouchable(fiber);
1373
- if (descriptor && chunkDZ7QRFHD_js.looksDestructiveActionLabel(descriptor)) return true;
888
+ if (descriptor && chunkYB77RYCC_js.looksDestructiveActionLabel(descriptor)) return true;
1374
889
  const props = fiber?.memoizedProps ?? {};
1375
- const haystack = [
1376
- props.testID,
1377
- props.accessibilityLabel,
1378
- props.accessibilityHint,
1379
- props.label
1380
- ].filter((value) => typeof value === "string").join(" ");
1381
- return chunkDZ7QRFHD_js.looksDestructiveActionLabel(haystack);
890
+ const haystack = [props.testID, props.accessibilityLabel, props.accessibilityHint, props.label].filter((value) => typeof value === "string").join(" ");
891
+ return chunkYB77RYCC_js.looksDestructiveActionLabel(haystack);
1382
892
  }
1383
893
  function describeItemCandidate(listIndex, zeroBasedIndex, item) {
1384
894
  const syntheticId = `list-${listIndex}-item-${zeroBasedIndex + 1}`;
@@ -1411,8 +921,8 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
1411
921
  (candidate) => candidate !== touchable && containsFiber(touchable, candidate)
1412
922
  );
1413
923
  if (primaryWrapsNestedTargets) {
1414
- console.log(
1415
- `[Appilots] listItemDispatch: item "list-${listIndex}-item-${itemIndex}" has nested pressables; pressing outer row target`
924
+ chunkYB77RYCC_js.appilotsDebugLog(
925
+ `listItemDispatch: item "list-${listIndex}-item-${itemIndex}" has nested pressables; pressing outer row target`
1416
926
  );
1417
927
  } else {
1418
928
  const candidates = safeIdentifiableTouchables.map(describeTouchable).filter((d) => !!d).slice(0, 8);
@@ -1446,14 +956,14 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
1446
956
  }
1447
957
  return {
1448
958
  ok: true,
1449
- containerType: getTypeName(container.type) ?? getTypeName(container.elementType) ?? list.containerType
959
+ containerType: chunkYB77RYCC_js.getTypeName(container.type) ?? chunkYB77RYCC_js.getTypeName(container.elementType) ?? list.containerType
1450
960
  };
1451
961
  } catch (err) {
1452
962
  return {
1453
963
  ok: false,
1454
964
  reason: "press-threw",
1455
965
  error: err?.message ?? "press handler threw",
1456
- containerType: getTypeName(container.type) ?? getTypeName(container.elementType) ?? list.containerType
966
+ containerType: chunkYB77RYCC_js.getTypeName(container.type) ?? chunkYB77RYCC_js.getTypeName(container.elementType) ?? list.containerType
1457
967
  };
1458
968
  }
1459
969
  }
@@ -1509,7 +1019,7 @@ function candidateLists(containers, locator) {
1509
1019
  return containers.map((list, listIndex) => ({ list, listIndex }));
1510
1020
  }
1511
1021
  function pressListItemAtOrdinal(listIndex, itemIndex) {
1512
- if (!chunkDZ7QRFHD_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1022
+ if (!chunkYB77RYCC_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1513
1023
  const containers = findListContainers({ allowSingleHeuristic: true });
1514
1024
  if (listIndex < 0 || listIndex >= containers.length) {
1515
1025
  return { ok: false, reason: "list-not-found" };
@@ -1522,14 +1032,14 @@ function pressListItemAtOrdinal(listIndex, itemIndex) {
1522
1032
  }
1523
1033
  return pressResolvedListItem(list, items[zeroBased], listIndex, itemIndex);
1524
1034
  }
1525
- function pressListItemByIdentity(locator) {
1526
- if (!chunkDZ7QRFHD_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1035
+ function resolveListItemByIdentity(locator) {
1036
+ if (!chunkYB77RYCC_js.getFiberRoot()) return { ok: false, result: { ok: false, reason: "no-fiber-root" } };
1527
1037
  const parsed = locator.syntheticId ? parseSyntheticListItemId(locator.syntheticId) : null;
1528
1038
  const effective = parsed ? { ...locator, listIndex: parsed.listIndex, itemIndex: parsed.itemIndex } : locator;
1529
1039
  const containers = findListContainers({ allowSingleHeuristic: true });
1530
1040
  const lists = candidateLists(containers, effective);
1531
1041
  if (lists.length === 0) {
1532
- return { ok: false, reason: "list-not-found" };
1042
+ return { ok: false, result: { ok: false, reason: "list-not-found" } };
1533
1043
  }
1534
1044
  const scoredCandidates = [];
1535
1045
  for (const { list, listIndex } of lists) {
@@ -1540,7 +1050,14 @@ function pressListItemByIdentity(locator) {
1540
1050
  }
1541
1051
  }
1542
1052
  if (scoredCandidates.length === 0) {
1543
- return { ok: false, reason: "item-not-found", containerType: lists[0]?.list.containerType };
1053
+ return {
1054
+ ok: false,
1055
+ result: {
1056
+ ok: false,
1057
+ reason: "item-not-found",
1058
+ containerType: lists[0]?.list.containerType
1059
+ }
1060
+ };
1544
1061
  }
1545
1062
  scoredCandidates.sort((a, b) => b.score - a.score);
1546
1063
  const best = scoredCandidates[0];
@@ -1549,13 +1066,104 @@ function pressListItemByIdentity(locator) {
1549
1066
  const candidates = tiedCandidates.map((c) => describeItemCandidate(c.listIndex, c.itemIndex - 1, c.item)).slice(0, 8);
1550
1067
  return {
1551
1068
  ok: false,
1552
- reason: "ambiguous-items",
1553
- error: "Multiple visible list items matched the requested target with equal confidence." + (candidates.length > 0 ? ` Candidates: ${candidates.join(", ")}.` : ""),
1554
- containerType: best.list.containerType,
1069
+ result: {
1070
+ ok: false,
1071
+ reason: "ambiguous-items",
1072
+ error: "Multiple visible list items matched the requested target with equal confidence." + (candidates.length > 0 ? ` Candidates: ${candidates.join(", ")}.` : ""),
1073
+ containerType: best.list.containerType,
1074
+ candidates
1075
+ }
1076
+ };
1077
+ }
1078
+ return {
1079
+ ok: true,
1080
+ list: best.list,
1081
+ item: best.item,
1082
+ listIndex: best.listIndex,
1083
+ itemIndex: best.itemIndex
1084
+ };
1085
+ }
1086
+ function findSwitchFibers(item) {
1087
+ if (!item) return [];
1088
+ const found = [];
1089
+ const visited = /* @__PURE__ */ new WeakSet();
1090
+ const stack = [
1091
+ { fiber: item, includeSibling: false }
1092
+ ];
1093
+ while (stack.length > 0) {
1094
+ const { fiber, includeSibling } = stack.pop();
1095
+ if (!fiber || visited.has(fiber)) continue;
1096
+ visited.add(fiber);
1097
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
1098
+ const props = fiber.memoizedProps ?? {};
1099
+ if (chunkYB77RYCC_js.isSwitchLike(fiber, props)) {
1100
+ if (props.__appilotsInternal !== true) found.push(fiber);
1101
+ if (includeSibling && fiber.sibling) {
1102
+ stack.push({ fiber: fiber.sibling, includeSibling: true });
1103
+ }
1104
+ continue;
1105
+ }
1106
+ if (includeSibling && fiber.sibling) {
1107
+ stack.push({ fiber: fiber.sibling, includeSibling: true });
1108
+ }
1109
+ if (fiber.child) stack.push({ fiber: fiber.child, includeSibling: true });
1110
+ }
1111
+ return found;
1112
+ }
1113
+ function toggleListItemByIdentity(locator, options) {
1114
+ const resolved = resolveListItemByIdentity(locator);
1115
+ if (!resolved.ok) return resolved.result;
1116
+ const { list, item } = resolved;
1117
+ const switches = findSwitchFibers(item);
1118
+ if (switches.length === 0) {
1119
+ return { ok: false, reason: "no-touchable", containerType: list.containerType };
1120
+ }
1121
+ if (switches.length > 1) {
1122
+ const candidates = switches.map((fiber, index) => describeTouchable(fiber) ?? `switch-${index + 1}`).slice(0, 8);
1123
+ return {
1124
+ ok: false,
1125
+ reason: "ambiguous-touchables",
1126
+ error: 'This row exposes more than one switch, so flipping "the" switch would be a guess.' + (candidates.length > 0 ? ` Candidates: ${candidates.join(", ")}.` : ""),
1127
+ containerType: list.containerType,
1555
1128
  candidates
1556
1129
  };
1557
1130
  }
1558
- return pressResolvedListItem(best.list, best.item, best.listIndex, best.itemIndex);
1131
+ const target = switches[0];
1132
+ const props = target?.memoizedProps ?? {};
1133
+ const current = chunkYB77RYCC_js.switchValue(props);
1134
+ if (options?.expected !== void 0 && current === options.expected) {
1135
+ return { ok: true, containerType: list.containerType, value: current };
1136
+ }
1137
+ const onValueChange = props.onValueChange ?? props.onChange;
1138
+ if (typeof onValueChange !== "function") {
1139
+ return {
1140
+ ok: false,
1141
+ reason: "no-touchable",
1142
+ error: "The row has a switch but it exposes no onValueChange handler.",
1143
+ containerType: list.containerType
1144
+ };
1145
+ }
1146
+ try {
1147
+ onValueChange(!current);
1148
+ } catch (err) {
1149
+ return {
1150
+ ok: false,
1151
+ reason: "press-threw",
1152
+ error: err?.message ?? "switch handler threw",
1153
+ containerType: list.containerType
1154
+ };
1155
+ }
1156
+ return { ok: true, containerType: list.containerType, value: !current };
1157
+ }
1158
+ function pressListItemByIdentity(locator) {
1159
+ const resolved = resolveListItemByIdentity(locator);
1160
+ if (!resolved.ok) return resolved.result;
1161
+ return pressResolvedListItem(
1162
+ resolved.list,
1163
+ resolved.item,
1164
+ resolved.listIndex,
1165
+ resolved.itemIndex
1166
+ );
1559
1167
  }
1560
1168
 
1561
1169
  // src/executor/handlers/elementDispatch.ts
@@ -1563,7 +1171,7 @@ function screenDiagnose(targetId, category = "component-not-found") {
1563
1171
  return {
1564
1172
  category,
1565
1173
  targetId,
1566
- screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0
1174
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0
1567
1175
  };
1568
1176
  }
1569
1177
  function isPressLike(action) {
@@ -1580,10 +1188,10 @@ function elementLookupKey(value) {
1580
1188
  return canonicalElementId(value).toLowerCase().replace(/[\s_]+/g, "-");
1581
1189
  }
1582
1190
  function findRegisteredElement(elementId) {
1583
- const direct = chunkDZ7QRFHD_js.elementRegistry.get(elementId) ?? chunkDZ7QRFHD_js.elementRegistry.get(canonicalElementId(elementId));
1191
+ const direct = chunkYB77RYCC_js.elementRegistry.get(elementId) ?? chunkYB77RYCC_js.elementRegistry.get(canonicalElementId(elementId));
1584
1192
  if (direct) return direct;
1585
1193
  const wanted = elementLookupKey(elementId);
1586
- return chunkDZ7QRFHD_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
1194
+ return chunkYB77RYCC_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
1587
1195
  }
1588
1196
  function resolveInteractionElement(elementId) {
1589
1197
  return getLatestElement(elementId);
@@ -1784,6 +1392,46 @@ function dispatchElement(element, registry, action) {
1784
1392
  };
1785
1393
  }
1786
1394
  if (element.role === "toggle" && (action === "toggle" || isPressLike(action))) {
1395
+ if (element.listContext) {
1396
+ const toggled = toggleListItemByIdentity(
1397
+ {
1398
+ listIndex: element.listContext.listIndex,
1399
+ listId: element.listContext.listId,
1400
+ listLabel: element.listContext.listLabel,
1401
+ itemIndex: element.listContext.itemIndex,
1402
+ itemKey: element.listContext.itemKey,
1403
+ reactKey: element.listContext.reactKey,
1404
+ syntheticId: element.listContext.syntheticId,
1405
+ label: element.label,
1406
+ texts: element.texts
1407
+ },
1408
+ // The observation's `selected` is the state BEFORE this action.
1409
+ // Passing the desired end state makes the flip idempotent: a
1410
+ // retry or a recovery hop must not undo the work and call it
1411
+ // success. A toggle only knows how to invert, so without this the
1412
+ // second attempt silently returns the row to where it started.
1413
+ typeof element.selected === "boolean" ? { expected: !element.selected } : void 0
1414
+ );
1415
+ if (toggled.ok) {
1416
+ return {
1417
+ success: true,
1418
+ // Grounded: read back off the fiber after the handler ran, not
1419
+ // inferred from "the call did not throw".
1420
+ effect: "changed"
1421
+ };
1422
+ }
1423
+ return {
1424
+ success: false,
1425
+ error: toggled.error ?? `Could not flip the switch in row "${element.label ?? element.id}" (${toggled.reason})`,
1426
+ diagnose: {
1427
+ ...screenDiagnose(
1428
+ element.id,
1429
+ toggled.reason === "ambiguous-touchables" || toggled.reason === "ambiguous-items" ? "ambiguous-target" : "component-not-found"
1430
+ ),
1431
+ ...toggled.candidates && toggled.candidates.length > 0 ? { candidates: toggled.candidates } : {}
1432
+ }
1433
+ };
1434
+ }
1787
1435
  const targetId = element.targetId ?? element.label ?? element.id;
1788
1436
  return dispatchLegacyTarget(targetId, registry, "toggle");
1789
1437
  }
@@ -1803,7 +1451,7 @@ function dispatchElement(element, registry, action) {
1803
1451
  }
1804
1452
  function dispatchStructuredElementId(identifier, action) {
1805
1453
  if (!isElementIdentifier(identifier) || !isPressLike(action)) return null;
1806
- const parsed = chunkDZ7QRFHD_js.parseStableElementId(identifier);
1454
+ const parsed = chunkYB77RYCC_js.parseStableElementId(identifier);
1807
1455
  if (!parsed || parsed.role !== "option") return null;
1808
1456
  if (!parsed.itemKey && !parsed.listId) return null;
1809
1457
  const pressed = pressListItemByIdentity({
@@ -1813,8 +1461,8 @@ function dispatchStructuredElementId(identifier, action) {
1813
1461
  texts: parsed.itemKey ? [parsed.itemKey] : void 0
1814
1462
  });
1815
1463
  if (pressed.ok) {
1816
- console.log(
1817
- `[Appilots] elementDispatch: resolved stale el id "${identifier}" via structural identity (listId="${parsed.listId}", itemKey="${parsed.itemKey}")`
1464
+ chunkYB77RYCC_js.appilotsDebugLog(
1465
+ `elementDispatch: resolved stale el id "${identifier}" via structural identity (listId="${parsed.listId}", itemKey="${parsed.itemKey}")`
1818
1466
  );
1819
1467
  return { success: true };
1820
1468
  }
@@ -1838,25 +1486,24 @@ function pressElementOrTarget(identifier, registry) {
1838
1486
 
1839
1487
  // src/executor/formFieldRewrite.ts
1840
1488
  var LIST_ORDINAL_RE = /^list-\d+-item-\d+$/i;
1841
- var PLATE_RE = /^[A-Z]{3}-?\d[A-Z0-9]\d{2}$/i;
1842
1489
  function normalize4(value) {
1843
1490
  return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
1844
1491
  }
1845
1492
  function resolveScreenForFormFields() {
1846
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
1493
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
1847
1494
  for (let i = activePath.length - 1; i >= 0; i--) {
1848
1495
  const name = activePath[i];
1849
- const meta = name ? chunkDZ7QRFHD_js.getScreenMetadata(name) : void 0;
1496
+ const meta = name ? chunkYB77RYCC_js.getScreenMetadata(name) : void 0;
1850
1497
  if (name && Array.isArray(meta?.fields) && meta.fields.length > 0) return name;
1851
1498
  }
1852
- return chunkDZ7QRFHD_js.getCurrentScreen();
1499
+ return chunkYB77RYCC_js.getCurrentScreen();
1853
1500
  }
1854
1501
  function collectKnownFormFields(registry) {
1855
1502
  const registryFields = registry.snapshot().filter((entry) => entry.kind === "field" || entry.kind === "slider").map((entry) => ({ id: entry.id, label: entry.label }));
1856
1503
  if (registryFields.length >= 2) return registryFields;
1857
1504
  const screen = resolveScreenForFormFields();
1858
1505
  if (screen) {
1859
- const metaFields = chunkDZ7QRFHD_js.getScreenMetadata(screen)?.fields;
1506
+ const metaFields = chunkYB77RYCC_js.getScreenMetadata(screen)?.fields;
1860
1507
  if (Array.isArray(metaFields) && metaFields.length > 0) {
1861
1508
  return metaFields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
1862
1509
  id: field.id,
@@ -1866,7 +1513,7 @@ function collectKnownFormFields(registry) {
1866
1513
  }));
1867
1514
  }
1868
1515
  }
1869
- for (const meta of chunkDZ7QRFHD_js.getAllScreens()) {
1516
+ for (const meta of chunkYB77RYCC_js.getAllScreens()) {
1870
1517
  if (Array.isArray(meta.fields) && meta.fields.length > 0) {
1871
1518
  return meta.fields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
1872
1519
  id: field.id,
@@ -1878,9 +1525,6 @@ function collectKnownFormFields(registry) {
1878
1525
  }
1879
1526
  return registryFields;
1880
1527
  }
1881
- function fieldHaystack(field) {
1882
- return normalize4(`${field.id} ${field.label ?? ""}`);
1883
- }
1884
1528
  function isMisplacedFieldId(fieldId, knownIds) {
1885
1529
  const trimmed = fieldId.trim();
1886
1530
  if (!trimmed) return true;
@@ -1904,50 +1548,68 @@ function valueMatchesOption(field, rawValue) {
1904
1548
  return label === value || optionValue === value || value.includes(label) || value.includes(optionValue);
1905
1549
  });
1906
1550
  }
1551
+ var NUMERIC_FIELD_TYPES = /* @__PURE__ */ new Set([
1552
+ "number",
1553
+ "numeric",
1554
+ "integer",
1555
+ "int",
1556
+ "decimal",
1557
+ "float",
1558
+ "range",
1559
+ "slider",
1560
+ "tel",
1561
+ "phone"
1562
+ ]);
1563
+ var DATE_FIELD_TYPES = /* @__PURE__ */ new Set(["date", "datetime", "datetimelocal", "time", "month"]);
1564
+ var EMAIL_FIELD_TYPES = /* @__PURE__ */ new Set(["email"]);
1565
+ var CHOICE_FIELD_TYPES = /* @__PURE__ */ new Set([
1566
+ "select",
1567
+ "picker",
1568
+ "dropdown",
1569
+ "combobox",
1570
+ "radio",
1571
+ "checkbox",
1572
+ "switch",
1573
+ "toggle",
1574
+ "segmented",
1575
+ "boolean"
1576
+ ]);
1577
+ function readValueShape(rawValue) {
1578
+ const value = String(rawValue ?? "").trim();
1579
+ if (!value) return "text";
1580
+ if (/^-?\d+(?:[.,]\d+)?$/.test(value)) return "number";
1581
+ if (/^\S+@\S+\.\S+$/.test(value)) return "email";
1582
+ if (/^\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}(?::\d{2})?)?$/.test(value)) return "date";
1583
+ if (/^\d{1,2}[/-]\d{1,2}[/-]\d{2,4}$/.test(value)) return "date";
1584
+ return "text";
1585
+ }
1586
+ function fieldTypeMatchesShape(field, shape) {
1587
+ const type = normalize4(field.type ?? "text");
1588
+ if (CHOICE_FIELD_TYPES.has(type)) return false;
1589
+ if (shape === "number") return NUMERIC_FIELD_TYPES.has(type);
1590
+ if (shape === "date") return DATE_FIELD_TYPES.has(type);
1591
+ if (shape === "email") return EMAIL_FIELD_TYPES.has(type);
1592
+ return false;
1593
+ }
1594
+ function fieldAcceptsFreeText(field, shape) {
1595
+ const type = normalize4(field.type ?? "text");
1596
+ if (CHOICE_FIELD_TYPES.has(type)) return false;
1597
+ if (NUMERIC_FIELD_TYPES.has(type)) return shape === "number";
1598
+ if (DATE_FIELD_TYPES.has(type)) return shape === "date";
1599
+ if (EMAIL_FIELD_TYPES.has(type)) return shape === "email";
1600
+ return true;
1601
+ }
1907
1602
  function inferFieldIdForValue(rawValue, fields, used) {
1908
1603
  const value = String(rawValue ?? "").trim();
1909
1604
  if (!value) return void 0;
1910
- const normalizedValue = normalize4(value);
1911
- for (const field of fields) {
1912
- if (used.has(field.id)) continue;
1605
+ const available = fields.filter((field) => field.id && !used.has(field.id));
1606
+ for (const field of available) {
1913
1607
  if (valueMatchesOption(field, value)) return field.id;
1914
1608
  }
1915
- if (PLATE_RE.test(value)) {
1916
- const field = fields.find((f) => /placa|plate/.test(fieldHaystack(f)) && !used.has(f.id));
1917
- if (field) return field.id;
1918
- }
1919
- if (/^(19|20)\d{2}$/.test(value)) {
1920
- const field = fields.find((f) => /ano|year/.test(fieldHaystack(f)) && !used.has(f.id));
1921
- if (field) return field.id;
1922
- }
1923
- if (/^\d+$/.test(value)) {
1924
- const mileage = fields.find((f) => /quilometragem|mileage|km/.test(fieldHaystack(f)) && !used.has(f.id));
1925
- if (mileage) return mileage.id;
1926
- const year = fields.find((f) => /ano|year/.test(fieldHaystack(f)) && !used.has(f.id));
1927
- if (year) return year.id;
1928
- }
1929
- if (/preto|branco|azul|vermelho|prata|black|white|red|blue|silver|gray|grey/.test(normalizedValue)) {
1930
- const cor = fields.find((f) => /cor|color/.test(fieldHaystack(f)) && !used.has(f.id));
1931
- if (cor) return cor.id;
1932
- }
1933
- const marca = fields.find((f) => /marca|brand|make/.test(fieldHaystack(f)) && !used.has(f.id));
1934
- if (marca && !/model/i.test(normalizedValue)) return marca.id;
1935
- const modelo = fields.find((f) => /modelo|model/.test(fieldHaystack(f)) && !used.has(f.id));
1936
- if (modelo) return modelo.id;
1937
- const tipo = fields.find((f) => /\btipo\b|type|vehicletype/.test(fieldHaystack(f)) && !used.has(f.id));
1938
- if (tipo && /carro|car|moto|truck|van|flex|gasoline|diesel|hybrid|electric|el[eé]trico/.test(normalizedValue)) {
1939
- return tipo.id;
1940
- }
1941
- const combustivel = fields.find((f) => /combustivel|fuel/.test(fieldHaystack(f)) && !used.has(f.id));
1942
- if (combustivel && /flex|gasoline|diesel|hybrid|electric|el[eé]trico/.test(normalizedValue)) {
1943
- return combustivel.id;
1944
- }
1945
- const nextText = fields.find((field) => {
1946
- if (used.has(field.id)) return false;
1947
- const type = normalize4(field.type ?? "text");
1948
- return type === "text" || type === "input" || type === "number" || type === "";
1949
- });
1950
- return nextText?.id;
1609
+ const shape = readValueShape(value);
1610
+ const typed = available.find((field) => fieldTypeMatchesShape(field, shape));
1611
+ if (typed) return typed.id;
1612
+ return available.find((field) => fieldAcceptsFreeText(field, shape))?.id;
1951
1613
  }
1952
1614
  function rewriteMisplacedFormFillFields(fields, registry) {
1953
1615
  const knownFields = collectKnownFormFields(registry);
@@ -1964,7 +1626,7 @@ function rewriteMisplacedFormFillFields(fields, registry) {
1964
1626
  const inferred = inferFieldIdForValue(String(field.value ?? ""), knownFields, used);
1965
1627
  if (!inferred) return field;
1966
1628
  used.add(inferred);
1967
- chunkDZ7QRFHD_js.appilotsDebugWarn(
1629
+ chunkYB77RYCC_js.appilotsDebugWarn(
1968
1630
  `formFieldRewrite: ${field.fieldId} \u2192 ${inferred} (value=${JSON.stringify(field.value)})`
1969
1631
  );
1970
1632
  return { ...field, fieldId: inferred };
@@ -1972,28 +1634,36 @@ function rewriteMisplacedFormFillFields(fields, registry) {
1972
1634
  }
1973
1635
 
1974
1636
  // src/executor/formValidation.ts
1975
- var FORM_VALIDATION_TEXT_RE = /(inv[aá]lid|obrigat[oó]ri|required|invalid|j[aá]\s+existe|already\s+exists|duplicad|formato|format|too\s+short|muito\s+curto|n[aã]o\s+(?:foi|pode)|must\s+be|deve\s+ser|selecione|escolha|select\s+(?:the|a|o|an))/i;
1976
- var FORM_SUCCESS_TEXT_RE = /\b(cadastrad[oa]s?\s+com\s+sucesso|registrad[oa]s?\s+com\s+sucesso|salv[oa]\s+com\s+sucesso|foi\s+cadastrad[oa]|foi\s+registrad[oa]|foi\s+salv[oa]|successfully\s+(?:registered|saved|created)|(?:has\s+been|was)\s+(?:registered|saved|created))\b/i;
1637
+ var FORM_VALIDATION_TEXT_RE2 = chunkYB77RYCC_js.FORM_VALIDATION_TEXT_RE;
1638
+ var FORM_SUCCESS_TEXT_RE = chunkYB77RYCC_js.FORM_WRITE_SUCCESS_TEXT_RE;
1977
1639
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1978
- var FIELD_HINTS = [
1979
- { re: /placa|plate|matr[ií]cula/i, fieldId: "placa" },
1980
- { re: /marca|brand/i, fieldId: "marca" },
1981
- { re: /modelo|model/i, fieldId: "modelo" },
1982
- { re: /\bcor\b|color|colour/i, fieldId: "cor" },
1983
- { re: /\bano\b|year/i, fieldId: "ano" },
1984
- { re: /email|e-mail|correo/i, fieldId: "email" }
1985
- ];
1986
- function inferValidationFieldId(message) {
1987
- for (const hint of FIELD_HINTS) {
1988
- if (hint.re.test(message)) return hint.fieldId;
1640
+ function inferValidationFieldId(message, inputs) {
1641
+ const haystack = normalizeText(message);
1642
+ if (!haystack || !inputs?.length) return void 0;
1643
+ let best;
1644
+ for (const input of inputs) {
1645
+ const id = input?.id;
1646
+ if (!id) continue;
1647
+ for (const naming of [input.label, input.placeholder, id]) {
1648
+ const needle = normalizeText(naming ?? "");
1649
+ if (needle.length < 3) continue;
1650
+ if (!containsWord(haystack, needle)) continue;
1651
+ if (!best || needle.length > best.length) best = { id, length: needle.length };
1652
+ }
1989
1653
  }
1990
- return void 0;
1654
+ return best?.id;
1655
+ }
1656
+ function normalizeText(value) {
1657
+ return String(value ?? "").normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
1658
+ }
1659
+ function containsWord(haystack, needle) {
1660
+ return ` ${haystack} `.includes(` ${needle} `);
1991
1661
  }
1992
1662
  function readVisibleFormValidation(snap) {
1993
1663
  if (!snap) return void 0;
1994
1664
  for (const text of snap.texts ?? []) {
1995
- if (!text?.trim() || !FORM_VALIDATION_TEXT_RE.test(text)) continue;
1996
- return { fieldId: inferValidationFieldId(text), message: text };
1665
+ if (!text?.trim() || !FORM_VALIDATION_TEXT_RE2.test(text)) continue;
1666
+ return { fieldId: inferValidationFieldId(text, snap.inputs), message: text };
1997
1667
  }
1998
1668
  return void 0;
1999
1669
  }
@@ -2002,7 +1672,7 @@ function readVisibleFormSuccess(snap) {
2002
1672
  return (snap.texts ?? []).find((text) => text?.trim() && FORM_SUCCESS_TEXT_RE.test(text));
2003
1673
  }
2004
1674
  function submitAsyncStillPending(submitTargetId) {
2005
- const probe = chunkDZ7QRFHD_js.probeLoadingState(submitTargetId ?? null, chunkDZ7QRFHD_js.getCurrentScreen());
1675
+ const probe = chunkYB77RYCC_js.probeLoadingState(submitTargetId ?? null, chunkYB77RYCC_js.getCurrentScreen());
2006
1676
  if (probe.loading) return true;
2007
1677
  if (submitTargetId && probe.pressedFound && probe.pressedDisabled) return true;
2008
1678
  return false;
@@ -2014,7 +1684,7 @@ function evaluatePostSubmitSnapshot(snap, activePath) {
2014
1684
  }
2015
1685
  const successText = readVisibleFormSuccess(snap);
2016
1686
  if (successText) return { status: "success", message: successText };
2017
- if (!chunkDZ7QRFHD_js.snapshotShowsOpenCreateForm(snap, activePath)) {
1687
+ if (!chunkYB77RYCC_js.snapshotShowsOpenCreateForm(snap, activePath)) {
2018
1688
  return { status: "success" };
2019
1689
  }
2020
1690
  return void 0;
@@ -2030,7 +1700,7 @@ async function waitForPostSubmitOutcome(options) {
2030
1700
  continue;
2031
1701
  }
2032
1702
  const snap2 = captureSnapshot();
2033
- const activePath2 = chunkDZ7QRFHD_js.getActiveRouteNames();
1703
+ const activePath2 = chunkYB77RYCC_js.getActiveRouteNames();
2034
1704
  const outcome2 = evaluatePostSubmitSnapshot(snap2, activePath2);
2035
1705
  if (outcome2) return outcome2;
2036
1706
  await sleep(pollMs);
@@ -2042,7 +1712,7 @@ async function waitForPostSubmitOutcome(options) {
2042
1712
  };
2043
1713
  }
2044
1714
  const snap = captureSnapshot();
2045
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
1715
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
2046
1716
  const outcome = evaluatePostSubmitSnapshot(snap, activePath);
2047
1717
  if (outcome) return outcome;
2048
1718
  return {
@@ -2148,16 +1818,16 @@ function findSnapshotButton(targetId) {
2148
1818
  }
2149
1819
  }
2150
1820
  function buildUiDiagnose(targetId, cause) {
2151
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
2152
- const screen = activePath[activePath.length - 1] ?? chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0;
1821
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
1822
+ const screen = activePath[activePath.length - 1] ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2153
1823
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
2154
1824
  const diagnose = {
2155
1825
  category: cause === "not-found" ? "component-not-found" : cause === "disabled" ? "disabled" : "unknown",
2156
1826
  targetId,
2157
1827
  screen: screenPath
2158
1828
  };
2159
- if (chunkDZ7QRFHD_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
2160
- diagnose.visibleMessage = chunkDZ7QRFHD_js.OPTIONAL_STEP_AUTOMATION_HINT;
1829
+ if (chunkYB77RYCC_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
1830
+ diagnose.visibleMessage = chunkYB77RYCC_js.OPTIONAL_STEP_AUTOMATION_HINT;
2161
1831
  diagnose.recoverable = true;
2162
1832
  }
2163
1833
  return diagnose;
@@ -2215,13 +1885,15 @@ function resolveComponentId(componentId, registry, action) {
2215
1885
  const snapshot = registry.snapshot();
2216
1886
  for (const comp of snapshot) {
2217
1887
  if (comp.id.toLowerCase() === lower) {
2218
- console.log(`[Appilots] resolveComponentId: case-insensitive match "${componentId}" \u2192 "${comp.id}"`);
1888
+ chunkYB77RYCC_js.appilotsDebugLog(
1889
+ `resolveComponentId: case-insensitive match "${componentId}" \u2192 "${comp.id}"`
1890
+ );
2219
1891
  return comp.id;
2220
1892
  }
2221
1893
  }
2222
- const currentScreen = chunkDZ7QRFHD_js.getCurrentScreen();
1894
+ const currentScreen = chunkYB77RYCC_js.getCurrentScreen();
2223
1895
  if (currentScreen) {
2224
- const screenMeta = chunkDZ7QRFHD_js.getScreenMetadata(currentScreen);
1896
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(currentScreen);
2225
1897
  const actions = screenMeta?.actions;
2226
1898
  if (actions && Array.isArray(actions)) {
2227
1899
  const metaAction = actions.find(
@@ -2230,12 +1902,16 @@ function resolveComponentId(componentId, registry, action) {
2230
1902
  if (metaAction && typeof metaAction === "object" && metaAction.label) {
2231
1903
  const metaLabel = metaAction.label;
2232
1904
  const normalizedMetaLabel = metaLabel.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
2233
- console.log(`[Appilots] resolveComponentId: found screen metadata for "${componentId}" \u2192 label="${metaLabel}"`);
1905
+ chunkYB77RYCC_js.appilotsDebugLog(
1906
+ `resolveComponentId: found screen metadata for "${componentId}" \u2192 label="${metaLabel}"`
1907
+ );
2234
1908
  for (const comp of snapshot) {
2235
1909
  if (!comp.label) continue;
2236
1910
  const compLabel = comp.label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
2237
1911
  if (compLabel === normalizedMetaLabel || compLabel.includes(normalizedMetaLabel) || normalizedMetaLabel.includes(compLabel)) {
2238
- console.log(`[Appilots] resolveComponentId: FOUND via metadata: "${componentId}" \u2192 "${comp.id}" (label="${comp.label}")`);
1912
+ chunkYB77RYCC_js.appilotsDebugLog(
1913
+ `resolveComponentId: FOUND via metadata: "${componentId}" \u2192 "${comp.id}" (label="${comp.label}")`
1914
+ );
2239
1915
  return comp.id;
2240
1916
  }
2241
1917
  }
@@ -2250,8 +1926,8 @@ function resolveComponentId(componentId, registry, action) {
2250
1926
  }));
2251
1927
  const match = resolveTarget(componentId, candidates, { action });
2252
1928
  if (match.status === "matched") {
2253
- console.log(
2254
- `[Appilots] resolveComponentId: matched "${componentId}" -> "${match.id}" (tier=${match.tier})`
1929
+ chunkYB77RYCC_js.appilotsDebugLog(
1930
+ `resolveComponentId: matched "${componentId}" -> "${match.id}" (tier=${match.tier})`
2255
1931
  );
2256
1932
  return match.id;
2257
1933
  }
@@ -2340,8 +2016,8 @@ function setValueHandler(rawComponentId, requested, registry) {
2340
2016
  try {
2341
2017
  slider.setValue(applied);
2342
2018
  if (applied !== requestedValue) {
2343
- console.log(
2344
- `[Appilots] uiInteractionHandler: set_value snapped ${requestedValue} \u2192 ${applied} for "${componentId}" (step=${step})`
2019
+ chunkYB77RYCC_js.appilotsDebugLog(
2020
+ `uiInteractionHandler: set_value snapped ${requestedValue} \u2192 ${applied} for "${componentId}" (step=${step})`
2345
2021
  );
2346
2022
  }
2347
2023
  return { success: true, effect: "changed" };
@@ -2375,11 +2051,26 @@ function checkModalOcclusion(rawComponentId, action) {
2375
2051
  return null;
2376
2052
  }
2377
2053
  if (typeof rawComponentId !== "string" || rawComponentId.trim().length === 0) return null;
2378
- const fiberRoot = chunkDZ7QRFHD_js.getFiberRoot();
2054
+ const dialog = chunkYB77RYCC_js.getOpenNativeDialog();
2055
+ if (dialog) {
2056
+ const needle = normalizeIdent(rawComponentId);
2057
+ if (dialog.buttons.some((b) => normalizeIdent(b.label) === needle)) return null;
2058
+ return {
2059
+ success: false,
2060
+ error: `"${rawComponentId}" is behind a native dialog${dialog.title ? ` ("${dialog.title}")` : ""} and cannot receive touches. Answer the dialog first \u2014 press one of: ` + dialog.buttons.map((b) => b.label).join(", "),
2061
+ diagnose: {
2062
+ category: "ambiguous-target",
2063
+ targetId: rawComponentId,
2064
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
2065
+ candidates: dialog.buttons.map((b) => b.label).slice(0, 8)
2066
+ }
2067
+ };
2068
+ }
2069
+ const fiberRoot = chunkYB77RYCC_js.getFiberRoot();
2379
2070
  if (!fiberRoot) return null;
2380
2071
  let snap;
2381
2072
  try {
2382
- snap = walkFiber(fiberRoot);
2073
+ snap = chunkYB77RYCC_js.walkFiber(fiberRoot);
2383
2074
  } catch {
2384
2075
  return null;
2385
2076
  }
@@ -2406,9 +2097,12 @@ function checkModalOcclusion(rawComponentId, action) {
2406
2097
  modalOptionLabels.push(button.label ?? button.id);
2407
2098
  }
2408
2099
  }
2409
- for (const toggle of snap.toggles ?? []) add(toggle.inModal ? inModal : outside, toggle.id, toggle.label);
2410
- for (const input of snap.inputs ?? []) add(input.inModal ? inModal : outside, input.id, input.label);
2411
- for (const slider of snap.sliders ?? []) add(slider.inModal ? inModal : outside, slider.id, slider.label);
2100
+ for (const toggle of snap.toggles ?? [])
2101
+ add(toggle.inModal ? inModal : outside, toggle.id, toggle.label);
2102
+ for (const input of snap.inputs ?? [])
2103
+ add(input.inModal ? inModal : outside, input.id, input.label);
2104
+ for (const slider of snap.sliders ?? [])
2105
+ add(slider.inModal ? inModal : outside, slider.id, slider.label);
2412
2106
  for (const list of snap.lists ?? []) {
2413
2107
  for (const item of list.items ?? []) {
2414
2108
  const itemInModal = (item.buttons ?? []).some((b) => b.inModal) || (item.inputs ?? []).some((i) => i.inModal) || (item.toggles ?? []).some((t) => t.inModal);
@@ -2438,12 +2132,15 @@ function checkModalOcclusion(rawComponentId, action) {
2438
2132
  }
2439
2133
  function uiInteractionHandler(payload, context) {
2440
2134
  const { permissions } = context;
2441
- const registry = context.registry ?? chunkDZ7QRFHD_js.componentRegistry;
2135
+ const registry = context.registry ?? chunkYB77RYCC_js.componentRegistry;
2442
2136
  if (!permissions.canInteractUI) {
2443
2137
  return {
2444
2138
  success: false,
2445
2139
  error: "UI interaction is not permitted",
2446
- diagnose: buildUiDiagnose(payload.componentId ?? payload.targetId ?? "", "unknown")
2140
+ diagnose: buildUiDiagnose(
2141
+ payload.componentId ?? payload.targetId ?? "",
2142
+ "unknown"
2143
+ )
2447
2144
  };
2448
2145
  }
2449
2146
  const { action } = payload;
@@ -2457,8 +2154,8 @@ function uiInteractionHandler(payload, context) {
2457
2154
  if (sliderId) {
2458
2155
  const smuggled = payload.value ?? payload.params?.value;
2459
2156
  if (smuggled !== void 0) {
2460
- console.log(
2461
- `[Appilots] uiInteractionHandler: "${actionStr}" on slider "${sliderId}" carried value=${JSON.stringify(smuggled)} \u2014 routing to set_value`
2157
+ chunkYB77RYCC_js.appilotsDebugLog(
2158
+ `uiInteractionHandler: "${actionStr}" on slider "${sliderId}" carried value=${JSON.stringify(smuggled)} \u2014 routing to set_value`
2462
2159
  );
2463
2160
  return setValueHandler(rawComponentId, smuggled, registry);
2464
2161
  }
@@ -2468,18 +2165,53 @@ function uiInteractionHandler(payload, context) {
2468
2165
  diagnose: { ...buildUiDiagnose(sliderId, "unknown"), recoverable: true }
2469
2166
  };
2470
2167
  }
2168
+ const openDialog = chunkYB77RYCC_js.getOpenNativeDialog();
2169
+ const isPressVerb = actionStr === "press" || actionStr === "tap" || actionStr === "click";
2170
+ if (openDialog && isPressVerb) {
2171
+ const needle = normalizeIdent(rawComponentId);
2172
+ const button = openDialog.buttons.find((b) => normalizeIdent(b.label) === needle);
2173
+ if (button) {
2174
+ button.press();
2175
+ chunkYB77RYCC_js.appilotsDebugLog(`uiInteractionHandler: pressed native dialog button "${button.label}"`);
2176
+ return { success: true, effect: "changed" };
2177
+ }
2178
+ }
2179
+ if (!openDialog && isPressVerb) {
2180
+ const answered = chunkYB77RYCC_js.getLastAnsweredNativeDialog();
2181
+ const needle = normalizeIdent(rawComponentId);
2182
+ if (answered && needle) {
2183
+ if (answered.answeredWith && normalizeIdent(answered.answeredWith) === needle) {
2184
+ chunkYB77RYCC_js.appilotsDebugLog(
2185
+ `uiInteractionHandler: native dialog button "${answered.answeredWith}" was already pressed and the dialog is closed \u2014 treating the repeat as done`
2186
+ );
2187
+ return { success: true, effect: "completed" };
2188
+ }
2189
+ if (answered.buttons.some((label) => normalizeIdent(label) === needle)) {
2190
+ return {
2191
+ success: false,
2192
+ error: `The dialog${answered.title ? ` ("${answered.title}")` : ""} was already answered with "${answered.answeredWith ?? "dismiss"}", so "${rawComponentId}" is no longer on screen. Read the current screen before acting again.`,
2193
+ diagnose: {
2194
+ category: "component-not-found",
2195
+ targetId: rawComponentId,
2196
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
2197
+ recoverable: false
2198
+ }
2199
+ };
2200
+ }
2201
+ }
2202
+ }
2471
2203
  const occluded = checkModalOcclusion(rawComponentId, actionStr);
2472
2204
  if (occluded) {
2473
- console.log(
2474
- `[Appilots] uiInteractionHandler: blocked "${actionStr}" on "${rawComponentId}" \u2014 target is behind an open modal`
2205
+ chunkYB77RYCC_js.appilotsDebugLog(
2206
+ `uiInteractionHandler: blocked "${actionStr}" on "${rawComponentId}" \u2014 target is behind an open modal`
2475
2207
  );
2476
2208
  return occluded;
2477
2209
  }
2478
2210
  if (typeof rawComponentId === "string" && rawComponentId.trim().toLowerCase().startsWith("el:")) {
2479
2211
  const result = dispatchElementOrTarget(rawComponentId, registry, actionStr);
2480
2212
  if (result.success) {
2481
- console.log(
2482
- `[Appilots] uiInteractionHandler: interaction element dispatch succeeded for "${rawComponentId}"`
2213
+ chunkYB77RYCC_js.appilotsDebugLog(
2214
+ `uiInteractionHandler: interaction element dispatch succeeded for "${rawComponentId}"`
2483
2215
  );
2484
2216
  return { success: true };
2485
2217
  }
@@ -2487,17 +2219,17 @@ function uiInteractionHandler(payload, context) {
2487
2219
  }
2488
2220
  const ordinal = parseSyntheticListItemId(rawComponentId);
2489
2221
  if (ordinal && (action === "press" || actionStr === "tap" || actionStr === "click" || actionStr === "longPress")) {
2490
- console.log(
2491
- `[Appilots] uiInteractionHandler: dispatching synthetic list ordinal \u2014 componentId="${rawComponentId}" list=${ordinal.listIndex} item=${ordinal.itemIndex}`
2222
+ chunkYB77RYCC_js.appilotsDebugLog(
2223
+ `uiInteractionHandler: dispatching synthetic list ordinal \u2014 componentId="${rawComponentId}" list=${ordinal.listIndex} item=${ordinal.itemIndex}`
2492
2224
  );
2493
2225
  const result = pressListItemAtOrdinal(ordinal.listIndex, ordinal.itemIndex);
2494
2226
  if (result.ok) {
2495
- console.log(
2496
- `[Appilots] uiInteractionHandler: synthetic ordinal press succeeded (container=${result.containerType ?? "List"})`
2227
+ chunkYB77RYCC_js.appilotsDebugLog(
2228
+ `uiInteractionHandler: synthetic ordinal press succeeded (container=${result.containerType ?? "List"})`
2497
2229
  );
2498
2230
  return { success: true };
2499
2231
  }
2500
- const screen = chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0;
2232
+ const screen = chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2501
2233
  if (result.reason === "list-not-found" || result.reason === "item-not-found") {
2502
2234
  return {
2503
2235
  success: false,
@@ -2538,7 +2270,9 @@ function uiInteractionHandler(payload, context) {
2538
2270
  };
2539
2271
  }
2540
2272
  const componentId = resolveComponentId(rawComponentId, registry, actionStr);
2541
- console.log(`[Appilots] uiInteractionHandler: resolved componentId="${payload.componentId}" \u2192 "${componentId}"`);
2273
+ chunkYB77RYCC_js.appilotsDebugLog(
2274
+ `uiInteractionHandler: resolved componentId="${payload.componentId}" \u2192 "${componentId}"`
2275
+ );
2542
2276
  const target = registry.getTarget(componentId);
2543
2277
  if (target) {
2544
2278
  try {
@@ -2589,7 +2323,9 @@ function uiInteractionHandler(payload, context) {
2589
2323
  return { success: false, error: err?.message ?? "Focus failed" };
2590
2324
  }
2591
2325
  }
2592
- console.log(`[Appilots] uiInteractionHandler: registry miss for "${componentId}", falling back to fiber tree`);
2326
+ chunkYB77RYCC_js.appilotsDebugLog(
2327
+ `uiInteractionHandler: registry miss for "${componentId}", falling back to fiber tree`
2328
+ );
2593
2329
  const handle = findInteractiveByIdentifier(componentId, {
2594
2330
  kind: actionStr === "toggle" ? "toggle" : actionStr === "focus" ? "field" : "target"
2595
2331
  });
@@ -2597,7 +2333,9 @@ function uiInteractionHandler(payload, context) {
2597
2333
  try {
2598
2334
  if (actionStr === "press" && handle.kind === "target" && handle.press) {
2599
2335
  handle.press();
2600
- console.log(`[Appilots] uiInteractionHandler: fiber fallback press succeeded for "${componentId}"`);
2336
+ chunkYB77RYCC_js.appilotsDebugLog(
2337
+ `uiInteractionHandler: fiber fallback press succeeded for "${componentId}"`
2338
+ );
2601
2339
  return { success: true };
2602
2340
  }
2603
2341
  if (actionStr === "press" && handle.kind === "toggle" && handle.setValue) {
@@ -2662,7 +2400,7 @@ function submitLabelHintsSubmit(label) {
2662
2400
  return SUBMIT_LABEL_HINT_RE.test(trimmed);
2663
2401
  }
2664
2402
  function screenDeclaresSubmitAction(screenName) {
2665
- const meta = chunkDZ7QRFHD_js.getScreenMetadata(screenName);
2403
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2666
2404
  return Array.isArray(meta?.actions) && meta.actions.some(
2667
2405
  (action) => typeof action === "object" && action !== null && action.type === "submit"
2668
2406
  );
@@ -2695,7 +2433,7 @@ function resolveFormScreensForSubmit(screen, activePath, registry) {
2695
2433
  } else {
2696
2434
  push(screen);
2697
2435
  }
2698
- push(chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0);
2436
+ push(chunkYB77RYCC_js.getCurrentScreen() ?? void 0);
2699
2437
  const withSubmit = [];
2700
2438
  const rest = [];
2701
2439
  for (const name of ordered) {
@@ -2713,7 +2451,7 @@ function collectSubmitTargetCandidates(screens, registry) {
2713
2451
  candidates.push(id);
2714
2452
  };
2715
2453
  for (const screenName of screens) {
2716
- const meta = chunkDZ7QRFHD_js.getScreenMetadata(screenName);
2454
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2717
2455
  const submitMeta = Array.isArray(meta?.actions) ? meta.actions.find(
2718
2456
  (action) => typeof action === "object" && action !== null && action.type === "submit"
2719
2457
  ) : void 0;
@@ -2743,12 +2481,10 @@ function readVisibleValidation(fieldId, label) {
2743
2481
  try {
2744
2482
  const snap = captureSnapshot();
2745
2483
  const texts = snap.texts ?? [];
2746
- const needles = [fieldId, label].filter(
2747
- (s) => !!s && s.length > 0
2748
- );
2484
+ const needles = [fieldId, label].filter((s) => !!s && s.length > 0);
2749
2485
  for (const text of texts) {
2750
2486
  const lower = text.toLowerCase();
2751
- if (FORM_VALIDATION_TEXT_RE.test(lower)) {
2487
+ if (FORM_VALIDATION_TEXT_RE2.test(lower)) {
2752
2488
  for (const needle of needles) {
2753
2489
  if (lower.includes(needle.toLowerCase())) return text;
2754
2490
  }
@@ -2759,8 +2495,8 @@ function readVisibleValidation(fieldId, label) {
2759
2495
  return void 0;
2760
2496
  }
2761
2497
  function resolveScreenContext() {
2762
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
2763
- const screen = activePath[activePath.length - 1] ?? chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0;
2498
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
2499
+ const screen = activePath[activePath.length - 1] ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2764
2500
  return { screen, activePath };
2765
2501
  }
2766
2502
  function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
@@ -2768,36 +2504,36 @@ function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
2768
2504
  if (!requested) return false;
2769
2505
  const meta = getMetadataField(fieldId, registry);
2770
2506
  const options = Array.isArray(meta?.options) ? meta.options : [];
2771
- const requestedNorm = chunkDZ7QRFHD_js.normalize3(requested);
2772
- const currentNorm = chunkDZ7QRFHD_js.normalize3(currentValue);
2507
+ const requestedNorm = chunkYB77RYCC_js.normalize3(requested);
2508
+ const currentNorm = chunkYB77RYCC_js.normalize3(currentValue);
2773
2509
  if (currentNorm === requestedNorm) return true;
2774
2510
  for (const option of options) {
2775
2511
  const value = typeof option?.value === "string" ? option.value : "";
2776
2512
  const label = typeof option?.label === "string" ? option.label : "";
2777
- if (chunkDZ7QRFHD_js.normalize3(value) === requestedNorm && chunkDZ7QRFHD_js.normalize3(label) === currentNorm) return true;
2778
- if (chunkDZ7QRFHD_js.normalize3(label) === requestedNorm && chunkDZ7QRFHD_js.normalize3(label) === currentNorm) return true;
2779
- if (chunkDZ7QRFHD_js.normalize3(value) === requestedNorm && chunkDZ7QRFHD_js.normalize3(value) === currentNorm) return true;
2513
+ if (chunkYB77RYCC_js.normalize3(value) === requestedNorm && chunkYB77RYCC_js.normalize3(label) === currentNorm) return true;
2514
+ if (chunkYB77RYCC_js.normalize3(label) === requestedNorm && chunkYB77RYCC_js.normalize3(label) === currentNorm) return true;
2515
+ if (chunkYB77RYCC_js.normalize3(value) === requestedNorm && chunkYB77RYCC_js.normalize3(value) === currentNorm) return true;
2780
2516
  }
2781
2517
  return false;
2782
2518
  }
2783
2519
  function getMetadataField(fieldId, registry) {
2784
2520
  const screens = /* @__PURE__ */ new Set();
2785
- for (const name of chunkDZ7QRFHD_js.getActiveRouteNames()) screens.add(name);
2786
- const current = chunkDZ7QRFHD_js.getCurrentScreen();
2521
+ for (const name of chunkYB77RYCC_js.getActiveRouteNames()) screens.add(name);
2522
+ const current = chunkYB77RYCC_js.getCurrentScreen();
2787
2523
  if (current) screens.add(current);
2788
2524
  if (registry) {
2789
2525
  for (const comp of registry.snapshot()) {
2790
2526
  if (comp.kind === "field" && comp.screen) screens.add(comp.screen);
2791
2527
  }
2792
2528
  }
2793
- const needle = chunkDZ7QRFHD_js.normalize3(fieldId);
2529
+ const needle = chunkYB77RYCC_js.normalize3(fieldId);
2794
2530
  for (const screenName of screens) {
2795
- const screenMeta = chunkDZ7QRFHD_js.getScreenMetadata(screenName);
2531
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2796
2532
  const fields = Array.isArray(screenMeta?.fields) ? screenMeta.fields : [];
2797
2533
  const match = fields.find((field) => {
2798
2534
  if (!field || typeof field !== "object") return false;
2799
- const id = typeof field.id === "string" ? chunkDZ7QRFHD_js.normalize3(field.id) : "";
2800
- const label = typeof field.label === "string" ? chunkDZ7QRFHD_js.normalize3(field.label) : "";
2535
+ const id = typeof field.id === "string" ? chunkYB77RYCC_js.normalize3(field.id) : "";
2536
+ const label = typeof field.label === "string" ? chunkYB77RYCC_js.normalize3(field.label) : "";
2801
2537
  return id === needle || label === needle;
2802
2538
  });
2803
2539
  if (match) return match;
@@ -2809,11 +2545,11 @@ function resolveSelectOption(fieldId, value, registry) {
2809
2545
  if (!requested) return void 0;
2810
2546
  const meta = getMetadataField(fieldId, registry);
2811
2547
  const options = Array.isArray(meta?.options) ? meta.options : [];
2812
- const requestedNorm = chunkDZ7QRFHD_js.normalize3(requested);
2548
+ const requestedNorm = chunkYB77RYCC_js.normalize3(requested);
2813
2549
  for (const option of options) {
2814
2550
  const optionValue = typeof option?.value === "string" ? option.value : "";
2815
2551
  const optionLabel = typeof option?.label === "string" ? option.label : "";
2816
- if (chunkDZ7QRFHD_js.normalize3(optionValue) === requestedNorm || chunkDZ7QRFHD_js.normalize3(optionLabel) === requestedNorm) {
2552
+ if (chunkYB77RYCC_js.normalize3(optionValue) === requestedNorm || chunkYB77RYCC_js.normalize3(optionLabel) === requestedNorm) {
2817
2553
  return { value: optionValue, label: optionLabel };
2818
2554
  }
2819
2555
  }
@@ -2863,14 +2599,16 @@ async function tryPressSelectOption(fieldId, value, registry, options = {}) {
2863
2599
  return {
2864
2600
  success: false,
2865
2601
  error: `No pressable option found for select field "${fieldId}"`,
2866
- diagnose: { category: "component-not-found", fieldId, screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0 }
2602
+ diagnose: { category: "component-not-found", fieldId, screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
2867
2603
  };
2868
2604
  }
2869
2605
  function normalizeFieldType(type) {
2870
2606
  if (typeof type !== "string") return void 0;
2871
- const normalized = chunkDZ7QRFHD_js.normalize3(type);
2872
- if (normalized === "select" || normalized === "picker" || normalized === "dropdown") return "select";
2873
- if (normalized === "toggle" || normalized === "switch" || normalized === "checkbox") return "toggle";
2607
+ const normalized = chunkYB77RYCC_js.normalize3(type);
2608
+ if (normalized === "select" || normalized === "picker" || normalized === "dropdown")
2609
+ return "select";
2610
+ if (normalized === "toggle" || normalized === "switch" || normalized === "checkbox")
2611
+ return "toggle";
2874
2612
  if (normalized === "date") return "date";
2875
2613
  if (normalized === "number" || normalized === "numeric") return "number";
2876
2614
  if (normalized === "custom") return "custom";
@@ -2896,7 +2634,7 @@ function fieldCueTerms(fieldId, label) {
2896
2634
  );
2897
2635
  const terms = /* @__PURE__ */ new Set();
2898
2636
  for (const value of raw) {
2899
- const normalized = chunkDZ7QRFHD_js.normalize3(value);
2637
+ const normalized = chunkYB77RYCC_js.normalize3(value);
2900
2638
  if (normalized.length >= 3 && normalized !== "id") terms.add(normalized);
2901
2639
  }
2902
2640
  return [...terms];
@@ -2904,20 +2642,17 @@ function fieldCueTerms(fieldId, label) {
2904
2642
  function snapshotHasFieldCue(snap, fieldId, label) {
2905
2643
  const terms = fieldCueTerms(fieldId, label);
2906
2644
  if (terms.length === 0) return false;
2907
- const visible = [
2908
- ...snap.texts ?? [],
2909
- ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")
2910
- ].map((text) => chunkDZ7QRFHD_js.normalize3(text)).filter(Boolean);
2645
+ const visible = [...snap.texts ?? [], ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")].map((text) => chunkYB77RYCC_js.normalize3(text)).filter(Boolean);
2911
2646
  return visible.some((text) => terms.some((term) => text.includes(term) || term.includes(text)));
2912
2647
  }
2913
2648
  function scoreCandidateText(value, texts) {
2914
- const valueNorm = chunkDZ7QRFHD_js.normalize3(String(value ?? ""));
2649
+ const valueNorm = chunkYB77RYCC_js.normalize3(String(value ?? ""));
2915
2650
  if (!valueNorm) return 0;
2916
2651
  let best = 0;
2917
2652
  for (const text of texts) {
2918
- const textNorm = chunkDZ7QRFHD_js.normalize3(text);
2653
+ const textNorm = chunkYB77RYCC_js.normalize3(text);
2919
2654
  if (!textNorm) continue;
2920
- best = Math.max(best, chunkDZ7QRFHD_js.matchScore(valueNorm, textNorm));
2655
+ best = Math.max(best, chunkYB77RYCC_js.matchScore(valueNorm, textNorm));
2921
2656
  }
2922
2657
  return best;
2923
2658
  }
@@ -2931,7 +2666,7 @@ function optionTexts(option) {
2931
2666
  function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue, registry) {
2932
2667
  const fieldLabel = getFieldLabel(fieldId, registry);
2933
2668
  const fieldCueVisible = snapshotHasFieldCue(snap, fieldId, fieldLabel);
2934
- const genericValue = chunkDZ7QRFHD_js.isGenericSelectValue(value);
2669
+ const genericValue = chunkYB77RYCC_js.isGenericSelectValue(value);
2935
2670
  const candidates = [];
2936
2671
  let order = 0;
2937
2672
  const choiceGroups = snap.choiceGroups ?? [];
@@ -2943,7 +2678,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
2943
2678
  const groupCueScore = Math.max(
2944
2679
  globalCueScore,
2945
2680
  ...groupTexts.map((text) => {
2946
- const normalized = chunkDZ7QRFHD_js.normalize3(text);
2681
+ const normalized = chunkYB77RYCC_js.normalize3(text);
2947
2682
  return fieldCueTerms(fieldId, fieldLabel).some(
2948
2683
  (term) => normalized.includes(term) || term.includes(normalized)
2949
2684
  ) ? 80 : 0;
@@ -2980,10 +2715,8 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
2980
2715
  const elementCueScore = Math.max(
2981
2716
  fieldCueVisible && elements.length <= 12 ? 50 : 0,
2982
2717
  ...cueTexts.map((text) => {
2983
- const normalized = chunkDZ7QRFHD_js.normalize3(text);
2984
- return fieldTerms.some(
2985
- (term) => normalized.includes(term) || term.includes(normalized)
2986
- ) ? 80 : 0;
2718
+ const normalized = chunkYB77RYCC_js.normalize3(text);
2719
+ return fieldTerms.some((term) => normalized.includes(term) || term.includes(normalized)) ? 80 : 0;
2987
2720
  })
2988
2721
  );
2989
2722
  const valueScore = genericValue ? 0 : scoreCandidateText(value, texts);
@@ -3040,7 +2773,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3040
2773
  return {
3041
2774
  success: false,
3042
2775
  error: err?.message ?? "Could not capture visible choices",
3043
- diagnose: { category: "unknown", fieldId, screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0 }
2776
+ diagnose: { category: "unknown", fieldId, screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
3044
2777
  };
3045
2778
  }
3046
2779
  const candidates = buildChoiceCandidates(
@@ -3055,7 +2788,11 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3055
2788
  return {
3056
2789
  success: false,
3057
2790
  error: `No visible option found for select field "${fieldId}"`,
3058
- diagnose: { category: "component-not-found", fieldId, screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0 }
2791
+ diagnose: {
2792
+ category: "component-not-found",
2793
+ fieldId,
2794
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0
2795
+ }
3059
2796
  };
3060
2797
  }
3061
2798
  const pressed = pressTargetByIdOrLabel(candidate.targetId, registry);
@@ -3068,7 +2805,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3068
2805
  }
3069
2806
  function isContinuationButton(label) {
3070
2807
  if (!label) return false;
3071
- return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkDZ7QRFHD_js.normalize3(label));
2808
+ return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkYB77RYCC_js.normalize3(label));
3072
2809
  }
3073
2810
  function pressContinuationButton(registry) {
3074
2811
  const snap = captureSnapshot();
@@ -3081,38 +2818,40 @@ function pressContinuationButton(registry) {
3081
2818
  return {
3082
2819
  success: false,
3083
2820
  error: "No enabled continuation button is visible",
3084
- diagnose: { category: "component-not-found", screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0 }
2821
+ diagnose: { category: "component-not-found", screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
3085
2822
  };
3086
2823
  }
3087
2824
  return pressTargetByIdOrLabel(id, registry);
3088
2825
  }
3089
2826
  function findField(fieldId, registry) {
3090
- console.log(`[Appilots] findField: searching for fieldId="${fieldId}"`);
2827
+ chunkYB77RYCC_js.appilotsDebugLog(`findField: searching for fieldId="${fieldId}"`);
3091
2828
  const exact = registry.getField(fieldId);
3092
2829
  if (exact) {
3093
- console.log(`[Appilots] findField: FOUND exact match for fieldId="${fieldId}"`);
2830
+ chunkYB77RYCC_js.appilotsDebugLog(`findField: FOUND exact match for fieldId="${fieldId}"`);
3094
2831
  return exact;
3095
2832
  }
3096
2833
  const lower = fieldId.toLowerCase();
3097
2834
  const snapshot = registry.snapshot();
3098
2835
  for (const comp of snapshot) {
3099
2836
  if (comp.kind === "field" && comp.id.toLowerCase() === lower) {
3100
- console.log(`[Appilots] findField: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`);
2837
+ chunkYB77RYCC_js.appilotsDebugLog(
2838
+ `findField: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
2839
+ );
3101
2840
  return registry.getField(comp.id);
3102
2841
  }
3103
2842
  }
3104
- const currentScreenForTieBreak = chunkDZ7QRFHD_js.getCurrentScreen();
3105
- const needle = chunkDZ7QRFHD_js.normalize3(fieldId);
2843
+ const currentScreenForTieBreak = chunkYB77RYCC_js.getCurrentScreen();
2844
+ const needle = chunkYB77RYCC_js.normalize3(fieldId);
3106
2845
  let bestComp;
3107
2846
  let bestScore = 0;
3108
2847
  let bestOnCurrentScreen = false;
3109
2848
  for (const comp of snapshot) {
3110
2849
  if (comp.kind !== "field") continue;
3111
- const candidates = [chunkDZ7QRFHD_js.normalize3(comp.id)];
3112
- if (comp.label) candidates.push(chunkDZ7QRFHD_js.normalize3(comp.label));
2850
+ const candidates = [chunkYB77RYCC_js.normalize3(comp.id)];
2851
+ if (comp.label) candidates.push(chunkYB77RYCC_js.normalize3(comp.label));
3113
2852
  let candidateScore = 0;
3114
2853
  for (const cand of candidates) {
3115
- const s = chunkDZ7QRFHD_js.matchScore(needle, cand);
2854
+ const s = chunkYB77RYCC_js.matchScore(needle, cand);
3116
2855
  if (s > candidateScore) candidateScore = s;
3117
2856
  }
3118
2857
  if (candidateScore === 0) continue;
@@ -3125,14 +2864,14 @@ function findField(fieldId, registry) {
3125
2864
  }
3126
2865
  }
3127
2866
  if (bestComp && bestScore >= 75) {
3128
- console.log(
3129
- `[Appilots] findField: scored match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
2867
+ chunkYB77RYCC_js.appilotsDebugLog(
2868
+ `findField: scored match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
3130
2869
  );
3131
2870
  return registry.getField(bestComp.id);
3132
2871
  }
3133
- const currentScreen = chunkDZ7QRFHD_js.getCurrentScreen();
2872
+ const currentScreen = chunkYB77RYCC_js.getCurrentScreen();
3134
2873
  if (currentScreen) {
3135
- const screenMeta = chunkDZ7QRFHD_js.getScreenMetadata(currentScreen);
2874
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(currentScreen);
3136
2875
  const fields = screenMeta?.fields;
3137
2876
  if (fields && Array.isArray(fields)) {
3138
2877
  const metaField = fields.find(
@@ -3140,20 +2879,20 @@ function findField(fieldId, registry) {
3140
2879
  );
3141
2880
  if (metaField && typeof metaField === "object" && metaField.label) {
3142
2881
  const metaLabel = metaField.label;
3143
- const metaNeedle = chunkDZ7QRFHD_js.normalize3(metaLabel);
2882
+ const metaNeedle = chunkYB77RYCC_js.normalize3(metaLabel);
3144
2883
  let mBest;
3145
2884
  let mBestScore = 0;
3146
2885
  for (const comp of snapshot) {
3147
2886
  if (comp.kind !== "field" || !comp.label) continue;
3148
- const score = chunkDZ7QRFHD_js.matchScore(metaNeedle, chunkDZ7QRFHD_js.normalize3(comp.label));
2887
+ const score = chunkYB77RYCC_js.matchScore(metaNeedle, chunkYB77RYCC_js.normalize3(comp.label));
3149
2888
  if (score > mBestScore) {
3150
2889
  mBestScore = score;
3151
2890
  mBest = comp;
3152
2891
  }
3153
2892
  }
3154
2893
  if (mBest && mBestScore >= 60) {
3155
- console.log(
3156
- `[Appilots] findField: FOUND via screen metadata translation: fieldId="${fieldId}" -> metaLabel="${metaLabel}" -> registered="${mBest.id}" (score=${mBestScore})`
2894
+ chunkYB77RYCC_js.appilotsDebugLog(
2895
+ `findField: FOUND via screen metadata translation: fieldId="${fieldId}" -> metaLabel="${metaLabel}" -> registered="${mBest.id}" (score=${mBestScore})`
3157
2896
  );
3158
2897
  return registry.getField(mBest.id);
3159
2898
  }
@@ -3161,32 +2900,34 @@ function findField(fieldId, registry) {
3161
2900
  }
3162
2901
  }
3163
2902
  if (bestComp && bestScore >= 40) {
3164
- console.log(
3165
- `[Appilots] findField: weak substring match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
2903
+ chunkYB77RYCC_js.appilotsDebugLog(
2904
+ `findField: weak substring match "${fieldId}" -> "${bestComp.id}" (label="${bestComp.label}", score=${bestScore})`
3166
2905
  );
3167
2906
  return registry.getField(bestComp.id);
3168
2907
  }
3169
- chunkDZ7QRFHD_js.appilotsDebugWarn(
2908
+ chunkYB77RYCC_js.appilotsDebugWarn(
3170
2909
  `findField: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available fields: ${snapshot.filter((c) => c.kind === "field").map((c) => `"${c.id}" (label: ${c.label})`).join(", ") || "none"}`
3171
2910
  );
3172
2911
  return void 0;
3173
2912
  }
3174
2913
  function findToggle(fieldId, registry) {
3175
- console.log(`[Appilots] findToggle: searching for fieldId="${fieldId}"`);
2914
+ chunkYB77RYCC_js.appilotsDebugLog(`findToggle: searching for fieldId="${fieldId}"`);
3176
2915
  const exact = registry.getToggle(fieldId);
3177
2916
  if (exact) {
3178
- console.log(`[Appilots] findToggle: FOUND exact match for "${fieldId}"`);
2917
+ chunkYB77RYCC_js.appilotsDebugLog(`findToggle: FOUND exact match for "${fieldId}"`);
3179
2918
  return exact;
3180
2919
  }
3181
2920
  const lower = fieldId.toLowerCase();
3182
2921
  const snapshot = registry.snapshot();
3183
2922
  for (const comp of snapshot) {
3184
2923
  if (comp.kind === "toggle" && comp.id.toLowerCase() === lower) {
3185
- console.log(`[Appilots] findToggle: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`);
2924
+ chunkYB77RYCC_js.appilotsDebugLog(
2925
+ `findToggle: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
2926
+ );
3186
2927
  return registry.getToggle(comp.id);
3187
2928
  }
3188
2929
  }
3189
- chunkDZ7QRFHD_js.appilotsDebugWarn(
2930
+ chunkYB77RYCC_js.appilotsDebugWarn(
3190
2931
  `findToggle: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available toggles: ${snapshot.filter((c) => c.kind === "toggle").map((c) => `"${c.id}"`).join(", ") || "none"}`
3191
2932
  );
3192
2933
  return void 0;
@@ -3197,7 +2938,9 @@ function findSlider(fieldId, registry) {
3197
2938
  const lower = fieldId.toLowerCase();
3198
2939
  for (const comp of registry.snapshot()) {
3199
2940
  if (comp.kind === "slider" && comp.id.toLowerCase() === lower) {
3200
- console.log(`[Appilots] findSlider: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`);
2941
+ chunkYB77RYCC_js.appilotsDebugLog(
2942
+ `findSlider: FOUND case-insensitive match: registered="${comp.id}" for searched="${fieldId}"`
2943
+ );
3201
2944
  return registry.getSlider(comp.id);
3202
2945
  }
3203
2946
  }
@@ -3206,7 +2949,7 @@ function findSlider(fieldId, registry) {
3206
2949
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3207
2950
  async function formFillHandler(payload, context) {
3208
2951
  const { permissions } = context;
3209
- const registry = context.registry ?? chunkDZ7QRFHD_js.componentRegistry;
2952
+ const registry = context.registry ?? chunkYB77RYCC_js.componentRegistry;
3210
2953
  const { screen, activePath } = resolveScreenContext();
3211
2954
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
3212
2955
  if (!permissions.canFillForms) {
@@ -3225,11 +2968,11 @@ async function formFillHandler(payload, context) {
3225
2968
  }
3226
2969
  const registrySnapshot = registry.snapshot();
3227
2970
  if (registrySnapshot.length === 0) {
3228
- chunkDZ7QRFHD_js.appilotsDebugWarn(
2971
+ chunkYB77RYCC_js.appilotsDebugWarn(
3229
2972
  "formFillHandler: registry is EMPTY \u2014 auto-tracking may not be active. Ensure enableAppilotsAutoTracking() runs before components mount."
3230
2973
  );
3231
2974
  } else {
3232
- console.log(
2975
+ chunkYB77RYCC_js.appilotsDebugLog(
3233
2976
  `[Appilots formFillHandler] Registry has ${registrySnapshot.length} components:`,
3234
2977
  registrySnapshot.map((c) => `${c.kind}:${c.id}`).join(", ")
3235
2978
  );
@@ -3237,7 +2980,7 @@ async function formFillHandler(payload, context) {
3237
2980
  const fieldResults = [];
3238
2981
  let allSuccess = true;
3239
2982
  let selectedChoiceThisBatch = false;
3240
- console.log(`[Appilots] formFillHandler: processing ${payload.fields.length} fields`);
2983
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: processing ${payload.fields.length} fields`);
3241
2984
  const availableFieldIds = () => registry.snapshot().filter((comp) => comp.kind === "field").map((comp) => `${comp.id}${comp.label ? ` (${comp.label})` : ""}`).slice(0, 8);
3242
2985
  const isElementIdField = (field) => typeof field.fieldId === "string" && field.fieldId.trim().toLowerCase().startsWith("el:");
3243
2986
  for (const field of payload.fields.filter(isElementIdField)) {
@@ -3264,13 +3007,13 @@ async function formFillHandler(payload, context) {
3264
3007
  const { fieldId, fieldType, value } = field;
3265
3008
  const effectiveFieldType = getEffectiveFieldType(fieldId, fieldType, registry);
3266
3009
  let selectFailure;
3267
- console.log(
3268
- `[Appilots] formFillHandler: looking up fieldId="${fieldId}" fieldType="${fieldType}" effectiveFieldType="${effectiveFieldType}" value="${value}"`
3010
+ chunkYB77RYCC_js.appilotsDebugLog(
3011
+ `formFillHandler: looking up fieldId="${fieldId}" fieldType="${fieldType}" effectiveFieldType="${effectiveFieldType}" value=${chunkYB77RYCC_js.describeValue(value)}`
3269
3012
  );
3270
3013
  const fieldEntry = findField(fieldId, registry);
3271
3014
  if (fieldEntry) {
3272
3015
  try {
3273
- chunkDZ7QRFHD_js.appilotsDebugLog(
3016
+ chunkYB77RYCC_js.appilotsDebugLog(
3274
3017
  `formFillHandler: found field "${fieldId}" via registry, calling setValue(<${String(value).length} chars>)`
3275
3018
  );
3276
3019
  const beforeValue = effectiveFieldType === "date" ? fieldEntry.getValue?.() ?? "" : void 0;
@@ -3301,7 +3044,7 @@ async function formFillHandler(payload, context) {
3301
3044
  after = fieldEntry.getValue?.() ?? "";
3302
3045
  }
3303
3046
  if (!selectValueApplied(fieldId, value, after, registry)) {
3304
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3047
+ chunkYB77RYCC_js.appilotsDebugWarn(
3305
3048
  `formFillHandler: select field "${fieldId}" setValue did not stick (wrote <${String(value).length} chars>, current is <${String(after ?? "").length} chars>), trying visible choice fallback`
3306
3049
  );
3307
3050
  const selectResult = await selectVisibleChoice(fieldId, value, registry, {
@@ -3316,7 +3059,11 @@ async function formFillHandler(payload, context) {
3316
3059
  fieldId,
3317
3060
  success: false,
3318
3061
  error: selectResult.error ?? `Select value "${String(value)}" was not applied for "${fieldId}"`,
3319
- diagnose: selectResult.diagnose ?? { category: "component-not-found", fieldId, screen: screenPath }
3062
+ diagnose: selectResult.diagnose ?? {
3063
+ category: "component-not-found",
3064
+ fieldId,
3065
+ screen: screenPath
3066
+ }
3320
3067
  });
3321
3068
  allSuccess = false;
3322
3069
  continue;
@@ -3371,7 +3118,9 @@ async function formFillHandler(payload, context) {
3371
3118
  continue;
3372
3119
  }
3373
3120
  try {
3374
- sliderEntry.setValue(snapSliderValue(numeric, sliderEntry.min, sliderEntry.max, sliderEntry.step));
3121
+ sliderEntry.setValue(
3122
+ snapSliderValue(numeric, sliderEntry.min, sliderEntry.max, sliderEntry.step)
3123
+ );
3375
3124
  fieldResults.push({ fieldId, success: true });
3376
3125
  } catch (err) {
3377
3126
  fieldResults.push({
@@ -3420,8 +3169,8 @@ async function formFillHandler(payload, context) {
3420
3169
  }
3421
3170
  if (selectResult.success) {
3422
3171
  selectedChoiceThisBatch = true;
3423
- console.log(
3424
- `[Appilots] formFillHandler: selected visible option for "${fieldId}"` + (selectResult.selectedLabel ? ` \u2192 "${selectResult.selectedLabel}"` : "")
3172
+ chunkYB77RYCC_js.appilotsDebugLog(
3173
+ `formFillHandler: selected visible option for "${fieldId}"` + (selectResult.selectedLabel ? ` \u2192 "${selectResult.selectedLabel}"` : "")
3425
3174
  );
3426
3175
  await sleep2(120);
3427
3176
  fieldResults.push({ fieldId, success: true });
@@ -3429,7 +3178,7 @@ async function formFillHandler(payload, context) {
3429
3178
  }
3430
3179
  selectFailure = selectResult;
3431
3180
  }
3432
- console.log(`[Appilots] formFillHandler: registry miss for "${fieldId}", falling back to fiber tree`);
3181
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: registry miss for "${fieldId}", falling back to fiber tree`);
3433
3182
  const handle = findInteractiveByIdentifier(fieldId, {
3434
3183
  kind: effectiveFieldType === "toggle" ? "toggle" : "field"
3435
3184
  });
@@ -3437,7 +3186,9 @@ async function formFillHandler(payload, context) {
3437
3186
  try {
3438
3187
  handle.focus?.();
3439
3188
  handle.setValue(value);
3440
- console.log(`[Appilots] formFillHandler: fiber fallback succeeded for "${fieldId}" \u2192 label="${handle.label}"`);
3189
+ chunkYB77RYCC_js.appilotsDebugLog(
3190
+ `formFillHandler: fiber fallback succeeded for "${fieldId}" \u2192 label="${handle.label}"`
3191
+ );
3441
3192
  fieldResults.push({ fieldId, success: true });
3442
3193
  continue;
3443
3194
  } catch (err) {
@@ -3474,14 +3225,22 @@ async function formFillHandler(payload, context) {
3474
3225
  if (payload.submitAfterFill === true) {
3475
3226
  if (!allSuccess) {
3476
3227
  const failedIds = fieldResults.filter((result) => !result.success).map((result) => result.fieldId);
3477
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3228
+ chunkYB77RYCC_js.appilotsDebugWarn(
3478
3229
  "formFillHandler: submitAfterFill=true requested but some fields failed; NOT submitting" + (failedIds.length > 0 ? ` (failed: ${failedIds.join(", ")})` : "")
3479
3230
  );
3480
3231
  } else {
3481
3232
  await sleep2(120);
3482
- const submitResult = pressSubmitButton({ screen, screenPath, activePath }, registry);
3233
+ const submitResult = pressSubmitButton(
3234
+ {
3235
+ screen,
3236
+ screenPath,
3237
+ activePath,
3238
+ filledFieldIds: fieldResults.filter((r) => r.success).map((r) => r.fieldId)
3239
+ },
3240
+ registry
3241
+ );
3483
3242
  if (!submitResult.success) {
3484
- chunkDZ7QRFHD_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
3243
+ chunkYB77RYCC_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
3485
3244
  return {
3486
3245
  success: false,
3487
3246
  error: submitResult.error,
@@ -3493,7 +3252,7 @@ async function formFillHandler(payload, context) {
3493
3252
  submitTargetId: submitResult.pressedTargetId
3494
3253
  });
3495
3254
  if (postSubmit.status === "pending") {
3496
- chunkDZ7QRFHD_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
3255
+ chunkYB77RYCC_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
3497
3256
  return {
3498
3257
  success: false,
3499
3258
  error: postSubmit.message,
@@ -3502,7 +3261,7 @@ async function formFillHandler(payload, context) {
3502
3261
  };
3503
3262
  }
3504
3263
  if (postSubmit.status === "failure") {
3505
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3264
+ chunkYB77RYCC_js.appilotsDebugWarn(
3506
3265
  `formFillHandler: submit rejected by visible validation \u2014 ${postSubmit.message}`
3507
3266
  );
3508
3267
  return {
@@ -3517,7 +3276,7 @@ async function formFillHandler(payload, context) {
3517
3276
  }
3518
3277
  };
3519
3278
  }
3520
- console.log("[Appilots] formFillHandler: submitAfterFill \u2014 submit completed");
3279
+ chunkYB77RYCC_js.appilotsDebugLog("formFillHandler: submitAfterFill \u2014 submit completed");
3521
3280
  }
3522
3281
  }
3523
3282
  const aggregatedDiagnose = aggregateFieldDiagnoses(fieldResults, screenPath);
@@ -3529,18 +3288,18 @@ async function formFillHandler(payload, context) {
3529
3288
  };
3530
3289
  }
3531
3290
  function pressSubmitButton(context, registry) {
3532
- const activePath = context.activePath ?? chunkDZ7QRFHD_js.getActiveRouteNames();
3291
+ const activePath = context.activePath ?? chunkYB77RYCC_js.getActiveRouteNames();
3533
3292
  const hintScreen = context.screen ?? context.screenPath;
3534
3293
  const formScreens = resolveFormScreensForSubmit(hintScreen, activePath, registry);
3535
- const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0;
3294
+ const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
3536
3295
  const candidates = collectSubmitTargetCandidates(formScreens, registry);
3537
3296
  for (const candidate of candidates) {
3538
3297
  const target = registry.getTarget(candidate);
3539
3298
  if (target) {
3540
3299
  try {
3541
3300
  target.press();
3542
- console.log(
3543
- `[Appilots] formFillHandler: submitAfterFill \u2014 pressed registry target "${candidate}"` + (resolvedScreen ? ` on screen "${resolvedScreen}"` : "")
3301
+ chunkYB77RYCC_js.appilotsDebugLog(
3302
+ `formFillHandler: submitAfterFill \u2014 pressed registry target "${candidate}"` + (resolvedScreen ? ` on screen "${resolvedScreen}"` : "")
3544
3303
  );
3545
3304
  return { success: true, pressedTargetId: candidate };
3546
3305
  } catch (err) {
@@ -3553,7 +3312,7 @@ function pressSubmitButton(context, registry) {
3553
3312
  }
3554
3313
  }
3555
3314
  for (const screenName of formScreens) {
3556
- const screenMeta = chunkDZ7QRFHD_js.getScreenMetadata(screenName);
3315
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(screenName);
3557
3316
  const submitMeta = Array.isArray(screenMeta?.actions) ? screenMeta.actions.find(
3558
3317
  (action) => typeof action === "object" && action !== null && action.type === "submit"
3559
3318
  ) : void 0;
@@ -3564,9 +3323,7 @@ function pressSubmitButton(context, registry) {
3564
3323
  if (handle?.press) {
3565
3324
  try {
3566
3325
  handle.press();
3567
- console.log(
3568
- `[Appilots] formFillHandler: submitAfterFill \u2014 fiber fallback "${submitLabel}"`
3569
- );
3326
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 fiber fallback "${submitLabel}"`);
3570
3327
  return { success: true, pressedTargetId: submitId ?? submitLabel };
3571
3328
  } catch (err) {
3572
3329
  return {
@@ -3588,9 +3345,7 @@ function pressSubmitButton(context, registry) {
3588
3345
  if (id) {
3589
3346
  const pressed = pressTargetByIdOrLabel(id, registry);
3590
3347
  if (pressed.success) {
3591
- console.log(
3592
- `[Appilots] formFillHandler: submitAfterFill \u2014 pressed visible heuristic "${id}"`
3593
- );
3348
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 pressed visible heuristic "${id}"`);
3594
3349
  return { success: true, pressedTargetId: id };
3595
3350
  }
3596
3351
  }
@@ -3604,8 +3359,8 @@ function pressSubmitButton(context, registry) {
3604
3359
  if (target) {
3605
3360
  try {
3606
3361
  target.press();
3607
- console.log(
3608
- `[Appilots] formFillHandler: submitAfterFill \u2014 pressed by label heuristic "${comp.label}"`
3362
+ chunkYB77RYCC_js.appilotsDebugLog(
3363
+ `formFillHandler: submitAfterFill \u2014 pressed by label heuristic "${comp.label}"`
3609
3364
  );
3610
3365
  return { success: true, pressedTargetId: comp.id };
3611
3366
  } catch (err) {
@@ -3617,9 +3372,16 @@ function pressSubmitButton(context, registry) {
3617
3372
  }
3618
3373
  }
3619
3374
  }
3375
+ for (const fieldId of [...context.filledFieldIds ?? []].reverse()) {
3376
+ const handle = findInteractiveByIdentifier(fieldId, { kind: "field" });
3377
+ if (handle?.submitFromKeyboard?.()) {
3378
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 return key on "${fieldId}"`);
3379
+ return { success: true, pressedTargetId: fieldId };
3380
+ }
3381
+ }
3620
3382
  return {
3621
3383
  success: false,
3622
- error: 'submitAfterFill requested but no submit button was found (declare it via registerScreen({ actions: [{ type: "submit", ... }] }) for reliable behavior)',
3384
+ error: 'submitAfterFill requested but the screen has no submit button and no field that submits on return (declare it via registerScreen({ actions: [{ type: "submit", ... }] }) for reliable behavior)',
3623
3385
  diagnose: { category: "component-not-found", screen: resolvedScreen }
3624
3386
  };
3625
3387
  }
@@ -3659,12 +3421,12 @@ function buildDiagnose(category, targetId, candidates) {
3659
3421
  return {
3660
3422
  category,
3661
3423
  targetId,
3662
- screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0,
3424
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
3663
3425
  ...candidates && candidates.length > 0 ? { candidates: candidates.slice(0, 8) } : {}
3664
3426
  };
3665
3427
  }
3666
3428
  function resolveListEntry(listId) {
3667
- const entries = chunkDZ7QRFHD_js.listRegistry.snapshot();
3429
+ const entries = chunkYB77RYCC_js.listRegistry.snapshot();
3668
3430
  if (entries.length === 0) return {};
3669
3431
  if (listId) {
3670
3432
  const wanted = normalizeId2(listId);
@@ -3673,6 +3435,8 @@ function resolveListEntry(listId) {
3673
3435
  return { candidates: entries.map((e) => e.id) };
3674
3436
  }
3675
3437
  if (entries.length === 1) return { entry: entries[0] };
3438
+ const lists = entries.filter((e) => e.kind === "list");
3439
+ if (lists.length === 1) return { entry: lists[0] };
3676
3440
  return { candidates: entries.map((e) => e.id) };
3677
3441
  }
3678
3442
  function pageOffset(metrics, direction) {
@@ -3712,7 +3476,7 @@ async function scrollListHandler(payload, context) {
3712
3476
  }
3713
3477
  const { entry, candidates } = resolveListEntry(payload.listId);
3714
3478
  if (!entry) {
3715
- const detail = candidates && candidates.length > 0 ? payload.listId ? `List "${payload.listId}" is not registered. Known lists: ${candidates.join(", ")}` : `Multiple lists are on screen \u2014 specify listId. Known lists: ${candidates.join(", ")}` : "No scrollable list is registered on the current screen (enableAppilotsAutoTracking() may be off).";
3479
+ const detail = candidates && candidates.length > 0 ? payload.listId ? `List "${payload.listId}" is not registered. Known lists: ${candidates.join(", ")}` : `Multiple lists are on screen \u2014 specify listId. Known lists: ${candidates.join(", ")}` : "Nothing scrollable is registered on the current screen (enableAppilotsAutoTracking() may be off).";
3716
3480
  return {
3717
3481
  success: false,
3718
3482
  error: detail,
@@ -3720,6 +3484,13 @@ async function scrollListHandler(payload, context) {
3720
3484
  };
3721
3485
  }
3722
3486
  if (toIndex !== void 0) {
3487
+ if (entry.kind === "scroll") {
3488
+ return {
3489
+ success: false,
3490
+ error: `"${entry.id}" is a scrollable screen, not a list \u2014 it has no numbered items. Use direction "down"/"up" to page through it.`,
3491
+ diagnose: buildDiagnose("validation", entry.id)
3492
+ };
3493
+ }
3723
3494
  if (typeof entry.itemCount === "number" && toIndex > entry.itemCount) {
3724
3495
  return {
3725
3496
  success: false,
@@ -3754,14 +3525,14 @@ async function scrollListHandler(payload, context) {
3754
3525
  }
3755
3526
  return {
3756
3527
  success: false,
3757
- error: `List "${entry.id}" does not expose a scrollable handle`,
3528
+ error: `"${entry.id}" does not expose a scrollable handle`,
3758
3529
  diagnose: buildDiagnose("unknown", entry.id)
3759
3530
  };
3760
3531
  }
3761
3532
 
3762
3533
  // src/executor/handlers/confirmHandler.ts
3763
3534
  async function confirmHandler(_actionId, _payload) {
3764
- return { success: true };
3535
+ return { success: true, effect: "unknown" };
3765
3536
  }
3766
3537
 
3767
3538
  // src/executor/postInteractionSettle.ts
@@ -3773,29 +3544,61 @@ function targetIdFromPayload(payload) {
3773
3544
  if (typeof targetId === "string" && targetId.trim()) return targetId.trim();
3774
3545
  return "";
3775
3546
  }
3547
+ function hashFieldValue(value) {
3548
+ let hash = 2166136261;
3549
+ for (let i = 0; i < value.length; i++) {
3550
+ hash ^= value.charCodeAt(i);
3551
+ hash = Math.imul(hash, 16777619);
3552
+ }
3553
+ return (hash >>> 0).toString(36);
3554
+ }
3555
+ var DISCRETE_FIELD_TYPES = /* @__PURE__ */ new Set(["select", "date"]);
3556
+ function discreteFieldSignature() {
3557
+ const sigs = [];
3558
+ for (const { id, kind } of chunkYB77RYCC_js.componentRegistry.snapshot()) {
3559
+ if (kind !== "field") continue;
3560
+ const entry = chunkYB77RYCC_js.componentRegistry.getField(id);
3561
+ if (!entry || !DISCRETE_FIELD_TYPES.has(entry.fieldType ?? "")) continue;
3562
+ try {
3563
+ sigs.push(`${id}:${hashFieldValue(String(entry.getValue() ?? ""))}`);
3564
+ } catch {
3565
+ }
3566
+ }
3567
+ return sigs.sort().join(",");
3568
+ }
3776
3569
  async function waitForPostInteractionSettle(payload) {
3777
3570
  const targetId = targetIdFromPayload(payload);
3778
- const fromScreen = chunkDZ7QRFHD_js.getCurrentScreen();
3779
- const baseline = chunkDZ7QRFHD_js.probeLoadingState(targetId || null, fromScreen);
3571
+ const fromScreen = chunkYB77RYCC_js.getCurrentScreen();
3572
+ const baseline = chunkYB77RYCC_js.probeLoadingState(targetId || null, fromScreen);
3573
+ const baselineFields = discreteFieldSignature();
3574
+ const readable = baseline.fingerprint !== "";
3780
3575
  await sleepMs(100);
3781
- const afterPress = chunkDZ7QRFHD_js.probeLoadingState(targetId || null, chunkDZ7QRFHD_js.getCurrentScreen());
3576
+ const afterPress = chunkYB77RYCC_js.probeLoadingState(targetId || null, chunkYB77RYCC_js.getCurrentScreen());
3782
3577
  const modalOrLoading = afterPress.modalOpen || afterPress.loading || afterPress.pressedDisabled;
3783
3578
  const fingerprintChanged = afterPress.fingerprint !== baseline.fingerprint;
3784
- const capMs = chunkDZ7QRFHD_js.isListItemPressTarget(targetId) ? 5e3 : 1e4;
3579
+ const verdict = () => {
3580
+ if (!readable) return { effect: "unknown" };
3581
+ const settled = chunkYB77RYCC_js.probeLoadingState(targetId || null, chunkYB77RYCC_js.getCurrentScreen());
3582
+ if (settled.fingerprint === "") return { effect: "unknown" };
3583
+ if (discreteFieldSignature() !== baselineFields) return { effect: "changed" };
3584
+ return { effect: settled.fingerprint !== baseline.fingerprint ? "changed" : "none" };
3585
+ };
3586
+ const capMs = chunkYB77RYCC_js.isListItemPressTarget(targetId) ? 5e3 : 1e4;
3785
3587
  if (modalOrLoading || fingerprintChanged) {
3786
- await chunkDZ7QRFHD_js.waitForLoadingSettle({
3588
+ await chunkYB77RYCC_js.waitForLoadingSettle({
3787
3589
  pressedComponentId: targetId || null,
3788
3590
  fromScreen,
3789
3591
  maxMs: capMs
3790
3592
  });
3791
- return;
3593
+ return verdict();
3792
3594
  }
3793
- if (chunkDZ7QRFHD_js.isListItemPressTarget(targetId)) {
3794
- await chunkDZ7QRFHD_js.waitForLoadingSettle({
3595
+ if (chunkYB77RYCC_js.isListItemPressTarget(targetId)) {
3596
+ await chunkYB77RYCC_js.waitForLoadingSettle({
3795
3597
  fromScreen,
3796
3598
  maxMs: 3e3
3797
3599
  });
3798
3600
  }
3601
+ return verdict();
3799
3602
  }
3800
3603
 
3801
3604
  // src/executor/ActionExecutor.ts
@@ -3811,7 +3614,7 @@ function validateActionPayload(action) {
3811
3614
  error: message,
3812
3615
  diagnose: {
3813
3616
  category: "validation",
3814
- screen: chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0,
3617
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
3815
3618
  ...ids ?? {}
3816
3619
  }
3817
3620
  });
@@ -3850,10 +3653,9 @@ function validateActionPayload(action) {
3850
3653
  const hasIndex = typeof payload.toIndex === "number";
3851
3654
  const hasDirection = payload.direction === "up" || payload.direction === "down";
3852
3655
  if (!hasIndex && !hasDirection) {
3853
- return invalid(
3854
- 'scroll_list action needs toIndex (1-based) or direction ("up"/"down")',
3855
- { targetId: typeof payload.listId === "string" ? payload.listId : void 0 }
3856
- );
3656
+ return invalid('scroll_list action needs toIndex (1-based) or direction ("up"/"down")', {
3657
+ targetId: typeof payload.listId === "string" ? payload.listId : void 0
3658
+ });
3857
3659
  }
3858
3660
  return null;
3859
3661
  }
@@ -3861,24 +3663,48 @@ function validateActionPayload(action) {
3861
3663
  return null;
3862
3664
  }
3863
3665
  }
3666
+ function effectFor(payload, observed) {
3667
+ if (observed === "none" && isDestructivePayload(payload)) return "unknown";
3668
+ return observed;
3669
+ }
3670
+ function isDestructivePayload(payload) {
3671
+ if (!payload || typeof payload !== "object") return false;
3672
+ const p = payload;
3673
+ if (p.destructive === true) return true;
3674
+ const params = p.params;
3675
+ return !!params && typeof params === "object" && params.destructive === true;
3676
+ }
3864
3677
  async function executeAction(action, context) {
3865
- console.log(`[Appilots] executeAction called: type="${action.type}", id="${action.id}", payload=${JSON.stringify(action.payload)}`);
3678
+ chunkYB77RYCC_js.appilotsDebugLog(
3679
+ `executeAction called: type="${action.type}", id="${action.id}", payload=${JSON.stringify(action.payload)}`
3680
+ );
3866
3681
  const permissions = context.permissions ?? DEFAULT_PERMISSIONS;
3867
- if (permissions.allowedActions && permissions.allowedActions.length > 0 && !permissions.allowedActions.includes(action.type)) {
3868
- return {
3869
- success: false,
3870
- error: `Action type "${action.type}" is not in the allowed actions list`
3871
- };
3872
- }
3873
3682
  context.emit({
3874
3683
  type: "agent:action:start",
3875
3684
  timestamp: Date.now(),
3876
3685
  data: { actionId: action.id, actionType: action.type }
3877
3686
  });
3687
+ if (permissions.allowedActions && permissions.allowedActions.length > 0 && !permissions.allowedActions.includes(action.type)) {
3688
+ const result2 = {
3689
+ success: false,
3690
+ error: `Action type "${action.type}" is not in the allowed actions list`
3691
+ };
3692
+ context.emit({
3693
+ type: "agent:action:error",
3694
+ timestamp: Date.now(),
3695
+ data: {
3696
+ actionId: action.id,
3697
+ actionType: action.type,
3698
+ success: false,
3699
+ error: result2.error
3700
+ }
3701
+ });
3702
+ return result2;
3703
+ }
3878
3704
  let result;
3879
3705
  const validationFailure = validateActionPayload(action);
3880
3706
  if (validationFailure) {
3881
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3707
+ chunkYB77RYCC_js.appilotsDebugWarn(
3882
3708
  `executeAction: payload validation failed for type="${action.type}" id="${action.id}": ${validationFailure.error}`
3883
3709
  );
3884
3710
  context.emit({
@@ -3905,28 +3731,28 @@ async function executeAction(action, context) {
3905
3731
  case "form_fill":
3906
3732
  result = await formFillHandler(action.payload, {
3907
3733
  permissions,
3908
- registry: context.registry ?? chunkDZ7QRFHD_js.getDefaultRegistry()
3734
+ registry: context.registry ?? chunkYB77RYCC_js.getDefaultRegistry()
3909
3735
  });
3910
3736
  break;
3911
- case "ui_interaction":
3912
- result = uiInteractionHandler(action.payload, {
3737
+ case "ui_interaction": {
3738
+ const payload = action.payload;
3739
+ result = uiInteractionHandler(payload, {
3913
3740
  permissions,
3914
- registry: context.registry ?? chunkDZ7QRFHD_js.getDefaultRegistry()
3741
+ registry: context.registry ?? chunkYB77RYCC_js.getDefaultRegistry()
3915
3742
  });
3916
3743
  if (result.success) {
3917
- await waitForPostInteractionSettle(action.payload);
3744
+ const settle = await waitForPostInteractionSettle(payload);
3745
+ result.effect = result.effect ?? effectFor(payload, settle.effect);
3918
3746
  }
3919
3747
  break;
3748
+ }
3920
3749
  case "scroll_list":
3921
3750
  result = await scrollListHandler(action.payload, {
3922
3751
  permissions
3923
3752
  });
3924
3753
  break;
3925
3754
  case "confirm":
3926
- result = await confirmHandler(
3927
- action.id,
3928
- action.payload
3929
- );
3755
+ result = await confirmHandler(action.id, action.payload);
3930
3756
  break;
3931
3757
  case "custom":
3932
3758
  result = {
@@ -3941,7 +3767,7 @@ async function executeAction(action, context) {
3941
3767
  };
3942
3768
  }
3943
3769
  } catch (err) {
3944
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3770
+ chunkYB77RYCC_js.appilotsDebugWarn(
3945
3771
  `executeAction: exception during action type="${action.type}" id="${action.id}": ${err?.message}`
3946
3772
  );
3947
3773
  result = {
@@ -3949,7 +3775,9 @@ async function executeAction(action, context) {
3949
3775
  error: err?.message ?? "Action execution failed unexpectedly"
3950
3776
  };
3951
3777
  }
3952
- console.log(`[Appilots] executeAction result: type="${action.type}", id="${action.id}", success=${result.success}, error=${result.error ?? "none"}`);
3778
+ chunkYB77RYCC_js.appilotsDebugLog(
3779
+ `executeAction result: type="${action.type}", id="${action.id}", success=${result.success}, error=${result.error ?? "none"}`
3780
+ );
3953
3781
  context.emit({
3954
3782
  type: result.success ? "agent:action:complete" : "agent:action:error",
3955
3783
  timestamp: Date.now(),
@@ -3965,37 +3793,124 @@ async function executeAction(action, context) {
3965
3793
  });
3966
3794
  return result;
3967
3795
  }
3796
+
3797
+ // src/platform/confirmedDestructiveAlert.ts
3798
+ var SUPPRESSION_WINDOW_MS = 1e3;
3799
+ var _active = null;
3800
+ function resolveConfirmButton(buttons) {
3801
+ if (!buttons || buttons.length === 0) return void 0;
3802
+ const destructive = buttons.find(
3803
+ (button) => button.style === "destructive" && typeof button.onPress === "function"
3804
+ );
3805
+ if (destructive) return destructive;
3806
+ return buttons.find(
3807
+ (button) => button.style !== "cancel" && typeof button.onPress === "function"
3808
+ );
3809
+ }
3810
+ function restore(suppression) {
3811
+ if (suppression.timer) {
3812
+ clearTimeout(suppression.timer);
3813
+ suppression.timer = null;
3814
+ }
3815
+ if (_active !== suppression) return;
3816
+ if (suppression.host.alert === _patchedAlert) {
3817
+ suppression.host.alert = suppression.originalAlert;
3818
+ }
3819
+ _active = null;
3820
+ }
3821
+ var _patchedAlert = (title, message, buttons, options) => {
3822
+ const suppression = _active;
3823
+ if (!suppression) return;
3824
+ if (suppression.consumed) {
3825
+ return suppression.originalAlert(title, message, buttons, options);
3826
+ }
3827
+ const button = resolveConfirmButton(buttons);
3828
+ if (!button?.onPress) {
3829
+ return suppression.originalAlert(title, message, buttons, options);
3830
+ }
3831
+ suppression.consumed = true;
3832
+ chunkYB77RYCC_js.appilotsDebugLog("Suppressing native Alert during already-confirmed destructive agent action");
3833
+ try {
3834
+ suppression.pending = Promise.resolve(button.onPress()).then(() => void 0).catch((err) => reportHandlerFailure(err));
3835
+ } catch (err) {
3836
+ reportHandlerFailure(err);
3837
+ suppression.pending = null;
3838
+ }
3839
+ };
3840
+ function reportHandlerFailure(err) {
3841
+ console.error("[Appilots] The app\u2019s Alert handler threw while being auto-confirmed", err);
3842
+ }
3843
+ async function runWithConfirmedDestructiveContext(enabled, host, fn) {
3844
+ if (!enabled) return fn();
3845
+ if (_active) {
3846
+ _active.depth += 1;
3847
+ const joined = _active;
3848
+ try {
3849
+ return await fn();
3850
+ } finally {
3851
+ joined.depth -= 1;
3852
+ if (joined.depth === 0) {
3853
+ if (joined.pending) await joined.pending.catch(() => void 0);
3854
+ restore(joined);
3855
+ }
3856
+ }
3857
+ }
3858
+ const suppression = {
3859
+ host,
3860
+ originalAlert: host.alert,
3861
+ depth: 1,
3862
+ consumed: false,
3863
+ pending: null,
3864
+ timer: null
3865
+ };
3866
+ _active = suppression;
3867
+ host.alert = _patchedAlert;
3868
+ suppression.timer = setTimeout(() => {
3869
+ if (!suppression.consumed) restore(suppression);
3870
+ }, SUPPRESSION_WINDOW_MS);
3871
+ suppression.timer?.unref?.();
3872
+ try {
3873
+ const result = await fn();
3874
+ if (suppression.pending) await suppression.pending.catch(() => void 0);
3875
+ return result;
3876
+ } finally {
3877
+ suppression.depth -= 1;
3878
+ if (suppression.depth === 0) restore(suppression);
3879
+ }
3880
+ }
3881
+
3882
+ // src/platform/reactNativeAdapter.ts
3968
3883
  var POST_ACTION_LOADING_MAX_MS = 6e3;
3969
3884
  function resolveScreenMetadata() {
3970
- const activePath = chunkDZ7QRFHD_js.getActiveRouteNames();
3885
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
3971
3886
  for (let i = activePath.length - 1; i >= 0; i--) {
3972
3887
  const name = activePath[i];
3973
- const meta = name ? chunkDZ7QRFHD_js.getScreenMetadata(name) : void 0;
3888
+ const meta = name ? chunkYB77RYCC_js.getScreenMetadata(name) : void 0;
3974
3889
  if (meta && (Array.isArray(meta.fields) && meta.fields.length > 0 || Array.isArray(meta.actions) && meta.actions.length > 0)) {
3975
3890
  return meta;
3976
3891
  }
3977
3892
  }
3978
- const screen = chunkDZ7QRFHD_js.getCurrentScreen();
3979
- return screen ? chunkDZ7QRFHD_js.getScreenMetadata(screen) : void 0;
3893
+ const screen = chunkYB77RYCC_js.getCurrentScreen();
3894
+ return screen ? chunkYB77RYCC_js.getScreenMetadata(screen) : void 0;
3980
3895
  }
3981
3896
  function buildAgentContext(extras = {}) {
3982
3897
  const context = {};
3983
3898
  context.platform = "react-native";
3984
- const screen = chunkDZ7QRFHD_js.getCurrentScreen();
3899
+ const screen = chunkYB77RYCC_js.getCurrentScreen();
3985
3900
  if (screen) context.currentScreen = screen;
3986
- const navigationState = chunkDZ7QRFHD_js.getNavigationStateSnapshot();
3901
+ const navigationState = chunkYB77RYCC_js.getNavigationStateSnapshot();
3987
3902
  if (navigationState) context.navigationState = navigationState;
3988
3903
  const screenMeta = resolveScreenMetadata();
3989
3904
  if (screenMeta) context.screenMetadata = screenMeta;
3990
3905
  try {
3991
3906
  context.snapshot = captureSnapshot();
3992
3907
  } catch (err) {
3993
- chunkDZ7QRFHD_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
3908
+ chunkYB77RYCC_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
3994
3909
  }
3995
- const registry = chunkDZ7QRFHD_js.componentRegistry.snapshot();
3910
+ const registry = chunkYB77RYCC_js.componentRegistry.snapshot();
3996
3911
  const filtered = screen ? registry.filter((c) => !c.screen || c.screen === screen) : registry;
3997
3912
  if (filtered.length > 0) context.registeredComponents = filtered;
3998
- const registeredLists = chunkDZ7QRFHD_js.listRegistry.snapshot();
3913
+ const registeredLists = chunkYB77RYCC_js.listRegistry.snapshot();
3999
3914
  if (registeredLists.length > 0) {
4000
3915
  context.registeredLists = registeredLists.map(
4001
3916
  ({ scrollToIndex, scrollToOffset, getScrollMetrics, dataPreview, ...rest }) => rest
@@ -4012,12 +3927,12 @@ function resolveActionHints(screen, pressedComponentId, actionPayload) {
4012
3927
  }
4013
3928
  }
4014
3929
  if (!screen || !pressedComponentId) return void 0;
4015
- const meta = chunkDZ7QRFHD_js.getScreenMetadata(screen);
3930
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screen);
4016
3931
  const actions = meta?.actions;
4017
3932
  if (!actions || actions.length === 0) return void 0;
4018
3933
  for (const a of actions) {
4019
3934
  if (typeof a === "string") continue;
4020
- if (chunkDZ7QRFHD_js.idLooselyMatches(a.id, pressedComponentId)) {
3935
+ if (chunkYB77RYCC_js.idLooselyMatches(a.id, pressedComponentId)) {
4021
3936
  const inferred = a.appilotsInferred;
4022
3937
  if (inferred && typeof inferred === "object") return inferred;
4023
3938
  return void 0;
@@ -4032,71 +3947,68 @@ async function settleTurn(input) {
4032
3947
  const successById = new Map(input.results.map((r) => [r.actionId, r.success]));
4033
3948
  const typeById = new Map(input.results.map((r) => [r.actionId, r.type]));
4034
3949
  if (input.hadNavigate) {
4035
- const settle = await chunkDZ7QRFHD_js.waitForScreenSettle({
3950
+ const settle = await chunkYB77RYCC_js.waitForScreenSettle({
4036
3951
  expectingChange: true,
4037
3952
  fromScreen: input.preNavigateScreen ?? null,
4038
3953
  fromSignature: input.preNavigateSignature ?? null,
4039
3954
  targetScreen: navigateTargetScreen,
4040
3955
  maxMs: 3500
4041
3956
  });
4042
- console.log(
4043
- `[Appilots] settleTurn: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
3957
+ chunkYB77RYCC_js.appilotsDebugLog(
3958
+ `settleTurn: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
4044
3959
  );
4045
- const navigationMoved = settle.transitioned || chunkDZ7QRFHD_js.screenDepartedBaseline(
4046
- input.preNavigateScreen ?? null,
4047
- input.preNavigateSignature ?? null
4048
- ) || !!navigateTargetScreen && !!settle.screen && chunkDZ7QRFHD_js.routesBelongToSameFeature(settle.screen, navigateTargetScreen);
3960
+ const navigationMoved = settle.transitioned || chunkYB77RYCC_js.screenDepartedBaseline(input.preNavigateScreen ?? null, input.preNavigateSignature ?? null) || !!navigateTargetScreen && !!settle.screen && chunkYB77RYCC_js.routesBelongToSameFeature(settle.screen, navigateTargetScreen);
4049
3961
  if (!navigationMoved) {
4050
- chunkDZ7QRFHD_js.appilotsDebugWarn(
3962
+ chunkYB77RYCC_js.appilotsDebugWarn(
4051
3963
  `tool-without-effect: navigate emitted but screen did not change (stayed at "${input.preNavigateScreen ?? "unknown"}", waitedMs=${settle.waitedMs}). Likely causes: target screenName missing from MCP doc, nested-nav path absent, or React Navigation rejected the route.`
4052
3964
  );
4053
3965
  for (const [actionId, type] of typeById) {
4054
3966
  if (type === "navigate") toolWithoutEffectIds.add(actionId);
4055
3967
  }
4056
3968
  }
4057
- const loadSettle = await chunkDZ7QRFHD_js.waitForLoadingSettle({
3969
+ const loadSettle = await chunkYB77RYCC_js.waitForLoadingSettle({
4058
3970
  fromScreen: settle.screen ?? null,
4059
3971
  maxMs: 3e3
4060
3972
  });
4061
- console.log(
4062
- `[Appilots] settleTurn: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs}`
3973
+ chunkYB77RYCC_js.appilotsDebugLog(
3974
+ `settleTurn: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs}`
4063
3975
  );
4064
3976
  if (loadSettle.loadingPending) loadingPending = true;
4065
3977
  } else {
4066
3978
  const pressedAction = turnActions.find(
4067
3979
  (a) => a.type === "ui_interaction" && a.payload?.componentId === pressedId
4068
3980
  );
4069
- const hints = resolveActionHints(chunkDZ7QRFHD_js.getCurrentScreen(), pressedId, pressedAction?.payload);
3981
+ const hints = resolveActionHints(chunkYB77RYCC_js.getCurrentScreen(), pressedId, pressedAction?.payload);
4070
3982
  const settleCapMs = hints?.isAsyncTrigger === true ? 1e4 : POST_ACTION_LOADING_MAX_MS;
4071
- const loadSettle = await chunkDZ7QRFHD_js.waitForLoadingSettle({
3983
+ const loadSettle = await chunkYB77RYCC_js.waitForLoadingSettle({
4072
3984
  pressedComponentId: pressedId,
4073
- fromScreen: chunkDZ7QRFHD_js.getCurrentScreen(),
3985
+ fromScreen: chunkYB77RYCC_js.getCurrentScreen(),
4074
3986
  maxMs: settleCapMs
4075
3987
  });
4076
- console.log(
4077
- `[Appilots] settleTurn: post-action loading settle \u2014 pressedId="${pressedId ?? ""}" settled=${loadSettle.settled} transitioned=${loadSettle.transitioned} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs} cap=${settleCapMs}${hints?.isAsyncTrigger ? " (mcp-inferred)" : ""}`
3988
+ chunkYB77RYCC_js.appilotsDebugLog(
3989
+ `settleTurn: post-action loading settle \u2014 pressedId="${pressedId ?? ""}" settled=${loadSettle.settled} transitioned=${loadSettle.transitioned} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs} cap=${settleCapMs}${hints?.isAsyncTrigger ? " (mcp-inferred)" : ""}`
4078
3990
  );
4079
3991
  if (loadSettle.loadingPending) loadingPending = true;
4080
3992
  const listPressActions = turnActions.filter((action) => {
4081
- const target = chunkDZ7QRFHD_js.actionPressTargetId(action);
4082
- return target ? chunkDZ7QRFHD_js.isListItemPressTarget(target) : false;
3993
+ const target = chunkYB77RYCC_js.actionPressTargetId(action);
3994
+ return target ? chunkYB77RYCC_js.isListItemPressTarget(target) : false;
4083
3995
  });
4084
3996
  if (listPressActions.length > 0) {
4085
- const baselineFingerprint = chunkDZ7QRFHD_js.probeLoadingState(pressedId, chunkDZ7QRFHD_js.getCurrentScreen()).fingerprint;
4086
- const postPressSettle = await chunkDZ7QRFHD_js.waitForScreenSettle({
3997
+ const baselineFingerprint = chunkYB77RYCC_js.probeLoadingState(pressedId, chunkYB77RYCC_js.getCurrentScreen()).fingerprint;
3998
+ const postPressSettle = await chunkYB77RYCC_js.waitForScreenSettle({
4087
3999
  expectingChange: true,
4088
4000
  fromScreen: input.preNavigateScreen ?? null,
4089
4001
  fromSignature: input.preNavigateSignature ?? null,
4090
4002
  maxMs: 2500
4091
4003
  });
4092
- await chunkDZ7QRFHD_js.waitForLoadingSettle({
4004
+ await chunkYB77RYCC_js.waitForLoadingSettle({
4093
4005
  pressedComponentId: pressedId,
4094
- fromScreen: chunkDZ7QRFHD_js.getCurrentScreen(),
4006
+ fromScreen: chunkYB77RYCC_js.getCurrentScreen(),
4095
4007
  maxMs: 4e3
4096
4008
  });
4097
- const afterFingerprint = chunkDZ7QRFHD_js.probeLoadingState(pressedId, chunkDZ7QRFHD_js.getCurrentScreen()).fingerprint;
4098
- console.log(
4099
- `[Appilots] settleTurn: post-list-press settle \u2014 screen="${postPressSettle.screen}" transitioned=${postPressSettle.transitioned} timedOut=${postPressSettle.timedOut} waitedMs=${postPressSettle.waitedMs}`
4009
+ const afterFingerprint = chunkYB77RYCC_js.probeLoadingState(pressedId, chunkYB77RYCC_js.getCurrentScreen()).fingerprint;
4010
+ chunkYB77RYCC_js.appilotsDebugLog(
4011
+ `settleTurn: post-list-press settle \u2014 screen="${postPressSettle.screen}" transitioned=${postPressSettle.transitioned} timedOut=${postPressSettle.timedOut} waitedMs=${postPressSettle.waitedMs}`
4100
4012
  );
4101
4013
  if (!postPressSettle.transitioned && baselineFingerprint === afterFingerprint) {
4102
4014
  for (const action of listPressActions) {
@@ -4111,46 +4023,18 @@ async function settleTurn(input) {
4111
4023
  }
4112
4024
  var reactNativeChatAdapter = {
4113
4025
  buildContext: buildAgentContext,
4114
- getCurrentScreen: chunkDZ7QRFHD_js.getCurrentScreen,
4115
- getCurrentScreenSignature: chunkDZ7QRFHD_js.getCurrentScreenSignature,
4026
+ getCurrentScreen: chunkYB77RYCC_js.getCurrentScreen,
4027
+ getCurrentScreenSignature: chunkYB77RYCC_js.getCurrentScreenSignature,
4116
4028
  settleTurn
4117
4029
  };
4118
- async function runWithConfirmedDestructiveContext(enabled, fn) {
4119
- if (!enabled) return fn();
4120
- const originalAlert = reactNative.Alert.alert;
4121
- let consumed = false;
4122
- let alertWork = null;
4123
- reactNative.Alert.alert = (title, message, buttons, options) => {
4124
- if (consumed) {
4125
- return originalAlert(title, message, buttons, options);
4126
- }
4127
- const destructive = buttons?.find((button) => button.style === "destructive");
4128
- const actionable = destructive ?? buttons?.find((button) => button.style !== "cancel" && typeof button.onPress === "function");
4129
- if (actionable?.onPress) {
4130
- consumed = true;
4131
- console.log(
4132
- "[Appilots] Suppressing native Alert during already-confirmed destructive agent action"
4133
- );
4134
- alertWork = Promise.resolve(actionable.onPress()).then(() => void 0);
4135
- return;
4136
- }
4137
- return originalAlert(title, message, buttons, options);
4138
- };
4139
- try {
4140
- const result = await fn();
4141
- if (alertWork) await alertWork;
4142
- return result;
4143
- } finally {
4144
- reactNative.Alert.alert = originalAlert;
4145
- }
4146
- }
4147
4030
  function createReactNativeActionRunner(getOptions) {
4148
4031
  return {
4149
4032
  async execute(action, { confirmedDestructive }) {
4150
- const { permissions, emit, navigationRef } = getOptions();
4151
- const navRef = navigationRef?.current ? navigationRef : { current: chunkDZ7QRFHD_js.getNavigationRef() };
4033
+ const { permissions, emit, navigationRef, suppressNativeConfirm } = getOptions();
4034
+ const navRef = navigationRef?.current ? navigationRef : { current: chunkYB77RYCC_js.getNavigationRef() };
4152
4035
  return runWithConfirmedDestructiveContext(
4153
- confirmedDestructive,
4036
+ confirmedDestructive && suppressNativeConfirm !== false,
4037
+ reactNative.Alert,
4154
4038
  () => executeAction(action, {
4155
4039
  navigationRef: navRef,
4156
4040
  permissions,
@@ -4158,21 +4042,21 @@ function createReactNativeActionRunner(getOptions) {
4158
4042
  })
4159
4043
  );
4160
4044
  },
4161
- getCurrentScreen: chunkDZ7QRFHD_js.getCurrentScreen,
4162
- getCurrentScreenSignature: chunkDZ7QRFHD_js.getCurrentScreenSignature,
4045
+ getCurrentScreen: chunkYB77RYCC_js.getCurrentScreen,
4046
+ getCurrentScreenSignature: chunkYB77RYCC_js.getCurrentScreenSignature,
4163
4047
  getScreenActionsMetadata(screen) {
4164
- return chunkDZ7QRFHD_js.getScreenMetadata(screen)?.actions;
4048
+ return chunkYB77RYCC_js.getScreenMetadata(screen)?.actions;
4165
4049
  },
4166
- waitForScreenSettle: chunkDZ7QRFHD_js.waitForScreenSettle
4050
+ waitForScreenSettle: chunkYB77RYCC_js.waitForScreenSettle
4167
4051
  };
4168
4052
  }
4169
4053
 
4170
4054
  // src/hooks/useAppilotsChat.ts
4171
4055
  function useAppilotsChat(options = {}) {
4172
- const { client, emit, subscribe } = chunkDZ7QRFHD_js.useAppilotsContext();
4173
- const machine = react.useMemo(
4174
- () => new chunkDZ7QRFHD_js.ChatSessionMachine(
4175
- { client, adapter: reactNativeChatAdapter, emit, warn: chunkDZ7QRFHD_js.appilotsDebugWarn },
4056
+ const { client, emit, subscribe } = chunkYB77RYCC_js.useAppilotsContext();
4057
+ const machine = React.useMemo(
4058
+ () => new chunkYB77RYCC_js.ChatSessionMachine(
4059
+ { client, adapter: reactNativeChatAdapter, emit, warn: chunkYB77RYCC_js.appilotsDebugWarn },
4176
4060
  options
4177
4061
  ),
4178
4062
  // A new machine per client/provider instance — options are pushed in
@@ -4180,20 +4064,20 @@ function useAppilotsChat(options = {}) {
4180
4064
  // eslint-disable-next-line react-hooks/exhaustive-deps
4181
4065
  [client, emit]
4182
4066
  );
4183
- const optionsRef = react.useRef(options);
4067
+ const optionsRef = React.useRef(options);
4184
4068
  optionsRef.current = options;
4185
4069
  machine.setOptions(options);
4186
- const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4187
- react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4188
- react.useEffect(() => () => machine.dispose(), [machine]);
4189
- const requestHuman = react.useCallback(
4070
+ const state = React.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4071
+ React.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4072
+ React.useEffect(() => () => machine.dispose(), [machine]);
4073
+ const requestHuman = React.useCallback(
4190
4074
  (reason) => machine.requestHuman(reason),
4191
4075
  [machine]
4192
4076
  );
4193
- const sendMessage = react.useCallback((content) => machine.sendMessage(content), [machine]);
4194
- const cancelMessage = react.useCallback(() => machine.cancelMessage(), [machine]);
4195
- const clearMessages = react.useCallback(() => machine.clearMessages(), [machine]);
4196
- const clearError = react.useCallback(() => machine.clearError(), [machine]);
4077
+ const sendMessage = React.useCallback((content) => machine.sendMessage(content), [machine]);
4078
+ const cancelMessage = React.useCallback(() => machine.cancelMessage(), [machine]);
4079
+ const clearMessages = React.useCallback(() => machine.clearMessages(), [machine]);
4080
+ const clearError = React.useCallback(() => machine.clearError(), [machine]);
4197
4081
  return {
4198
4082
  messages: state.messages,
4199
4083
  isLoading: state.isLoading,
@@ -4215,25 +4099,27 @@ var DEFAULT_PERMISSIONS2 = {
4215
4099
  canSubmitForms: true
4216
4100
  };
4217
4101
  function useAppilotsActions(options = {}) {
4218
- const { client, subscribe, config, emit } = chunkDZ7QRFHD_js.useAppilotsContext();
4102
+ const { client, subscribe, config, emit } = chunkYB77RYCC_js.useAppilotsContext();
4219
4103
  const { navigationRef, autoExecute = false } = options;
4220
- const runnerOptionsRef = react.useRef({
4104
+ const runnerOptionsRef = React.useRef({
4221
4105
  permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
4222
4106
  emit,
4223
- navigationRef
4107
+ navigationRef,
4108
+ suppressNativeConfirm: config.suppressNativeConfirm
4224
4109
  });
4225
4110
  runnerOptionsRef.current = {
4226
4111
  permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
4227
4112
  emit,
4228
- navigationRef
4113
+ navigationRef,
4114
+ suppressNativeConfirm: config.suppressNativeConfirm
4229
4115
  };
4230
- const machine = react.useMemo(
4231
- () => new chunkDZ7QRFHD_js.ActionQueueMachine(
4116
+ const machine = React.useMemo(
4117
+ () => new chunkYB77RYCC_js.ActionQueueMachine(
4232
4118
  {
4233
4119
  client,
4234
4120
  adapter: createReactNativeActionRunner(() => runnerOptionsRef.current),
4235
4121
  emit,
4236
- warn: chunkDZ7QRFHD_js.appilotsDebugWarn
4122
+ warn: chunkYB77RYCC_js.appilotsDebugWarn
4237
4123
  },
4238
4124
  { autoExecute }
4239
4125
  ),
@@ -4241,16 +4127,16 @@ function useAppilotsActions(options = {}) {
4241
4127
  [client, emit]
4242
4128
  );
4243
4129
  machine.setOptions({ autoExecute });
4244
- const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4245
- react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4246
- react.useEffect(() => {
4130
+ const state = React.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4131
+ React.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4132
+ React.useEffect(() => {
4247
4133
  if (autoExecute) machine.scheduleDrain();
4248
4134
  }, [autoExecute, machine, state.actions]);
4249
- const approveAction = react.useCallback(
4135
+ const approveAction = React.useCallback(
4250
4136
  (actionId) => machine.approveAction(actionId),
4251
4137
  [machine]
4252
4138
  );
4253
- const rejectAction = react.useCallback((actionId) => machine.rejectAction(actionId), [machine]);
4139
+ const rejectAction = React.useCallback((actionId) => machine.rejectAction(actionId), [machine]);
4254
4140
  return {
4255
4141
  pendingActions: state.actions.filter((a) => a.status === "pending"),
4256
4142
  executingActions: state.actions.filter((a) => a.status === "executing"),
@@ -4290,18 +4176,18 @@ function shouldShowSuggestedPrompts(args) {
4290
4176
 
4291
4177
  // src/hooks/useSuggestedPrompts.ts
4292
4178
  function useSuggestedPrompts(options) {
4293
- const { client } = chunkDZ7QRFHD_js.useAppilotsContext();
4179
+ const { client } = chunkYB77RYCC_js.useAppilotsContext();
4294
4180
  const { enabled, limit = 4 } = options;
4295
- const [prompts, setPrompts] = react.useState([]);
4296
- const [isLoading, setIsLoading] = react.useState(false);
4297
- const [refreshTick, setRefreshTick] = react.useState(0);
4298
- const requestIdRef = react.useRef(0);
4299
- react.useEffect(() => {
4181
+ const [prompts, setPrompts] = React.useState([]);
4182
+ const [isLoading, setIsLoading] = React.useState(false);
4183
+ const [refreshTick, setRefreshTick] = React.useState(0);
4184
+ const requestIdRef = React.useRef(0);
4185
+ React.useEffect(() => {
4300
4186
  if (!enabled) return;
4301
4187
  const requestId = ++requestIdRef.current;
4302
4188
  let cancelled = false;
4303
- const screen = chunkDZ7QRFHD_js.getCurrentScreen() ?? void 0;
4304
- const localDev = screen ? (chunkDZ7QRFHD_js.getScreenMetadata(screen)?.suggestedPrompts ?? []).map((text) => ({
4189
+ const screen = chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
4190
+ const localDev = screen ? (chunkYB77RYCC_js.getScreenMetadata(screen)?.suggestedPrompts ?? []).map((text) => ({
4305
4191
  text,
4306
4192
  source: "dev-defined"
4307
4193
  })) : [];
@@ -4315,7 +4201,7 @@ function useSuggestedPrompts(options) {
4315
4201
  if (cancelled || requestIdRef.current !== requestId) return;
4316
4202
  setPrompts(mergePromptSources(localDev, data, limit));
4317
4203
  }).catch((err) => {
4318
- console.warn("[Appilots] useSuggestedPrompts: fetch failed", err);
4204
+ chunkYB77RYCC_js.appilotsDebugWarn("useSuggestedPrompts: fetch failed", err);
4319
4205
  }).finally(() => {
4320
4206
  if (cancelled || requestIdRef.current !== requestId) return;
4321
4207
  setIsLoading(false);
@@ -4324,11 +4210,11 @@ function useSuggestedPrompts(options) {
4324
4210
  cancelled = true;
4325
4211
  };
4326
4212
  }, [client, enabled, limit, refreshTick]);
4327
- react.useEffect(() => {
4213
+ React.useEffect(() => {
4328
4214
  if (!enabled) return;
4329
- let lastScreen = chunkDZ7QRFHD_js.getCurrentScreen();
4215
+ let lastScreen = chunkYB77RYCC_js.getCurrentScreen();
4330
4216
  const interval = setInterval(() => {
4331
- const current = chunkDZ7QRFHD_js.getCurrentScreen();
4217
+ const current = chunkYB77RYCC_js.getCurrentScreen();
4332
4218
  if (current !== lastScreen) {
4333
4219
  lastScreen = current;
4334
4220
  setRefreshTick((t) => t + 1);
@@ -4343,14 +4229,14 @@ function useSuggestedPrompts(options) {
4343
4229
  };
4344
4230
  }
4345
4231
  function useAppilotsNavigation() {
4346
- const { emit } = chunkDZ7QRFHD_js.useAppilotsContext();
4347
- const [currentScreen, setCurrentScreenState] = react.useState(null);
4348
- const [navigationHistory, setNavigationHistory] = react.useState([]);
4349
- const navigationRef = react.useRef(null);
4350
- const setCurrentScreen2 = react.useCallback(
4232
+ const { emit } = chunkYB77RYCC_js.useAppilotsContext();
4233
+ const [currentScreen, setCurrentScreenState] = React.useState(null);
4234
+ const [navigationHistory, setNavigationHistory] = React.useState([]);
4235
+ const navigationRef = React.useRef(null);
4236
+ const setCurrentScreen2 = React.useCallback(
4351
4237
  (screenName) => {
4352
4238
  setCurrentScreenState(screenName);
4353
- chunkDZ7QRFHD_js.setCurrentScreen(screenName);
4239
+ chunkYB77RYCC_js.setCurrentScreen(screenName);
4354
4240
  setNavigationHistory((prev) => [...prev, screenName]);
4355
4241
  emit({
4356
4242
  type: "navigation:change",
@@ -4360,7 +4246,7 @@ function useAppilotsNavigation() {
4360
4246
  },
4361
4247
  [emit]
4362
4248
  );
4363
- react.useEffect(() => {
4249
+ React.useEffect(() => {
4364
4250
  const nav = navigationRef.current;
4365
4251
  if (!nav?.addListener) return;
4366
4252
  const unsubscribe = nav.addListener("state", () => {
@@ -4381,7 +4267,7 @@ function useAppilotsNavigation() {
4381
4267
 
4382
4268
  // src/hooks/useAppilots.ts
4383
4269
  function useAppilots() {
4384
- const { config, client } = chunkDZ7QRFHD_js.useAppilotsContext();
4270
+ const { config, client } = chunkYB77RYCC_js.useAppilotsContext();
4385
4271
  const chat = useAppilotsChat();
4386
4272
  const navigation = useAppilotsNavigation();
4387
4273
  const actions = useAppilotsActions();
@@ -4410,17 +4296,17 @@ function useAppilots() {
4410
4296
  }
4411
4297
  function useAppilotsField(id, options) {
4412
4298
  const { value, onChangeText, ref, fieldType, label, screen } = options;
4413
- const registry = chunkDZ7QRFHD_js.useResolvedRegistry();
4414
- const valueRef = react.useRef(value);
4415
- const onChangeRef = react.useRef(onChangeText);
4299
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4300
+ const valueRef = React.useRef(value);
4301
+ const onChangeRef = React.useRef(onChangeText);
4416
4302
  valueRef.current = value;
4417
4303
  onChangeRef.current = onChangeText;
4418
- const getValue = react.useCallback(() => valueRef.current, []);
4419
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4420
- const focus = react.useCallback(() => {
4304
+ const getValue = React.useCallback(() => valueRef.current, []);
4305
+ const setValue = React.useCallback((v) => onChangeRef.current(v), []);
4306
+ const focus = React.useCallback(() => {
4421
4307
  ref?.current?.focus?.();
4422
4308
  }, [ref]);
4423
- react.useEffect(() => {
4309
+ React.useEffect(() => {
4424
4310
  const entry = {
4425
4311
  kind: "field",
4426
4312
  getValue,
@@ -4438,17 +4324,17 @@ function useAppilotsField(id, options) {
4438
4324
  }
4439
4325
  function useAppilotsTarget(id, options) {
4440
4326
  const { onPress, onLongPress, onScrollTo, label, screen } = options;
4441
- const registry = chunkDZ7QRFHD_js.useResolvedRegistry();
4442
- const onPressRef = react.useRef(onPress);
4443
- const onLongPressRef = react.useRef(onLongPress);
4444
- const onScrollToRef = react.useRef(onScrollTo);
4327
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4328
+ const onPressRef = React.useRef(onPress);
4329
+ const onLongPressRef = React.useRef(onLongPress);
4330
+ const onScrollToRef = React.useRef(onScrollTo);
4445
4331
  onPressRef.current = onPress;
4446
4332
  onLongPressRef.current = onLongPress;
4447
4333
  onScrollToRef.current = onScrollTo;
4448
- const press = react.useCallback(() => onPressRef.current(), []);
4449
- const longPress = react.useCallback(() => onLongPressRef.current?.(), []);
4450
- const scrollTo = react.useCallback(() => onScrollToRef.current?.(), []);
4451
- react.useEffect(() => {
4334
+ const press = React.useCallback(() => onPressRef.current(), []);
4335
+ const longPress = React.useCallback(() => onLongPressRef.current?.(), []);
4336
+ const scrollTo = React.useCallback(() => onScrollToRef.current?.(), []);
4337
+ React.useEffect(() => {
4452
4338
  const entry = {
4453
4339
  kind: "target",
4454
4340
  press,
@@ -4465,14 +4351,14 @@ function useAppilotsTarget(id, options) {
4465
4351
  }
4466
4352
  function useAppilotsToggle(id, options) {
4467
4353
  const { value, onValueChange, label, screen } = options;
4468
- const registry = chunkDZ7QRFHD_js.useResolvedRegistry();
4469
- const valueRef = react.useRef(value);
4470
- const onChangeRef = react.useRef(onValueChange);
4354
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4355
+ const valueRef = React.useRef(value);
4356
+ const onChangeRef = React.useRef(onValueChange);
4471
4357
  valueRef.current = value;
4472
4358
  onChangeRef.current = onValueChange;
4473
- const getValue = react.useCallback(() => valueRef.current, []);
4474
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4475
- react.useEffect(() => {
4359
+ const getValue = React.useCallback(() => valueRef.current, []);
4360
+ const setValue = React.useCallback((v) => onChangeRef.current(v), []);
4361
+ React.useEffect(() => {
4476
4362
  const entry = {
4477
4363
  kind: "toggle",
4478
4364
  getValue,
@@ -4488,14 +4374,14 @@ function useAppilotsToggle(id, options) {
4488
4374
  }
4489
4375
  function useAppilotsSlider(id, options) {
4490
4376
  const { value, onValueChange, min, max, step, label, screen } = options;
4491
- const registry = chunkDZ7QRFHD_js.useResolvedRegistry();
4492
- const valueRef = react.useRef(value);
4493
- const onChangeRef = react.useRef(onValueChange);
4377
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4378
+ const valueRef = React.useRef(value);
4379
+ const onChangeRef = React.useRef(onValueChange);
4494
4380
  valueRef.current = value;
4495
4381
  onChangeRef.current = onValueChange;
4496
- const getValue = react.useCallback(() => valueRef.current, []);
4497
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4498
- react.useEffect(() => {
4382
+ const getValue = React.useCallback(() => valueRef.current, []);
4383
+ const setValue = React.useCallback((v) => onChangeRef.current(v), []);
4384
+ React.useEffect(() => {
4499
4385
  const entry = {
4500
4386
  kind: "slider",
4501
4387
  getValue,
@@ -4513,6 +4399,7 @@ function useAppilotsSlider(id, options) {
4513
4399
  }, [id, registry, getValue, setValue, min, max, step, label, screen]);
4514
4400
  }
4515
4401
 
4402
+ exports.appilotsSelfCheck = appilotsSelfCheck;
4516
4403
  exports.captureSnapshot = captureSnapshot;
4517
4404
  exports.executeAction = executeAction;
4518
4405
  exports.shouldShowSuggestedPrompts = shouldShowSuggestedPrompts;