@appilots/sdk 0.8.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 chunkAYWMBMSN_js = require('./chunk-AYWMBMSN.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: chunkAYWMBMSN_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 chunkAYWMBMSN_js.componentRegistry.snapshot()) {
26
+ for (const { id, kind } of chunkYB77RYCC_js.componentRegistry.snapshot()) {
675
27
  if (kind !== "slider") continue;
676
- const entry = chunkAYWMBMSN_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 = chunkAYWMBMSN_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 = chunkAYWMBMSN_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
- chunkAYWMBMSN_js.recordIntrospectionFailure("never-mounted", null);
184
+ chunkYB77RYCC_js.recordIntrospectionFailure("never-mounted", null);
754
185
  return {
755
- route: chunkAYWMBMSN_js.getCurrentScreen(),
186
+ route: chunkYB77RYCC_js.getCurrentScreen(),
756
187
  texts: [],
757
188
  inputs: [],
758
189
  buttons: [],
@@ -766,37 +197,84 @@ function captureSnapshot() {
766
197
  };
767
198
  }
768
199
  const start = Date.now();
769
- const snapshot = walkFiber(root);
770
- const activePath = chunkAYWMBMSN_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
- chunkAYWMBMSN_js.clampSnapshotToWireLimits(snapshot);
776
- snapshot.elements = chunkAYWMBMSN_js.deriveInteractionElements(snapshot);
777
- snapshot.choiceGroups = chunkAYWMBMSN_js.attachElementIdsToChoiceGroups(
778
- snapshot.choiceGroups,
779
- 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]] : [])
780
214
  );
781
- chunkAYWMBMSN_js.clampSnapshotToWireLimits(snapshot);
782
- chunkAYWMBMSN_js.elementRegistry.replaceAll(snapshot.elements);
783
- const elapsed = Date.now() - start;
784
- const totalListItems = snapshot.lists.reduce(
785
- (acc, l) => acc + l.items.length,
786
- 0
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
+ })
787
223
  );
224
+ const elapsed = Date.now() - start;
225
+ const totalListItems = snapshot.lists.reduce((acc, l) => acc + l.items.length, 0);
788
226
  const totalListDataItems = snapshot.lists.reduce(
789
227
  (acc, l) => acc + (typeof l.itemCount === "number" ? l.itemCount : 0),
790
228
  0
791
229
  );
792
- console.log(
793
- `[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} ` + (snapshot.truncated ? "truncated=true " : "") + `(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)`
794
232
  );
795
- console.log(
796
- `[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(", ")}]`
797
235
  );
798
236
  return snapshot;
799
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
+ }
800
278
 
801
279
  // src/introspection/findInteractive.ts
802
280
  function getTypeName2(type) {
@@ -810,7 +288,7 @@ function getTypeName2(type) {
810
288
  }
811
289
  return null;
812
290
  }
813
- function matchesName2(fiber, name) {
291
+ function matchesName(fiber, name) {
814
292
  return getTypeName2(fiber.type) === name || getTypeName2(fiber.elementType) === name;
815
293
  }
816
294
  var TOUCHABLE_NAMES2 = /* @__PURE__ */ new Set([
@@ -823,33 +301,33 @@ var TOUCHABLE_NAMES2 = /* @__PURE__ */ new Set([
823
301
  function isTouchable(fiber) {
824
302
  return TOUCHABLE_NAMES2.has(getTypeName2(fiber.type) ?? "") || TOUCHABLE_NAMES2.has(getTypeName2(fiber.elementType) ?? "");
825
303
  }
826
- function hasPressHandler2(fiber) {
304
+ function hasPressHandler(fiber) {
827
305
  const props = fiber?.memoizedProps ?? {};
828
306
  return typeof props.onPress === "function" || typeof props.onPressIn === "function";
829
307
  }
830
- function isPressableTarget2(fiber) {
831
- return isTouchable(fiber) || hasPressHandler2(fiber);
308
+ function isPressableTarget(fiber) {
309
+ return isTouchable(fiber) || hasPressHandler(fiber);
832
310
  }
833
- var SELF_REFERENTIAL_COMPONENTS2 = /* @__PURE__ */ new Set([
311
+ var SELF_REFERENTIAL_COMPONENTS = /* @__PURE__ */ new Set([
834
312
  "AppilotsChat",
835
313
  "AppilotsChatInner",
836
314
  "ActionBreadcrumb",
837
315
  "ConfirmDialog"
838
316
  ]);
839
- function isAppilotsSkipMarked2(props) {
317
+ function isAppilotsSkipMarked(props) {
840
318
  if (!props) return false;
841
319
  return props.__appilotsSkip === true || props["data-appilots-skip"] === true || props.appilotsSkip === true;
842
320
  }
843
- function extractTextFromChildren2(children) {
321
+ function extractTextFromChildren(children) {
844
322
  if (children == null) return "";
845
323
  if (typeof children === "string") return children;
846
324
  if (typeof children === "number") return String(children);
847
325
  if (Array.isArray(children)) {
848
- return children.map(extractTextFromChildren2).filter(Boolean).join("");
326
+ return children.map(extractTextFromChildren).filter(Boolean).join("");
849
327
  }
850
328
  return "";
851
329
  }
852
- function findChildText2(fiber) {
330
+ function findChildText(fiber) {
853
331
  const stack = [];
854
332
  if (fiber.child) stack.push(fiber.child);
855
333
  const visited = /* @__PURE__ */ new WeakSet();
@@ -857,8 +335,8 @@ function findChildText2(fiber) {
857
335
  const node = stack.pop();
858
336
  if (!node || visited.has(node)) continue;
859
337
  visited.add(node);
860
- if (matchesName2(node, "Text")) {
861
- const text = extractTextFromChildren2(node.memoizedProps?.children);
338
+ if (matchesName(node, "Text")) {
339
+ const text = extractTextFromChildren(node.memoizedProps?.children);
862
340
  if (text && text.trim().length > 0) return text.trim();
863
341
  }
864
342
  if (node.sibling) stack.push(node.sibling);
@@ -870,10 +348,10 @@ function shouldSkipSubtree2(fiber) {
870
348
  const props = fiber.memoizedProps;
871
349
  if (!props) return false;
872
350
  const typeName = getTypeName2(fiber.type) ?? getTypeName2(fiber.elementType);
873
- if (typeName && SELF_REFERENTIAL_COMPONENTS2.has(typeName)) return true;
874
- if (isAppilotsSkipMarked2(props)) return true;
875
- if (matchesName2(fiber, "Modal") && props.visible === false) return true;
876
- 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;
877
355
  const style = props.style;
878
356
  if (style) {
879
357
  const flat = Array.isArray(style) ? Object.assign({}, ...style.filter(Boolean)) : style;
@@ -882,20 +360,19 @@ function shouldSkipSubtree2(fiber) {
882
360
  }
883
361
  return false;
884
362
  }
885
- function normalize(s) {
886
- if (!s) return "";
887
- return s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
888
- }
363
+ var normalize = chunkYB77RYCC_js.foldForCompare;
889
364
  function scoreMatch(fiber, queryNorm, queryRaw) {
890
365
  const props = fiber.memoizedProps ?? {};
891
366
  const candidates = [];
892
367
  if (typeof props.testID === "string") candidates.push({ val: props.testID, weight: 100 });
893
- 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 });
894
370
  if (typeof props.label === "string") candidates.push({ val: props.label, weight: 90 });
895
- 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 });
896
373
  if (typeof props.title === "string") candidates.push({ val: props.title, weight: 85 });
897
- if (isPressableTarget2(fiber)) {
898
- const childText = findChildText2(fiber);
374
+ if (isPressableTarget(fiber)) {
375
+ const childText = findChildText(fiber);
899
376
  if (childText) candidates.push({ val: childText, weight: 80 });
900
377
  }
901
378
  let best = 0;
@@ -904,7 +381,8 @@ function scoreMatch(fiber, queryNorm, queryRaw) {
904
381
  if (!vNorm) continue;
905
382
  if (val === queryRaw) best = Math.max(best, weight + 20);
906
383
  else if (vNorm === queryNorm) best = Math.max(best, weight + 10);
907
- 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);
908
386
  }
909
387
  if (best > 0 && props.disabled === true) {
910
388
  best = Math.max(1, best - 60);
@@ -935,6 +413,12 @@ function wrapTextInput(fiber) {
935
413
  if (node && typeof node.focus === "function") {
936
414
  node.focus();
937
415
  }
416
+ },
417
+ submitFromKeyboard: () => {
418
+ const { onSubmitEditing, value } = getProps();
419
+ if (typeof onSubmitEditing !== "function") return false;
420
+ onSubmitEditing({ nativeEvent: { text: value ?? "" } });
421
+ return true;
938
422
  }
939
423
  };
940
424
  }
@@ -972,16 +456,16 @@ function wrapTouchable(fiber, label) {
972
456
  };
973
457
  }
974
458
  function findInteractiveByIdentifier(query, options = {}) {
975
- const root = chunkAYWMBMSN_js.getFiberRoot();
459
+ const root = chunkYB77RYCC_js.getFiberRoot();
976
460
  if (!root) {
977
- console.warn("[Appilots] findInteractiveByIdentifier: fiber root not captured yet");
461
+ chunkYB77RYCC_js.appilotsDebugWarn("findInteractiveByIdentifier: fiber root not captured yet");
978
462
  return null;
979
463
  }
980
464
  const queryNorm = normalize(query);
981
465
  const queryRaw = query;
982
466
  let bestScore = 0;
983
467
  let bestHandle = null;
984
- let bestId2;
468
+ let bestId;
985
469
  const visited = /* @__PURE__ */ new WeakSet();
986
470
  const stack = [];
987
471
  if (root.child) stack.push(root.child);
@@ -992,40 +476,50 @@ function findInteractiveByIdentifier(query, options = {}) {
992
476
  if (fiber.sibling) stack.push(fiber.sibling);
993
477
  if (shouldSkipSubtree2(fiber)) continue;
994
478
  let kind = null;
995
- if (matchesName2(fiber, "TextInput")) kind = "field";
996
- else if (matchesName2(fiber, "Switch")) kind = "toggle";
997
- 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";
998
482
  if (kind && (!options.kind || options.kind === kind)) {
999
483
  const score = scoreMatch(fiber, queryNorm, queryRaw);
1000
484
  if (score > bestScore) {
1001
485
  bestScore = score;
1002
486
  const props = fiber.memoizedProps ?? {};
1003
- 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);
1004
488
  if (kind === "field") bestHandle = wrapTextInput(fiber);
1005
489
  else if (kind === "toggle") bestHandle = wrapSwitch(fiber);
1006
- else bestHandle = wrapTouchable(fiber, findChildText2(fiber));
490
+ else bestHandle = wrapTouchable(fiber, findChildText(fiber));
1007
491
  }
1008
492
  }
1009
493
  if (fiber.child) stack.push(fiber.child);
1010
494
  }
1011
495
  if (bestHandle) {
1012
- console.log(
1013
- `[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}`
1014
498
  );
1015
499
  } else {
1016
- console.log(`[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 no match`);
500
+ chunkYB77RYCC_js.appilotsDebugLog(`findInteractiveByIdentifier: query="${query}" \u2192 no match`);
1017
501
  }
1018
502
  return bestHandle;
1019
503
  }
1020
504
 
1021
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
+ }
1022
514
  function categorizeNavigationError(message) {
1023
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(
1024
516
  message
1025
517
  )) {
1026
518
  return "component-not-found";
1027
519
  }
1028
- 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
+ )) {
1029
523
  return "screen-timeout";
1030
524
  }
1031
525
  return "unknown";
@@ -1052,7 +546,9 @@ function screenExistsAnywhere(state, screenName) {
1052
546
  function safeNavigate(nav, screenName, params, path) {
1053
547
  if (path && path.length > 0) {
1054
548
  const { root, nestedParams } = buildNestedParams(path, screenName, params);
1055
- 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
+ );
1056
552
  nav.navigate(root, nestedParams);
1057
553
  return;
1058
554
  }
@@ -1067,11 +563,17 @@ function safeNavigate(nav, screenName, params, path) {
1067
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.`
1068
564
  );
1069
565
  }
1070
- 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
+ );
1071
569
  nav.navigate(screenName, params);
1072
570
  }
1073
571
  function navigateHandler(payload, context) {
1074
- 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
+ );
1075
577
  const { navigationRef, permissions } = context;
1076
578
  const nav = navigationRef.current;
1077
579
  if (!permissions.canNavigate) {
@@ -1081,14 +583,15 @@ function navigateHandler(payload, context) {
1081
583
  diagnose: { category: "unknown", screen: payload.screenName }
1082
584
  };
1083
585
  }
1084
- if (permissions.blockedScreens?.includes(payload.screenName)) {
586
+ const isGoBack = payload.navigationAction === "goBack";
587
+ if (!isGoBack && permissions.blockedScreens?.includes(payload.screenName)) {
1085
588
  return {
1086
589
  success: false,
1087
590
  error: `Navigation to "${payload.screenName}" is blocked`,
1088
591
  diagnose: { category: "unknown", screen: payload.screenName }
1089
592
  };
1090
593
  }
1091
- 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)) {
1092
595
  return {
1093
596
  success: false,
1094
597
  error: `Navigation to "${payload.screenName}" is not in allowed screens`,
@@ -1096,10 +599,11 @@ function navigateHandler(payload, context) {
1096
599
  };
1097
600
  }
1098
601
  if (!nav) {
602
+ reportMissingNavigationRef();
1099
603
  return {
1100
604
  success: false,
1101
- error: "Navigation ref is not available",
1102
- 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 }
1103
607
  };
1104
608
  }
1105
609
  if (!nav.isReady || typeof nav.isReady === "function" && !nav.isReady()) {
@@ -1110,7 +614,15 @@ function navigateHandler(payload, context) {
1110
614
  };
1111
615
  }
1112
616
  try {
1113
- 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;
1114
626
  switch (navigationAction) {
1115
627
  case "navigate":
1116
628
  safeNavigate(nav, screenName, params ?? {}, path);
@@ -1153,10 +665,14 @@ function navigateHandler(payload, context) {
1153
665
  diagnose: { category: "unknown", screen: payload.screenName }
1154
666
  };
1155
667
  }
1156
- 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
+ );
1157
671
  return { success: true };
1158
672
  } catch (err) {
1159
- 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
+ );
1160
676
  const msg = String(err?.message ?? "Navigation failed");
1161
677
  const category = categorizeNavigationError(msg);
1162
678
  return {
@@ -1179,7 +695,7 @@ function parseSyntheticListItemId(id) {
1179
695
  if (listIndex < 0 || itemIndex < 1) return null;
1180
696
  return { listIndex, itemIndex };
1181
697
  }
1182
- function stringProp2(props, key) {
698
+ function stringProp(props, key) {
1183
699
  const value = props?.[key];
1184
700
  if (typeof value === "string" && value.trim()) return value.trim();
1185
701
  if (typeof value === "number") return String(value);
@@ -1187,33 +703,33 @@ function stringProp2(props, key) {
1187
703
  }
1188
704
  function listIdFromContainer(container) {
1189
705
  const props = container?.memoizedProps ?? {};
1190
- 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");
1191
707
  }
1192
708
  function listLabelFromContainer(container) {
1193
709
  const props = container?.memoizedProps ?? {};
1194
- 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");
1195
711
  }
1196
712
  function itemKeyFromFiber(fiber) {
1197
713
  const props = fiber?.memoizedProps ?? {};
1198
- 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);
1199
715
  }
1200
716
  function markedItemIndexFromFiber(fiber) {
1201
717
  const value = fiber?.memoizedProps?.__appilotsItemIndex;
1202
718
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1203
719
  }
1204
720
  function normalize2(value) {
1205
- return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "");
721
+ return chunkYB77RYCC_js.foldForCompare(String(value ?? ""));
1206
722
  }
1207
- function hasPressHandler3(fiber) {
723
+ function hasPressHandler2(fiber) {
1208
724
  const props = fiber?.memoizedProps ?? {};
1209
725
  return typeof props.onPress === "function" || typeof props.onPressIn === "function";
1210
726
  }
1211
727
  function isPressableFiber(fiber) {
1212
- const typeName = getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "";
1213
- 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);
1214
730
  }
1215
731
  function findListContainers(options = {}) {
1216
- const root = chunkAYWMBMSN_js.getFiberRoot();
732
+ const root = chunkYB77RYCC_js.getFiberRoot();
1217
733
  if (!root) return [];
1218
734
  const containers = [];
1219
735
  const visited = /* @__PURE__ */ new WeakSet();
@@ -1224,17 +740,17 @@ function findListContainers(options = {}) {
1224
740
  if (!fiber || visited.has(fiber)) continue;
1225
741
  visited.add(fiber);
1226
742
  if (fiber.sibling) stack.push(fiber.sibling);
1227
- if (shouldSkipSubtree(fiber)) continue;
1228
- if (isAlwaysListContainer(fiber) || isHeuristicListContainer(fiber)) {
1229
- const minItems = isAlwaysListContainer(fiber) || options.allowSingleHeuristic ? 1 : 2;
1230
- 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);
1231
747
  if (items && items.length >= minItems) {
1232
748
  containers.push({
1233
749
  container: fiber,
1234
750
  items,
1235
751
  listId: listIdFromContainer(fiber),
1236
752
  listLabel: listLabelFromContainer(fiber),
1237
- containerType: getTypeName(fiber.type) ?? getTypeName(fiber.elementType) ?? "List"
753
+ containerType: chunkYB77RYCC_js.getTypeName(fiber.type) ?? chunkYB77RYCC_js.getTypeName(fiber.elementType) ?? "List"
1238
754
  });
1239
755
  continue;
1240
756
  }
@@ -1253,7 +769,7 @@ function findFirstTouchable(item) {
1253
769
  const { fiber, includeSibling } = stack.pop();
1254
770
  if (!fiber || visited.has(fiber)) continue;
1255
771
  visited.add(fiber);
1256
- if (shouldSkipSubtree(fiber)) continue;
772
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
1257
773
  if (isPressableFiber(fiber)) {
1258
774
  const props = fiber.memoizedProps ?? {};
1259
775
  if (typeof props.onPress === "function" || typeof props.onPressIn === "function") {
@@ -1280,7 +796,7 @@ function findTouchableFibers(item) {
1280
796
  const { fiber, includeSibling } = stack.pop();
1281
797
  if (!fiber || visited.has(fiber)) continue;
1282
798
  visited.add(fiber);
1283
- if (shouldSkipSubtree(fiber)) continue;
799
+ if (chunkYB77RYCC_js.shouldSkipSubtree(fiber)) continue;
1284
800
  const props = fiber.memoizedProps ?? {};
1285
801
  if (isPressableFiber(fiber) && (typeof props.onPress === "function" || typeof props.onPressIn === "function")) {
1286
802
  found.push(fiber);
@@ -1324,7 +840,7 @@ function findFirstText(fiber) {
1324
840
  const node = stack.pop();
1325
841
  if (!node || visited.has(node)) continue;
1326
842
  visited.add(node);
1327
- const typeName = getTypeName(node.type) ?? getTypeName(node.elementType) ?? "";
843
+ const typeName = chunkYB77RYCC_js.getTypeName(node.type) ?? chunkYB77RYCC_js.getTypeName(node.elementType) ?? "";
1328
844
  if (typeName === "Text") {
1329
845
  const text = textFromChildren(node.memoizedProps?.children).trim();
1330
846
  if (text) return text;
@@ -1343,7 +859,7 @@ function collectTexts(fiber) {
1343
859
  const node = stack.pop();
1344
860
  if (!node || visited.has(node)) continue;
1345
861
  visited.add(node);
1346
- const typeName = getTypeName(node.type) ?? getTypeName(node.elementType) ?? "";
862
+ const typeName = chunkYB77RYCC_js.getTypeName(node.type) ?? chunkYB77RYCC_js.getTypeName(node.elementType) ?? "";
1347
863
  if (typeName === "Text") {
1348
864
  const text = textFromChildren(node.memoizedProps?.children).trim();
1349
865
  if (text) out.push(text);
@@ -1355,13 +871,10 @@ function collectTexts(fiber) {
1355
871
  }
1356
872
  function hasUsefulTouchableIdentity(fiber) {
1357
873
  const props = fiber?.memoizedProps ?? {};
1358
- if (typeof props.testID === "string" && /[a-z0-9]/i.test(props.testID)) return true;
1359
- if (typeof props.accessibilityLabel === "string" && /[a-z0-9]/i.test(props.accessibilityLabel)) {
1360
- return true;
1361
- }
1362
- if (typeof props.label === "string" && /[a-z0-9]/i.test(props.label)) return true;
1363
- const label = findFirstText(fiber);
1364
- 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));
1365
878
  }
1366
879
  function describeTouchable(fiber) {
1367
880
  const props = fiber?.memoizedProps ?? {};
@@ -1372,15 +885,10 @@ function describeTouchable(fiber) {
1372
885
  }
1373
886
  function touchableLooksDestructive(fiber) {
1374
887
  const descriptor = describeTouchable(fiber);
1375
- if (descriptor && chunkAYWMBMSN_js.looksDestructiveActionLabel(descriptor)) return true;
888
+ if (descriptor && chunkYB77RYCC_js.looksDestructiveActionLabel(descriptor)) return true;
1376
889
  const props = fiber?.memoizedProps ?? {};
1377
- const haystack = [
1378
- props.testID,
1379
- props.accessibilityLabel,
1380
- props.accessibilityHint,
1381
- props.label
1382
- ].filter((value) => typeof value === "string").join(" ");
1383
- return chunkAYWMBMSN_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);
1384
892
  }
1385
893
  function describeItemCandidate(listIndex, zeroBasedIndex, item) {
1386
894
  const syntheticId = `list-${listIndex}-item-${zeroBasedIndex + 1}`;
@@ -1413,8 +921,8 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
1413
921
  (candidate) => candidate !== touchable && containsFiber(touchable, candidate)
1414
922
  );
1415
923
  if (primaryWrapsNestedTargets) {
1416
- console.log(
1417
- `[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`
1418
926
  );
1419
927
  } else {
1420
928
  const candidates = safeIdentifiableTouchables.map(describeTouchable).filter((d) => !!d).slice(0, 8);
@@ -1448,14 +956,14 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
1448
956
  }
1449
957
  return {
1450
958
  ok: true,
1451
- containerType: getTypeName(container.type) ?? getTypeName(container.elementType) ?? list.containerType
959
+ containerType: chunkYB77RYCC_js.getTypeName(container.type) ?? chunkYB77RYCC_js.getTypeName(container.elementType) ?? list.containerType
1452
960
  };
1453
961
  } catch (err) {
1454
962
  return {
1455
963
  ok: false,
1456
964
  reason: "press-threw",
1457
965
  error: err?.message ?? "press handler threw",
1458
- containerType: getTypeName(container.type) ?? getTypeName(container.elementType) ?? list.containerType
966
+ containerType: chunkYB77RYCC_js.getTypeName(container.type) ?? chunkYB77RYCC_js.getTypeName(container.elementType) ?? list.containerType
1459
967
  };
1460
968
  }
1461
969
  }
@@ -1511,7 +1019,7 @@ function candidateLists(containers, locator) {
1511
1019
  return containers.map((list, listIndex) => ({ list, listIndex }));
1512
1020
  }
1513
1021
  function pressListItemAtOrdinal(listIndex, itemIndex) {
1514
- if (!chunkAYWMBMSN_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1022
+ if (!chunkYB77RYCC_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1515
1023
  const containers = findListContainers({ allowSingleHeuristic: true });
1516
1024
  if (listIndex < 0 || listIndex >= containers.length) {
1517
1025
  return { ok: false, reason: "list-not-found" };
@@ -1524,14 +1032,14 @@ function pressListItemAtOrdinal(listIndex, itemIndex) {
1524
1032
  }
1525
1033
  return pressResolvedListItem(list, items[zeroBased], listIndex, itemIndex);
1526
1034
  }
1527
- function pressListItemByIdentity(locator) {
1528
- if (!chunkAYWMBMSN_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" } };
1529
1037
  const parsed = locator.syntheticId ? parseSyntheticListItemId(locator.syntheticId) : null;
1530
1038
  const effective = parsed ? { ...locator, listIndex: parsed.listIndex, itemIndex: parsed.itemIndex } : locator;
1531
1039
  const containers = findListContainers({ allowSingleHeuristic: true });
1532
1040
  const lists = candidateLists(containers, effective);
1533
1041
  if (lists.length === 0) {
1534
- return { ok: false, reason: "list-not-found" };
1042
+ return { ok: false, result: { ok: false, reason: "list-not-found" } };
1535
1043
  }
1536
1044
  const scoredCandidates = [];
1537
1045
  for (const { list, listIndex } of lists) {
@@ -1542,7 +1050,14 @@ function pressListItemByIdentity(locator) {
1542
1050
  }
1543
1051
  }
1544
1052
  if (scoredCandidates.length === 0) {
1545
- 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
+ };
1546
1061
  }
1547
1062
  scoredCandidates.sort((a, b) => b.score - a.score);
1548
1063
  const best = scoredCandidates[0];
@@ -1551,13 +1066,104 @@ function pressListItemByIdentity(locator) {
1551
1066
  const candidates = tiedCandidates.map((c) => describeItemCandidate(c.listIndex, c.itemIndex - 1, c.item)).slice(0, 8);
1552
1067
  return {
1553
1068
  ok: false,
1554
- reason: "ambiguous-items",
1555
- error: "Multiple visible list items matched the requested target with equal confidence." + (candidates.length > 0 ? ` Candidates: ${candidates.join(", ")}.` : ""),
1556
- 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,
1557
1128
  candidates
1558
1129
  };
1559
1130
  }
1560
- 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
+ );
1561
1167
  }
1562
1168
 
1563
1169
  // src/executor/handlers/elementDispatch.ts
@@ -1565,7 +1171,7 @@ function screenDiagnose(targetId, category = "component-not-found") {
1565
1171
  return {
1566
1172
  category,
1567
1173
  targetId,
1568
- screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0
1174
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0
1569
1175
  };
1570
1176
  }
1571
1177
  function isPressLike(action) {
@@ -1582,10 +1188,10 @@ function elementLookupKey(value) {
1582
1188
  return canonicalElementId(value).toLowerCase().replace(/[\s_]+/g, "-");
1583
1189
  }
1584
1190
  function findRegisteredElement(elementId) {
1585
- const direct = chunkAYWMBMSN_js.elementRegistry.get(elementId) ?? chunkAYWMBMSN_js.elementRegistry.get(canonicalElementId(elementId));
1191
+ const direct = chunkYB77RYCC_js.elementRegistry.get(elementId) ?? chunkYB77RYCC_js.elementRegistry.get(canonicalElementId(elementId));
1586
1192
  if (direct) return direct;
1587
1193
  const wanted = elementLookupKey(elementId);
1588
- return chunkAYWMBMSN_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
1194
+ return chunkYB77RYCC_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
1589
1195
  }
1590
1196
  function resolveInteractionElement(elementId) {
1591
1197
  return getLatestElement(elementId);
@@ -1786,6 +1392,46 @@ function dispatchElement(element, registry, action) {
1786
1392
  };
1787
1393
  }
1788
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
+ }
1789
1435
  const targetId = element.targetId ?? element.label ?? element.id;
1790
1436
  return dispatchLegacyTarget(targetId, registry, "toggle");
1791
1437
  }
@@ -1805,7 +1451,7 @@ function dispatchElement(element, registry, action) {
1805
1451
  }
1806
1452
  function dispatchStructuredElementId(identifier, action) {
1807
1453
  if (!isElementIdentifier(identifier) || !isPressLike(action)) return null;
1808
- const parsed = chunkAYWMBMSN_js.parseStableElementId(identifier);
1454
+ const parsed = chunkYB77RYCC_js.parseStableElementId(identifier);
1809
1455
  if (!parsed || parsed.role !== "option") return null;
1810
1456
  if (!parsed.itemKey && !parsed.listId) return null;
1811
1457
  const pressed = pressListItemByIdentity({
@@ -1815,8 +1461,8 @@ function dispatchStructuredElementId(identifier, action) {
1815
1461
  texts: parsed.itemKey ? [parsed.itemKey] : void 0
1816
1462
  });
1817
1463
  if (pressed.ok) {
1818
- console.log(
1819
- `[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}")`
1820
1466
  );
1821
1467
  return { success: true };
1822
1468
  }
@@ -1840,25 +1486,24 @@ function pressElementOrTarget(identifier, registry) {
1840
1486
 
1841
1487
  // src/executor/formFieldRewrite.ts
1842
1488
  var LIST_ORDINAL_RE = /^list-\d+-item-\d+$/i;
1843
- var PLATE_RE = /^[A-Z]{3}-?\d[A-Z0-9]\d{2}$/i;
1844
1489
  function normalize4(value) {
1845
1490
  return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
1846
1491
  }
1847
1492
  function resolveScreenForFormFields() {
1848
- const activePath = chunkAYWMBMSN_js.getActiveRouteNames();
1493
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
1849
1494
  for (let i = activePath.length - 1; i >= 0; i--) {
1850
1495
  const name = activePath[i];
1851
- const meta = name ? chunkAYWMBMSN_js.getScreenMetadata(name) : void 0;
1496
+ const meta = name ? chunkYB77RYCC_js.getScreenMetadata(name) : void 0;
1852
1497
  if (name && Array.isArray(meta?.fields) && meta.fields.length > 0) return name;
1853
1498
  }
1854
- return chunkAYWMBMSN_js.getCurrentScreen();
1499
+ return chunkYB77RYCC_js.getCurrentScreen();
1855
1500
  }
1856
1501
  function collectKnownFormFields(registry) {
1857
1502
  const registryFields = registry.snapshot().filter((entry) => entry.kind === "field" || entry.kind === "slider").map((entry) => ({ id: entry.id, label: entry.label }));
1858
1503
  if (registryFields.length >= 2) return registryFields;
1859
1504
  const screen = resolveScreenForFormFields();
1860
1505
  if (screen) {
1861
- const metaFields = chunkAYWMBMSN_js.getScreenMetadata(screen)?.fields;
1506
+ const metaFields = chunkYB77RYCC_js.getScreenMetadata(screen)?.fields;
1862
1507
  if (Array.isArray(metaFields) && metaFields.length > 0) {
1863
1508
  return metaFields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
1864
1509
  id: field.id,
@@ -1868,7 +1513,7 @@ function collectKnownFormFields(registry) {
1868
1513
  }));
1869
1514
  }
1870
1515
  }
1871
- for (const meta of chunkAYWMBMSN_js.getAllScreens()) {
1516
+ for (const meta of chunkYB77RYCC_js.getAllScreens()) {
1872
1517
  if (Array.isArray(meta.fields) && meta.fields.length > 0) {
1873
1518
  return meta.fields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
1874
1519
  id: field.id,
@@ -1880,9 +1525,6 @@ function collectKnownFormFields(registry) {
1880
1525
  }
1881
1526
  return registryFields;
1882
1527
  }
1883
- function fieldHaystack(field) {
1884
- return normalize4(`${field.id} ${field.label ?? ""}`);
1885
- }
1886
1528
  function isMisplacedFieldId(fieldId, knownIds) {
1887
1529
  const trimmed = fieldId.trim();
1888
1530
  if (!trimmed) return true;
@@ -1906,50 +1548,68 @@ function valueMatchesOption(field, rawValue) {
1906
1548
  return label === value || optionValue === value || value.includes(label) || value.includes(optionValue);
1907
1549
  });
1908
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
+ }
1909
1602
  function inferFieldIdForValue(rawValue, fields, used) {
1910
1603
  const value = String(rawValue ?? "").trim();
1911
1604
  if (!value) return void 0;
1912
- const normalizedValue = normalize4(value);
1913
- for (const field of fields) {
1914
- if (used.has(field.id)) continue;
1605
+ const available = fields.filter((field) => field.id && !used.has(field.id));
1606
+ for (const field of available) {
1915
1607
  if (valueMatchesOption(field, value)) return field.id;
1916
1608
  }
1917
- if (PLATE_RE.test(value)) {
1918
- const field = fields.find((f) => /placa|plate/.test(fieldHaystack(f)) && !used.has(f.id));
1919
- if (field) return field.id;
1920
- }
1921
- if (/^(19|20)\d{2}$/.test(value)) {
1922
- const field = fields.find((f) => /ano|year/.test(fieldHaystack(f)) && !used.has(f.id));
1923
- if (field) return field.id;
1924
- }
1925
- if (/^\d+$/.test(value)) {
1926
- const mileage = fields.find((f) => /quilometragem|mileage|km/.test(fieldHaystack(f)) && !used.has(f.id));
1927
- if (mileage) return mileage.id;
1928
- const year = fields.find((f) => /ano|year/.test(fieldHaystack(f)) && !used.has(f.id));
1929
- if (year) return year.id;
1930
- }
1931
- if (/preto|branco|azul|vermelho|prata|black|white|red|blue|silver|gray|grey/.test(normalizedValue)) {
1932
- const cor = fields.find((f) => /cor|color/.test(fieldHaystack(f)) && !used.has(f.id));
1933
- if (cor) return cor.id;
1934
- }
1935
- const marca = fields.find((f) => /marca|brand|make/.test(fieldHaystack(f)) && !used.has(f.id));
1936
- if (marca && !/model/i.test(normalizedValue)) return marca.id;
1937
- const modelo = fields.find((f) => /modelo|model/.test(fieldHaystack(f)) && !used.has(f.id));
1938
- if (modelo) return modelo.id;
1939
- const tipo = fields.find((f) => /\btipo\b|type|vehicletype/.test(fieldHaystack(f)) && !used.has(f.id));
1940
- if (tipo && /carro|car|moto|truck|van|flex|gasoline|diesel|hybrid|electric|el[eé]trico/.test(normalizedValue)) {
1941
- return tipo.id;
1942
- }
1943
- const combustivel = fields.find((f) => /combustivel|fuel/.test(fieldHaystack(f)) && !used.has(f.id));
1944
- if (combustivel && /flex|gasoline|diesel|hybrid|electric|el[eé]trico/.test(normalizedValue)) {
1945
- return combustivel.id;
1946
- }
1947
- const nextText = fields.find((field) => {
1948
- if (used.has(field.id)) return false;
1949
- const type = normalize4(field.type ?? "text");
1950
- return type === "text" || type === "input" || type === "number" || type === "";
1951
- });
1952
- 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;
1953
1613
  }
1954
1614
  function rewriteMisplacedFormFillFields(fields, registry) {
1955
1615
  const knownFields = collectKnownFormFields(registry);
@@ -1966,7 +1626,7 @@ function rewriteMisplacedFormFillFields(fields, registry) {
1966
1626
  const inferred = inferFieldIdForValue(String(field.value ?? ""), knownFields, used);
1967
1627
  if (!inferred) return field;
1968
1628
  used.add(inferred);
1969
- chunkAYWMBMSN_js.appilotsDebugWarn(
1629
+ chunkYB77RYCC_js.appilotsDebugWarn(
1970
1630
  `formFieldRewrite: ${field.fieldId} \u2192 ${inferred} (value=${JSON.stringify(field.value)})`
1971
1631
  );
1972
1632
  return { ...field, fieldId: inferred };
@@ -1974,28 +1634,36 @@ function rewriteMisplacedFormFillFields(fields, registry) {
1974
1634
  }
1975
1635
 
1976
1636
  // src/executor/formValidation.ts
1977
- 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;
1978
- 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;
1979
1639
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1980
- var FIELD_HINTS = [
1981
- { re: /placa|plate|matr[ií]cula/i, fieldId: "placa" },
1982
- { re: /marca|brand/i, fieldId: "marca" },
1983
- { re: /modelo|model/i, fieldId: "modelo" },
1984
- { re: /\bcor\b|color|colour/i, fieldId: "cor" },
1985
- { re: /\bano\b|year/i, fieldId: "ano" },
1986
- { re: /email|e-mail|correo/i, fieldId: "email" }
1987
- ];
1988
- function inferValidationFieldId(message) {
1989
- for (const hint of FIELD_HINTS) {
1990
- 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
+ }
1991
1653
  }
1992
- 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} `);
1993
1661
  }
1994
1662
  function readVisibleFormValidation(snap) {
1995
1663
  if (!snap) return void 0;
1996
1664
  for (const text of snap.texts ?? []) {
1997
- if (!text?.trim() || !FORM_VALIDATION_TEXT_RE.test(text)) continue;
1998
- 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 };
1999
1667
  }
2000
1668
  return void 0;
2001
1669
  }
@@ -2004,7 +1672,7 @@ function readVisibleFormSuccess(snap) {
2004
1672
  return (snap.texts ?? []).find((text) => text?.trim() && FORM_SUCCESS_TEXT_RE.test(text));
2005
1673
  }
2006
1674
  function submitAsyncStillPending(submitTargetId) {
2007
- const probe = chunkAYWMBMSN_js.probeLoadingState(submitTargetId ?? null, chunkAYWMBMSN_js.getCurrentScreen());
1675
+ const probe = chunkYB77RYCC_js.probeLoadingState(submitTargetId ?? null, chunkYB77RYCC_js.getCurrentScreen());
2008
1676
  if (probe.loading) return true;
2009
1677
  if (submitTargetId && probe.pressedFound && probe.pressedDisabled) return true;
2010
1678
  return false;
@@ -2016,7 +1684,7 @@ function evaluatePostSubmitSnapshot(snap, activePath) {
2016
1684
  }
2017
1685
  const successText = readVisibleFormSuccess(snap);
2018
1686
  if (successText) return { status: "success", message: successText };
2019
- if (!chunkAYWMBMSN_js.snapshotShowsOpenCreateForm(snap, activePath)) {
1687
+ if (!chunkYB77RYCC_js.snapshotShowsOpenCreateForm(snap, activePath)) {
2020
1688
  return { status: "success" };
2021
1689
  }
2022
1690
  return void 0;
@@ -2032,7 +1700,7 @@ async function waitForPostSubmitOutcome(options) {
2032
1700
  continue;
2033
1701
  }
2034
1702
  const snap2 = captureSnapshot();
2035
- const activePath2 = chunkAYWMBMSN_js.getActiveRouteNames();
1703
+ const activePath2 = chunkYB77RYCC_js.getActiveRouteNames();
2036
1704
  const outcome2 = evaluatePostSubmitSnapshot(snap2, activePath2);
2037
1705
  if (outcome2) return outcome2;
2038
1706
  await sleep(pollMs);
@@ -2044,7 +1712,7 @@ async function waitForPostSubmitOutcome(options) {
2044
1712
  };
2045
1713
  }
2046
1714
  const snap = captureSnapshot();
2047
- const activePath = chunkAYWMBMSN_js.getActiveRouteNames();
1715
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
2048
1716
  const outcome = evaluatePostSubmitSnapshot(snap, activePath);
2049
1717
  if (outcome) return outcome;
2050
1718
  return {
@@ -2150,16 +1818,16 @@ function findSnapshotButton(targetId) {
2150
1818
  }
2151
1819
  }
2152
1820
  function buildUiDiagnose(targetId, cause) {
2153
- const activePath = chunkAYWMBMSN_js.getActiveRouteNames();
2154
- const screen = activePath[activePath.length - 1] ?? chunkAYWMBMSN_js.getCurrentScreen() ?? void 0;
1821
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
1822
+ const screen = activePath[activePath.length - 1] ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2155
1823
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
2156
1824
  const diagnose = {
2157
1825
  category: cause === "not-found" ? "component-not-found" : cause === "disabled" ? "disabled" : "unknown",
2158
1826
  targetId,
2159
1827
  screen: screenPath
2160
1828
  };
2161
- if (chunkAYWMBMSN_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
2162
- diagnose.visibleMessage = chunkAYWMBMSN_js.OPTIONAL_STEP_AUTOMATION_HINT;
1829
+ if (chunkYB77RYCC_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
1830
+ diagnose.visibleMessage = chunkYB77RYCC_js.OPTIONAL_STEP_AUTOMATION_HINT;
2163
1831
  diagnose.recoverable = true;
2164
1832
  }
2165
1833
  return diagnose;
@@ -2217,13 +1885,15 @@ function resolveComponentId(componentId, registry, action) {
2217
1885
  const snapshot = registry.snapshot();
2218
1886
  for (const comp of snapshot) {
2219
1887
  if (comp.id.toLowerCase() === lower) {
2220
- 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
+ );
2221
1891
  return comp.id;
2222
1892
  }
2223
1893
  }
2224
- const currentScreen = chunkAYWMBMSN_js.getCurrentScreen();
1894
+ const currentScreen = chunkYB77RYCC_js.getCurrentScreen();
2225
1895
  if (currentScreen) {
2226
- const screenMeta = chunkAYWMBMSN_js.getScreenMetadata(currentScreen);
1896
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(currentScreen);
2227
1897
  const actions = screenMeta?.actions;
2228
1898
  if (actions && Array.isArray(actions)) {
2229
1899
  const metaAction = actions.find(
@@ -2232,12 +1902,16 @@ function resolveComponentId(componentId, registry, action) {
2232
1902
  if (metaAction && typeof metaAction === "object" && metaAction.label) {
2233
1903
  const metaLabel = metaAction.label;
2234
1904
  const normalizedMetaLabel = metaLabel.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
2235
- 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
+ );
2236
1908
  for (const comp of snapshot) {
2237
1909
  if (!comp.label) continue;
2238
1910
  const compLabel = comp.label.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
2239
1911
  if (compLabel === normalizedMetaLabel || compLabel.includes(normalizedMetaLabel) || normalizedMetaLabel.includes(compLabel)) {
2240
- 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
+ );
2241
1915
  return comp.id;
2242
1916
  }
2243
1917
  }
@@ -2252,8 +1926,8 @@ function resolveComponentId(componentId, registry, action) {
2252
1926
  }));
2253
1927
  const match = resolveTarget(componentId, candidates, { action });
2254
1928
  if (match.status === "matched") {
2255
- console.log(
2256
- `[Appilots] resolveComponentId: matched "${componentId}" -> "${match.id}" (tier=${match.tier})`
1929
+ chunkYB77RYCC_js.appilotsDebugLog(
1930
+ `resolveComponentId: matched "${componentId}" -> "${match.id}" (tier=${match.tier})`
2257
1931
  );
2258
1932
  return match.id;
2259
1933
  }
@@ -2342,8 +2016,8 @@ function setValueHandler(rawComponentId, requested, registry) {
2342
2016
  try {
2343
2017
  slider.setValue(applied);
2344
2018
  if (applied !== requestedValue) {
2345
- console.log(
2346
- `[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})`
2347
2021
  );
2348
2022
  }
2349
2023
  return { success: true, effect: "changed" };
@@ -2377,11 +2051,26 @@ function checkModalOcclusion(rawComponentId, action) {
2377
2051
  return null;
2378
2052
  }
2379
2053
  if (typeof rawComponentId !== "string" || rawComponentId.trim().length === 0) return null;
2380
- const fiberRoot = chunkAYWMBMSN_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();
2381
2070
  if (!fiberRoot) return null;
2382
2071
  let snap;
2383
2072
  try {
2384
- snap = walkFiber(fiberRoot);
2073
+ snap = chunkYB77RYCC_js.walkFiber(fiberRoot);
2385
2074
  } catch {
2386
2075
  return null;
2387
2076
  }
@@ -2408,9 +2097,12 @@ function checkModalOcclusion(rawComponentId, action) {
2408
2097
  modalOptionLabels.push(button.label ?? button.id);
2409
2098
  }
2410
2099
  }
2411
- for (const toggle of snap.toggles ?? []) add(toggle.inModal ? inModal : outside, toggle.id, toggle.label);
2412
- for (const input of snap.inputs ?? []) add(input.inModal ? inModal : outside, input.id, input.label);
2413
- 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);
2414
2106
  for (const list of snap.lists ?? []) {
2415
2107
  for (const item of list.items ?? []) {
2416
2108
  const itemInModal = (item.buttons ?? []).some((b) => b.inModal) || (item.inputs ?? []).some((i) => i.inModal) || (item.toggles ?? []).some((t) => t.inModal);
@@ -2440,12 +2132,15 @@ function checkModalOcclusion(rawComponentId, action) {
2440
2132
  }
2441
2133
  function uiInteractionHandler(payload, context) {
2442
2134
  const { permissions } = context;
2443
- const registry = context.registry ?? chunkAYWMBMSN_js.componentRegistry;
2135
+ const registry = context.registry ?? chunkYB77RYCC_js.componentRegistry;
2444
2136
  if (!permissions.canInteractUI) {
2445
2137
  return {
2446
2138
  success: false,
2447
2139
  error: "UI interaction is not permitted",
2448
- diagnose: buildUiDiagnose(payload.componentId ?? payload.targetId ?? "", "unknown")
2140
+ diagnose: buildUiDiagnose(
2141
+ payload.componentId ?? payload.targetId ?? "",
2142
+ "unknown"
2143
+ )
2449
2144
  };
2450
2145
  }
2451
2146
  const { action } = payload;
@@ -2459,8 +2154,8 @@ function uiInteractionHandler(payload, context) {
2459
2154
  if (sliderId) {
2460
2155
  const smuggled = payload.value ?? payload.params?.value;
2461
2156
  if (smuggled !== void 0) {
2462
- console.log(
2463
- `[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`
2464
2159
  );
2465
2160
  return setValueHandler(rawComponentId, smuggled, registry);
2466
2161
  }
@@ -2470,18 +2165,53 @@ function uiInteractionHandler(payload, context) {
2470
2165
  diagnose: { ...buildUiDiagnose(sliderId, "unknown"), recoverable: true }
2471
2166
  };
2472
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
+ }
2473
2203
  const occluded = checkModalOcclusion(rawComponentId, actionStr);
2474
2204
  if (occluded) {
2475
- console.log(
2476
- `[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`
2477
2207
  );
2478
2208
  return occluded;
2479
2209
  }
2480
2210
  if (typeof rawComponentId === "string" && rawComponentId.trim().toLowerCase().startsWith("el:")) {
2481
2211
  const result = dispatchElementOrTarget(rawComponentId, registry, actionStr);
2482
2212
  if (result.success) {
2483
- console.log(
2484
- `[Appilots] uiInteractionHandler: interaction element dispatch succeeded for "${rawComponentId}"`
2213
+ chunkYB77RYCC_js.appilotsDebugLog(
2214
+ `uiInteractionHandler: interaction element dispatch succeeded for "${rawComponentId}"`
2485
2215
  );
2486
2216
  return { success: true };
2487
2217
  }
@@ -2489,17 +2219,17 @@ function uiInteractionHandler(payload, context) {
2489
2219
  }
2490
2220
  const ordinal = parseSyntheticListItemId(rawComponentId);
2491
2221
  if (ordinal && (action === "press" || actionStr === "tap" || actionStr === "click" || actionStr === "longPress")) {
2492
- console.log(
2493
- `[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}`
2494
2224
  );
2495
2225
  const result = pressListItemAtOrdinal(ordinal.listIndex, ordinal.itemIndex);
2496
2226
  if (result.ok) {
2497
- console.log(
2498
- `[Appilots] uiInteractionHandler: synthetic ordinal press succeeded (container=${result.containerType ?? "List"})`
2227
+ chunkYB77RYCC_js.appilotsDebugLog(
2228
+ `uiInteractionHandler: synthetic ordinal press succeeded (container=${result.containerType ?? "List"})`
2499
2229
  );
2500
2230
  return { success: true };
2501
2231
  }
2502
- const screen = chunkAYWMBMSN_js.getCurrentScreen() ?? void 0;
2232
+ const screen = chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2503
2233
  if (result.reason === "list-not-found" || result.reason === "item-not-found") {
2504
2234
  return {
2505
2235
  success: false,
@@ -2540,7 +2270,9 @@ function uiInteractionHandler(payload, context) {
2540
2270
  };
2541
2271
  }
2542
2272
  const componentId = resolveComponentId(rawComponentId, registry, actionStr);
2543
- console.log(`[Appilots] uiInteractionHandler: resolved componentId="${payload.componentId}" \u2192 "${componentId}"`);
2273
+ chunkYB77RYCC_js.appilotsDebugLog(
2274
+ `uiInteractionHandler: resolved componentId="${payload.componentId}" \u2192 "${componentId}"`
2275
+ );
2544
2276
  const target = registry.getTarget(componentId);
2545
2277
  if (target) {
2546
2278
  try {
@@ -2591,7 +2323,9 @@ function uiInteractionHandler(payload, context) {
2591
2323
  return { success: false, error: err?.message ?? "Focus failed" };
2592
2324
  }
2593
2325
  }
2594
- 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
+ );
2595
2329
  const handle = findInteractiveByIdentifier(componentId, {
2596
2330
  kind: actionStr === "toggle" ? "toggle" : actionStr === "focus" ? "field" : "target"
2597
2331
  });
@@ -2599,7 +2333,9 @@ function uiInteractionHandler(payload, context) {
2599
2333
  try {
2600
2334
  if (actionStr === "press" && handle.kind === "target" && handle.press) {
2601
2335
  handle.press();
2602
- console.log(`[Appilots] uiInteractionHandler: fiber fallback press succeeded for "${componentId}"`);
2336
+ chunkYB77RYCC_js.appilotsDebugLog(
2337
+ `uiInteractionHandler: fiber fallback press succeeded for "${componentId}"`
2338
+ );
2603
2339
  return { success: true };
2604
2340
  }
2605
2341
  if (actionStr === "press" && handle.kind === "toggle" && handle.setValue) {
@@ -2664,7 +2400,7 @@ function submitLabelHintsSubmit(label) {
2664
2400
  return SUBMIT_LABEL_HINT_RE.test(trimmed);
2665
2401
  }
2666
2402
  function screenDeclaresSubmitAction(screenName) {
2667
- const meta = chunkAYWMBMSN_js.getScreenMetadata(screenName);
2403
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2668
2404
  return Array.isArray(meta?.actions) && meta.actions.some(
2669
2405
  (action) => typeof action === "object" && action !== null && action.type === "submit"
2670
2406
  );
@@ -2697,7 +2433,7 @@ function resolveFormScreensForSubmit(screen, activePath, registry) {
2697
2433
  } else {
2698
2434
  push(screen);
2699
2435
  }
2700
- push(chunkAYWMBMSN_js.getCurrentScreen() ?? void 0);
2436
+ push(chunkYB77RYCC_js.getCurrentScreen() ?? void 0);
2701
2437
  const withSubmit = [];
2702
2438
  const rest = [];
2703
2439
  for (const name of ordered) {
@@ -2715,7 +2451,7 @@ function collectSubmitTargetCandidates(screens, registry) {
2715
2451
  candidates.push(id);
2716
2452
  };
2717
2453
  for (const screenName of screens) {
2718
- const meta = chunkAYWMBMSN_js.getScreenMetadata(screenName);
2454
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2719
2455
  const submitMeta = Array.isArray(meta?.actions) ? meta.actions.find(
2720
2456
  (action) => typeof action === "object" && action !== null && action.type === "submit"
2721
2457
  ) : void 0;
@@ -2745,12 +2481,10 @@ function readVisibleValidation(fieldId, label) {
2745
2481
  try {
2746
2482
  const snap = captureSnapshot();
2747
2483
  const texts = snap.texts ?? [];
2748
- const needles = [fieldId, label].filter(
2749
- (s) => !!s && s.length > 0
2750
- );
2484
+ const needles = [fieldId, label].filter((s) => !!s && s.length > 0);
2751
2485
  for (const text of texts) {
2752
2486
  const lower = text.toLowerCase();
2753
- if (FORM_VALIDATION_TEXT_RE.test(lower)) {
2487
+ if (FORM_VALIDATION_TEXT_RE2.test(lower)) {
2754
2488
  for (const needle of needles) {
2755
2489
  if (lower.includes(needle.toLowerCase())) return text;
2756
2490
  }
@@ -2761,8 +2495,8 @@ function readVisibleValidation(fieldId, label) {
2761
2495
  return void 0;
2762
2496
  }
2763
2497
  function resolveScreenContext() {
2764
- const activePath = chunkAYWMBMSN_js.getActiveRouteNames();
2765
- const screen = activePath[activePath.length - 1] ?? chunkAYWMBMSN_js.getCurrentScreen() ?? void 0;
2498
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
2499
+ const screen = activePath[activePath.length - 1] ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
2766
2500
  return { screen, activePath };
2767
2501
  }
2768
2502
  function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
@@ -2770,36 +2504,36 @@ function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
2770
2504
  if (!requested) return false;
2771
2505
  const meta = getMetadataField(fieldId, registry);
2772
2506
  const options = Array.isArray(meta?.options) ? meta.options : [];
2773
- const requestedNorm = chunkAYWMBMSN_js.normalize3(requested);
2774
- const currentNorm = chunkAYWMBMSN_js.normalize3(currentValue);
2507
+ const requestedNorm = chunkYB77RYCC_js.normalize3(requested);
2508
+ const currentNorm = chunkYB77RYCC_js.normalize3(currentValue);
2775
2509
  if (currentNorm === requestedNorm) return true;
2776
2510
  for (const option of options) {
2777
2511
  const value = typeof option?.value === "string" ? option.value : "";
2778
2512
  const label = typeof option?.label === "string" ? option.label : "";
2779
- if (chunkAYWMBMSN_js.normalize3(value) === requestedNorm && chunkAYWMBMSN_js.normalize3(label) === currentNorm) return true;
2780
- if (chunkAYWMBMSN_js.normalize3(label) === requestedNorm && chunkAYWMBMSN_js.normalize3(label) === currentNorm) return true;
2781
- if (chunkAYWMBMSN_js.normalize3(value) === requestedNorm && chunkAYWMBMSN_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;
2782
2516
  }
2783
2517
  return false;
2784
2518
  }
2785
2519
  function getMetadataField(fieldId, registry) {
2786
2520
  const screens = /* @__PURE__ */ new Set();
2787
- for (const name of chunkAYWMBMSN_js.getActiveRouteNames()) screens.add(name);
2788
- const current = chunkAYWMBMSN_js.getCurrentScreen();
2521
+ for (const name of chunkYB77RYCC_js.getActiveRouteNames()) screens.add(name);
2522
+ const current = chunkYB77RYCC_js.getCurrentScreen();
2789
2523
  if (current) screens.add(current);
2790
2524
  if (registry) {
2791
2525
  for (const comp of registry.snapshot()) {
2792
2526
  if (comp.kind === "field" && comp.screen) screens.add(comp.screen);
2793
2527
  }
2794
2528
  }
2795
- const needle = chunkAYWMBMSN_js.normalize3(fieldId);
2529
+ const needle = chunkYB77RYCC_js.normalize3(fieldId);
2796
2530
  for (const screenName of screens) {
2797
- const screenMeta = chunkAYWMBMSN_js.getScreenMetadata(screenName);
2531
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(screenName);
2798
2532
  const fields = Array.isArray(screenMeta?.fields) ? screenMeta.fields : [];
2799
2533
  const match = fields.find((field) => {
2800
2534
  if (!field || typeof field !== "object") return false;
2801
- const id = typeof field.id === "string" ? chunkAYWMBMSN_js.normalize3(field.id) : "";
2802
- const label = typeof field.label === "string" ? chunkAYWMBMSN_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) : "";
2803
2537
  return id === needle || label === needle;
2804
2538
  });
2805
2539
  if (match) return match;
@@ -2811,11 +2545,11 @@ function resolveSelectOption(fieldId, value, registry) {
2811
2545
  if (!requested) return void 0;
2812
2546
  const meta = getMetadataField(fieldId, registry);
2813
2547
  const options = Array.isArray(meta?.options) ? meta.options : [];
2814
- const requestedNorm = chunkAYWMBMSN_js.normalize3(requested);
2548
+ const requestedNorm = chunkYB77RYCC_js.normalize3(requested);
2815
2549
  for (const option of options) {
2816
2550
  const optionValue = typeof option?.value === "string" ? option.value : "";
2817
2551
  const optionLabel = typeof option?.label === "string" ? option.label : "";
2818
- if (chunkAYWMBMSN_js.normalize3(optionValue) === requestedNorm || chunkAYWMBMSN_js.normalize3(optionLabel) === requestedNorm) {
2552
+ if (chunkYB77RYCC_js.normalize3(optionValue) === requestedNorm || chunkYB77RYCC_js.normalize3(optionLabel) === requestedNorm) {
2819
2553
  return { value: optionValue, label: optionLabel };
2820
2554
  }
2821
2555
  }
@@ -2865,14 +2599,16 @@ async function tryPressSelectOption(fieldId, value, registry, options = {}) {
2865
2599
  return {
2866
2600
  success: false,
2867
2601
  error: `No pressable option found for select field "${fieldId}"`,
2868
- diagnose: { category: "component-not-found", fieldId, screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0 }
2602
+ diagnose: { category: "component-not-found", fieldId, screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
2869
2603
  };
2870
2604
  }
2871
2605
  function normalizeFieldType(type) {
2872
2606
  if (typeof type !== "string") return void 0;
2873
- const normalized = chunkAYWMBMSN_js.normalize3(type);
2874
- if (normalized === "select" || normalized === "picker" || normalized === "dropdown") return "select";
2875
- 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";
2876
2612
  if (normalized === "date") return "date";
2877
2613
  if (normalized === "number" || normalized === "numeric") return "number";
2878
2614
  if (normalized === "custom") return "custom";
@@ -2898,7 +2634,7 @@ function fieldCueTerms(fieldId, label) {
2898
2634
  );
2899
2635
  const terms = /* @__PURE__ */ new Set();
2900
2636
  for (const value of raw) {
2901
- const normalized = chunkAYWMBMSN_js.normalize3(value);
2637
+ const normalized = chunkYB77RYCC_js.normalize3(value);
2902
2638
  if (normalized.length >= 3 && normalized !== "id") terms.add(normalized);
2903
2639
  }
2904
2640
  return [...terms];
@@ -2906,20 +2642,17 @@ function fieldCueTerms(fieldId, label) {
2906
2642
  function snapshotHasFieldCue(snap, fieldId, label) {
2907
2643
  const terms = fieldCueTerms(fieldId, label);
2908
2644
  if (terms.length === 0) return false;
2909
- const visible = [
2910
- ...snap.texts ?? [],
2911
- ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")
2912
- ].map((text) => chunkAYWMBMSN_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);
2913
2646
  return visible.some((text) => terms.some((term) => text.includes(term) || term.includes(text)));
2914
2647
  }
2915
2648
  function scoreCandidateText(value, texts) {
2916
- const valueNorm = chunkAYWMBMSN_js.normalize3(String(value ?? ""));
2649
+ const valueNorm = chunkYB77RYCC_js.normalize3(String(value ?? ""));
2917
2650
  if (!valueNorm) return 0;
2918
2651
  let best = 0;
2919
2652
  for (const text of texts) {
2920
- const textNorm = chunkAYWMBMSN_js.normalize3(text);
2653
+ const textNorm = chunkYB77RYCC_js.normalize3(text);
2921
2654
  if (!textNorm) continue;
2922
- best = Math.max(best, chunkAYWMBMSN_js.matchScore(valueNorm, textNorm));
2655
+ best = Math.max(best, chunkYB77RYCC_js.matchScore(valueNorm, textNorm));
2923
2656
  }
2924
2657
  return best;
2925
2658
  }
@@ -2933,7 +2666,7 @@ function optionTexts(option) {
2933
2666
  function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue, registry) {
2934
2667
  const fieldLabel = getFieldLabel(fieldId, registry);
2935
2668
  const fieldCueVisible = snapshotHasFieldCue(snap, fieldId, fieldLabel);
2936
- const genericValue = chunkAYWMBMSN_js.isGenericSelectValue(value);
2669
+ const genericValue = chunkYB77RYCC_js.isGenericSelectValue(value);
2937
2670
  const candidates = [];
2938
2671
  let order = 0;
2939
2672
  const choiceGroups = snap.choiceGroups ?? [];
@@ -2945,7 +2678,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
2945
2678
  const groupCueScore = Math.max(
2946
2679
  globalCueScore,
2947
2680
  ...groupTexts.map((text) => {
2948
- const normalized = chunkAYWMBMSN_js.normalize3(text);
2681
+ const normalized = chunkYB77RYCC_js.normalize3(text);
2949
2682
  return fieldCueTerms(fieldId, fieldLabel).some(
2950
2683
  (term) => normalized.includes(term) || term.includes(normalized)
2951
2684
  ) ? 80 : 0;
@@ -2982,10 +2715,8 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
2982
2715
  const elementCueScore = Math.max(
2983
2716
  fieldCueVisible && elements.length <= 12 ? 50 : 0,
2984
2717
  ...cueTexts.map((text) => {
2985
- const normalized = chunkAYWMBMSN_js.normalize3(text);
2986
- return fieldTerms.some(
2987
- (term) => normalized.includes(term) || term.includes(normalized)
2988
- ) ? 80 : 0;
2718
+ const normalized = chunkYB77RYCC_js.normalize3(text);
2719
+ return fieldTerms.some((term) => normalized.includes(term) || term.includes(normalized)) ? 80 : 0;
2989
2720
  })
2990
2721
  );
2991
2722
  const valueScore = genericValue ? 0 : scoreCandidateText(value, texts);
@@ -3042,7 +2773,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3042
2773
  return {
3043
2774
  success: false,
3044
2775
  error: err?.message ?? "Could not capture visible choices",
3045
- diagnose: { category: "unknown", fieldId, screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0 }
2776
+ diagnose: { category: "unknown", fieldId, screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
3046
2777
  };
3047
2778
  }
3048
2779
  const candidates = buildChoiceCandidates(
@@ -3057,7 +2788,11 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3057
2788
  return {
3058
2789
  success: false,
3059
2790
  error: `No visible option found for select field "${fieldId}"`,
3060
- diagnose: { category: "component-not-found", fieldId, screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0 }
2791
+ diagnose: {
2792
+ category: "component-not-found",
2793
+ fieldId,
2794
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0
2795
+ }
3061
2796
  };
3062
2797
  }
3063
2798
  const pressed = pressTargetByIdOrLabel(candidate.targetId, registry);
@@ -3070,7 +2805,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
3070
2805
  }
3071
2806
  function isContinuationButton(label) {
3072
2807
  if (!label) return false;
3073
- return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkAYWMBMSN_js.normalize3(label));
2808
+ return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkYB77RYCC_js.normalize3(label));
3074
2809
  }
3075
2810
  function pressContinuationButton(registry) {
3076
2811
  const snap = captureSnapshot();
@@ -3083,38 +2818,40 @@ function pressContinuationButton(registry) {
3083
2818
  return {
3084
2819
  success: false,
3085
2820
  error: "No enabled continuation button is visible",
3086
- diagnose: { category: "component-not-found", screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0 }
2821
+ diagnose: { category: "component-not-found", screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0 }
3087
2822
  };
3088
2823
  }
3089
2824
  return pressTargetByIdOrLabel(id, registry);
3090
2825
  }
3091
2826
  function findField(fieldId, registry) {
3092
- console.log(`[Appilots] findField: searching for fieldId="${fieldId}"`);
2827
+ chunkYB77RYCC_js.appilotsDebugLog(`findField: searching for fieldId="${fieldId}"`);
3093
2828
  const exact = registry.getField(fieldId);
3094
2829
  if (exact) {
3095
- console.log(`[Appilots] findField: FOUND exact match for fieldId="${fieldId}"`);
2830
+ chunkYB77RYCC_js.appilotsDebugLog(`findField: FOUND exact match for fieldId="${fieldId}"`);
3096
2831
  return exact;
3097
2832
  }
3098
2833
  const lower = fieldId.toLowerCase();
3099
2834
  const snapshot = registry.snapshot();
3100
2835
  for (const comp of snapshot) {
3101
2836
  if (comp.kind === "field" && comp.id.toLowerCase() === lower) {
3102
- 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
+ );
3103
2840
  return registry.getField(comp.id);
3104
2841
  }
3105
2842
  }
3106
- const currentScreenForTieBreak = chunkAYWMBMSN_js.getCurrentScreen();
3107
- const needle = chunkAYWMBMSN_js.normalize3(fieldId);
2843
+ const currentScreenForTieBreak = chunkYB77RYCC_js.getCurrentScreen();
2844
+ const needle = chunkYB77RYCC_js.normalize3(fieldId);
3108
2845
  let bestComp;
3109
2846
  let bestScore = 0;
3110
2847
  let bestOnCurrentScreen = false;
3111
2848
  for (const comp of snapshot) {
3112
2849
  if (comp.kind !== "field") continue;
3113
- const candidates = [chunkAYWMBMSN_js.normalize3(comp.id)];
3114
- if (comp.label) candidates.push(chunkAYWMBMSN_js.normalize3(comp.label));
2850
+ const candidates = [chunkYB77RYCC_js.normalize3(comp.id)];
2851
+ if (comp.label) candidates.push(chunkYB77RYCC_js.normalize3(comp.label));
3115
2852
  let candidateScore = 0;
3116
2853
  for (const cand of candidates) {
3117
- const s = chunkAYWMBMSN_js.matchScore(needle, cand);
2854
+ const s = chunkYB77RYCC_js.matchScore(needle, cand);
3118
2855
  if (s > candidateScore) candidateScore = s;
3119
2856
  }
3120
2857
  if (candidateScore === 0) continue;
@@ -3127,14 +2864,14 @@ function findField(fieldId, registry) {
3127
2864
  }
3128
2865
  }
3129
2866
  if (bestComp && bestScore >= 75) {
3130
- console.log(
3131
- `[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})`
3132
2869
  );
3133
2870
  return registry.getField(bestComp.id);
3134
2871
  }
3135
- const currentScreen = chunkAYWMBMSN_js.getCurrentScreen();
2872
+ const currentScreen = chunkYB77RYCC_js.getCurrentScreen();
3136
2873
  if (currentScreen) {
3137
- const screenMeta = chunkAYWMBMSN_js.getScreenMetadata(currentScreen);
2874
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(currentScreen);
3138
2875
  const fields = screenMeta?.fields;
3139
2876
  if (fields && Array.isArray(fields)) {
3140
2877
  const metaField = fields.find(
@@ -3142,20 +2879,20 @@ function findField(fieldId, registry) {
3142
2879
  );
3143
2880
  if (metaField && typeof metaField === "object" && metaField.label) {
3144
2881
  const metaLabel = metaField.label;
3145
- const metaNeedle = chunkAYWMBMSN_js.normalize3(metaLabel);
2882
+ const metaNeedle = chunkYB77RYCC_js.normalize3(metaLabel);
3146
2883
  let mBest;
3147
2884
  let mBestScore = 0;
3148
2885
  for (const comp of snapshot) {
3149
2886
  if (comp.kind !== "field" || !comp.label) continue;
3150
- const score = chunkAYWMBMSN_js.matchScore(metaNeedle, chunkAYWMBMSN_js.normalize3(comp.label));
2887
+ const score = chunkYB77RYCC_js.matchScore(metaNeedle, chunkYB77RYCC_js.normalize3(comp.label));
3151
2888
  if (score > mBestScore) {
3152
2889
  mBestScore = score;
3153
2890
  mBest = comp;
3154
2891
  }
3155
2892
  }
3156
2893
  if (mBest && mBestScore >= 60) {
3157
- console.log(
3158
- `[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})`
3159
2896
  );
3160
2897
  return registry.getField(mBest.id);
3161
2898
  }
@@ -3163,32 +2900,34 @@ function findField(fieldId, registry) {
3163
2900
  }
3164
2901
  }
3165
2902
  if (bestComp && bestScore >= 40) {
3166
- console.log(
3167
- `[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})`
3168
2905
  );
3169
2906
  return registry.getField(bestComp.id);
3170
2907
  }
3171
- chunkAYWMBMSN_js.appilotsDebugWarn(
2908
+ chunkYB77RYCC_js.appilotsDebugWarn(
3172
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"}`
3173
2910
  );
3174
2911
  return void 0;
3175
2912
  }
3176
2913
  function findToggle(fieldId, registry) {
3177
- console.log(`[Appilots] findToggle: searching for fieldId="${fieldId}"`);
2914
+ chunkYB77RYCC_js.appilotsDebugLog(`findToggle: searching for fieldId="${fieldId}"`);
3178
2915
  const exact = registry.getToggle(fieldId);
3179
2916
  if (exact) {
3180
- console.log(`[Appilots] findToggle: FOUND exact match for "${fieldId}"`);
2917
+ chunkYB77RYCC_js.appilotsDebugLog(`findToggle: FOUND exact match for "${fieldId}"`);
3181
2918
  return exact;
3182
2919
  }
3183
2920
  const lower = fieldId.toLowerCase();
3184
2921
  const snapshot = registry.snapshot();
3185
2922
  for (const comp of snapshot) {
3186
2923
  if (comp.kind === "toggle" && comp.id.toLowerCase() === lower) {
3187
- 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
+ );
3188
2927
  return registry.getToggle(comp.id);
3189
2928
  }
3190
2929
  }
3191
- chunkAYWMBMSN_js.appilotsDebugWarn(
2930
+ chunkYB77RYCC_js.appilotsDebugWarn(
3192
2931
  `findToggle: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available toggles: ${snapshot.filter((c) => c.kind === "toggle").map((c) => `"${c.id}"`).join(", ") || "none"}`
3193
2932
  );
3194
2933
  return void 0;
@@ -3199,7 +2938,9 @@ function findSlider(fieldId, registry) {
3199
2938
  const lower = fieldId.toLowerCase();
3200
2939
  for (const comp of registry.snapshot()) {
3201
2940
  if (comp.kind === "slider" && comp.id.toLowerCase() === lower) {
3202
- 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
+ );
3203
2944
  return registry.getSlider(comp.id);
3204
2945
  }
3205
2946
  }
@@ -3208,7 +2949,7 @@ function findSlider(fieldId, registry) {
3208
2949
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3209
2950
  async function formFillHandler(payload, context) {
3210
2951
  const { permissions } = context;
3211
- const registry = context.registry ?? chunkAYWMBMSN_js.componentRegistry;
2952
+ const registry = context.registry ?? chunkYB77RYCC_js.componentRegistry;
3212
2953
  const { screen, activePath } = resolveScreenContext();
3213
2954
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
3214
2955
  if (!permissions.canFillForms) {
@@ -3227,11 +2968,11 @@ async function formFillHandler(payload, context) {
3227
2968
  }
3228
2969
  const registrySnapshot = registry.snapshot();
3229
2970
  if (registrySnapshot.length === 0) {
3230
- chunkAYWMBMSN_js.appilotsDebugWarn(
2971
+ chunkYB77RYCC_js.appilotsDebugWarn(
3231
2972
  "formFillHandler: registry is EMPTY \u2014 auto-tracking may not be active. Ensure enableAppilotsAutoTracking() runs before components mount."
3232
2973
  );
3233
2974
  } else {
3234
- console.log(
2975
+ chunkYB77RYCC_js.appilotsDebugLog(
3235
2976
  `[Appilots formFillHandler] Registry has ${registrySnapshot.length} components:`,
3236
2977
  registrySnapshot.map((c) => `${c.kind}:${c.id}`).join(", ")
3237
2978
  );
@@ -3239,7 +2980,7 @@ async function formFillHandler(payload, context) {
3239
2980
  const fieldResults = [];
3240
2981
  let allSuccess = true;
3241
2982
  let selectedChoiceThisBatch = false;
3242
- console.log(`[Appilots] formFillHandler: processing ${payload.fields.length} fields`);
2983
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: processing ${payload.fields.length} fields`);
3243
2984
  const availableFieldIds = () => registry.snapshot().filter((comp) => comp.kind === "field").map((comp) => `${comp.id}${comp.label ? ` (${comp.label})` : ""}`).slice(0, 8);
3244
2985
  const isElementIdField = (field) => typeof field.fieldId === "string" && field.fieldId.trim().toLowerCase().startsWith("el:");
3245
2986
  for (const field of payload.fields.filter(isElementIdField)) {
@@ -3266,13 +3007,13 @@ async function formFillHandler(payload, context) {
3266
3007
  const { fieldId, fieldType, value } = field;
3267
3008
  const effectiveFieldType = getEffectiveFieldType(fieldId, fieldType, registry);
3268
3009
  let selectFailure;
3269
- console.log(
3270
- `[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)}`
3271
3012
  );
3272
3013
  const fieldEntry = findField(fieldId, registry);
3273
3014
  if (fieldEntry) {
3274
3015
  try {
3275
- chunkAYWMBMSN_js.appilotsDebugLog(
3016
+ chunkYB77RYCC_js.appilotsDebugLog(
3276
3017
  `formFillHandler: found field "${fieldId}" via registry, calling setValue(<${String(value).length} chars>)`
3277
3018
  );
3278
3019
  const beforeValue = effectiveFieldType === "date" ? fieldEntry.getValue?.() ?? "" : void 0;
@@ -3303,7 +3044,7 @@ async function formFillHandler(payload, context) {
3303
3044
  after = fieldEntry.getValue?.() ?? "";
3304
3045
  }
3305
3046
  if (!selectValueApplied(fieldId, value, after, registry)) {
3306
- chunkAYWMBMSN_js.appilotsDebugWarn(
3047
+ chunkYB77RYCC_js.appilotsDebugWarn(
3307
3048
  `formFillHandler: select field "${fieldId}" setValue did not stick (wrote <${String(value).length} chars>, current is <${String(after ?? "").length} chars>), trying visible choice fallback`
3308
3049
  );
3309
3050
  const selectResult = await selectVisibleChoice(fieldId, value, registry, {
@@ -3318,7 +3059,11 @@ async function formFillHandler(payload, context) {
3318
3059
  fieldId,
3319
3060
  success: false,
3320
3061
  error: selectResult.error ?? `Select value "${String(value)}" was not applied for "${fieldId}"`,
3321
- 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
+ }
3322
3067
  });
3323
3068
  allSuccess = false;
3324
3069
  continue;
@@ -3373,7 +3118,9 @@ async function formFillHandler(payload, context) {
3373
3118
  continue;
3374
3119
  }
3375
3120
  try {
3376
- sliderEntry.setValue(snapSliderValue(numeric, sliderEntry.min, sliderEntry.max, sliderEntry.step));
3121
+ sliderEntry.setValue(
3122
+ snapSliderValue(numeric, sliderEntry.min, sliderEntry.max, sliderEntry.step)
3123
+ );
3377
3124
  fieldResults.push({ fieldId, success: true });
3378
3125
  } catch (err) {
3379
3126
  fieldResults.push({
@@ -3422,8 +3169,8 @@ async function formFillHandler(payload, context) {
3422
3169
  }
3423
3170
  if (selectResult.success) {
3424
3171
  selectedChoiceThisBatch = true;
3425
- console.log(
3426
- `[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}"` : "")
3427
3174
  );
3428
3175
  await sleep2(120);
3429
3176
  fieldResults.push({ fieldId, success: true });
@@ -3431,7 +3178,7 @@ async function formFillHandler(payload, context) {
3431
3178
  }
3432
3179
  selectFailure = selectResult;
3433
3180
  }
3434
- 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`);
3435
3182
  const handle = findInteractiveByIdentifier(fieldId, {
3436
3183
  kind: effectiveFieldType === "toggle" ? "toggle" : "field"
3437
3184
  });
@@ -3439,7 +3186,9 @@ async function formFillHandler(payload, context) {
3439
3186
  try {
3440
3187
  handle.focus?.();
3441
3188
  handle.setValue(value);
3442
- 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
+ );
3443
3192
  fieldResults.push({ fieldId, success: true });
3444
3193
  continue;
3445
3194
  } catch (err) {
@@ -3476,14 +3225,22 @@ async function formFillHandler(payload, context) {
3476
3225
  if (payload.submitAfterFill === true) {
3477
3226
  if (!allSuccess) {
3478
3227
  const failedIds = fieldResults.filter((result) => !result.success).map((result) => result.fieldId);
3479
- chunkAYWMBMSN_js.appilotsDebugWarn(
3228
+ chunkYB77RYCC_js.appilotsDebugWarn(
3480
3229
  "formFillHandler: submitAfterFill=true requested but some fields failed; NOT submitting" + (failedIds.length > 0 ? ` (failed: ${failedIds.join(", ")})` : "")
3481
3230
  );
3482
3231
  } else {
3483
3232
  await sleep2(120);
3484
- 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
+ );
3485
3242
  if (!submitResult.success) {
3486
- chunkAYWMBMSN_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
3243
+ chunkYB77RYCC_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
3487
3244
  return {
3488
3245
  success: false,
3489
3246
  error: submitResult.error,
@@ -3495,7 +3252,7 @@ async function formFillHandler(payload, context) {
3495
3252
  submitTargetId: submitResult.pressedTargetId
3496
3253
  });
3497
3254
  if (postSubmit.status === "pending") {
3498
- chunkAYWMBMSN_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
3255
+ chunkYB77RYCC_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
3499
3256
  return {
3500
3257
  success: false,
3501
3258
  error: postSubmit.message,
@@ -3504,7 +3261,7 @@ async function formFillHandler(payload, context) {
3504
3261
  };
3505
3262
  }
3506
3263
  if (postSubmit.status === "failure") {
3507
- chunkAYWMBMSN_js.appilotsDebugWarn(
3264
+ chunkYB77RYCC_js.appilotsDebugWarn(
3508
3265
  `formFillHandler: submit rejected by visible validation \u2014 ${postSubmit.message}`
3509
3266
  );
3510
3267
  return {
@@ -3519,7 +3276,7 @@ async function formFillHandler(payload, context) {
3519
3276
  }
3520
3277
  };
3521
3278
  }
3522
- console.log("[Appilots] formFillHandler: submitAfterFill \u2014 submit completed");
3279
+ chunkYB77RYCC_js.appilotsDebugLog("formFillHandler: submitAfterFill \u2014 submit completed");
3523
3280
  }
3524
3281
  }
3525
3282
  const aggregatedDiagnose = aggregateFieldDiagnoses(fieldResults, screenPath);
@@ -3531,18 +3288,18 @@ async function formFillHandler(payload, context) {
3531
3288
  };
3532
3289
  }
3533
3290
  function pressSubmitButton(context, registry) {
3534
- const activePath = context.activePath ?? chunkAYWMBMSN_js.getActiveRouteNames();
3291
+ const activePath = context.activePath ?? chunkYB77RYCC_js.getActiveRouteNames();
3535
3292
  const hintScreen = context.screen ?? context.screenPath;
3536
3293
  const formScreens = resolveFormScreensForSubmit(hintScreen, activePath, registry);
3537
- const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkAYWMBMSN_js.getCurrentScreen() ?? void 0;
3294
+ const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkYB77RYCC_js.getCurrentScreen() ?? void 0;
3538
3295
  const candidates = collectSubmitTargetCandidates(formScreens, registry);
3539
3296
  for (const candidate of candidates) {
3540
3297
  const target = registry.getTarget(candidate);
3541
3298
  if (target) {
3542
3299
  try {
3543
3300
  target.press();
3544
- console.log(
3545
- `[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}"` : "")
3546
3303
  );
3547
3304
  return { success: true, pressedTargetId: candidate };
3548
3305
  } catch (err) {
@@ -3555,7 +3312,7 @@ function pressSubmitButton(context, registry) {
3555
3312
  }
3556
3313
  }
3557
3314
  for (const screenName of formScreens) {
3558
- const screenMeta = chunkAYWMBMSN_js.getScreenMetadata(screenName);
3315
+ const screenMeta = chunkYB77RYCC_js.getScreenMetadata(screenName);
3559
3316
  const submitMeta = Array.isArray(screenMeta?.actions) ? screenMeta.actions.find(
3560
3317
  (action) => typeof action === "object" && action !== null && action.type === "submit"
3561
3318
  ) : void 0;
@@ -3566,9 +3323,7 @@ function pressSubmitButton(context, registry) {
3566
3323
  if (handle?.press) {
3567
3324
  try {
3568
3325
  handle.press();
3569
- console.log(
3570
- `[Appilots] formFillHandler: submitAfterFill \u2014 fiber fallback "${submitLabel}"`
3571
- );
3326
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 fiber fallback "${submitLabel}"`);
3572
3327
  return { success: true, pressedTargetId: submitId ?? submitLabel };
3573
3328
  } catch (err) {
3574
3329
  return {
@@ -3590,9 +3345,7 @@ function pressSubmitButton(context, registry) {
3590
3345
  if (id) {
3591
3346
  const pressed = pressTargetByIdOrLabel(id, registry);
3592
3347
  if (pressed.success) {
3593
- console.log(
3594
- `[Appilots] formFillHandler: submitAfterFill \u2014 pressed visible heuristic "${id}"`
3595
- );
3348
+ chunkYB77RYCC_js.appilotsDebugLog(`formFillHandler: submitAfterFill \u2014 pressed visible heuristic "${id}"`);
3596
3349
  return { success: true, pressedTargetId: id };
3597
3350
  }
3598
3351
  }
@@ -3606,8 +3359,8 @@ function pressSubmitButton(context, registry) {
3606
3359
  if (target) {
3607
3360
  try {
3608
3361
  target.press();
3609
- console.log(
3610
- `[Appilots] formFillHandler: submitAfterFill \u2014 pressed by label heuristic "${comp.label}"`
3362
+ chunkYB77RYCC_js.appilotsDebugLog(
3363
+ `formFillHandler: submitAfterFill \u2014 pressed by label heuristic "${comp.label}"`
3611
3364
  );
3612
3365
  return { success: true, pressedTargetId: comp.id };
3613
3366
  } catch (err) {
@@ -3619,9 +3372,16 @@ function pressSubmitButton(context, registry) {
3619
3372
  }
3620
3373
  }
3621
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
+ }
3622
3382
  return {
3623
3383
  success: false,
3624
- 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)',
3625
3385
  diagnose: { category: "component-not-found", screen: resolvedScreen }
3626
3386
  };
3627
3387
  }
@@ -3661,12 +3421,12 @@ function buildDiagnose(category, targetId, candidates) {
3661
3421
  return {
3662
3422
  category,
3663
3423
  targetId,
3664
- screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0,
3424
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
3665
3425
  ...candidates && candidates.length > 0 ? { candidates: candidates.slice(0, 8) } : {}
3666
3426
  };
3667
3427
  }
3668
3428
  function resolveListEntry(listId) {
3669
- const entries = chunkAYWMBMSN_js.listRegistry.snapshot();
3429
+ const entries = chunkYB77RYCC_js.listRegistry.snapshot();
3670
3430
  if (entries.length === 0) return {};
3671
3431
  if (listId) {
3672
3432
  const wanted = normalizeId2(listId);
@@ -3675,6 +3435,8 @@ function resolveListEntry(listId) {
3675
3435
  return { candidates: entries.map((e) => e.id) };
3676
3436
  }
3677
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] };
3678
3440
  return { candidates: entries.map((e) => e.id) };
3679
3441
  }
3680
3442
  function pageOffset(metrics, direction) {
@@ -3714,7 +3476,7 @@ async function scrollListHandler(payload, context) {
3714
3476
  }
3715
3477
  const { entry, candidates } = resolveListEntry(payload.listId);
3716
3478
  if (!entry) {
3717
- 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).";
3718
3480
  return {
3719
3481
  success: false,
3720
3482
  error: detail,
@@ -3722,6 +3484,13 @@ async function scrollListHandler(payload, context) {
3722
3484
  };
3723
3485
  }
3724
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
+ }
3725
3494
  if (typeof entry.itemCount === "number" && toIndex > entry.itemCount) {
3726
3495
  return {
3727
3496
  success: false,
@@ -3756,14 +3525,14 @@ async function scrollListHandler(payload, context) {
3756
3525
  }
3757
3526
  return {
3758
3527
  success: false,
3759
- error: `List "${entry.id}" does not expose a scrollable handle`,
3528
+ error: `"${entry.id}" does not expose a scrollable handle`,
3760
3529
  diagnose: buildDiagnose("unknown", entry.id)
3761
3530
  };
3762
3531
  }
3763
3532
 
3764
3533
  // src/executor/handlers/confirmHandler.ts
3765
3534
  async function confirmHandler(_actionId, _payload) {
3766
- return { success: true };
3535
+ return { success: true, effect: "unknown" };
3767
3536
  }
3768
3537
 
3769
3538
  // src/executor/postInteractionSettle.ts
@@ -3775,29 +3544,61 @@ function targetIdFromPayload(payload) {
3775
3544
  if (typeof targetId === "string" && targetId.trim()) return targetId.trim();
3776
3545
  return "";
3777
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
+ }
3778
3569
  async function waitForPostInteractionSettle(payload) {
3779
3570
  const targetId = targetIdFromPayload(payload);
3780
- const fromScreen = chunkAYWMBMSN_js.getCurrentScreen();
3781
- const baseline = chunkAYWMBMSN_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 !== "";
3782
3575
  await sleepMs(100);
3783
- const afterPress = chunkAYWMBMSN_js.probeLoadingState(targetId || null, chunkAYWMBMSN_js.getCurrentScreen());
3576
+ const afterPress = chunkYB77RYCC_js.probeLoadingState(targetId || null, chunkYB77RYCC_js.getCurrentScreen());
3784
3577
  const modalOrLoading = afterPress.modalOpen || afterPress.loading || afterPress.pressedDisabled;
3785
3578
  const fingerprintChanged = afterPress.fingerprint !== baseline.fingerprint;
3786
- const capMs = chunkAYWMBMSN_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;
3787
3587
  if (modalOrLoading || fingerprintChanged) {
3788
- await chunkAYWMBMSN_js.waitForLoadingSettle({
3588
+ await chunkYB77RYCC_js.waitForLoadingSettle({
3789
3589
  pressedComponentId: targetId || null,
3790
3590
  fromScreen,
3791
3591
  maxMs: capMs
3792
3592
  });
3793
- return;
3593
+ return verdict();
3794
3594
  }
3795
- if (chunkAYWMBMSN_js.isListItemPressTarget(targetId)) {
3796
- await chunkAYWMBMSN_js.waitForLoadingSettle({
3595
+ if (chunkYB77RYCC_js.isListItemPressTarget(targetId)) {
3596
+ await chunkYB77RYCC_js.waitForLoadingSettle({
3797
3597
  fromScreen,
3798
3598
  maxMs: 3e3
3799
3599
  });
3800
3600
  }
3601
+ return verdict();
3801
3602
  }
3802
3603
 
3803
3604
  // src/executor/ActionExecutor.ts
@@ -3813,7 +3614,7 @@ function validateActionPayload(action) {
3813
3614
  error: message,
3814
3615
  diagnose: {
3815
3616
  category: "validation",
3816
- screen: chunkAYWMBMSN_js.getCurrentScreen() ?? void 0,
3617
+ screen: chunkYB77RYCC_js.getCurrentScreen() ?? void 0,
3817
3618
  ...ids ?? {}
3818
3619
  }
3819
3620
  });
@@ -3852,10 +3653,9 @@ function validateActionPayload(action) {
3852
3653
  const hasIndex = typeof payload.toIndex === "number";
3853
3654
  const hasDirection = payload.direction === "up" || payload.direction === "down";
3854
3655
  if (!hasIndex && !hasDirection) {
3855
- return invalid(
3856
- 'scroll_list action needs toIndex (1-based) or direction ("up"/"down")',
3857
- { targetId: typeof payload.listId === "string" ? payload.listId : void 0 }
3858
- );
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
+ });
3859
3659
  }
3860
3660
  return null;
3861
3661
  }
@@ -3863,24 +3663,48 @@ function validateActionPayload(action) {
3863
3663
  return null;
3864
3664
  }
3865
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
+ }
3866
3677
  async function executeAction(action, context) {
3867
- 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
+ );
3868
3681
  const permissions = context.permissions ?? DEFAULT_PERMISSIONS;
3869
- if (permissions.allowedActions && permissions.allowedActions.length > 0 && !permissions.allowedActions.includes(action.type)) {
3870
- return {
3871
- success: false,
3872
- error: `Action type "${action.type}" is not in the allowed actions list`
3873
- };
3874
- }
3875
3682
  context.emit({
3876
3683
  type: "agent:action:start",
3877
3684
  timestamp: Date.now(),
3878
3685
  data: { actionId: action.id, actionType: action.type }
3879
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
+ }
3880
3704
  let result;
3881
3705
  const validationFailure = validateActionPayload(action);
3882
3706
  if (validationFailure) {
3883
- chunkAYWMBMSN_js.appilotsDebugWarn(
3707
+ chunkYB77RYCC_js.appilotsDebugWarn(
3884
3708
  `executeAction: payload validation failed for type="${action.type}" id="${action.id}": ${validationFailure.error}`
3885
3709
  );
3886
3710
  context.emit({
@@ -3907,28 +3731,28 @@ async function executeAction(action, context) {
3907
3731
  case "form_fill":
3908
3732
  result = await formFillHandler(action.payload, {
3909
3733
  permissions,
3910
- registry: context.registry ?? chunkAYWMBMSN_js.getDefaultRegistry()
3734
+ registry: context.registry ?? chunkYB77RYCC_js.getDefaultRegistry()
3911
3735
  });
3912
3736
  break;
3913
- case "ui_interaction":
3914
- result = uiInteractionHandler(action.payload, {
3737
+ case "ui_interaction": {
3738
+ const payload = action.payload;
3739
+ result = uiInteractionHandler(payload, {
3915
3740
  permissions,
3916
- registry: context.registry ?? chunkAYWMBMSN_js.getDefaultRegistry()
3741
+ registry: context.registry ?? chunkYB77RYCC_js.getDefaultRegistry()
3917
3742
  });
3918
3743
  if (result.success) {
3919
- await waitForPostInteractionSettle(action.payload);
3744
+ const settle = await waitForPostInteractionSettle(payload);
3745
+ result.effect = result.effect ?? effectFor(payload, settle.effect);
3920
3746
  }
3921
3747
  break;
3748
+ }
3922
3749
  case "scroll_list":
3923
3750
  result = await scrollListHandler(action.payload, {
3924
3751
  permissions
3925
3752
  });
3926
3753
  break;
3927
3754
  case "confirm":
3928
- result = await confirmHandler(
3929
- action.id,
3930
- action.payload
3931
- );
3755
+ result = await confirmHandler(action.id, action.payload);
3932
3756
  break;
3933
3757
  case "custom":
3934
3758
  result = {
@@ -3943,7 +3767,7 @@ async function executeAction(action, context) {
3943
3767
  };
3944
3768
  }
3945
3769
  } catch (err) {
3946
- chunkAYWMBMSN_js.appilotsDebugWarn(
3770
+ chunkYB77RYCC_js.appilotsDebugWarn(
3947
3771
  `executeAction: exception during action type="${action.type}" id="${action.id}": ${err?.message}`
3948
3772
  );
3949
3773
  result = {
@@ -3951,7 +3775,9 @@ async function executeAction(action, context) {
3951
3775
  error: err?.message ?? "Action execution failed unexpectedly"
3952
3776
  };
3953
3777
  }
3954
- 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
+ );
3955
3781
  context.emit({
3956
3782
  type: result.success ? "agent:action:complete" : "agent:action:error",
3957
3783
  timestamp: Date.now(),
@@ -4003,9 +3829,7 @@ var _patchedAlert = (title, message, buttons, options) => {
4003
3829
  return suppression.originalAlert(title, message, buttons, options);
4004
3830
  }
4005
3831
  suppression.consumed = true;
4006
- console.log(
4007
- "[Appilots] Suppressing native Alert during already-confirmed destructive agent action"
4008
- );
3832
+ chunkYB77RYCC_js.appilotsDebugLog("Suppressing native Alert during already-confirmed destructive agent action");
4009
3833
  try {
4010
3834
  suppression.pending = Promise.resolve(button.onPress()).then(() => void 0).catch((err) => reportHandlerFailure(err));
4011
3835
  } catch (err) {
@@ -4058,35 +3882,35 @@ async function runWithConfirmedDestructiveContext(enabled, host, fn) {
4058
3882
  // src/platform/reactNativeAdapter.ts
4059
3883
  var POST_ACTION_LOADING_MAX_MS = 6e3;
4060
3884
  function resolveScreenMetadata() {
4061
- const activePath = chunkAYWMBMSN_js.getActiveRouteNames();
3885
+ const activePath = chunkYB77RYCC_js.getActiveRouteNames();
4062
3886
  for (let i = activePath.length - 1; i >= 0; i--) {
4063
3887
  const name = activePath[i];
4064
- const meta = name ? chunkAYWMBMSN_js.getScreenMetadata(name) : void 0;
3888
+ const meta = name ? chunkYB77RYCC_js.getScreenMetadata(name) : void 0;
4065
3889
  if (meta && (Array.isArray(meta.fields) && meta.fields.length > 0 || Array.isArray(meta.actions) && meta.actions.length > 0)) {
4066
3890
  return meta;
4067
3891
  }
4068
3892
  }
4069
- const screen = chunkAYWMBMSN_js.getCurrentScreen();
4070
- return screen ? chunkAYWMBMSN_js.getScreenMetadata(screen) : void 0;
3893
+ const screen = chunkYB77RYCC_js.getCurrentScreen();
3894
+ return screen ? chunkYB77RYCC_js.getScreenMetadata(screen) : void 0;
4071
3895
  }
4072
3896
  function buildAgentContext(extras = {}) {
4073
3897
  const context = {};
4074
3898
  context.platform = "react-native";
4075
- const screen = chunkAYWMBMSN_js.getCurrentScreen();
3899
+ const screen = chunkYB77RYCC_js.getCurrentScreen();
4076
3900
  if (screen) context.currentScreen = screen;
4077
- const navigationState = chunkAYWMBMSN_js.getNavigationStateSnapshot();
3901
+ const navigationState = chunkYB77RYCC_js.getNavigationStateSnapshot();
4078
3902
  if (navigationState) context.navigationState = navigationState;
4079
3903
  const screenMeta = resolveScreenMetadata();
4080
3904
  if (screenMeta) context.screenMetadata = screenMeta;
4081
3905
  try {
4082
3906
  context.snapshot = captureSnapshot();
4083
3907
  } catch (err) {
4084
- chunkAYWMBMSN_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
3908
+ chunkYB77RYCC_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
4085
3909
  }
4086
- const registry = chunkAYWMBMSN_js.componentRegistry.snapshot();
3910
+ const registry = chunkYB77RYCC_js.componentRegistry.snapshot();
4087
3911
  const filtered = screen ? registry.filter((c) => !c.screen || c.screen === screen) : registry;
4088
3912
  if (filtered.length > 0) context.registeredComponents = filtered;
4089
- const registeredLists = chunkAYWMBMSN_js.listRegistry.snapshot();
3913
+ const registeredLists = chunkYB77RYCC_js.listRegistry.snapshot();
4090
3914
  if (registeredLists.length > 0) {
4091
3915
  context.registeredLists = registeredLists.map(
4092
3916
  ({ scrollToIndex, scrollToOffset, getScrollMetrics, dataPreview, ...rest }) => rest
@@ -4103,12 +3927,12 @@ function resolveActionHints(screen, pressedComponentId, actionPayload) {
4103
3927
  }
4104
3928
  }
4105
3929
  if (!screen || !pressedComponentId) return void 0;
4106
- const meta = chunkAYWMBMSN_js.getScreenMetadata(screen);
3930
+ const meta = chunkYB77RYCC_js.getScreenMetadata(screen);
4107
3931
  const actions = meta?.actions;
4108
3932
  if (!actions || actions.length === 0) return void 0;
4109
3933
  for (const a of actions) {
4110
3934
  if (typeof a === "string") continue;
4111
- if (chunkAYWMBMSN_js.idLooselyMatches(a.id, pressedComponentId)) {
3935
+ if (chunkYB77RYCC_js.idLooselyMatches(a.id, pressedComponentId)) {
4112
3936
  const inferred = a.appilotsInferred;
4113
3937
  if (inferred && typeof inferred === "object") return inferred;
4114
3938
  return void 0;
@@ -4123,71 +3947,68 @@ async function settleTurn(input) {
4123
3947
  const successById = new Map(input.results.map((r) => [r.actionId, r.success]));
4124
3948
  const typeById = new Map(input.results.map((r) => [r.actionId, r.type]));
4125
3949
  if (input.hadNavigate) {
4126
- const settle = await chunkAYWMBMSN_js.waitForScreenSettle({
3950
+ const settle = await chunkYB77RYCC_js.waitForScreenSettle({
4127
3951
  expectingChange: true,
4128
3952
  fromScreen: input.preNavigateScreen ?? null,
4129
3953
  fromSignature: input.preNavigateSignature ?? null,
4130
3954
  targetScreen: navigateTargetScreen,
4131
3955
  maxMs: 3500
4132
3956
  });
4133
- console.log(
4134
- `[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}`
4135
3959
  );
4136
- const navigationMoved = settle.transitioned || chunkAYWMBMSN_js.screenDepartedBaseline(
4137
- input.preNavigateScreen ?? null,
4138
- input.preNavigateSignature ?? null
4139
- ) || !!navigateTargetScreen && !!settle.screen && chunkAYWMBMSN_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);
4140
3961
  if (!navigationMoved) {
4141
- chunkAYWMBMSN_js.appilotsDebugWarn(
3962
+ chunkYB77RYCC_js.appilotsDebugWarn(
4142
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.`
4143
3964
  );
4144
3965
  for (const [actionId, type] of typeById) {
4145
3966
  if (type === "navigate") toolWithoutEffectIds.add(actionId);
4146
3967
  }
4147
3968
  }
4148
- const loadSettle = await chunkAYWMBMSN_js.waitForLoadingSettle({
3969
+ const loadSettle = await chunkYB77RYCC_js.waitForLoadingSettle({
4149
3970
  fromScreen: settle.screen ?? null,
4150
3971
  maxMs: 3e3
4151
3972
  });
4152
- console.log(
4153
- `[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}`
4154
3975
  );
4155
3976
  if (loadSettle.loadingPending) loadingPending = true;
4156
3977
  } else {
4157
3978
  const pressedAction = turnActions.find(
4158
3979
  (a) => a.type === "ui_interaction" && a.payload?.componentId === pressedId
4159
3980
  );
4160
- const hints = resolveActionHints(chunkAYWMBMSN_js.getCurrentScreen(), pressedId, pressedAction?.payload);
3981
+ const hints = resolveActionHints(chunkYB77RYCC_js.getCurrentScreen(), pressedId, pressedAction?.payload);
4161
3982
  const settleCapMs = hints?.isAsyncTrigger === true ? 1e4 : POST_ACTION_LOADING_MAX_MS;
4162
- const loadSettle = await chunkAYWMBMSN_js.waitForLoadingSettle({
3983
+ const loadSettle = await chunkYB77RYCC_js.waitForLoadingSettle({
4163
3984
  pressedComponentId: pressedId,
4164
- fromScreen: chunkAYWMBMSN_js.getCurrentScreen(),
3985
+ fromScreen: chunkYB77RYCC_js.getCurrentScreen(),
4165
3986
  maxMs: settleCapMs
4166
3987
  });
4167
- console.log(
4168
- `[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)" : ""}`
4169
3990
  );
4170
3991
  if (loadSettle.loadingPending) loadingPending = true;
4171
3992
  const listPressActions = turnActions.filter((action) => {
4172
- const target = chunkAYWMBMSN_js.actionPressTargetId(action);
4173
- return target ? chunkAYWMBMSN_js.isListItemPressTarget(target) : false;
3993
+ const target = chunkYB77RYCC_js.actionPressTargetId(action);
3994
+ return target ? chunkYB77RYCC_js.isListItemPressTarget(target) : false;
4174
3995
  });
4175
3996
  if (listPressActions.length > 0) {
4176
- const baselineFingerprint = chunkAYWMBMSN_js.probeLoadingState(pressedId, chunkAYWMBMSN_js.getCurrentScreen()).fingerprint;
4177
- const postPressSettle = await chunkAYWMBMSN_js.waitForScreenSettle({
3997
+ const baselineFingerprint = chunkYB77RYCC_js.probeLoadingState(pressedId, chunkYB77RYCC_js.getCurrentScreen()).fingerprint;
3998
+ const postPressSettle = await chunkYB77RYCC_js.waitForScreenSettle({
4178
3999
  expectingChange: true,
4179
4000
  fromScreen: input.preNavigateScreen ?? null,
4180
4001
  fromSignature: input.preNavigateSignature ?? null,
4181
4002
  maxMs: 2500
4182
4003
  });
4183
- await chunkAYWMBMSN_js.waitForLoadingSettle({
4004
+ await chunkYB77RYCC_js.waitForLoadingSettle({
4184
4005
  pressedComponentId: pressedId,
4185
- fromScreen: chunkAYWMBMSN_js.getCurrentScreen(),
4006
+ fromScreen: chunkYB77RYCC_js.getCurrentScreen(),
4186
4007
  maxMs: 4e3
4187
4008
  });
4188
- const afterFingerprint = chunkAYWMBMSN_js.probeLoadingState(pressedId, chunkAYWMBMSN_js.getCurrentScreen()).fingerprint;
4189
- console.log(
4190
- `[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}`
4191
4012
  );
4192
4013
  if (!postPressSettle.transitioned && baselineFingerprint === afterFingerprint) {
4193
4014
  for (const action of listPressActions) {
@@ -4202,15 +4023,15 @@ async function settleTurn(input) {
4202
4023
  }
4203
4024
  var reactNativeChatAdapter = {
4204
4025
  buildContext: buildAgentContext,
4205
- getCurrentScreen: chunkAYWMBMSN_js.getCurrentScreen,
4206
- getCurrentScreenSignature: chunkAYWMBMSN_js.getCurrentScreenSignature,
4026
+ getCurrentScreen: chunkYB77RYCC_js.getCurrentScreen,
4027
+ getCurrentScreenSignature: chunkYB77RYCC_js.getCurrentScreenSignature,
4207
4028
  settleTurn
4208
4029
  };
4209
4030
  function createReactNativeActionRunner(getOptions) {
4210
4031
  return {
4211
4032
  async execute(action, { confirmedDestructive }) {
4212
4033
  const { permissions, emit, navigationRef, suppressNativeConfirm } = getOptions();
4213
- const navRef = navigationRef?.current ? navigationRef : { current: chunkAYWMBMSN_js.getNavigationRef() };
4034
+ const navRef = navigationRef?.current ? navigationRef : { current: chunkYB77RYCC_js.getNavigationRef() };
4214
4035
  return runWithConfirmedDestructiveContext(
4215
4036
  confirmedDestructive && suppressNativeConfirm !== false,
4216
4037
  reactNative.Alert,
@@ -4221,21 +4042,21 @@ function createReactNativeActionRunner(getOptions) {
4221
4042
  })
4222
4043
  );
4223
4044
  },
4224
- getCurrentScreen: chunkAYWMBMSN_js.getCurrentScreen,
4225
- getCurrentScreenSignature: chunkAYWMBMSN_js.getCurrentScreenSignature,
4045
+ getCurrentScreen: chunkYB77RYCC_js.getCurrentScreen,
4046
+ getCurrentScreenSignature: chunkYB77RYCC_js.getCurrentScreenSignature,
4226
4047
  getScreenActionsMetadata(screen) {
4227
- return chunkAYWMBMSN_js.getScreenMetadata(screen)?.actions;
4048
+ return chunkYB77RYCC_js.getScreenMetadata(screen)?.actions;
4228
4049
  },
4229
- waitForScreenSettle: chunkAYWMBMSN_js.waitForScreenSettle
4050
+ waitForScreenSettle: chunkYB77RYCC_js.waitForScreenSettle
4230
4051
  };
4231
4052
  }
4232
4053
 
4233
4054
  // src/hooks/useAppilotsChat.ts
4234
4055
  function useAppilotsChat(options = {}) {
4235
- const { client, emit, subscribe } = chunkAYWMBMSN_js.useAppilotsContext();
4236
- const machine = react.useMemo(
4237
- () => new chunkAYWMBMSN_js.ChatSessionMachine(
4238
- { client, adapter: reactNativeChatAdapter, emit, warn: chunkAYWMBMSN_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 },
4239
4060
  options
4240
4061
  ),
4241
4062
  // A new machine per client/provider instance — options are pushed in
@@ -4243,20 +4064,20 @@ function useAppilotsChat(options = {}) {
4243
4064
  // eslint-disable-next-line react-hooks/exhaustive-deps
4244
4065
  [client, emit]
4245
4066
  );
4246
- const optionsRef = react.useRef(options);
4067
+ const optionsRef = React.useRef(options);
4247
4068
  optionsRef.current = options;
4248
4069
  machine.setOptions(options);
4249
- const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4250
- react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4251
- react.useEffect(() => () => machine.dispose(), [machine]);
4252
- 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(
4253
4074
  (reason) => machine.requestHuman(reason),
4254
4075
  [machine]
4255
4076
  );
4256
- const sendMessage = react.useCallback((content) => machine.sendMessage(content), [machine]);
4257
- const cancelMessage = react.useCallback(() => machine.cancelMessage(), [machine]);
4258
- const clearMessages = react.useCallback(() => machine.clearMessages(), [machine]);
4259
- 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]);
4260
4081
  return {
4261
4082
  messages: state.messages,
4262
4083
  isLoading: state.isLoading,
@@ -4278,9 +4099,9 @@ var DEFAULT_PERMISSIONS2 = {
4278
4099
  canSubmitForms: true
4279
4100
  };
4280
4101
  function useAppilotsActions(options = {}) {
4281
- const { client, subscribe, config, emit } = chunkAYWMBMSN_js.useAppilotsContext();
4102
+ const { client, subscribe, config, emit } = chunkYB77RYCC_js.useAppilotsContext();
4282
4103
  const { navigationRef, autoExecute = false } = options;
4283
- const runnerOptionsRef = react.useRef({
4104
+ const runnerOptionsRef = React.useRef({
4284
4105
  permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
4285
4106
  emit,
4286
4107
  navigationRef,
@@ -4292,13 +4113,13 @@ function useAppilotsActions(options = {}) {
4292
4113
  navigationRef,
4293
4114
  suppressNativeConfirm: config.suppressNativeConfirm
4294
4115
  };
4295
- const machine = react.useMemo(
4296
- () => new chunkAYWMBMSN_js.ActionQueueMachine(
4116
+ const machine = React.useMemo(
4117
+ () => new chunkYB77RYCC_js.ActionQueueMachine(
4297
4118
  {
4298
4119
  client,
4299
4120
  adapter: createReactNativeActionRunner(() => runnerOptionsRef.current),
4300
4121
  emit,
4301
- warn: chunkAYWMBMSN_js.appilotsDebugWarn
4122
+ warn: chunkYB77RYCC_js.appilotsDebugWarn
4302
4123
  },
4303
4124
  { autoExecute }
4304
4125
  ),
@@ -4306,16 +4127,16 @@ function useAppilotsActions(options = {}) {
4306
4127
  [client, emit]
4307
4128
  );
4308
4129
  machine.setOptions({ autoExecute });
4309
- const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4310
- react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4311
- react.useEffect(() => {
4130
+ const state = React.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4131
+ React.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4132
+ React.useEffect(() => {
4312
4133
  if (autoExecute) machine.scheduleDrain();
4313
4134
  }, [autoExecute, machine, state.actions]);
4314
- const approveAction = react.useCallback(
4135
+ const approveAction = React.useCallback(
4315
4136
  (actionId) => machine.approveAction(actionId),
4316
4137
  [machine]
4317
4138
  );
4318
- const rejectAction = react.useCallback((actionId) => machine.rejectAction(actionId), [machine]);
4139
+ const rejectAction = React.useCallback((actionId) => machine.rejectAction(actionId), [machine]);
4319
4140
  return {
4320
4141
  pendingActions: state.actions.filter((a) => a.status === "pending"),
4321
4142
  executingActions: state.actions.filter((a) => a.status === "executing"),
@@ -4355,18 +4176,18 @@ function shouldShowSuggestedPrompts(args) {
4355
4176
 
4356
4177
  // src/hooks/useSuggestedPrompts.ts
4357
4178
  function useSuggestedPrompts(options) {
4358
- const { client } = chunkAYWMBMSN_js.useAppilotsContext();
4179
+ const { client } = chunkYB77RYCC_js.useAppilotsContext();
4359
4180
  const { enabled, limit = 4 } = options;
4360
- const [prompts, setPrompts] = react.useState([]);
4361
- const [isLoading, setIsLoading] = react.useState(false);
4362
- const [refreshTick, setRefreshTick] = react.useState(0);
4363
- const requestIdRef = react.useRef(0);
4364
- 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(() => {
4365
4186
  if (!enabled) return;
4366
4187
  const requestId = ++requestIdRef.current;
4367
4188
  let cancelled = false;
4368
- const screen = chunkAYWMBMSN_js.getCurrentScreen() ?? void 0;
4369
- const localDev = screen ? (chunkAYWMBMSN_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) => ({
4370
4191
  text,
4371
4192
  source: "dev-defined"
4372
4193
  })) : [];
@@ -4380,7 +4201,7 @@ function useSuggestedPrompts(options) {
4380
4201
  if (cancelled || requestIdRef.current !== requestId) return;
4381
4202
  setPrompts(mergePromptSources(localDev, data, limit));
4382
4203
  }).catch((err) => {
4383
- console.warn("[Appilots] useSuggestedPrompts: fetch failed", err);
4204
+ chunkYB77RYCC_js.appilotsDebugWarn("useSuggestedPrompts: fetch failed", err);
4384
4205
  }).finally(() => {
4385
4206
  if (cancelled || requestIdRef.current !== requestId) return;
4386
4207
  setIsLoading(false);
@@ -4389,11 +4210,11 @@ function useSuggestedPrompts(options) {
4389
4210
  cancelled = true;
4390
4211
  };
4391
4212
  }, [client, enabled, limit, refreshTick]);
4392
- react.useEffect(() => {
4213
+ React.useEffect(() => {
4393
4214
  if (!enabled) return;
4394
- let lastScreen = chunkAYWMBMSN_js.getCurrentScreen();
4215
+ let lastScreen = chunkYB77RYCC_js.getCurrentScreen();
4395
4216
  const interval = setInterval(() => {
4396
- const current = chunkAYWMBMSN_js.getCurrentScreen();
4217
+ const current = chunkYB77RYCC_js.getCurrentScreen();
4397
4218
  if (current !== lastScreen) {
4398
4219
  lastScreen = current;
4399
4220
  setRefreshTick((t) => t + 1);
@@ -4408,14 +4229,14 @@ function useSuggestedPrompts(options) {
4408
4229
  };
4409
4230
  }
4410
4231
  function useAppilotsNavigation() {
4411
- const { emit } = chunkAYWMBMSN_js.useAppilotsContext();
4412
- const [currentScreen, setCurrentScreenState] = react.useState(null);
4413
- const [navigationHistory, setNavigationHistory] = react.useState([]);
4414
- const navigationRef = react.useRef(null);
4415
- 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(
4416
4237
  (screenName) => {
4417
4238
  setCurrentScreenState(screenName);
4418
- chunkAYWMBMSN_js.setCurrentScreen(screenName);
4239
+ chunkYB77RYCC_js.setCurrentScreen(screenName);
4419
4240
  setNavigationHistory((prev) => [...prev, screenName]);
4420
4241
  emit({
4421
4242
  type: "navigation:change",
@@ -4425,7 +4246,7 @@ function useAppilotsNavigation() {
4425
4246
  },
4426
4247
  [emit]
4427
4248
  );
4428
- react.useEffect(() => {
4249
+ React.useEffect(() => {
4429
4250
  const nav = navigationRef.current;
4430
4251
  if (!nav?.addListener) return;
4431
4252
  const unsubscribe = nav.addListener("state", () => {
@@ -4446,7 +4267,7 @@ function useAppilotsNavigation() {
4446
4267
 
4447
4268
  // src/hooks/useAppilots.ts
4448
4269
  function useAppilots() {
4449
- const { config, client } = chunkAYWMBMSN_js.useAppilotsContext();
4270
+ const { config, client } = chunkYB77RYCC_js.useAppilotsContext();
4450
4271
  const chat = useAppilotsChat();
4451
4272
  const navigation = useAppilotsNavigation();
4452
4273
  const actions = useAppilotsActions();
@@ -4475,17 +4296,17 @@ function useAppilots() {
4475
4296
  }
4476
4297
  function useAppilotsField(id, options) {
4477
4298
  const { value, onChangeText, ref, fieldType, label, screen } = options;
4478
- const registry = chunkAYWMBMSN_js.useResolvedRegistry();
4479
- const valueRef = react.useRef(value);
4480
- const onChangeRef = react.useRef(onChangeText);
4299
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4300
+ const valueRef = React.useRef(value);
4301
+ const onChangeRef = React.useRef(onChangeText);
4481
4302
  valueRef.current = value;
4482
4303
  onChangeRef.current = onChangeText;
4483
- const getValue = react.useCallback(() => valueRef.current, []);
4484
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4485
- 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(() => {
4486
4307
  ref?.current?.focus?.();
4487
4308
  }, [ref]);
4488
- react.useEffect(() => {
4309
+ React.useEffect(() => {
4489
4310
  const entry = {
4490
4311
  kind: "field",
4491
4312
  getValue,
@@ -4503,17 +4324,17 @@ function useAppilotsField(id, options) {
4503
4324
  }
4504
4325
  function useAppilotsTarget(id, options) {
4505
4326
  const { onPress, onLongPress, onScrollTo, label, screen } = options;
4506
- const registry = chunkAYWMBMSN_js.useResolvedRegistry();
4507
- const onPressRef = react.useRef(onPress);
4508
- const onLongPressRef = react.useRef(onLongPress);
4509
- 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);
4510
4331
  onPressRef.current = onPress;
4511
4332
  onLongPressRef.current = onLongPress;
4512
4333
  onScrollToRef.current = onScrollTo;
4513
- const press = react.useCallback(() => onPressRef.current(), []);
4514
- const longPress = react.useCallback(() => onLongPressRef.current?.(), []);
4515
- const scrollTo = react.useCallback(() => onScrollToRef.current?.(), []);
4516
- 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(() => {
4517
4338
  const entry = {
4518
4339
  kind: "target",
4519
4340
  press,
@@ -4530,14 +4351,14 @@ function useAppilotsTarget(id, options) {
4530
4351
  }
4531
4352
  function useAppilotsToggle(id, options) {
4532
4353
  const { value, onValueChange, label, screen } = options;
4533
- const registry = chunkAYWMBMSN_js.useResolvedRegistry();
4534
- const valueRef = react.useRef(value);
4535
- const onChangeRef = react.useRef(onValueChange);
4354
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4355
+ const valueRef = React.useRef(value);
4356
+ const onChangeRef = React.useRef(onValueChange);
4536
4357
  valueRef.current = value;
4537
4358
  onChangeRef.current = onValueChange;
4538
- const getValue = react.useCallback(() => valueRef.current, []);
4539
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4540
- react.useEffect(() => {
4359
+ const getValue = React.useCallback(() => valueRef.current, []);
4360
+ const setValue = React.useCallback((v) => onChangeRef.current(v), []);
4361
+ React.useEffect(() => {
4541
4362
  const entry = {
4542
4363
  kind: "toggle",
4543
4364
  getValue,
@@ -4553,14 +4374,14 @@ function useAppilotsToggle(id, options) {
4553
4374
  }
4554
4375
  function useAppilotsSlider(id, options) {
4555
4376
  const { value, onValueChange, min, max, step, label, screen } = options;
4556
- const registry = chunkAYWMBMSN_js.useResolvedRegistry();
4557
- const valueRef = react.useRef(value);
4558
- const onChangeRef = react.useRef(onValueChange);
4377
+ const registry = chunkYB77RYCC_js.useResolvedRegistry();
4378
+ const valueRef = React.useRef(value);
4379
+ const onChangeRef = React.useRef(onValueChange);
4559
4380
  valueRef.current = value;
4560
4381
  onChangeRef.current = onValueChange;
4561
- const getValue = react.useCallback(() => valueRef.current, []);
4562
- const setValue = react.useCallback((v) => onChangeRef.current(v), []);
4563
- react.useEffect(() => {
4382
+ const getValue = React.useCallback(() => valueRef.current, []);
4383
+ const setValue = React.useCallback((v) => onChangeRef.current(v), []);
4384
+ React.useEffect(() => {
4564
4385
  const entry = {
4565
4386
  kind: "slider",
4566
4387
  getValue,
@@ -4578,6 +4399,7 @@ function useAppilotsSlider(id, options) {
4578
4399
  }, [id, registry, getValue, setValue, min, max, step, label, screen]);
4579
4400
  }
4580
4401
 
4402
+ exports.appilotsSelfCheck = appilotsSelfCheck;
4581
4403
  exports.captureSnapshot = captureSnapshot;
4582
4404
  exports.executeAction = executeAction;
4583
4405
  exports.shouldShowSuggestedPrompts = shouldShowSuggestedPrompts;