@appilots/sdk 0.2.0 → 0.4.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,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkSIBKF7AA_js = require('./chunk-SIBKF7AA.js');
3
+ var chunkV3TUIIT2_js = require('./chunk-V3TUIIT2.js');
4
4
  var react = require('react');
5
5
  var reactNative = require('react-native');
6
6
 
@@ -495,7 +495,7 @@ function walkSubtree(root, detectLists, startInModal = false) {
495
495
  }
496
496
  function walkFiber(root) {
497
497
  const snapshot = {
498
- route: chunkSIBKF7AA_js.getCurrentScreen(),
498
+ route: chunkV3TUIIT2_js.getCurrentScreen(),
499
499
  texts: [],
500
500
  inputs: [],
501
501
  buttons: [],
@@ -656,225 +656,6 @@ function normalizeLabel(label) {
656
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
657
  }
658
658
 
659
- // src/introspection/interactionGraph.ts
660
- function normalizePart(value) {
661
- return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
662
- }
663
- function hashString(value) {
664
- let hash = 2166136261;
665
- for (let i = 0; i < value.length; i++) {
666
- hash ^= value.charCodeAt(i);
667
- hash = Math.imul(hash, 16777619);
668
- }
669
- return (hash >>> 0).toString(36);
670
- }
671
- function stableElementId(parts) {
672
- const raw = parts.filter((p) => p !== void 0 && String(p).length > 0).join("|");
673
- const readable = parts.map(normalizePart).filter(Boolean).join(":").slice(0, 120);
674
- return `el:${readable}:${hashString(raw)}`;
675
- }
676
- function parseStableElementId(id) {
677
- if (typeof id !== "string") return null;
678
- const trimmed = id.trim();
679
- if (!/^el:/i.test(trimmed)) return null;
680
- const parts = trimmed.split(":");
681
- if (parts.length < 3) return null;
682
- const hash = parts[parts.length - 1];
683
- const segments = parts.slice(1, -1);
684
- if (segments.length === 0) return null;
685
- const role = segments[0];
686
- const result = { role, segments, hash };
687
- if (role === "option" && segments.length >= 4) {
688
- result.listId = segments[segments.length - 2];
689
- result.itemKey = segments[segments.length - 1];
690
- }
691
- return result;
692
- }
693
- function uniqueTexts(texts) {
694
- const seen = /* @__PURE__ */ new Set();
695
- const out = [];
696
- for (const text of texts) {
697
- const t = typeof text === "string" ? text.trim() : "";
698
- if (!t || seen.has(t)) continue;
699
- seen.add(t);
700
- out.push(t);
701
- }
702
- return out;
703
- }
704
- function labelForListItem(item) {
705
- return uniqueTexts([
706
- ...item.texts ?? [],
707
- ...(item.buttons ?? []).map((button) => button.label ?? button.id)
708
- ]).slice(0, 2).join(" \xB7 ") || void 0;
709
- }
710
- function listItemElement(route, list, item) {
711
- const texts = uniqueTexts([
712
- ...item.texts ?? [],
713
- ...(item.buttons ?? []).map((button) => button.label ?? button.id)
714
- ]);
715
- const label = labelForListItem(item);
716
- const key = item.itemKey ?? item.reactKey ?? label ?? item.syntheticId;
717
- const id = stableElementId([
718
- "option",
719
- route ?? "unknown",
720
- list.id ?? list.label ?? `list-${list.index}`,
721
- key
722
- ]);
723
- const inModal = (item.buttons ?? []).some((button) => button.inModal) || (item.inputs ?? []).some((input) => input.inModal) || (item.toggles ?? []).some((toggle) => toggle.inModal);
724
- return {
725
- id,
726
- role: "option",
727
- label,
728
- texts,
729
- actions: ["press"],
730
- disabled: false,
731
- source: "list",
732
- targetId: item.syntheticId,
733
- ...inModal ? { inModal: true } : {},
734
- listContext: {
735
- listIndex: list.index,
736
- listId: list.id,
737
- listLabel: list.label,
738
- itemIndex: item.index,
739
- itemKey: item.itemKey,
740
- reactKey: item.reactKey,
741
- syntheticId: item.syntheticId
742
- }
743
- };
744
- }
745
- function buttonElement(route, button, index) {
746
- const label = button.label ?? button.id;
747
- const id = stableElementId([
748
- "button",
749
- route ?? "unknown",
750
- button.id ?? label ?? `button-${index}`
751
- ]);
752
- return {
753
- id,
754
- role: "button",
755
- label,
756
- texts: uniqueTexts([label]),
757
- actions: ["press"],
758
- disabled: button.disabled,
759
- selected: button.selected,
760
- source: "button",
761
- targetId: button.id ?? button.label,
762
- ...button.inModal ? { inModal: true } : {}
763
- };
764
- }
765
- function inputElement(route, input, index) {
766
- const label = input.label ?? input.placeholder ?? input.id;
767
- const id = stableElementId([
768
- "input",
769
- route ?? "unknown",
770
- input.id ?? label ?? `input-${index}`
771
- ]);
772
- return {
773
- id,
774
- role: "input",
775
- label,
776
- texts: uniqueTexts([label, input.placeholder]),
777
- actions: ["focus", "setValue"],
778
- disabled: input.editable === false,
779
- source: "input",
780
- targetId: input.id ?? input.label ?? input.placeholder,
781
- ...input.inModal ? { inModal: true } : {}
782
- };
783
- }
784
- function toggleElement(route, toggle, index) {
785
- const label = toggle.label ?? toggle.id;
786
- const id = stableElementId([
787
- "toggle",
788
- route ?? "unknown",
789
- toggle.id ?? label ?? `toggle-${index}`
790
- ]);
791
- return {
792
- id,
793
- role: "toggle",
794
- label,
795
- texts: uniqueTexts([label]),
796
- actions: ["toggle", "press"],
797
- selected: toggle.value,
798
- source: "toggle",
799
- targetId: toggle.id ?? toggle.label,
800
- ...toggle.inModal ? { inModal: true } : {}
801
- };
802
- }
803
- function sliderElement(route, slider, index) {
804
- const label = slider.label ?? slider.id;
805
- const id = stableElementId([
806
- "slider",
807
- route ?? "unknown",
808
- slider.id ?? label ?? `slider-${index}`
809
- ]);
810
- return {
811
- id,
812
- role: "slider",
813
- label,
814
- texts: uniqueTexts([label]),
815
- actions: ["setValue"],
816
- disabled: slider.disabled,
817
- source: "slider",
818
- targetId: slider.id ?? slider.label,
819
- ...slider.inModal ? { inModal: true } : {}
820
- };
821
- }
822
- function deriveInteractionElements(snapshot) {
823
- const elements = [];
824
- const seen = /* @__PURE__ */ new Set();
825
- const push = (element) => {
826
- if (!element.id || seen.has(element.id)) return;
827
- seen.add(element.id);
828
- elements.push(element);
829
- };
830
- for (const list of snapshot.lists ?? []) {
831
- for (const item of list.items ?? []) {
832
- push(listItemElement(snapshot.route, list, item));
833
- }
834
- }
835
- for (const [index, button] of (snapshot.buttons ?? []).entries()) {
836
- push(buttonElement(snapshot.route, button, index));
837
- }
838
- for (const [index, input] of (snapshot.inputs ?? []).entries()) {
839
- push(inputElement(snapshot.route, input, index));
840
- }
841
- for (const [index, toggle] of (snapshot.toggles ?? []).entries()) {
842
- push(toggleElement(snapshot.route, toggle, index));
843
- }
844
- for (const [index, slider] of (snapshot.sliders ?? []).entries()) {
845
- push(sliderElement(snapshot.route, slider, index));
846
- }
847
- return elements;
848
- }
849
- function findElementForChoice(elements, option) {
850
- if (option.targetId) {
851
- const byTarget = elements.find((element) => element.targetId === option.targetId);
852
- if (byTarget) return byTarget;
853
- }
854
- const optionLabel = normalizePart(option.label ?? option.texts?.join(" "));
855
- if (!optionLabel) return void 0;
856
- return elements.find((element) => {
857
- if (element.role !== "option" && element.role !== "button") return false;
858
- const label = normalizePart(element.label ?? element.texts.join(" "));
859
- return label === optionLabel || label.includes(optionLabel) || optionLabel.includes(label);
860
- });
861
- }
862
- function attachElementIdsToChoiceGroups(choiceGroups, elements) {
863
- return choiceGroups.map((group) => ({
864
- ...group,
865
- options: group.options.map((option) => {
866
- const element = findElementForChoice(elements, option);
867
- if (!element) return option;
868
- const handle = element.listContext?.syntheticId ?? element.id;
869
- return {
870
- ...option,
871
- syntheticId: handle,
872
- targetId: handle
873
- };
874
- })
875
- }));
876
- }
877
-
878
659
  // src/introspection/captureSnapshot.ts
879
660
  function normalizeSliderKey(value) {
880
661
  return (value ?? "").toLowerCase().replace(/^slider[-_]/, "");
@@ -890,9 +671,9 @@ function fiberSliderMatches(fiber, registryId, registryLabel) {
890
671
  function reconcileSliders(snapshot) {
891
672
  const fiberSliders = snapshot.sliders;
892
673
  const out = [];
893
- for (const { id, kind } of chunkSIBKF7AA_js.componentRegistry.snapshot()) {
674
+ for (const { id, kind } of chunkV3TUIIT2_js.componentRegistry.snapshot()) {
894
675
  if (kind !== "slider") continue;
895
- const entry = chunkSIBKF7AA_js.componentRegistry.getSlider(id);
676
+ const entry = chunkV3TUIIT2_js.componentRegistry.getSlider(id);
896
677
  if (!entry) continue;
897
678
  const fiber = fiberSliders.find((s) => fiberSliderMatches(s, id, entry.label));
898
679
  const visible = !!fiber || typeof entry.screen === "string" && entry.screen === snapshot.route;
@@ -916,7 +697,7 @@ function reconcileSliders(snapshot) {
916
697
  snapshot.sliders = out;
917
698
  }
918
699
  function mergeRegisteredLists(snapshot) {
919
- const registered = chunkSIBKF7AA_js.listRegistry.snapshot();
700
+ const registered = chunkV3TUIIT2_js.listRegistry.snapshot();
920
701
  if (registered.length === 0) return;
921
702
  const byId = /* @__PURE__ */ new Map();
922
703
  for (const list of snapshot.lists) {
@@ -964,13 +745,13 @@ function mergeRegisteredLists(snapshot) {
964
745
  }
965
746
  }
966
747
  function captureSnapshot() {
967
- const root = chunkSIBKF7AA_js.getFiberRoot();
748
+ const root = chunkV3TUIIT2_js.getFiberRoot();
968
749
  if (!root) {
969
750
  console.warn(
970
751
  "[Appilots] captureSnapshot: fiber root not captured yet. Ensure <AppilotsProvider> has rendered before calling this."
971
752
  );
972
753
  return {
973
- route: chunkSIBKF7AA_js.getCurrentScreen(),
754
+ route: chunkV3TUIIT2_js.getCurrentScreen(),
974
755
  texts: [],
975
756
  inputs: [],
976
757
  buttons: [],
@@ -985,17 +766,17 @@ function captureSnapshot() {
985
766
  }
986
767
  const start = Date.now();
987
768
  const snapshot = walkFiber(root);
988
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
769
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
989
770
  const deepestRoute = activePath[activePath.length - 1];
990
771
  if (deepestRoute) snapshot.route = deepestRoute;
991
772
  mergeRegisteredLists(snapshot);
992
773
  reconcileSliders(snapshot);
993
- snapshot.elements = deriveInteractionElements(snapshot);
994
- snapshot.choiceGroups = attachElementIdsToChoiceGroups(
774
+ snapshot.elements = chunkV3TUIIT2_js.deriveInteractionElements(snapshot);
775
+ snapshot.choiceGroups = chunkV3TUIIT2_js.attachElementIdsToChoiceGroups(
995
776
  snapshot.choiceGroups,
996
777
  snapshot.elements
997
778
  );
998
- chunkSIBKF7AA_js.elementRegistry.replaceAll(snapshot.elements);
779
+ chunkV3TUIIT2_js.elementRegistry.replaceAll(snapshot.elements);
999
780
  const elapsed = Date.now() - start;
1000
781
  const totalListItems = snapshot.lists.reduce(
1001
782
  (acc, l) => acc + l.items.length,
@@ -1188,7 +969,7 @@ function wrapTouchable(fiber, label) {
1188
969
  };
1189
970
  }
1190
971
  function findInteractiveByIdentifier(query, options = {}) {
1191
- const root = chunkSIBKF7AA_js.getFiberRoot();
972
+ const root = chunkV3TUIIT2_js.getFiberRoot();
1192
973
  if (!root) {
1193
974
  console.warn("[Appilots] findInteractiveByIdentifier: fiber root not captured yet");
1194
975
  return null;
@@ -1215,938 +996,23 @@ function findInteractiveByIdentifier(query, options = {}) {
1215
996
  const score = scoreMatch(fiber, queryNorm, queryRaw);
1216
997
  if (score > bestScore) {
1217
998
  bestScore = score;
1218
- const props = fiber.memoizedProps ?? {};
1219
- bestId2 = props.testID ?? props.accessibilityLabel ?? props.placeholder ?? (kind === "target" ? findChildText2(fiber) : void 0);
1220
- if (kind === "field") bestHandle = wrapTextInput(fiber);
1221
- else if (kind === "toggle") bestHandle = wrapSwitch(fiber);
1222
- else bestHandle = wrapTouchable(fiber, findChildText2(fiber));
1223
- }
1224
- }
1225
- if (fiber.child) stack.push(fiber.child);
1226
- }
1227
- if (bestHandle) {
1228
- console.log(
1229
- `[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 kind=${bestHandle.kind} label="${bestHandle.label ?? bestId2}" score=${bestScore}`
1230
- );
1231
- } else {
1232
- console.log(`[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 no match`);
1233
- }
1234
- return bestHandle;
1235
- }
1236
-
1237
- // src/hooks/fingerprint.ts
1238
- function fingerprintAction(action, screen) {
1239
- const p = action.payload ?? {};
1240
- const scope = `@${screen ?? "?"}`;
1241
- switch (action.type) {
1242
- case "navigate":
1243
- return `navigate${scope}:${p.screenName ?? "?"}`;
1244
- case "form_fill": {
1245
- const fields = p.fields ?? [];
1246
- const ids = fields.map((f) => String(f?.fieldId ?? "?")).sort();
1247
- return `form_fill${scope}:${ids.join(",")}`;
1248
- }
1249
- case "ui_interaction":
1250
- return `ui_interaction${scope}:${p.action ?? "?"}:${p.componentId ?? p.targetId ?? "?"}`;
1251
- case "confirm":
1252
- return `confirm${scope}:${p.message ?? p.title ?? "?"}`;
1253
- default:
1254
- return `${action.type}${scope}:${JSON.stringify(p)}`;
1255
- }
1256
- }
1257
-
1258
- // src/hooks/visibleMessages.ts
1259
- var INTERNAL_MARKER_RE = /^\[(?:Permission policy notice|Recovery exhausted|User rejected the proposed action)[^\]]*\]:\s*/i;
1260
- var TECHNICAL_TRACE_RE = /(^|\n)\s*(?:Results:|[-*]\s*[✓✗]\s+|(?:press|click|tap|navigate|form_fill|ui_interaction|scroll_list)\b|(?:Cliquei|Clicked)\s+em\s+(?:el:|list-\d+-item-\d+|[A-Za-z]+:))/i;
1261
- var TECHNICAL_SELECTOR_RE = /\b(?:el:[^\s]+|list-\d+-item-\d+|[A-Za-z][\w-]*:(?!\/\/)[^\s]+|(?:testID|test-id|accessibilityId|accessibility-id)[:=_-][^\s]+)/i;
1262
- function sanitizeVisibleAssistantContent(content) {
1263
- return content.split("\n").map((line) => line.replace(INTERNAL_MARKER_RE, "").trimEnd()).filter((line) => !INTERNAL_MARKER_RE.test(line)).join("\n").trim();
1264
- }
1265
- function humanizeAssistantFallback(content) {
1266
- let text = sanitizeVisibleAssistantContent(content).replace(/\blist-\d+-item-\d+\b/gi, "o item da lista").replace(/\bel:[^\s".]+/gi, "o elemento").replace(
1267
- /"\s*(?:press|click|tap|navigate|form_fill|ui_interaction|scroll_list)\s+on\s+[^"]+"/gi,
1268
- '"a a\xE7\xE3o solicitada"'
1269
- ).replace(/\bsubscription-cancel-[^\s"]+/gi, "cancelamento de assinatura").trim();
1270
- if (text.length < 16) return null;
1271
- const probe = {
1272
- role: "assistant",
1273
- content: text};
1274
- if (isInternalTraceMessage(probe)) return null;
1275
- return text;
1276
- }
1277
- function isInternalTraceMessage(message) {
1278
- if (message.role !== "assistant") return false;
1279
- const content = message.content.trim();
1280
- if (!content) return true;
1281
- return TECHNICAL_TRACE_RE.test(content) || TECHNICAL_SELECTOR_RE.test(content);
1282
- }
1283
-
1284
- // src/hooks/continuationErrors.ts
1285
- function normalize2(value) {
1286
- return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[‘’]/g, "'").toLowerCase();
1287
- }
1288
- function detectLocaleFromUserTexts(texts) {
1289
- for (const raw of texts) {
1290
- const normalized = normalize2(raw);
1291
- if (/[ãõáéíóúâêôç]/i.test(raw) || /\b(voce|voces|pra|assinatura|cancela|canela|segunda|certo|quais|tenho|pode|posso)\b/.test(
1292
- normalized
1293
- )) {
1294
- return "pt";
1295
- }
1296
- if (/[áéíóúñ¿¡]/i.test(raw) || /\b(cancela|segunda|suscripcion|puedo|cuales|hola)\b/.test(normalized)) {
1297
- return "es";
1298
- }
1299
- if (/[àâçéèêëîïôûùüÿœ]/i.test(raw) || /\b(annuler|deuxieme|abonnement|bonjour)\b/.test(normalized)) {
1300
- return "fr";
1301
- }
1302
- }
1303
- return "en";
1304
- }
1305
- var copy = {
1306
- pt: {
1307
- rateLimit: "O provedor de IA atingiu o limite de uso durante a automa\xE7\xE3o. Aguarde um momento e pe\xE7a para continuar, ou aumente o limite de tokens por minuto.",
1308
- invalidInput: "N\xE3o consegui continuar a automa\xE7\xE3o por um problema interno de sincroniza\xE7\xE3o. Pode tentar de novo ou fazer essa parte manualmente?",
1309
- generic: (detail) => `Perdi o fio da automa\xE7\xE3o (${detail}). Pode continuar manualmente ou me pedir de novo?`
1310
- },
1311
- es: {
1312
- rateLimit: "El proveedor de IA alcanz\xF3 su l\xEDmite de uso durante la automatizaci\xF3n. Espera un momento y p\xEDdeme continuar, o aumenta el l\xEDmite de tokens por minuto.",
1313
- invalidInput: "No pude continuar la automatizaci\xF3n por un problema interno de sincronizaci\xF3n. \xBFPuedes intentarlo de nuevo o hacer esta parte manualmente?",
1314
- generic: (detail) => `Perd\xED el hilo de la automatizaci\xF3n (${detail}). \xBFPuedes continuar manualmente o ped\xEDrmelo de nuevo?`
1315
- },
1316
- fr: {
1317
- rateLimit: "Le fournisseur d'IA a atteint sa limite d'utilisation pendant l'automatisation. Attendez un instant et demandez-moi de continuer, ou augmentez la limite de tokens par minute.",
1318
- invalidInput: "Je n'ai pas pu poursuivre l'automatisation \xE0 cause d'un probl\xE8me interne de synchronisation. Pouvez-vous r\xE9essayer ou faire cette \xE9tape manuellement ?",
1319
- generic: (detail) => `J'ai perdu le fil de l'automatisation (${detail}). Vous pouvez continuer manuellement ou me redemander ?`
1320
- },
1321
- en: {
1322
- rateLimit: "Your AI provider hit its rate limit during automation. Wait a moment and ask me to continue, or raise your TPM limit.",
1323
- invalidInput: "I could not continue the automation because of an internal sync issue. You can try again or take over manually.",
1324
- generic: (detail) => `I lost my footing during automation (${detail}). You can take over from here.`
1325
- }
1326
- };
1327
- function buildContinuationFailureMessage(rawError, recentUserTexts) {
1328
- const locale = detectLocaleFromUserTexts(recentUserTexts);
1329
- const strings = copy[locale] ?? copy.en;
1330
- if (/rate limit|tokens per min|tpm/i.test(rawError)) {
1331
- return strings.rateLimit;
1332
- }
1333
- if (/invalid input|validation_error|422/i.test(rawError)) {
1334
- return strings.invalidInput;
1335
- }
1336
- return strings.generic(rawError);
1337
- }
1338
-
1339
- // src/executor/formWriteEffect.ts
1340
- var CREATE_FORM_ROUTE_RE = /vehiclecreate|subscriptioncreate|vehicleedit|subscriptionedit|maintenancecreate|create|cadastr|register|novo|edit/i;
1341
- var SUBMIT_BUTTON_RE = /cadastrar|registrar|salvar|submit|register|guardar|enviar|confirmar|save/i;
1342
- 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;
1343
- function normalize3(value) {
1344
- return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
1345
- }
1346
- function routeHintsCreateForm(routeNames) {
1347
- return routeNames.some((name) => CREATE_FORM_ROUTE_RE.test(normalize3(name)));
1348
- }
1349
- function snapshotHasSubmitControl(snap) {
1350
- return (snap.buttons ?? []).some(
1351
- (btn) => SUBMIT_BUTTON_RE.test(normalize3(`${btn.label ?? btn.id ?? ""}`))
1352
- );
1353
- }
1354
- function snapshotHasVisibleSubmitButton(snap) {
1355
- return (snap.buttons ?? []).some(
1356
- (btn) => !btn.disabled && SUBMIT_BUTTON_RE.test(normalize3(`${btn.label ?? btn.id ?? ""}`))
1357
- );
1358
- }
1359
- function snapshotHasVisibleValidation(snap) {
1360
- return (snap.texts ?? []).some((text) => typeof text === "string" && FORM_VALIDATION_TEXT_RE.test(text));
1361
- }
1362
- function snapshotShowsOpenCreateForm(snap, activePath = []) {
1363
- if (!snap) return false;
1364
- const routeNames = [
1365
- ...typeof snap.route === "string" && snap.route ? [snap.route] : [],
1366
- ...activePath
1367
- ];
1368
- const hasFormInputs = (snap.inputs?.length ?? 0) > 0;
1369
- const hasValidation = snapshotHasVisibleValidation(snap);
1370
- const hasFormContext = routeHintsCreateForm(routeNames) || hasFormInputs || hasValidation;
1371
- if (!hasFormContext) return false;
1372
- if (snap.loading === true) return true;
1373
- if (snapshotHasVisibleSubmitButton(snap)) return true;
1374
- if (snapshotHasSubmitControl(snap) && hasFormInputs) return true;
1375
- if (hasValidation) return true;
1376
- return false;
1377
- }
1378
- function formFillLackedWriteEffect(action, snap, activePath = []) {
1379
- if (action.type !== "form_fill") return false;
1380
- if (!snapshotShowsOpenCreateForm(snap, activePath)) return false;
1381
- const payload = action.payload;
1382
- if (payload?.submitAfterFill === true) return true;
1383
- return Array.isArray(payload?.fields) && payload.fields.length > 0;
1384
- }
1385
-
1386
- // src/introspection/actionTargets.ts
1387
- var LIST_ITEM_TARGET_RE = /^list-\d+-item-\d+$/i;
1388
- var DESTRUCTIVE_LABEL_RE = /\b(cancelar?\w*|cancel(?:ar|led|ation|amento)?|delete\w*|exclu\w*|delet\w*|remov\w*|remove|apag\w*|destroy\w*|unsubscribe\w*)\b/i;
1389
- function isListItemPressTarget(value) {
1390
- if (typeof value !== "string" || !value.trim()) return false;
1391
- return LIST_ITEM_TARGET_RE.test(value.trim());
1392
- }
1393
- function looksDestructiveActionLabel(value) {
1394
- if (typeof value !== "string" || !value.trim()) return false;
1395
- return DESTRUCTIVE_LABEL_RE.test(value.trim());
1396
- }
1397
-
1398
- // src/hooks/turnContinuation.ts
1399
- function actionPressTargetId(action) {
1400
- if (action.type !== "ui_interaction") return null;
1401
- const payload = action.payload;
1402
- const componentId = payload?.componentId;
1403
- if (typeof componentId === "string" && componentId.trim()) return componentId.trim();
1404
- const targetId = payload?.targetId;
1405
- if (typeof targetId === "string" && targetId.trim()) return targetId.trim();
1406
- return null;
1407
- }
1408
- function turnHasConfirmActions(actions) {
1409
- return actions.some((action) => action.type === "confirm");
1410
- }
1411
-
1412
- // src/hooks/useAppilotsChat.ts
1413
- var ESCALATION_RECONNECT_MAX_MS = 3e4;
1414
- function resolveScreenMetadata() {
1415
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
1416
- for (let i = activePath.length - 1; i >= 0; i--) {
1417
- const name = activePath[i];
1418
- const meta = name ? chunkSIBKF7AA_js.getScreenMetadata(name) : void 0;
1419
- if (meta && (Array.isArray(meta.fields) && meta.fields.length > 0 || Array.isArray(meta.actions) && meta.actions.length > 0)) {
1420
- return meta;
1421
- }
1422
- }
1423
- const screen = chunkSIBKF7AA_js.getCurrentScreen();
1424
- return screen ? chunkSIBKF7AA_js.getScreenMetadata(screen) : void 0;
1425
- }
1426
- function buildAgentContext(extras = {}) {
1427
- const context = {};
1428
- const screen = chunkSIBKF7AA_js.getCurrentScreen();
1429
- if (screen) context.currentScreen = screen;
1430
- const navigationState = chunkSIBKF7AA_js.getNavigationStateSnapshot();
1431
- if (navigationState) context.navigationState = navigationState;
1432
- const screenMeta = resolveScreenMetadata();
1433
- if (screenMeta) context.screenMetadata = screenMeta;
1434
- try {
1435
- context.snapshot = captureSnapshot();
1436
- } catch (err) {
1437
- chunkSIBKF7AA_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
1438
- }
1439
- const registry = chunkSIBKF7AA_js.componentRegistry.snapshot();
1440
- const filtered = screen ? registry.filter((c) => !c.screen || c.screen === screen) : registry;
1441
- if (filtered.length > 0) context.registeredComponents = filtered;
1442
- const registeredLists = chunkSIBKF7AA_js.listRegistry.snapshot();
1443
- if (registeredLists.length > 0) {
1444
- context.registeredLists = registeredLists.map(
1445
- ({ scrollToIndex, scrollToOffset, getScrollMetrics, dataPreview, ...rest }) => rest
1446
- );
1447
- }
1448
- if (extras.loadingPending === true) context.loadingPending = true;
1449
- return context;
1450
- }
1451
- function extractPressedComponentId(actions) {
1452
- for (let i = actions.length - 1; i >= 0; i--) {
1453
- const a = actions[i];
1454
- if (!a || a.type !== "ui_interaction") continue;
1455
- const p = a.payload;
1456
- const interaction = p?.action ?? "press";
1457
- if (interaction !== "press" && interaction !== "longPress") continue;
1458
- const id = p?.componentId;
1459
- if (typeof id === "string" && id.length > 0) return id;
1460
- }
1461
- return null;
1462
- }
1463
- function extractNavigateTargetScreen(actions) {
1464
- for (let i = actions.length - 1; i >= 0; i--) {
1465
- const a = actions[i];
1466
- if (!a || a.type !== "navigate") continue;
1467
- const screenName = a.payload?.screenName;
1468
- if (typeof screenName === "string" && screenName.length > 0) return screenName;
1469
- }
1470
- return null;
1471
- }
1472
- function idLooselyMatches(candidate, target) {
1473
- if (!candidate || !target) return false;
1474
- if (candidate === target) return true;
1475
- const c = candidate.toLowerCase();
1476
- const t = target.toLowerCase();
1477
- if (c === t) return true;
1478
- return c.endsWith(`-${t}`) || c.endsWith(`_${t}`) || t.endsWith(`-${c}`) || t.endsWith(`_${c}`);
1479
- }
1480
- function resolveActionHints(screen, pressedComponentId, actionPayload) {
1481
- if (actionPayload && typeof actionPayload === "object") {
1482
- const inline = actionPayload._appilotsInferred;
1483
- if (inline && typeof inline === "object") {
1484
- return inline;
1485
- }
1486
- }
1487
- if (!screen || !pressedComponentId) return void 0;
1488
- const meta = chunkSIBKF7AA_js.getScreenMetadata(screen);
1489
- const actions = meta?.actions;
1490
- if (!actions || actions.length === 0) return void 0;
1491
- for (const a of actions) {
1492
- if (typeof a === "string") continue;
1493
- if (idLooselyMatches(a.id, pressedComponentId)) {
1494
- const inferred = a.appilotsInferred;
1495
- if (inferred && typeof inferred === "object") return inferred;
1496
- return void 0;
1497
- }
1498
- }
1499
- return void 0;
1500
- }
1501
- function summarizeAction(action) {
1502
- const p = action.payload;
1503
- switch (action.type) {
1504
- case "navigate":
1505
- return `navigate to ${p?.screenName ?? "?"}`;
1506
- case "form_fill": {
1507
- const fields = p?.fields ?? [];
1508
- if (fields.length === 0) return "form_fill (no fields)";
1509
- const parts = fields.slice(0, 3).map((f) => `${f.fieldId}=${JSON.stringify(f.value)}`);
1510
- const extra = fields.length > 3 ? ` +${fields.length - 3} more` : "";
1511
- return `form_fill ${parts.join(", ")}${extra}`;
1512
- }
1513
- case "ui_interaction":
1514
- return `${p?.action ?? "press"} on ${p?.componentId ?? "?"}`;
1515
- case "scroll_list": {
1516
- const target = typeof p?.toIndex === "number" ? `to item #${p.toIndex}` : p?.direction ?? "down";
1517
- return `scroll_list ${p?.listId ? `"${p.listId}" ` : ""}${target}`;
1518
- }
1519
- case "confirm":
1520
- return `confirm: ${p?.message ?? p?.title ?? ""}`;
1521
- default:
1522
- return action.type;
1523
- }
1524
- }
1525
- var MAX_RECOVERY_ATTEMPTS_PER_ACTION = 2;
1526
- var POST_ACTION_LOADING_MAX_MS = 6e3;
1527
- function useAppilotsChat(options = {}) {
1528
- const { client, emit, subscribe } = chunkSIBKF7AA_js.useAppilotsContext();
1529
- const errorPrefix = options.errorPrefix ?? "Algo deu errado";
1530
- const streamingEnabled = options.streaming !== false;
1531
- const abortRef = react.useRef(null);
1532
- const [messages, setMessages] = react.useState([]);
1533
- const [pendingActions, setPendingActions] = react.useState([]);
1534
- const [isLoading, setIsLoading] = react.useState(false);
1535
- const [loadingStatusKey, setLoadingStatusKey] = react.useState("thinking");
1536
- const [error, setError] = react.useState(null);
1537
- const messageIdCounter = react.useRef(0);
1538
- const [escalation, setEscalation] = react.useState(null);
1539
- const escalationRef = react.useRef(null);
1540
- escalationRef.current = escalation;
1541
- const [escalationStreamEpoch, setEscalationStreamEpoch] = react.useState(0);
1542
- const escalationReconnectAttemptRef = react.useRef(0);
1543
- const escalationReconnectTimerRef = react.useRef(null);
1544
- const escalationSinceRef = react.useRef(void 0);
1545
- const seenHumanMessageIdsRef = react.useRef(/* @__PURE__ */ new Set());
1546
- const escalationStrings = options.escalationStrings;
1547
- const currentTurnRef = react.useRef(null);
1548
- const continuationInFlightRef = react.useRef(false);
1549
- const recoveryCountByFingerprintRef = react.useRef(/* @__PURE__ */ new Map());
1550
- const pendingActionsRef = react.useRef([]);
1551
- pendingActionsRef.current = pendingActions;
1552
- const messagesRef = react.useRef([]);
1553
- messagesRef.current = messages;
1554
- const addAssistantMessage = react.useCallback((message) => {
1555
- const visibleContent = message.role === "assistant" ? sanitizeVisibleAssistantContent(message.content) : message.content;
1556
- const candidate = { ...message, content: visibleContent };
1557
- if (isInternalTraceMessage(candidate)) {
1558
- chunkSIBKF7AA_js.recordAppilotsDebugTrace({
1559
- type: "agent:trace",
1560
- timestamp: Date.now(),
1561
- messageId: candidate.id,
1562
- summary: "Suppressed internal assistant trace from visible chat",
1563
- data: { role: candidate.role, content: message.content }
1564
- });
1565
- const fallback = humanizeAssistantFallback(message.content);
1566
- if (fallback) {
1567
- setMessages((prev) => [...prev, { ...candidate, content: fallback }]);
1568
- }
1569
- return;
1570
- }
1571
- setMessages((prev) => [...prev, candidate]);
1572
- }, []);
1573
- const appendLocalSystemMessage = react.useCallback(
1574
- (content, metadata) => {
1575
- if (!content) return;
1576
- setMessages((prev) => [
1577
- ...prev,
1578
- {
1579
- id: `system_${++messageIdCounter.current}`,
1580
- role: "system",
1581
- content,
1582
- timestamp: Date.now(),
1583
- ...metadata ? { metadata } : {}
1584
- }
1585
- ]);
1586
- },
1587
- []
1588
- );
1589
- const requestHuman = react.useCallback(
1590
- async (reason = "user_requested") => {
1591
- if (escalationRef.current) return;
1592
- try {
1593
- const lastError = messagesRef.current.slice().reverse().find((m) => m.role === "assistant" && m.id.startsWith("error_"));
1594
- const result = await client.requestEscalation(reason, lastError?.content);
1595
- setEscalation({ id: result.escalationId, status: result.status });
1596
- escalationReconnectAttemptRef.current = 0;
1597
- appendLocalSystemMessage(escalationStrings?.requested ?? "");
1598
- emit({
1599
- type: "chat:escalation:start",
1600
- timestamp: Date.now(),
1601
- data: { escalationId: result.escalationId, reason }
1602
- });
1603
- } catch (err) {
1604
- setError(err instanceof Error ? err.message : "Failed to request a human");
1605
- }
1606
- },
1607
- [client, emit, appendLocalSystemMessage, escalationStrings]
1608
- );
1609
- react.useEffect(() => {
1610
- if (!escalation?.id) return;
1611
- const escalationId = escalation.id;
1612
- const close = client.openEscalationStream(escalationId, {
1613
- since: escalationSinceRef.current,
1614
- onHumanMessage: (message) => {
1615
- escalationReconnectAttemptRef.current = 0;
1616
- if (seenHumanMessageIdsRef.current.has(message.id)) return;
1617
- seenHumanMessageIdsRef.current.add(message.id);
1618
- escalationSinceRef.current = message.createdAt;
1619
- setMessages((prev) => [
1620
- ...prev,
1621
- {
1622
- id: message.id,
1623
- role: "human_agent",
1624
- content: message.content,
1625
- timestamp: Date.now()
1626
- }
1627
- ]);
1628
- emit({
1629
- type: "chat:escalation:message",
1630
- timestamp: Date.now(),
1631
- data: { escalationId, messageId: message.id }
1632
- });
1633
- },
1634
- onStatus: (status, operatorName) => {
1635
- escalationReconnectAttemptRef.current = 0;
1636
- if (status === "active") {
1637
- setEscalation((prev) => {
1638
- if (!prev || prev.id !== escalationId) return prev;
1639
- if (prev.status === "active") return prev;
1640
- appendLocalSystemMessage(escalationStrings?.connected ?? "");
1641
- return { ...prev, status: "active", operatorName };
1642
- });
1643
- } else if (status === "resolved") {
1644
- appendLocalSystemMessage(escalationStrings?.resolved ?? "");
1645
- setEscalation(null);
1646
- emit({
1647
- type: "chat:escalation:end",
1648
- timestamp: Date.now(),
1649
- data: { escalationId }
1650
- });
1651
- }
1652
- },
1653
- onClose: () => {
1654
- if (!escalationRef.current || escalationRef.current.id !== escalationId) return;
1655
- const attempt = ++escalationReconnectAttemptRef.current;
1656
- const delay = Math.min(
1657
- ESCALATION_RECONNECT_MAX_MS,
1658
- 1e3 * 2 ** Math.min(attempt, 5)
1659
- );
1660
- escalationReconnectTimerRef.current = setTimeout(() => {
1661
- setEscalationStreamEpoch((n) => n + 1);
1662
- }, delay);
1663
- }
1664
- });
1665
- return () => {
1666
- if (escalationReconnectTimerRef.current) {
1667
- clearTimeout(escalationReconnectTimerRef.current);
1668
- escalationReconnectTimerRef.current = null;
1669
- }
1670
- close();
1671
- };
1672
- }, [client, emit, appendLocalSystemMessage, escalationStrings, escalation?.id, escalationStreamEpoch]);
1673
- const sendEscalationMessage = react.useCallback(
1674
- async (content) => {
1675
- const current = escalationRef.current;
1676
- if (!current) return;
1677
- const userMessage = {
1678
- id: `local_${++messageIdCounter.current}`,
1679
- role: "user",
1680
- content,
1681
- timestamp: Date.now()
1682
- };
1683
- setMessages((prev) => [...prev, userMessage]);
1684
- try {
1685
- await client.sendEscalationMessage(current.id, content);
1686
- } catch (err) {
1687
- setError(err instanceof Error ? err.message : "Failed to send message");
1688
- }
1689
- },
1690
- [client]
1691
- );
1692
- const beginTurn = react.useCallback(
1693
- (assistantMessageId, actions, hop) => {
1694
- if (!actions || actions.length === 0) {
1695
- currentTurnRef.current = null;
1696
- return;
1697
- }
1698
- const stamped = actions.map((a) => ({ ...a, messageId: assistantMessageId }));
1699
- setPendingActions((prev) => [...prev, ...stamped]);
1700
- const turn = {
1701
- messageId: assistantMessageId,
1702
- actionIds: new Set(stamped.map((a) => a.id)),
1703
- results: /* @__PURE__ */ new Map(),
1704
- reportedIds: /* @__PURE__ */ new Set(),
1705
- hop,
1706
- hadNavigate: stamped.some((a) => a.type === "navigate"),
1707
- // Snapshot the current screen NOW, before any navigate
1708
- // dispatches. waitForScreenSettle will use this as the
1709
- // baseline to detect that the navigate completed.
1710
- preNavigateScreen: chunkSIBKF7AA_js.getCurrentScreen(),
1711
- // Full route+params signature — lets settle detect navigate
1712
- // to the same route name with different params.
1713
- preNavigateSignature: chunkSIBKF7AA_js.getCurrentScreenSignature()
1714
- };
1715
- const originScreen = chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
1716
- for (const a of stamped) {
1717
- turn.results.set(a.id, {
1718
- type: a.type,
1719
- success: false,
1720
- summary: summarizeAction(a),
1721
- fingerprint: fingerprintAction(a, originScreen)
1722
- });
1723
- }
1724
- currentTurnRef.current = turn;
1725
- for (const action of stamped) {
1726
- emit({
1727
- type: "agent:action:start",
1728
- timestamp: Date.now(),
1729
- data: { action }
1730
- });
1731
- }
1732
- if (turnHasConfirmActions(stamped)) {
1733
- setIsLoading(false);
1734
- setLoadingStatusKey("thinking");
1735
- }
1736
- },
1737
- [emit]
1738
- );
1739
- const registerSynthesizedTurnAction = react.useCallback((action) => {
1740
- const turn = currentTurnRef.current;
1741
- if (!turn || turn.actionIds.has(action.id)) return;
1742
- const stamped = { ...action, messageId: turn.messageId };
1743
- turn.actionIds.add(stamped.id);
1744
- turn.results.set(stamped.id, {
1745
- type: stamped.type,
1746
- success: false,
1747
- summary: summarizeAction(stamped),
1748
- fingerprint: fingerprintAction(stamped, chunkSIBKF7AA_js.getCurrentScreen() ?? void 0)
1749
- });
1750
- setPendingActions((prev) => {
1751
- if (prev.some((candidate) => candidate.id === stamped.id)) return prev;
1752
- return [...prev, stamped];
1753
- });
1754
- if (stamped.type === "confirm") {
1755
- setIsLoading(false);
1756
- setLoadingStatusKey("thinking");
1757
- }
1758
- }, []);
1759
- const runContinuation = react.useCallback(
1760
- async (turn) => {
1761
- if (continuationInFlightRef.current) return;
1762
- continuationInFlightRef.current = true;
1763
- try {
1764
- setIsLoading(true);
1765
- setLoadingStatusKey("statusWaitingApp");
1766
- const toolWithoutEffectIds = /* @__PURE__ */ new Set();
1767
- let loadingPending = false;
1768
- const turnActions = pendingActionsRef.current.filter(
1769
- (a) => turn.actionIds.has(a.id)
1770
- );
1771
- const pressedId = extractPressedComponentId(turnActions);
1772
- const navigateTargetScreen = extractNavigateTargetScreen(turnActions);
1773
- if (turn.hadNavigate) {
1774
- const settle = await chunkSIBKF7AA_js.waitForScreenSettle({
1775
- expectingChange: true,
1776
- fromScreen: turn.preNavigateScreen ?? null,
1777
- fromSignature: turn.preNavigateSignature ?? null,
1778
- targetScreen: navigateTargetScreen,
1779
- maxMs: 3500
1780
- });
1781
- console.log(
1782
- `[Appilots] runContinuation: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
1783
- );
1784
- const navigationMoved = settle.transitioned || chunkSIBKF7AA_js.screenDepartedBaseline(turn.preNavigateScreen ?? null, turn.preNavigateSignature ?? null) || !!navigateTargetScreen && !!settle.screen && chunkSIBKF7AA_js.routesBelongToSameFeature(settle.screen, navigateTargetScreen);
1785
- if (!navigationMoved) {
1786
- chunkSIBKF7AA_js.appilotsDebugWarn(
1787
- `tool-without-effect: navigate emitted but screen did not change (stayed at "${turn.preNavigateScreen ?? "unknown"}", waitedMs=${settle.waitedMs}). Likely causes: target screenName missing from MCP doc, nested-nav path absent, or React Navigation rejected the route.`
1788
- );
1789
- for (const actionId of turn.actionIds) {
1790
- const r = turn.results.get(actionId);
1791
- if (r && r.type === "navigate") {
1792
- toolWithoutEffectIds.add(actionId);
1793
- }
1794
- }
1795
- }
1796
- const loadSettle = await chunkSIBKF7AA_js.waitForLoadingSettle({
1797
- fromScreen: settle.screen ?? null,
1798
- maxMs: 3e3
1799
- });
1800
- console.log(
1801
- `[Appilots] runContinuation: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs}`
1802
- );
1803
- if (loadSettle.loadingPending) loadingPending = true;
1804
- } else {
1805
- const pressedAction = turnActions.find(
1806
- (a) => a.type === "ui_interaction" && a.payload?.componentId === pressedId
1807
- );
1808
- const hints = resolveActionHints(
1809
- chunkSIBKF7AA_js.getCurrentScreen(),
1810
- pressedId,
1811
- pressedAction?.payload
1812
- );
1813
- const settleCapMs = hints?.isAsyncTrigger === true ? 1e4 : POST_ACTION_LOADING_MAX_MS;
1814
- const loadSettle = await chunkSIBKF7AA_js.waitForLoadingSettle({
1815
- pressedComponentId: pressedId,
1816
- fromScreen: chunkSIBKF7AA_js.getCurrentScreen(),
1817
- maxMs: settleCapMs
1818
- });
1819
- console.log(
1820
- `[Appilots] runContinuation: 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)" : ""}`
1821
- );
1822
- if (loadSettle.loadingPending) loadingPending = true;
1823
- const listPressActions = turnActions.filter((action) => {
1824
- const target = actionPressTargetId(action);
1825
- return target ? isListItemPressTarget(target) : false;
1826
- });
1827
- if (listPressActions.length > 0) {
1828
- const baselineFingerprint = chunkSIBKF7AA_js.probeLoadingState(
1829
- pressedId,
1830
- chunkSIBKF7AA_js.getCurrentScreen()
1831
- ).fingerprint;
1832
- const postPressSettle = await chunkSIBKF7AA_js.waitForScreenSettle({
1833
- expectingChange: true,
1834
- fromScreen: turn.preNavigateScreen ?? null,
1835
- fromSignature: turn.preNavigateSignature ?? null,
1836
- maxMs: 2500
1837
- });
1838
- await chunkSIBKF7AA_js.waitForLoadingSettle({
1839
- pressedComponentId: pressedId,
1840
- fromScreen: chunkSIBKF7AA_js.getCurrentScreen(),
1841
- maxMs: 4e3
1842
- });
1843
- const afterFingerprint = chunkSIBKF7AA_js.probeLoadingState(
1844
- pressedId,
1845
- chunkSIBKF7AA_js.getCurrentScreen()
1846
- ).fingerprint;
1847
- console.log(
1848
- `[Appilots] runContinuation: post-list-press settle \u2014 screen="${postPressSettle.screen}" transitioned=${postPressSettle.transitioned} timedOut=${postPressSettle.timedOut} waitedMs=${postPressSettle.waitedMs}`
1849
- );
1850
- if (!postPressSettle.transitioned && baselineFingerprint === afterFingerprint) {
1851
- for (const action of listPressActions) {
1852
- const result = turn.results.get(action.id);
1853
- if (result?.success) {
1854
- toolWithoutEffectIds.add(action.id);
1855
- }
1856
- }
1857
- }
1858
- }
1859
- }
1860
- const context = buildAgentContext({ loadingPending });
1861
- const snap = context.snapshot;
1862
- const activePath = context.navigationState?.activePath ?? [];
1863
- for (const action of turnActions) {
1864
- const result = turn.results.get(action.id);
1865
- if (result?.success && formFillLackedWriteEffect(action, snap, activePath)) {
1866
- toolWithoutEffectIds.add(action.id);
1867
- chunkSIBKF7AA_js.appilotsDebugWarn(
1868
- `tool-without-effect: form_fill succeeded but create form is still open (actionId="${action.id}")`
1869
- );
1870
- }
1871
- }
1872
- const results = Array.from(turn.actionIds).map((actionId) => {
1873
- const r = turn.results.get(actionId);
1874
- if (!r) {
1875
- return {
1876
- actionId,
1877
- type: "unknown",
1878
- success: false,
1879
- error: "no result reported",
1880
- summary: actionId,
1881
- diagnose: void 0,
1882
- recoveryAttempt: 0,
1883
- recoveryExhausted: false,
1884
- toolWithoutEffect: false,
1885
- effect: "unknown"
1886
- };
1887
- }
1888
- const hasToolWithoutEffect = toolWithoutEffectIds.has(actionId);
1889
- let recoveryAttempt = 0;
1890
- let recoveryExhausted = false;
1891
- if (!r.success || hasToolWithoutEffect) {
1892
- const counts = recoveryCountByFingerprintRef.current;
1893
- const previous = counts.get(r.fingerprint) ?? 0;
1894
- const next = previous + 1;
1895
- counts.set(r.fingerprint, next);
1896
- recoveryAttempt = next;
1897
- recoveryExhausted = next >= MAX_RECOVERY_ATTEMPTS_PER_ACTION;
1898
- }
1899
- return {
1900
- actionId,
1901
- type: r.type,
1902
- success: r.success,
1903
- error: r.error,
1904
- summary: r.summary,
1905
- diagnose: r.diagnose,
1906
- recoveryAttempt,
1907
- recoveryExhausted,
1908
- toolWithoutEffect: hasToolWithoutEffect,
1909
- effect: hasToolWithoutEffect ? "none" : r.effect,
1910
- userVisibleStatusKey: r.userVisibleStatusKey
1911
- };
1912
- });
1913
- const exhausted = results.filter((r) => r.recoveryExhausted);
1914
- setLoadingStatusKey(
1915
- results.some((r) => !r.success || r.toolWithoutEffect) ? "statusAdjusting" : "statusAnalyzing"
1916
- );
1917
- console.log(
1918
- `[Appilots] useAppilotsChat: running continuation hop=${turn.hop} (${results.filter((r) => r.success).length}/${results.length} succeeded` + (exhausted.length > 0 ? `, ${exhausted.length} recovery-exhausted` : "") + ")"
1919
- );
1920
- const response = await client.continueAgent(results, context, turn.hop);
1921
- addAssistantMessage(response.message);
1922
- emit({
1923
- type: "agent:message",
1924
- timestamp: Date.now(),
1925
- data: { message: response.message, usage: response.usage }
1926
- });
1927
- if (response.isDone || !response.actions || response.actions.length === 0) {
1928
- currentTurnRef.current = null;
1929
- setIsLoading(false);
1930
- setLoadingStatusKey("thinking");
1931
- return;
1932
- }
1933
- beginTurn(response.message.id, response.actions, response.hop);
1934
- } catch (err) {
1935
- const raw = err instanceof Error ? err.message : "Continuation failed";
1936
- chunkSIBKF7AA_js.appilotsDebugWarn("useAppilotsChat: continuation failed \u2014", raw);
1937
- const recentUserTexts = messagesRef.current.filter((m) => m.role === "user").slice(-4).map((m) => m.content);
1938
- const friendly = buildContinuationFailureMessage(raw, recentUserTexts);
1939
- addAssistantMessage({
1940
- id: `error_${++messageIdCounter.current}`,
1941
- role: "assistant",
1942
- content: friendly,
1943
- timestamp: Date.now()
1944
- });
1945
- if (!escalationRef.current && escalationStrings?.offer) {
1946
- appendLocalSystemMessage(escalationStrings.offer, { escalationOffer: true });
1947
- }
1948
- if (turn) {
1949
- setPendingActions(
1950
- (prev) => prev.map(
1951
- (a) => turn.actionIds.has(a.id) && (a.status === "pending" || a.status === "executing") ? { ...a, status: "failed", error: friendly } : a
1952
- )
1953
- );
1954
- for (const actionId of turn.actionIds) {
1955
- if (turn.reportedIds.has(actionId)) continue;
1956
- emit({
1957
- type: "agent:action:error",
1958
- timestamp: Date.now(),
1959
- data: { actionId, error: friendly, abandoned: true }
1960
- });
1961
- }
1962
- }
1963
- currentTurnRef.current = null;
1964
- setIsLoading(false);
1965
- setLoadingStatusKey("thinking");
1966
- } finally {
1967
- continuationInFlightRef.current = false;
1968
- }
1969
- },
1970
- [client, emit, addAssistantMessage, beginTurn]
1971
- );
1972
- react.useEffect(() => {
1973
- return subscribe((event) => {
1974
- if (event.type === "agent:action:start") {
1975
- const action = event.data?.action;
1976
- if (!action?.id || action.type !== "confirm") return;
1977
- const injectedBy = action.payload?.injectedBy;
1978
- if (injectedBy !== "sdk-local") return;
1979
- registerSynthesizedTurnAction(action);
1980
- return;
1981
- }
1982
- if (event.type !== "agent:action:complete" && event.type !== "agent:action:error") return;
1983
- const turn = currentTurnRef.current;
1984
- if (!turn) return;
1985
- const actionId = event.data?.actionId;
1986
- if (!actionId || !turn.actionIds.has(actionId)) return;
1987
- if (turn.reportedIds.has(actionId)) return;
1988
- const success = event.type === "agent:action:complete";
1989
- const errorMsg = event.data?.error || void 0;
1990
- const diagnose = event.data?.diagnose;
1991
- const effect = event.data?.effect;
1992
- const userVisibleStatusKey = event.data?.userVisibleStatusKey;
1993
- const existing = turn.results.get(actionId);
1994
- if (existing) {
1995
- existing.success = success;
1996
- existing.error = errorMsg;
1997
- existing.diagnose = diagnose;
1998
- existing.effect = effect;
1999
- existing.userVisibleStatusKey = userVisibleStatusKey;
2000
- }
2001
- turn.reportedIds.add(actionId);
2002
- if (turn.reportedIds.size >= turn.actionIds.size) {
2003
- void runContinuation(turn);
2004
- }
2005
- });
2006
- }, [subscribe, runContinuation, registerSynthesizedTurnAction]);
2007
- const sendMessage = react.useCallback(
2008
- async (content) => {
2009
- if (!content.trim() || isLoading) return;
2010
- if (escalationRef.current) {
2011
- await sendEscalationMessage(content.trim());
2012
- return;
2013
- }
2014
- setError(null);
2015
- setIsLoading(true);
2016
- setLoadingStatusKey("statusAnalyzing");
2017
- currentTurnRef.current = null;
2018
- recoveryCountByFingerprintRef.current = /* @__PURE__ */ new Map();
2019
- const userMessage = {
2020
- id: `local_${++messageIdCounter.current}`,
2021
- role: "user",
2022
- content: content.trim(),
2023
- timestamp: Date.now()
2024
- };
2025
- setMessages((prev) => [...prev, userMessage]);
2026
- const streamingId = `streaming_${++messageIdCounter.current}`;
2027
- let streamedVisible = false;
2028
- const removeStreamingPlaceholder = () => {
2029
- if (!streamedVisible) return;
2030
- streamedVisible = false;
2031
- setMessages((prev) => prev.filter((m) => m.id !== streamingId));
2032
- };
2033
- const abortController = new AbortController();
2034
- abortRef.current = abortController;
2035
- try {
2036
- const context = buildAgentContext();
2037
- console.log(
2038
- `[Appilots] useAppilotsChat sendMessage: context \u2014 currentScreen="${context.currentScreen ?? "unknown"}", snapshot={texts:${context.snapshot?.texts?.length ?? 0}, inputs:${context.snapshot?.inputs?.length ?? 0}, buttons:${context.snapshot?.buttons?.length ?? 0}, elements:${context.snapshot?.elements?.length ?? 0}, lists:${context.snapshot?.lists?.length ?? 0}, listItems:${(context.snapshot?.lists ?? []).reduce((acc, l) => acc + (l.items?.length ?? 0), 0)}, choiceGroups:${context.snapshot?.choiceGroups?.length ?? 0}}`
2039
- );
2040
- let response;
2041
- if (streamingEnabled) {
2042
- try {
2043
- response = await client.sendMessageStream(content.trim(), context, {
2044
- signal: abortController.signal,
2045
- onTextDelta: (_chunk, fullText) => {
2046
- const visible = sanitizeVisibleAssistantContent(fullText);
2047
- if (!streamedVisible) {
2048
- streamedVisible = true;
2049
- setMessages((prev) => [
2050
- ...prev,
2051
- { id: streamingId, role: "assistant", content: visible, timestamp: Date.now() }
2052
- ]);
2053
- } else {
2054
- setMessages(
2055
- (prev) => prev.map((m) => m.id === streamingId ? { ...m, content: visible } : m)
2056
- );
2057
- }
2058
- }
2059
- });
2060
- } catch (err) {
2061
- if (err instanceof chunkSIBKF7AA_js.StreamTransportError) {
2062
- console.warn(`[Appilots] streaming unavailable, falling back to JSON: ${err.message}`);
2063
- response = await client.sendMessage(content.trim(), context);
2064
- } else {
2065
- throw err;
2066
- }
2067
- }
2068
- } else {
2069
- response = await client.sendMessage(content.trim(), context);
2070
- }
2071
- console.log(
2072
- `[Appilots] useAppilotsChat sendMessage: response received \u2014 actions=${response.actions?.length ?? 0}, hasSummary=${!!response.summaryMessage}`
2073
- );
2074
- removeStreamingPlaceholder();
2075
- addAssistantMessage(response.message);
2076
- beginTurn(response.message.id, response.actions, 1);
2077
- if (response.summaryMessage) {
2078
- addAssistantMessage(response.summaryMessage);
2079
- }
2080
- emit({
2081
- type: "agent:message",
2082
- timestamp: Date.now(),
2083
- data: { message: response.message, usage: response.usage }
2084
- });
2085
- if (!response.actions || response.actions.length === 0) {
2086
- setIsLoading(false);
2087
- setLoadingStatusKey("thinking");
2088
- }
2089
- } catch (err) {
2090
- if (err instanceof chunkSIBKF7AA_js.StreamAbortError || err instanceof Error && err.name === "AbortError") {
2091
- setIsLoading(false);
2092
- setLoadingStatusKey("thinking");
2093
- return;
2094
- }
2095
- removeStreamingPlaceholder();
2096
- const errorMessage = err instanceof Error ? err.message : "Failed to send message";
2097
- setError(errorMessage);
2098
- const errorMsg = {
2099
- id: `error_${++messageIdCounter.current}`,
2100
- role: "assistant",
2101
- content: `${errorPrefix}: ${errorMessage}`,
2102
- timestamp: Date.now()
2103
- };
2104
- addAssistantMessage(errorMsg);
2105
- setIsLoading(false);
2106
- setLoadingStatusKey("thinking");
2107
- } finally {
2108
- if (abortRef.current === abortController) {
2109
- abortRef.current = null;
2110
- }
999
+ const props = fiber.memoizedProps ?? {};
1000
+ bestId2 = props.testID ?? props.accessibilityLabel ?? props.placeholder ?? (kind === "target" ? findChildText2(fiber) : void 0);
1001
+ if (kind === "field") bestHandle = wrapTextInput(fiber);
1002
+ else if (kind === "toggle") bestHandle = wrapSwitch(fiber);
1003
+ else bestHandle = wrapTouchable(fiber, findChildText2(fiber));
2111
1004
  }
2112
- },
2113
- [client, emit, isLoading, addAssistantMessage, beginTurn, errorPrefix, streamingEnabled]
2114
- );
2115
- const cancelMessage = react.useCallback(() => {
2116
- abortRef.current?.abort();
2117
- }, []);
2118
- const clearMessages = react.useCallback(() => {
2119
- setMessages([]);
2120
- setPendingActions([]);
2121
- setError(null);
2122
- setIsLoading(false);
2123
- setLoadingStatusKey("thinking");
2124
- currentTurnRef.current = null;
2125
- continuationInFlightRef.current = false;
2126
- recoveryCountByFingerprintRef.current = /* @__PURE__ */ new Map();
2127
- if (escalationRef.current) {
2128
- void client.abandonEscalation(escalationRef.current.id);
2129
1005
  }
2130
- setEscalation(null);
2131
- escalationSinceRef.current = void 0;
2132
- seenHumanMessageIdsRef.current = /* @__PURE__ */ new Set();
2133
- escalationReconnectAttemptRef.current = 0;
2134
- client.destroySession();
2135
- }, [client]);
2136
- const clearError = react.useCallback(() => setError(null), []);
2137
- return {
2138
- messages,
2139
- isLoading,
2140
- loadingStatusKey,
2141
- error,
2142
- pendingActions,
2143
- escalation,
2144
- requestHuman,
2145
- sendMessage,
2146
- cancelMessage,
2147
- clearMessages,
2148
- clearError
2149
- };
1006
+ if (fiber.child) stack.push(fiber.child);
1007
+ }
1008
+ if (bestHandle) {
1009
+ console.log(
1010
+ `[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 kind=${bestHandle.kind} label="${bestHandle.label ?? bestId2}" score=${bestScore}`
1011
+ );
1012
+ } else {
1013
+ console.log(`[Appilots] findInteractiveByIdentifier: query="${query}" \u2192 no match`);
1014
+ }
1015
+ return bestHandle;
2150
1016
  }
2151
1017
 
2152
1018
  // src/executor/handlers/navigateHandler.ts
@@ -2332,7 +1198,7 @@ function markedItemIndexFromFiber(fiber) {
2332
1198
  const value = fiber?.memoizedProps?.__appilotsItemIndex;
2333
1199
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
2334
1200
  }
2335
- function normalize4(value) {
1201
+ function normalize2(value) {
2336
1202
  return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "");
2337
1203
  }
2338
1204
  function hasPressHandler3(fiber) {
@@ -2344,7 +1210,7 @@ function isPressableFiber(fiber) {
2344
1210
  return TOUCHABLE_NAMES.has(typeName) || hasPressHandler3(fiber);
2345
1211
  }
2346
1212
  function findListContainers(options = {}) {
2347
- const root = chunkSIBKF7AA_js.getFiberRoot();
1213
+ const root = chunkV3TUIIT2_js.getFiberRoot();
2348
1214
  if (!root) return [];
2349
1215
  const containers = [];
2350
1216
  const visited = /* @__PURE__ */ new WeakSet();
@@ -2503,7 +1369,7 @@ function describeTouchable(fiber) {
2503
1369
  }
2504
1370
  function touchableLooksDestructive(fiber) {
2505
1371
  const descriptor = describeTouchable(fiber);
2506
- if (descriptor && looksDestructiveActionLabel(descriptor)) return true;
1372
+ if (descriptor && chunkV3TUIIT2_js.looksDestructiveActionLabel(descriptor)) return true;
2507
1373
  const props = fiber?.memoizedProps ?? {};
2508
1374
  const haystack = [
2509
1375
  props.testID,
@@ -2511,7 +1377,7 @@ function touchableLooksDestructive(fiber) {
2511
1377
  props.accessibilityHint,
2512
1378
  props.label
2513
1379
  ].filter((value) => typeof value === "string").join(" ");
2514
- return looksDestructiveActionLabel(haystack);
1380
+ return chunkV3TUIIT2_js.looksDestructiveActionLabel(haystack);
2515
1381
  }
2516
1382
  function describeItemCandidate(listIndex, zeroBasedIndex, item) {
2517
1383
  const syntheticId = `list-${listIndex}-item-${zeroBasedIndex + 1}`;
@@ -2591,9 +1457,9 @@ function pressResolvedListItem(list, itemFiber, listIndex, itemIndex) {
2591
1457
  }
2592
1458
  }
2593
1459
  function itemTextScore(item, locator) {
2594
- const needles = [locator.label, ...locator.texts ?? []].map(normalize4).filter((text) => text.length >= 2);
1460
+ const needles = [locator.label, ...locator.texts ?? []].map(normalize2).filter((text) => text.length >= 2);
2595
1461
  if (needles.length === 0) return 0;
2596
- const haystack = collectTexts(item).map(normalize4).filter(Boolean);
1462
+ const haystack = collectTexts(item).map(normalize2).filter(Boolean);
2597
1463
  if (haystack.length === 0) return 0;
2598
1464
  let score = 0;
2599
1465
  for (const needle of needles) {
@@ -2611,11 +1477,11 @@ function scoreItemCandidate(item, zeroBasedIndex, locator) {
2611
1477
  const markedIndex = markedItemIndexFromFiber(item);
2612
1478
  if (locator.itemKey) {
2613
1479
  if (itemKey === locator.itemKey) score += 1e3;
2614
- else if (itemKey && normalize4(itemKey) === normalize4(locator.itemKey)) score += 950;
1480
+ else if (itemKey && normalize2(itemKey) === normalize2(locator.itemKey)) score += 950;
2615
1481
  }
2616
1482
  if (locator.reactKey) {
2617
1483
  if (reactKey === locator.reactKey) score += 900;
2618
- else if (reactKey && normalize4(reactKey) === normalize4(locator.reactKey)) score += 850;
1484
+ else if (reactKey && normalize2(reactKey) === normalize2(locator.reactKey)) score += 850;
2619
1485
  }
2620
1486
  if (locator.itemIndex && zeroBasedIndex === locator.itemIndex - 1) score += 750;
2621
1487
  if (locator.itemIndex && markedIndex !== void 0 && (markedIndex === locator.itemIndex || markedIndex === locator.itemIndex - 1)) {
@@ -2626,8 +1492,8 @@ function scoreItemCandidate(item, zeroBasedIndex, locator) {
2626
1492
  }
2627
1493
  function candidateLists(containers, locator) {
2628
1494
  if (locator.listId) {
2629
- const normalizedId = normalize4(locator.listId);
2630
- const matches = containers.map((list, listIndex) => ({ list, listIndex })).filter(({ list }) => normalize4(list.listId) === normalizedId);
1495
+ const normalizedId = normalize2(locator.listId);
1496
+ const matches = containers.map((list, listIndex) => ({ list, listIndex })).filter(({ list }) => normalize2(list.listId) === normalizedId);
2631
1497
  if (matches.length > 0) return matches;
2632
1498
  }
2633
1499
  if (typeof locator.listIndex === "number") {
@@ -2635,14 +1501,14 @@ function candidateLists(containers, locator) {
2635
1501
  return list ? [{ list, listIndex: locator.listIndex }] : [];
2636
1502
  }
2637
1503
  if (locator.listLabel) {
2638
- const normalizedLabel = normalize4(locator.listLabel);
2639
- const matches = containers.map((list, listIndex) => ({ list, listIndex })).filter(({ list }) => normalize4(list.listLabel).includes(normalizedLabel));
1504
+ const normalizedLabel = normalize2(locator.listLabel);
1505
+ const matches = containers.map((list, listIndex) => ({ list, listIndex })).filter(({ list }) => normalize2(list.listLabel).includes(normalizedLabel));
2640
1506
  if (matches.length > 0) return matches;
2641
1507
  }
2642
1508
  return containers.map((list, listIndex) => ({ list, listIndex }));
2643
1509
  }
2644
1510
  function pressListItemAtOrdinal(listIndex, itemIndex) {
2645
- if (!chunkSIBKF7AA_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1511
+ if (!chunkV3TUIIT2_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
2646
1512
  const containers = findListContainers({ allowSingleHeuristic: true });
2647
1513
  if (listIndex < 0 || listIndex >= containers.length) {
2648
1514
  return { ok: false, reason: "list-not-found" };
@@ -2656,7 +1522,7 @@ function pressListItemAtOrdinal(listIndex, itemIndex) {
2656
1522
  return pressResolvedListItem(list, items[zeroBased], listIndex, itemIndex);
2657
1523
  }
2658
1524
  function pressListItemByIdentity(locator) {
2659
- if (!chunkSIBKF7AA_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
1525
+ if (!chunkV3TUIIT2_js.getFiberRoot()) return { ok: false, reason: "no-fiber-root" };
2660
1526
  const parsed = locator.syntheticId ? parseSyntheticListItemId(locator.syntheticId) : null;
2661
1527
  const effective = parsed ? { ...locator, listIndex: parsed.listIndex, itemIndex: parsed.itemIndex } : locator;
2662
1528
  const containers = findListContainers({ allowSingleHeuristic: true });
@@ -2696,7 +1562,7 @@ function screenDiagnose(targetId, category = "component-not-found") {
2696
1562
  return {
2697
1563
  category,
2698
1564
  targetId,
2699
- screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0
1565
+ screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0
2700
1566
  };
2701
1567
  }
2702
1568
  function isPressLike(action) {
@@ -2713,10 +1579,10 @@ function elementLookupKey(value) {
2713
1579
  return canonicalElementId(value).toLowerCase().replace(/[\s_]+/g, "-");
2714
1580
  }
2715
1581
  function findRegisteredElement(elementId) {
2716
- const direct = chunkSIBKF7AA_js.elementRegistry.get(elementId) ?? chunkSIBKF7AA_js.elementRegistry.get(canonicalElementId(elementId));
1582
+ const direct = chunkV3TUIIT2_js.elementRegistry.get(elementId) ?? chunkV3TUIIT2_js.elementRegistry.get(canonicalElementId(elementId));
2717
1583
  if (direct) return direct;
2718
1584
  const wanted = elementLookupKey(elementId);
2719
- return chunkSIBKF7AA_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
1585
+ return chunkV3TUIIT2_js.elementRegistry.snapshot().find((element) => elementLookupKey(element.id) === wanted);
2720
1586
  }
2721
1587
  function resolveInteractionElement(elementId) {
2722
1588
  return getLatestElement(elementId);
@@ -2936,7 +1802,7 @@ function dispatchElement(element, registry, action) {
2936
1802
  }
2937
1803
  function dispatchStructuredElementId(identifier, action) {
2938
1804
  if (!isElementIdentifier(identifier) || !isPressLike(action)) return null;
2939
- const parsed = parseStableElementId(identifier);
1805
+ const parsed = chunkV3TUIIT2_js.parseStableElementId(identifier);
2940
1806
  if (!parsed || parsed.role !== "option") return null;
2941
1807
  if (!parsed.itemKey && !parsed.listId) return null;
2942
1808
  const pressed = pressListItemByIdentity({
@@ -2972,24 +1838,24 @@ function pressElementOrTarget(identifier, registry) {
2972
1838
  // src/executor/formFieldRewrite.ts
2973
1839
  var LIST_ORDINAL_RE = /^list-\d+-item-\d+$/i;
2974
1840
  var PLATE_RE = /^[A-Z]{3}-?\d[A-Z0-9]\d{2}$/i;
2975
- function normalize5(value) {
1841
+ function normalize4(value) {
2976
1842
  return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
2977
1843
  }
2978
1844
  function resolveScreenForFormFields() {
2979
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
1845
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
2980
1846
  for (let i = activePath.length - 1; i >= 0; i--) {
2981
1847
  const name = activePath[i];
2982
- const meta = name ? chunkSIBKF7AA_js.getScreenMetadata(name) : void 0;
1848
+ const meta = name ? chunkV3TUIIT2_js.getScreenMetadata(name) : void 0;
2983
1849
  if (name && Array.isArray(meta?.fields) && meta.fields.length > 0) return name;
2984
1850
  }
2985
- return chunkSIBKF7AA_js.getCurrentScreen();
1851
+ return chunkV3TUIIT2_js.getCurrentScreen();
2986
1852
  }
2987
1853
  function collectKnownFormFields(registry) {
2988
1854
  const registryFields = registry.snapshot().filter((entry) => entry.kind === "field" || entry.kind === "slider").map((entry) => ({ id: entry.id, label: entry.label }));
2989
1855
  if (registryFields.length >= 2) return registryFields;
2990
1856
  const screen = resolveScreenForFormFields();
2991
1857
  if (screen) {
2992
- const metaFields = chunkSIBKF7AA_js.getScreenMetadata(screen)?.fields;
1858
+ const metaFields = chunkV3TUIIT2_js.getScreenMetadata(screen)?.fields;
2993
1859
  if (Array.isArray(metaFields) && metaFields.length > 0) {
2994
1860
  return metaFields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
2995
1861
  id: field.id,
@@ -2999,7 +1865,7 @@ function collectKnownFormFields(registry) {
2999
1865
  }));
3000
1866
  }
3001
1867
  }
3002
- for (const meta of chunkSIBKF7AA_js.getAllScreens()) {
1868
+ for (const meta of chunkV3TUIIT2_js.getAllScreens()) {
3003
1869
  if (Array.isArray(meta.fields) && meta.fields.length > 0) {
3004
1870
  return meta.fields.filter((field) => !!field && typeof field.id === "string").map((field) => ({
3005
1871
  id: field.id,
@@ -3012,14 +1878,14 @@ function collectKnownFormFields(registry) {
3012
1878
  return registryFields;
3013
1879
  }
3014
1880
  function fieldHaystack(field) {
3015
- return normalize5(`${field.id} ${field.label ?? ""}`);
1881
+ return normalize4(`${field.id} ${field.label ?? ""}`);
3016
1882
  }
3017
1883
  function isMisplacedFieldId(fieldId, knownIds) {
3018
1884
  const trimmed = fieldId.trim();
3019
1885
  if (!trimmed) return true;
3020
1886
  if (LIST_ORDINAL_RE.test(trimmed)) return true;
3021
1887
  if (/^\d+$/.test(trimmed)) return true;
3022
- const normalized = normalize5(trimmed);
1888
+ const normalized = normalize4(trimmed);
3023
1889
  if (knownIds.has(normalized)) return false;
3024
1890
  for (const known of knownIds) {
3025
1891
  if (known.length >= 4 && (known.includes(normalized) || normalized.includes(known))) {
@@ -3029,18 +1895,18 @@ function isMisplacedFieldId(fieldId, knownIds) {
3029
1895
  return true;
3030
1896
  }
3031
1897
  function valueMatchesOption(field, rawValue) {
3032
- const value = normalize5(String(rawValue ?? ""));
1898
+ const value = normalize4(String(rawValue ?? ""));
3033
1899
  if (!value || !Array.isArray(field.options)) return false;
3034
1900
  return field.options.some((option) => {
3035
- const label = normalize5(option.label ?? "");
3036
- const optionValue = normalize5(option.value ?? "");
1901
+ const label = normalize4(option.label ?? "");
1902
+ const optionValue = normalize4(option.value ?? "");
3037
1903
  return label === value || optionValue === value || value.includes(label) || value.includes(optionValue);
3038
1904
  });
3039
1905
  }
3040
1906
  function inferFieldIdForValue(rawValue, fields, used) {
3041
1907
  const value = String(rawValue ?? "").trim();
3042
1908
  if (!value) return void 0;
3043
- const normalizedValue = normalize5(value);
1909
+ const normalizedValue = normalize4(value);
3044
1910
  for (const field of fields) {
3045
1911
  if (used.has(field.id)) continue;
3046
1912
  if (valueMatchesOption(field, value)) return field.id;
@@ -3077,7 +1943,7 @@ function inferFieldIdForValue(rawValue, fields, used) {
3077
1943
  }
3078
1944
  const nextText = fields.find((field) => {
3079
1945
  if (used.has(field.id)) return false;
3080
- const type = normalize5(field.type ?? "text");
1946
+ const type = normalize4(field.type ?? "text");
3081
1947
  return type === "text" || type === "input" || type === "number" || type === "";
3082
1948
  });
3083
1949
  return nextText?.id;
@@ -3085,7 +1951,7 @@ function inferFieldIdForValue(rawValue, fields, used) {
3085
1951
  function rewriteMisplacedFormFillFields(fields, registry) {
3086
1952
  const knownFields = collectKnownFormFields(registry);
3087
1953
  if (knownFields.length === 0) return fields;
3088
- const knownIds = new Set(knownFields.map((field) => normalize5(field.id)));
1954
+ const knownIds = new Set(knownFields.map((field) => normalize4(field.id)));
3089
1955
  const needsRewrite = fields.some((field) => isMisplacedFieldId(field.fieldId, knownIds));
3090
1956
  if (!needsRewrite) return fields;
3091
1957
  const used = /* @__PURE__ */ new Set();
@@ -3097,7 +1963,7 @@ function rewriteMisplacedFormFillFields(fields, registry) {
3097
1963
  const inferred = inferFieldIdForValue(String(field.value ?? ""), knownFields, used);
3098
1964
  if (!inferred) return field;
3099
1965
  used.add(inferred);
3100
- chunkSIBKF7AA_js.appilotsDebugWarn(
1966
+ chunkV3TUIIT2_js.appilotsDebugWarn(
3101
1967
  `formFieldRewrite: ${field.fieldId} \u2192 ${inferred} (value=${JSON.stringify(field.value)})`
3102
1968
  );
3103
1969
  return { ...field, fieldId: inferred };
@@ -3105,7 +1971,7 @@ function rewriteMisplacedFormFillFields(fields, registry) {
3105
1971
  }
3106
1972
 
3107
1973
  // src/executor/formValidation.ts
3108
- var FORM_VALIDATION_TEXT_RE2 = /(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;
1974
+ 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;
3109
1975
  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;
3110
1976
  var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3111
1977
  var FIELD_HINTS = [
@@ -3125,7 +1991,7 @@ function inferValidationFieldId(message) {
3125
1991
  function readVisibleFormValidation(snap) {
3126
1992
  if (!snap) return void 0;
3127
1993
  for (const text of snap.texts ?? []) {
3128
- if (!text?.trim() || !FORM_VALIDATION_TEXT_RE2.test(text)) continue;
1994
+ if (!text?.trim() || !FORM_VALIDATION_TEXT_RE.test(text)) continue;
3129
1995
  return { fieldId: inferValidationFieldId(text), message: text };
3130
1996
  }
3131
1997
  return void 0;
@@ -3135,7 +2001,7 @@ function readVisibleFormSuccess(snap) {
3135
2001
  return (snap.texts ?? []).find((text) => text?.trim() && FORM_SUCCESS_TEXT_RE.test(text));
3136
2002
  }
3137
2003
  function submitAsyncStillPending(submitTargetId) {
3138
- const probe = chunkSIBKF7AA_js.probeLoadingState(submitTargetId ?? null, chunkSIBKF7AA_js.getCurrentScreen());
2004
+ const probe = chunkV3TUIIT2_js.probeLoadingState(submitTargetId ?? null, chunkV3TUIIT2_js.getCurrentScreen());
3139
2005
  if (probe.loading) return true;
3140
2006
  if (submitTargetId && probe.pressedFound && probe.pressedDisabled) return true;
3141
2007
  return false;
@@ -3147,7 +2013,7 @@ function evaluatePostSubmitSnapshot(snap, activePath) {
3147
2013
  }
3148
2014
  const successText = readVisibleFormSuccess(snap);
3149
2015
  if (successText) return { status: "success", message: successText };
3150
- if (!snapshotShowsOpenCreateForm(snap, activePath)) {
2016
+ if (!chunkV3TUIIT2_js.snapshotShowsOpenCreateForm(snap, activePath)) {
3151
2017
  return { status: "success" };
3152
2018
  }
3153
2019
  return void 0;
@@ -3163,7 +2029,7 @@ async function waitForPostSubmitOutcome(options) {
3163
2029
  continue;
3164
2030
  }
3165
2031
  const snap2 = captureSnapshot();
3166
- const activePath2 = chunkSIBKF7AA_js.getActiveRouteNames();
2032
+ const activePath2 = chunkV3TUIIT2_js.getActiveRouteNames();
3167
2033
  const outcome2 = evaluatePostSubmitSnapshot(snap2, activePath2);
3168
2034
  if (outcome2) return outcome2;
3169
2035
  await sleep(pollMs);
@@ -3175,7 +2041,7 @@ async function waitForPostSubmitOutcome(options) {
3175
2041
  };
3176
2042
  }
3177
2043
  const snap = captureSnapshot();
3178
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
2044
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
3179
2045
  const outcome = evaluatePostSubmitSnapshot(snap, activePath);
3180
2046
  if (outcome) return outcome;
3181
2047
  return {
@@ -3184,27 +2050,6 @@ async function waitForPostSubmitOutcome(options) {
3184
2050
  };
3185
2051
  }
3186
2052
 
3187
- // src/executor/handlers/formFillMatching.ts
3188
- function normalize6(s) {
3189
- return s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
3190
- }
3191
- function matchScore(needle, hay) {
3192
- if (!needle || !hay) return 0;
3193
- if (needle === hay) return 100;
3194
- if (hay.startsWith(needle) || needle.startsWith(hay)) return 75;
3195
- if (hay.endsWith(needle) || needle.endsWith(hay)) return 60;
3196
- if (hay.includes(needle) || needle.includes(hay)) return 40;
3197
- return 0;
3198
- }
3199
- function isGenericSelectValue(value) {
3200
- if (value === void 0 || value === null || value === "") return true;
3201
- const normalized = normalize6(String(value));
3202
- if (!normalized) return true;
3203
- return /^(any|qualquer|random|aleatorio|aleatoria|auto|automatico|automatica|mock|mockado|mockada|mockados|mockadas|dummy|sample|exemplo|default|padrao|teste|test)$/.test(
3204
- normalized
3205
- );
3206
- }
3207
-
3208
2053
  // ../shared/dist/chunk-ERITSWKE.mjs
3209
2054
  var DEFAULT_FUZZY_FLOOR = 4;
3210
2055
  function normalizeId(value) {
@@ -3290,39 +2135,6 @@ function resolveTarget(requested, candidates, opts = {}) {
3290
2135
  return { status: "matched", id: ids[0], tier: "fuzzy" };
3291
2136
  }
3292
2137
 
3293
- // src/executor/interactionGuidance.ts
3294
- var LIST_ORDINAL_RE2 = /^list-\d+-item-\d+$/i;
3295
- function normalizeId2(value) {
3296
- return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
3297
- }
3298
- function isOptionalCosmeticTargetId(targetId) {
3299
- if (typeof targetId !== "string" || !targetId.trim()) return false;
3300
- const id = normalizeId2(targetId);
3301
- return /foto|photo|avatar|icone|icon|emoji|sheetaction|sheet-action|btn-foto/.test(id) || id.includes("photo-sheet");
3302
- }
3303
- function routeLooksLikeFormContext(route) {
3304
- const haystack = normalizeId2(route ?? "");
3305
- return /create|edit|form|cadastr|register|novo|vehiclecreate|subscriptioncreate|vehicleedit|subscriptioncreate/.test(
3306
- haystack
3307
- );
3308
- }
3309
- function screenPathParts(screen) {
3310
- if (!screen) return [];
3311
- return screen.split("/").map((part) => part.trim()).filter(Boolean);
3312
- }
3313
- function isMisappliedListOrdinalOnForm(targetId, screen, activePath) {
3314
- if (typeof targetId !== "string" || !LIST_ORDINAL_RE2.test(targetId.trim())) {
3315
- return false;
3316
- }
3317
- const routes = [...screenPathParts(screen), ...activePath ?? []];
3318
- if (routes.length === 0) return routeLooksLikeFormContext(screen);
3319
- return routes.some((route) => routeLooksLikeFormContext(route));
3320
- }
3321
- function isOptionalStepAutomationFailure(targetId, screen, activePath) {
3322
- return isOptionalCosmeticTargetId(targetId) || isMisappliedListOrdinalOnForm(targetId, screen, activePath);
3323
- }
3324
- var OPTIONAL_STEP_AUTOMATION_HINT = "optional-step-automation-failed";
3325
-
3326
2138
  // src/executor/handlers/uiInteractionHandler.ts
3327
2139
  function findSnapshotButton(targetId) {
3328
2140
  try {
@@ -3335,16 +2147,16 @@ function findSnapshotButton(targetId) {
3335
2147
  }
3336
2148
  }
3337
2149
  function buildUiDiagnose(targetId, cause) {
3338
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
3339
- const screen = activePath[activePath.length - 1] ?? chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
2150
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
2151
+ const screen = activePath[activePath.length - 1] ?? chunkV3TUIIT2_js.getCurrentScreen() ?? void 0;
3340
2152
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
3341
2153
  const diagnose = {
3342
2154
  category: cause === "not-found" ? "component-not-found" : cause === "disabled" ? "disabled" : "unknown",
3343
2155
  targetId,
3344
2156
  screen: screenPath
3345
2157
  };
3346
- if (isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
3347
- diagnose.visibleMessage = OPTIONAL_STEP_AUTOMATION_HINT;
2158
+ if (chunkV3TUIIT2_js.isOptionalStepAutomationFailure(targetId, screenPath, activePath)) {
2159
+ diagnose.visibleMessage = chunkV3TUIIT2_js.OPTIONAL_STEP_AUTOMATION_HINT;
3348
2160
  diagnose.recoverable = true;
3349
2161
  }
3350
2162
  return diagnose;
@@ -3406,9 +2218,9 @@ function resolveComponentId(componentId, registry, action) {
3406
2218
  return comp.id;
3407
2219
  }
3408
2220
  }
3409
- const currentScreen = chunkSIBKF7AA_js.getCurrentScreen();
2221
+ const currentScreen = chunkV3TUIIT2_js.getCurrentScreen();
3410
2222
  if (currentScreen) {
3411
- const screenMeta = chunkSIBKF7AA_js.getScreenMetadata(currentScreen);
2223
+ const screenMeta = chunkV3TUIIT2_js.getScreenMetadata(currentScreen);
3412
2224
  const actions = screenMeta?.actions;
3413
2225
  if (actions && Array.isArray(actions)) {
3414
2226
  const metaAction = actions.find(
@@ -3562,7 +2374,7 @@ function checkModalOcclusion(rawComponentId, action) {
3562
2374
  return null;
3563
2375
  }
3564
2376
  if (typeof rawComponentId !== "string" || rawComponentId.trim().length === 0) return null;
3565
- const fiberRoot = chunkSIBKF7AA_js.getFiberRoot();
2377
+ const fiberRoot = chunkV3TUIIT2_js.getFiberRoot();
3566
2378
  if (!fiberRoot) return null;
3567
2379
  let snap;
3568
2380
  try {
@@ -3625,7 +2437,7 @@ function checkModalOcclusion(rawComponentId, action) {
3625
2437
  }
3626
2438
  function uiInteractionHandler(payload, context) {
3627
2439
  const { permissions } = context;
3628
- const registry = context.registry ?? chunkSIBKF7AA_js.componentRegistry;
2440
+ const registry = context.registry ?? chunkV3TUIIT2_js.componentRegistry;
3629
2441
  if (!permissions.canInteractUI) {
3630
2442
  return {
3631
2443
  success: false,
@@ -3684,7 +2496,7 @@ function uiInteractionHandler(payload, context) {
3684
2496
  );
3685
2497
  return { success: true };
3686
2498
  }
3687
- const screen = chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
2499
+ const screen = chunkV3TUIIT2_js.getCurrentScreen() ?? void 0;
3688
2500
  if (result.reason === "list-not-found" || result.reason === "item-not-found") {
3689
2501
  return {
3690
2502
  success: false,
@@ -3825,18 +2637,18 @@ function uiInteractionHandler(payload, context) {
3825
2637
  // src/executor/formSubmitResolve.ts
3826
2638
  var SUBMIT_LABEL_HINT_RE = /\b(submit|save|send|continue|next|sign\s*in|log\s*in|register|salvar|enviar|entrar|cadastrar|continuar|proximo|próximo|avancar|avançar|confirmar|guardar|registrarse|iniciar\s+sesi[óo]n|enregistrer|envoyer|valider|soumettre|confirmer|se\s+connecter|s['e]\s*inscrire)\b/i;
3827
2639
  var AGENT_CHROME_TARGET_RE = /\b(fechar|close|dismiss|cancelar|cancel|limpar|clear|chat\s+do\s+assistente|assistant\s+chat)\b/i;
3828
- function normalize7(value) {
2640
+ function normalize5(value) {
3829
2641
  return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
3830
2642
  }
3831
2643
  function isAgentChromeTarget(id, label) {
3832
- const hay = normalize7(`${id ?? ""} ${label ?? ""}`);
2644
+ const hay = normalize5(`${id ?? ""} ${label ?? ""}`);
3833
2645
  return AGENT_CHROME_TARGET_RE.test(hay);
3834
2646
  }
3835
2647
  function isSubmitLikeTarget(id, label) {
3836
2648
  if (!id && !label) return false;
3837
2649
  if (isAgentChromeTarget(id, label)) return false;
3838
- const idNorm = normalize7(id ?? "");
3839
- normalize7(label ?? "");
2650
+ const idNorm = normalize5(id ?? "");
2651
+ normalize5(label ?? "");
3840
2652
  if (/^submit[-_]/i.test(id ?? "")) return true;
3841
2653
  if (submitLabelHintsSubmit(label ?? "")) return true;
3842
2654
  if (submitLabelHintsSubmit(id ?? "")) return true;
@@ -3849,7 +2661,7 @@ function submitLabelHintsSubmit(label) {
3849
2661
  return SUBMIT_LABEL_HINT_RE.test(trimmed);
3850
2662
  }
3851
2663
  function screenDeclaresSubmitAction(screenName) {
3852
- const meta = chunkSIBKF7AA_js.getScreenMetadata(screenName);
2664
+ const meta = chunkV3TUIIT2_js.getScreenMetadata(screenName);
3853
2665
  return Array.isArray(meta?.actions) && meta.actions.some(
3854
2666
  (action) => typeof action === "object" && action !== null && action.type === "submit"
3855
2667
  );
@@ -3882,7 +2694,7 @@ function resolveFormScreensForSubmit(screen, activePath, registry) {
3882
2694
  } else {
3883
2695
  push(screen);
3884
2696
  }
3885
- push(chunkSIBKF7AA_js.getCurrentScreen() ?? void 0);
2697
+ push(chunkV3TUIIT2_js.getCurrentScreen() ?? void 0);
3886
2698
  const withSubmit = [];
3887
2699
  const rest = [];
3888
2700
  for (const name of ordered) {
@@ -3900,7 +2712,7 @@ function collectSubmitTargetCandidates(screens, registry) {
3900
2712
  candidates.push(id);
3901
2713
  };
3902
2714
  for (const screenName of screens) {
3903
- const meta = chunkSIBKF7AA_js.getScreenMetadata(screenName);
2715
+ const meta = chunkV3TUIIT2_js.getScreenMetadata(screenName);
3904
2716
  const submitMeta = Array.isArray(meta?.actions) ? meta.actions.find(
3905
2717
  (action) => typeof action === "object" && action !== null && action.type === "submit"
3906
2718
  ) : void 0;
@@ -3935,7 +2747,7 @@ function readVisibleValidation(fieldId, label) {
3935
2747
  );
3936
2748
  for (const text of texts) {
3937
2749
  const lower = text.toLowerCase();
3938
- if (FORM_VALIDATION_TEXT_RE2.test(lower)) {
2750
+ if (FORM_VALIDATION_TEXT_RE.test(lower)) {
3939
2751
  for (const needle of needles) {
3940
2752
  if (lower.includes(needle.toLowerCase())) return text;
3941
2753
  }
@@ -3946,8 +2758,8 @@ function readVisibleValidation(fieldId, label) {
3946
2758
  return void 0;
3947
2759
  }
3948
2760
  function resolveScreenContext() {
3949
- const activePath = chunkSIBKF7AA_js.getActiveRouteNames();
3950
- const screen = activePath[activePath.length - 1] ?? chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
2761
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
2762
+ const screen = activePath[activePath.length - 1] ?? chunkV3TUIIT2_js.getCurrentScreen() ?? void 0;
3951
2763
  return { screen, activePath };
3952
2764
  }
3953
2765
  function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
@@ -3955,36 +2767,36 @@ function selectValueApplied(fieldId, requestedValue, currentValue, registry) {
3955
2767
  if (!requested) return false;
3956
2768
  const meta = getMetadataField(fieldId, registry);
3957
2769
  const options = Array.isArray(meta?.options) ? meta.options : [];
3958
- const requestedNorm = normalize6(requested);
3959
- const currentNorm = normalize6(currentValue);
2770
+ const requestedNorm = chunkV3TUIIT2_js.normalize3(requested);
2771
+ const currentNorm = chunkV3TUIIT2_js.normalize3(currentValue);
3960
2772
  if (currentNorm === requestedNorm) return true;
3961
2773
  for (const option of options) {
3962
2774
  const value = typeof option?.value === "string" ? option.value : "";
3963
2775
  const label = typeof option?.label === "string" ? option.label : "";
3964
- if (normalize6(value) === requestedNorm && normalize6(label) === currentNorm) return true;
3965
- if (normalize6(label) === requestedNorm && normalize6(label) === currentNorm) return true;
3966
- if (normalize6(value) === requestedNorm && normalize6(value) === currentNorm) return true;
2776
+ if (chunkV3TUIIT2_js.normalize3(value) === requestedNorm && chunkV3TUIIT2_js.normalize3(label) === currentNorm) return true;
2777
+ if (chunkV3TUIIT2_js.normalize3(label) === requestedNorm && chunkV3TUIIT2_js.normalize3(label) === currentNorm) return true;
2778
+ if (chunkV3TUIIT2_js.normalize3(value) === requestedNorm && chunkV3TUIIT2_js.normalize3(value) === currentNorm) return true;
3967
2779
  }
3968
2780
  return false;
3969
2781
  }
3970
2782
  function getMetadataField(fieldId, registry) {
3971
2783
  const screens = /* @__PURE__ */ new Set();
3972
- for (const name of chunkSIBKF7AA_js.getActiveRouteNames()) screens.add(name);
3973
- const current = chunkSIBKF7AA_js.getCurrentScreen();
2784
+ for (const name of chunkV3TUIIT2_js.getActiveRouteNames()) screens.add(name);
2785
+ const current = chunkV3TUIIT2_js.getCurrentScreen();
3974
2786
  if (current) screens.add(current);
3975
2787
  if (registry) {
3976
2788
  for (const comp of registry.snapshot()) {
3977
2789
  if (comp.kind === "field" && comp.screen) screens.add(comp.screen);
3978
2790
  }
3979
2791
  }
3980
- const needle = normalize6(fieldId);
2792
+ const needle = chunkV3TUIIT2_js.normalize3(fieldId);
3981
2793
  for (const screenName of screens) {
3982
- const screenMeta = chunkSIBKF7AA_js.getScreenMetadata(screenName);
2794
+ const screenMeta = chunkV3TUIIT2_js.getScreenMetadata(screenName);
3983
2795
  const fields = Array.isArray(screenMeta?.fields) ? screenMeta.fields : [];
3984
2796
  const match = fields.find((field) => {
3985
2797
  if (!field || typeof field !== "object") return false;
3986
- const id = typeof field.id === "string" ? normalize6(field.id) : "";
3987
- const label = typeof field.label === "string" ? normalize6(field.label) : "";
2798
+ const id = typeof field.id === "string" ? chunkV3TUIIT2_js.normalize3(field.id) : "";
2799
+ const label = typeof field.label === "string" ? chunkV3TUIIT2_js.normalize3(field.label) : "";
3988
2800
  return id === needle || label === needle;
3989
2801
  });
3990
2802
  if (match) return match;
@@ -3996,11 +2808,11 @@ function resolveSelectOption(fieldId, value, registry) {
3996
2808
  if (!requested) return void 0;
3997
2809
  const meta = getMetadataField(fieldId, registry);
3998
2810
  const options = Array.isArray(meta?.options) ? meta.options : [];
3999
- const requestedNorm = normalize6(requested);
2811
+ const requestedNorm = chunkV3TUIIT2_js.normalize3(requested);
4000
2812
  for (const option of options) {
4001
2813
  const optionValue = typeof option?.value === "string" ? option.value : "";
4002
2814
  const optionLabel = typeof option?.label === "string" ? option.label : "";
4003
- if (normalize6(optionValue) === requestedNorm || normalize6(optionLabel) === requestedNorm) {
2815
+ if (chunkV3TUIIT2_js.normalize3(optionValue) === requestedNorm || chunkV3TUIIT2_js.normalize3(optionLabel) === requestedNorm) {
4004
2816
  return { value: optionValue, label: optionLabel };
4005
2817
  }
4006
2818
  }
@@ -4050,12 +2862,12 @@ async function tryPressSelectOption(fieldId, value, registry, options = {}) {
4050
2862
  return {
4051
2863
  success: false,
4052
2864
  error: `No pressable option found for select field "${fieldId}"`,
4053
- diagnose: { category: "component-not-found", fieldId, screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0 }
2865
+ diagnose: { category: "component-not-found", fieldId, screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0 }
4054
2866
  };
4055
2867
  }
4056
2868
  function normalizeFieldType(type) {
4057
2869
  if (typeof type !== "string") return void 0;
4058
- const normalized = normalize6(type);
2870
+ const normalized = chunkV3TUIIT2_js.normalize3(type);
4059
2871
  if (normalized === "select" || normalized === "picker" || normalized === "dropdown") return "select";
4060
2872
  if (normalized === "toggle" || normalized === "switch" || normalized === "checkbox") return "toggle";
4061
2873
  if (normalized === "date") return "date";
@@ -4083,7 +2895,7 @@ function fieldCueTerms(fieldId, label) {
4083
2895
  );
4084
2896
  const terms = /* @__PURE__ */ new Set();
4085
2897
  for (const value of raw) {
4086
- const normalized = normalize6(value);
2898
+ const normalized = chunkV3TUIIT2_js.normalize3(value);
4087
2899
  if (normalized.length >= 3 && normalized !== "id") terms.add(normalized);
4088
2900
  }
4089
2901
  return [...terms];
@@ -4094,17 +2906,17 @@ function snapshotHasFieldCue(snap, fieldId, label) {
4094
2906
  const visible = [
4095
2907
  ...snap.texts ?? [],
4096
2908
  ...(snap.buttons ?? []).map((b) => b.label ?? b.id ?? "")
4097
- ].map((text) => normalize6(text)).filter(Boolean);
2909
+ ].map((text) => chunkV3TUIIT2_js.normalize3(text)).filter(Boolean);
4098
2910
  return visible.some((text) => terms.some((term) => text.includes(term) || term.includes(text)));
4099
2911
  }
4100
2912
  function scoreCandidateText(value, texts) {
4101
- const valueNorm = normalize6(String(value ?? ""));
2913
+ const valueNorm = chunkV3TUIIT2_js.normalize3(String(value ?? ""));
4102
2914
  if (!valueNorm) return 0;
4103
2915
  let best = 0;
4104
2916
  for (const text of texts) {
4105
- const textNorm = normalize6(text);
2917
+ const textNorm = chunkV3TUIIT2_js.normalize3(text);
4106
2918
  if (!textNorm) continue;
4107
- best = Math.max(best, matchScore(valueNorm, textNorm));
2919
+ best = Math.max(best, chunkV3TUIIT2_js.matchScore(valueNorm, textNorm));
4108
2920
  }
4109
2921
  return best;
4110
2922
  }
@@ -4118,7 +2930,7 @@ function optionTexts(option) {
4118
2930
  function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue, registry) {
4119
2931
  const fieldLabel = getFieldLabel(fieldId, registry);
4120
2932
  const fieldCueVisible = snapshotHasFieldCue(snap, fieldId, fieldLabel);
4121
- const genericValue = isGenericSelectValue(value);
2933
+ const genericValue = chunkV3TUIIT2_js.isGenericSelectValue(value);
4122
2934
  const candidates = [];
4123
2935
  let order = 0;
4124
2936
  const choiceGroups = snap.choiceGroups ?? [];
@@ -4130,7 +2942,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
4130
2942
  const groupCueScore = Math.max(
4131
2943
  globalCueScore,
4132
2944
  ...groupTexts.map((text) => {
4133
- const normalized = normalize6(text);
2945
+ const normalized = chunkV3TUIIT2_js.normalize3(text);
4134
2946
  return fieldCueTerms(fieldId, fieldLabel).some(
4135
2947
  (term) => normalized.includes(term) || term.includes(normalized)
4136
2948
  ) ? 80 : 0;
@@ -4167,7 +2979,7 @@ function buildChoiceCandidates(snap, fieldId, value, allowFirstVisibleWhenNoCue,
4167
2979
  const elementCueScore = Math.max(
4168
2980
  fieldCueVisible && elements.length <= 12 ? 50 : 0,
4169
2981
  ...cueTexts.map((text) => {
4170
- const normalized = normalize6(text);
2982
+ const normalized = chunkV3TUIIT2_js.normalize3(text);
4171
2983
  return fieldTerms.some(
4172
2984
  (term) => normalized.includes(term) || term.includes(normalized)
4173
2985
  ) ? 80 : 0;
@@ -4227,7 +3039,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
4227
3039
  return {
4228
3040
  success: false,
4229
3041
  error: err?.message ?? "Could not capture visible choices",
4230
- diagnose: { category: "unknown", fieldId, screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0 }
3042
+ diagnose: { category: "unknown", fieldId, screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0 }
4231
3043
  };
4232
3044
  }
4233
3045
  const candidates = buildChoiceCandidates(
@@ -4242,7 +3054,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
4242
3054
  return {
4243
3055
  success: false,
4244
3056
  error: `No visible option found for select field "${fieldId}"`,
4245
- diagnose: { category: "component-not-found", fieldId, screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0 }
3057
+ diagnose: { category: "component-not-found", fieldId, screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0 }
4246
3058
  };
4247
3059
  }
4248
3060
  const pressed = pressTargetByIdOrLabel(candidate.targetId, registry);
@@ -4255,7 +3067,7 @@ async function selectVisibleChoiceAsync(fieldId, value, registry, options) {
4255
3067
  }
4256
3068
  function isContinuationButton(label) {
4257
3069
  if (!label) return false;
4258
- return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(normalize6(label));
3070
+ return /^(next|continue|proximo|prox|continuar|avancar|avançar)$/i.test(chunkV3TUIIT2_js.normalize3(label));
4259
3071
  }
4260
3072
  function pressContinuationButton(registry) {
4261
3073
  const snap = captureSnapshot();
@@ -4268,7 +3080,7 @@ function pressContinuationButton(registry) {
4268
3080
  return {
4269
3081
  success: false,
4270
3082
  error: "No enabled continuation button is visible",
4271
- diagnose: { category: "component-not-found", screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0 }
3083
+ diagnose: { category: "component-not-found", screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0 }
4272
3084
  };
4273
3085
  }
4274
3086
  return pressTargetByIdOrLabel(id, registry);
@@ -4288,18 +3100,18 @@ function findField(fieldId, registry) {
4288
3100
  return registry.getField(comp.id);
4289
3101
  }
4290
3102
  }
4291
- const currentScreenForTieBreak = chunkSIBKF7AA_js.getCurrentScreen();
4292
- const needle = normalize6(fieldId);
3103
+ const currentScreenForTieBreak = chunkV3TUIIT2_js.getCurrentScreen();
3104
+ const needle = chunkV3TUIIT2_js.normalize3(fieldId);
4293
3105
  let bestComp;
4294
3106
  let bestScore = 0;
4295
3107
  let bestOnCurrentScreen = false;
4296
3108
  for (const comp of snapshot) {
4297
3109
  if (comp.kind !== "field") continue;
4298
- const candidates = [normalize6(comp.id)];
4299
- if (comp.label) candidates.push(normalize6(comp.label));
3110
+ const candidates = [chunkV3TUIIT2_js.normalize3(comp.id)];
3111
+ if (comp.label) candidates.push(chunkV3TUIIT2_js.normalize3(comp.label));
4300
3112
  let candidateScore = 0;
4301
3113
  for (const cand of candidates) {
4302
- const s = matchScore(needle, cand);
3114
+ const s = chunkV3TUIIT2_js.matchScore(needle, cand);
4303
3115
  if (s > candidateScore) candidateScore = s;
4304
3116
  }
4305
3117
  if (candidateScore === 0) continue;
@@ -4317,9 +3129,9 @@ function findField(fieldId, registry) {
4317
3129
  );
4318
3130
  return registry.getField(bestComp.id);
4319
3131
  }
4320
- const currentScreen = chunkSIBKF7AA_js.getCurrentScreen();
3132
+ const currentScreen = chunkV3TUIIT2_js.getCurrentScreen();
4321
3133
  if (currentScreen) {
4322
- const screenMeta = chunkSIBKF7AA_js.getScreenMetadata(currentScreen);
3134
+ const screenMeta = chunkV3TUIIT2_js.getScreenMetadata(currentScreen);
4323
3135
  const fields = screenMeta?.fields;
4324
3136
  if (fields && Array.isArray(fields)) {
4325
3137
  const metaField = fields.find(
@@ -4327,12 +3139,12 @@ function findField(fieldId, registry) {
4327
3139
  );
4328
3140
  if (metaField && typeof metaField === "object" && metaField.label) {
4329
3141
  const metaLabel = metaField.label;
4330
- const metaNeedle = normalize6(metaLabel);
3142
+ const metaNeedle = chunkV3TUIIT2_js.normalize3(metaLabel);
4331
3143
  let mBest;
4332
3144
  let mBestScore = 0;
4333
3145
  for (const comp of snapshot) {
4334
3146
  if (comp.kind !== "field" || !comp.label) continue;
4335
- const score = matchScore(metaNeedle, normalize6(comp.label));
3147
+ const score = chunkV3TUIIT2_js.matchScore(metaNeedle, chunkV3TUIIT2_js.normalize3(comp.label));
4336
3148
  if (score > mBestScore) {
4337
3149
  mBestScore = score;
4338
3150
  mBest = comp;
@@ -4353,7 +3165,7 @@ function findField(fieldId, registry) {
4353
3165
  );
4354
3166
  return registry.getField(bestComp.id);
4355
3167
  }
4356
- chunkSIBKF7AA_js.appilotsDebugWarn(
3168
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4357
3169
  `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"}`
4358
3170
  );
4359
3171
  return void 0;
@@ -4373,7 +3185,7 @@ function findToggle(fieldId, registry) {
4373
3185
  return registry.getToggle(comp.id);
4374
3186
  }
4375
3187
  }
4376
- chunkSIBKF7AA_js.appilotsDebugWarn(
3188
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4377
3189
  `findToggle: NOT FOUND \u2014 fieldId="${fieldId}" not in registry. Available toggles: ${snapshot.filter((c) => c.kind === "toggle").map((c) => `"${c.id}"`).join(", ") || "none"}`
4378
3190
  );
4379
3191
  return void 0;
@@ -4393,7 +3205,7 @@ function findSlider(fieldId, registry) {
4393
3205
  var sleep2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
4394
3206
  async function formFillHandler(payload, context) {
4395
3207
  const { permissions } = context;
4396
- const registry = context.registry ?? chunkSIBKF7AA_js.componentRegistry;
3208
+ const registry = context.registry ?? chunkV3TUIIT2_js.componentRegistry;
4397
3209
  const { screen, activePath } = resolveScreenContext();
4398
3210
  const screenPath = activePath.length > 1 ? activePath.join("/") : screen;
4399
3211
  if (!permissions.canFillForms) {
@@ -4412,7 +3224,7 @@ async function formFillHandler(payload, context) {
4412
3224
  }
4413
3225
  const registrySnapshot = registry.snapshot();
4414
3226
  if (registrySnapshot.length === 0) {
4415
- chunkSIBKF7AA_js.appilotsDebugWarn(
3227
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4416
3228
  "formFillHandler: registry is EMPTY \u2014 auto-tracking may not be active. Ensure enableAppilotsAutoTracking() runs before components mount."
4417
3229
  );
4418
3230
  } else {
@@ -4486,7 +3298,7 @@ async function formFillHandler(payload, context) {
4486
3298
  after = fieldEntry.getValue?.() ?? "";
4487
3299
  }
4488
3300
  if (!selectValueApplied(fieldId, value, after, registry)) {
4489
- chunkSIBKF7AA_js.appilotsDebugWarn(
3301
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4490
3302
  `formFillHandler: select field "${fieldId}" setValue("${value}") did not stick (current="${after}"), trying visible choice fallback`
4491
3303
  );
4492
3304
  const selectResult = await selectVisibleChoice(fieldId, value, registry, {
@@ -4659,14 +3471,14 @@ async function formFillHandler(payload, context) {
4659
3471
  if (payload.submitAfterFill === true) {
4660
3472
  if (!allSuccess) {
4661
3473
  const failedIds = fieldResults.filter((result) => !result.success).map((result) => result.fieldId);
4662
- chunkSIBKF7AA_js.appilotsDebugWarn(
3474
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4663
3475
  "formFillHandler: submitAfterFill=true requested but some fields failed; NOT submitting" + (failedIds.length > 0 ? ` (failed: ${failedIds.join(", ")})` : "")
4664
3476
  );
4665
3477
  } else {
4666
3478
  await sleep2(120);
4667
3479
  const submitResult = pressSubmitButton({ screen, screenPath, activePath }, registry);
4668
3480
  if (!submitResult.success) {
4669
- chunkSIBKF7AA_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
3481
+ chunkV3TUIIT2_js.appilotsDebugWarn(`formFillHandler: submitAfterFill failed \u2014 ${submitResult.error}`);
4670
3482
  return {
4671
3483
  success: false,
4672
3484
  error: submitResult.error,
@@ -4678,7 +3490,7 @@ async function formFillHandler(payload, context) {
4678
3490
  submitTargetId: submitResult.pressedTargetId
4679
3491
  });
4680
3492
  if (postSubmit.status === "pending") {
4681
- chunkSIBKF7AA_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
3493
+ chunkV3TUIIT2_js.appilotsDebugWarn(`formFillHandler: submit still pending \u2014 ${postSubmit.message}`);
4682
3494
  return {
4683
3495
  success: false,
4684
3496
  error: postSubmit.message,
@@ -4687,7 +3499,7 @@ async function formFillHandler(payload, context) {
4687
3499
  };
4688
3500
  }
4689
3501
  if (postSubmit.status === "failure") {
4690
- chunkSIBKF7AA_js.appilotsDebugWarn(
3502
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4691
3503
  `formFillHandler: submit rejected by visible validation \u2014 ${postSubmit.message}`
4692
3504
  );
4693
3505
  return {
@@ -4714,10 +3526,10 @@ async function formFillHandler(payload, context) {
4714
3526
  };
4715
3527
  }
4716
3528
  function pressSubmitButton(context, registry) {
4717
- const activePath = context.activePath ?? chunkSIBKF7AA_js.getActiveRouteNames();
3529
+ const activePath = context.activePath ?? chunkV3TUIIT2_js.getActiveRouteNames();
4718
3530
  const hintScreen = context.screen ?? context.screenPath;
4719
3531
  const formScreens = resolveFormScreensForSubmit(hintScreen, activePath, registry);
4720
- const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
3532
+ const resolvedScreen = formScreens.find((name) => screenDeclaresSubmit(name)) ?? formScreens[0] ?? hintScreen ?? chunkV3TUIIT2_js.getCurrentScreen() ?? void 0;
4721
3533
  const candidates = collectSubmitTargetCandidates(formScreens, registry);
4722
3534
  for (const candidate of candidates) {
4723
3535
  const target = registry.getTarget(candidate);
@@ -4738,7 +3550,7 @@ function pressSubmitButton(context, registry) {
4738
3550
  }
4739
3551
  }
4740
3552
  for (const screenName of formScreens) {
4741
- const screenMeta = chunkSIBKF7AA_js.getScreenMetadata(screenName);
3553
+ const screenMeta = chunkV3TUIIT2_js.getScreenMetadata(screenName);
4742
3554
  const submitMeta = Array.isArray(screenMeta?.actions) ? screenMeta.actions.find(
4743
3555
  (action) => typeof action === "object" && action !== null && action.type === "submit"
4744
3556
  ) : void 0;
@@ -4837,23 +3649,23 @@ var FALLBACK_PAGE_PX = 600;
4837
3649
  var PAGE_FRACTION = 0.85;
4838
3650
  var POST_SCROLL_MOUNT_MS = 400;
4839
3651
  var sleep3 = (ms) => new Promise((r) => setTimeout(r, ms));
4840
- function normalizeId3(value) {
3652
+ function normalizeId2(value) {
4841
3653
  return String(value ?? "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "");
4842
3654
  }
4843
3655
  function buildDiagnose(category, targetId, candidates) {
4844
3656
  return {
4845
3657
  category,
4846
3658
  targetId,
4847
- screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0,
3659
+ screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0,
4848
3660
  ...candidates && candidates.length > 0 ? { candidates: candidates.slice(0, 8) } : {}
4849
3661
  };
4850
3662
  }
4851
3663
  function resolveListEntry(listId) {
4852
- const entries = chunkSIBKF7AA_js.listRegistry.snapshot();
3664
+ const entries = chunkV3TUIIT2_js.listRegistry.snapshot();
4853
3665
  if (entries.length === 0) return {};
4854
3666
  if (listId) {
4855
- const wanted = normalizeId3(listId);
4856
- const match = entries.find((e) => normalizeId3(e.id) === wanted);
3667
+ const wanted = normalizeId2(listId);
3668
+ const match = entries.find((e) => normalizeId2(e.id) === wanted);
4857
3669
  if (match) return { entry: match };
4858
3670
  return { candidates: entries.map((e) => e.id) };
4859
3671
  }
@@ -4960,23 +3772,23 @@ function targetIdFromPayload(payload) {
4960
3772
  }
4961
3773
  async function waitForPostInteractionSettle(payload) {
4962
3774
  const targetId = targetIdFromPayload(payload);
4963
- const fromScreen = chunkSIBKF7AA_js.getCurrentScreen();
4964
- const baseline = chunkSIBKF7AA_js.probeLoadingState(targetId || null, fromScreen);
3775
+ const fromScreen = chunkV3TUIIT2_js.getCurrentScreen();
3776
+ const baseline = chunkV3TUIIT2_js.probeLoadingState(targetId || null, fromScreen);
4965
3777
  await sleepMs(100);
4966
- const afterPress = chunkSIBKF7AA_js.probeLoadingState(targetId || null, chunkSIBKF7AA_js.getCurrentScreen());
3778
+ const afterPress = chunkV3TUIIT2_js.probeLoadingState(targetId || null, chunkV3TUIIT2_js.getCurrentScreen());
4967
3779
  const modalOrLoading = afterPress.modalOpen || afterPress.loading || afterPress.pressedDisabled;
4968
3780
  const fingerprintChanged = afterPress.fingerprint !== baseline.fingerprint;
4969
- const capMs = isListItemPressTarget(targetId) ? 5e3 : 1e4;
3781
+ const capMs = chunkV3TUIIT2_js.isListItemPressTarget(targetId) ? 5e3 : 1e4;
4970
3782
  if (modalOrLoading || fingerprintChanged) {
4971
- await chunkSIBKF7AA_js.waitForLoadingSettle({
3783
+ await chunkV3TUIIT2_js.waitForLoadingSettle({
4972
3784
  pressedComponentId: targetId || null,
4973
3785
  fromScreen,
4974
3786
  maxMs: capMs
4975
3787
  });
4976
3788
  return;
4977
3789
  }
4978
- if (isListItemPressTarget(targetId)) {
4979
- await chunkSIBKF7AA_js.waitForLoadingSettle({
3790
+ if (chunkV3TUIIT2_js.isListItemPressTarget(targetId)) {
3791
+ await chunkV3TUIIT2_js.waitForLoadingSettle({
4980
3792
  fromScreen,
4981
3793
  maxMs: 3e3
4982
3794
  });
@@ -4996,7 +3808,7 @@ function validateActionPayload(action) {
4996
3808
  error: message,
4997
3809
  diagnose: {
4998
3810
  category: "validation",
4999
- screen: chunkSIBKF7AA_js.getCurrentScreen() ?? void 0,
3811
+ screen: chunkV3TUIIT2_js.getCurrentScreen() ?? void 0,
5000
3812
  ...ids ?? {}
5001
3813
  }
5002
3814
  });
@@ -5063,7 +3875,7 @@ async function executeAction(action, context) {
5063
3875
  let result;
5064
3876
  const validationFailure = validateActionPayload(action);
5065
3877
  if (validationFailure) {
5066
- chunkSIBKF7AA_js.appilotsDebugWarn(
3878
+ chunkV3TUIIT2_js.appilotsDebugWarn(
5067
3879
  `executeAction: payload validation failed for type="${action.type}" id="${action.id}": ${validationFailure.error}`
5068
3880
  );
5069
3881
  context.emit({
@@ -5090,13 +3902,13 @@ async function executeAction(action, context) {
5090
3902
  case "form_fill":
5091
3903
  result = await formFillHandler(action.payload, {
5092
3904
  permissions,
5093
- registry: context.registry ?? chunkSIBKF7AA_js.getDefaultRegistry()
3905
+ registry: context.registry ?? chunkV3TUIIT2_js.getDefaultRegistry()
5094
3906
  });
5095
3907
  break;
5096
3908
  case "ui_interaction":
5097
3909
  result = uiInteractionHandler(action.payload, {
5098
3910
  permissions,
5099
- registry: context.registry ?? chunkSIBKF7AA_js.getDefaultRegistry()
3911
+ registry: context.registry ?? chunkV3TUIIT2_js.getDefaultRegistry()
5100
3912
  });
5101
3913
  if (result.success) {
5102
3914
  await waitForPostInteractionSettle(action.payload);
@@ -5126,7 +3938,7 @@ async function executeAction(action, context) {
5126
3938
  };
5127
3939
  }
5128
3940
  } catch (err) {
5129
- chunkSIBKF7AA_js.appilotsDebugWarn(
3941
+ chunkV3TUIIT2_js.appilotsDebugWarn(
5130
3942
  `executeAction: exception during action type="${action.type}" id="${action.id}": ${err?.message}`
5131
3943
  );
5132
3944
  result = {
@@ -5150,90 +3962,156 @@ async function executeAction(action, context) {
5150
3962
  });
5151
3963
  return result;
5152
3964
  }
5153
-
5154
- // src/hooks/confirmMatching.ts
5155
- function metadataMatchesComponentId(metaId, componentId) {
5156
- const norm = (s) => s.toLowerCase().replace(/^el:(button|link|input|toggle|listitem)[:_-]/, "").replace(/^(btn-|btn_|button-|button_|link-|link_)/, "").trim();
5157
- const meta = norm(metaId);
5158
- const comp = norm(componentId);
5159
- if (!meta || !comp) return false;
5160
- return meta === comp;
5161
- }
5162
-
5163
- // src/hooks/useAppilotsActions.ts
5164
- var DEFAULT_PERMISSIONS2 = {
5165
- canNavigate: true,
5166
- canFillForms: true,
5167
- canInteractUI: true,
5168
- canSubmitForms: true
5169
- };
5170
- function readPayload(action) {
5171
- return action.payload ?? {};
5172
- }
5173
- function isStructuredRisky(value) {
5174
- return value === true || value === "destructive" || value === "danger" || value === "high";
3965
+ var POST_ACTION_LOADING_MAX_MS = 6e3;
3966
+ function resolveScreenMetadata() {
3967
+ const activePath = chunkV3TUIIT2_js.getActiveRouteNames();
3968
+ for (let i = activePath.length - 1; i >= 0; i--) {
3969
+ const name = activePath[i];
3970
+ const meta = name ? chunkV3TUIIT2_js.getScreenMetadata(name) : void 0;
3971
+ if (meta && (Array.isArray(meta.fields) && meta.fields.length > 0 || Array.isArray(meta.actions) && meta.actions.length > 0)) {
3972
+ return meta;
3973
+ }
3974
+ }
3975
+ const screen = chunkV3TUIIT2_js.getCurrentScreen();
3976
+ return screen ? chunkV3TUIIT2_js.getScreenMetadata(screen) : void 0;
5175
3977
  }
5176
- function actionMetadataRequiresConfirmation(meta) {
5177
- if (meta.requiresConfirmation === true || meta.destructive === true || meta.effect === "destructive" || meta.riskLevel === "high" || meta.risk === "destructive") {
5178
- return { required: true, label: meta.label, source: "screen-metadata" };
3978
+ function buildAgentContext(extras = {}) {
3979
+ const context = {};
3980
+ context.platform = "react-native";
3981
+ const screen = chunkV3TUIIT2_js.getCurrentScreen();
3982
+ if (screen) context.currentScreen = screen;
3983
+ const navigationState = chunkV3TUIIT2_js.getNavigationStateSnapshot();
3984
+ if (navigationState) context.navigationState = navigationState;
3985
+ const screenMeta = resolveScreenMetadata();
3986
+ if (screenMeta) context.screenMetadata = screenMeta;
3987
+ try {
3988
+ context.snapshot = captureSnapshot();
3989
+ } catch (err) {
3990
+ chunkV3TUIIT2_js.appilotsDebugWarn("buildAgentContext: captureSnapshot failed", err);
3991
+ }
3992
+ const registry = chunkV3TUIIT2_js.componentRegistry.snapshot();
3993
+ const filtered = screen ? registry.filter((c) => !c.screen || c.screen === screen) : registry;
3994
+ if (filtered.length > 0) context.registeredComponents = filtered;
3995
+ const registeredLists = chunkV3TUIIT2_js.listRegistry.snapshot();
3996
+ if (registeredLists.length > 0) {
3997
+ context.registeredLists = registeredLists.map(
3998
+ ({ scrollToIndex, scrollToOffset, getScrollMetrics, dataPreview, ...rest }) => rest
3999
+ );
5179
4000
  }
5180
- return { required: false };
4001
+ if (extras.loadingPending === true) context.loadingPending = true;
4002
+ return context;
5181
4003
  }
5182
- function payloadRequiresConfirmation(action) {
5183
- const payload = readPayload(action);
5184
- if (action.destructive === true || payload.destructive === true || payload.requiresConfirmation === true || isStructuredRisky(payload.effect) || isStructuredRisky(payload.risk) || isStructuredRisky(payload.riskLevel) || isStructuredRisky(payload.actionRisk)) {
5185
- return {
5186
- required: true,
5187
- label: typeof payload.actionDescription === "string" && payload.actionDescription || typeof payload.label === "string" && payload.label || void 0,
5188
- source: "action-policy"
5189
- };
4004
+ function resolveActionHints(screen, pressedComponentId, actionPayload) {
4005
+ if (actionPayload && typeof actionPayload === "object") {
4006
+ const inline = actionPayload._appilotsInferred;
4007
+ if (inline && typeof inline === "object") {
4008
+ return inline;
4009
+ }
5190
4010
  }
5191
- const policy = payload._appilotsPolicy;
5192
- if (policy && typeof policy === "object") {
5193
- const p = policy;
5194
- if (p.requiresConfirmation === true || isStructuredRisky(p.effect) || isStructuredRisky(p.risk) || isStructuredRisky(p.riskLevel)) {
5195
- return {
5196
- required: true,
5197
- label: typeof p.summary === "string" ? p.summary : void 0,
5198
- source: "inline-policy"
5199
- };
4011
+ if (!screen || !pressedComponentId) return void 0;
4012
+ const meta = chunkV3TUIIT2_js.getScreenMetadata(screen);
4013
+ const actions = meta?.actions;
4014
+ if (!actions || actions.length === 0) return void 0;
4015
+ for (const a of actions) {
4016
+ if (typeof a === "string") continue;
4017
+ if (chunkV3TUIIT2_js.idLooselyMatches(a.id, pressedComponentId)) {
4018
+ const inferred = a.appilotsInferred;
4019
+ if (inferred && typeof inferred === "object") return inferred;
4020
+ return void 0;
5200
4021
  }
5201
4022
  }
5202
- return { required: false };
5203
- }
5204
- function isConfirmGateFor(confirm, target) {
5205
- if (confirm.type !== "confirm") return false;
5206
- const payload = readPayload(confirm);
5207
- const injectedBy = payload.injectedBy;
5208
- return payload.gatedActionId === target.id && (injectedBy === "permissions" || injectedBy === "sdk-local");
5209
- }
5210
- function toDestructiveConfirmPayload(confirm, policy, fallbackLabel) {
5211
- const payload = readPayload(confirm);
5212
- const existingDescription = typeof payload.actionDescription === "string" && payload.actionDescription ? payload.actionDescription : void 0;
5213
- const labelText = policy.label ?? existingDescription ?? fallbackLabel ?? "esta a\xE7\xE3o";
5214
- return {
5215
- ...payload,
5216
- title: "A\xE7\xE3o destrutiva",
5217
- message: `Tem certeza que deseja "${labelText}"?`,
5218
- actionDescription: labelText,
5219
- severity: "danger",
5220
- destructive: true,
5221
- confirmLabel: typeof payload.confirmLabel === "string" && payload.confirmLabel ? payload.confirmLabel : "Sim, executar",
5222
- cancelLabel: typeof payload.cancelLabel === "string" && payload.cancelLabel ? payload.cancelLabel : "Cancelar"
5223
- };
5224
- }
5225
- function confirmNeedsDestructiveUpgrade(confirm) {
5226
- const payload = readPayload(confirm);
5227
- return confirm.destructive !== true || payload.destructive !== true || payload.severity !== "danger";
4023
+ return void 0;
5228
4024
  }
5229
- function actionHasCompletedConfirmGate(action, actions) {
5230
- return actions.some((candidate) => {
5231
- if (!isConfirmGateFor(candidate, action)) return false;
5232
- if (candidate.status !== "completed") return false;
5233
- const payload = readPayload(candidate);
5234
- return payload.destructive === true || payload.severity === "danger";
5235
- });
4025
+ async function settleTurn(input) {
4026
+ const toolWithoutEffectIds = /* @__PURE__ */ new Set();
4027
+ let loadingPending = false;
4028
+ const { turnActions, pressedComponentId: pressedId, navigateTargetScreen } = input;
4029
+ const successById = new Map(input.results.map((r) => [r.actionId, r.success]));
4030
+ const typeById = new Map(input.results.map((r) => [r.actionId, r.type]));
4031
+ if (input.hadNavigate) {
4032
+ const settle = await chunkV3TUIIT2_js.waitForScreenSettle({
4033
+ expectingChange: true,
4034
+ fromScreen: input.preNavigateScreen ?? null,
4035
+ fromSignature: input.preNavigateSignature ?? null,
4036
+ targetScreen: navigateTargetScreen,
4037
+ maxMs: 3500
4038
+ });
4039
+ console.log(
4040
+ `[Appilots] settleTurn: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
4041
+ );
4042
+ const navigationMoved = settle.transitioned || chunkV3TUIIT2_js.screenDepartedBaseline(
4043
+ input.preNavigateScreen ?? null,
4044
+ input.preNavigateSignature ?? null
4045
+ ) || !!navigateTargetScreen && !!settle.screen && chunkV3TUIIT2_js.routesBelongToSameFeature(settle.screen, navigateTargetScreen);
4046
+ if (!navigationMoved) {
4047
+ chunkV3TUIIT2_js.appilotsDebugWarn(
4048
+ `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.`
4049
+ );
4050
+ for (const [actionId, type] of typeById) {
4051
+ if (type === "navigate") toolWithoutEffectIds.add(actionId);
4052
+ }
4053
+ }
4054
+ const loadSettle = await chunkV3TUIIT2_js.waitForLoadingSettle({
4055
+ fromScreen: settle.screen ?? null,
4056
+ maxMs: 3e3
4057
+ });
4058
+ console.log(
4059
+ `[Appilots] settleTurn: post-navigate loading settle \u2014 settled=${loadSettle.settled} loadingPending=${loadSettle.loadingPending} probes=${loadSettle.probeCount} waitedMs=${loadSettle.waitedMs}`
4060
+ );
4061
+ if (loadSettle.loadingPending) loadingPending = true;
4062
+ } else {
4063
+ const pressedAction = turnActions.find(
4064
+ (a) => a.type === "ui_interaction" && a.payload?.componentId === pressedId
4065
+ );
4066
+ const hints = resolveActionHints(chunkV3TUIIT2_js.getCurrentScreen(), pressedId, pressedAction?.payload);
4067
+ const settleCapMs = hints?.isAsyncTrigger === true ? 1e4 : POST_ACTION_LOADING_MAX_MS;
4068
+ const loadSettle = await chunkV3TUIIT2_js.waitForLoadingSettle({
4069
+ pressedComponentId: pressedId,
4070
+ fromScreen: chunkV3TUIIT2_js.getCurrentScreen(),
4071
+ maxMs: settleCapMs
4072
+ });
4073
+ console.log(
4074
+ `[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)" : ""}`
4075
+ );
4076
+ if (loadSettle.loadingPending) loadingPending = true;
4077
+ const listPressActions = turnActions.filter((action) => {
4078
+ const target = chunkV3TUIIT2_js.actionPressTargetId(action);
4079
+ return target ? chunkV3TUIIT2_js.isListItemPressTarget(target) : false;
4080
+ });
4081
+ if (listPressActions.length > 0) {
4082
+ const baselineFingerprint = chunkV3TUIIT2_js.probeLoadingState(pressedId, chunkV3TUIIT2_js.getCurrentScreen()).fingerprint;
4083
+ const postPressSettle = await chunkV3TUIIT2_js.waitForScreenSettle({
4084
+ expectingChange: true,
4085
+ fromScreen: input.preNavigateScreen ?? null,
4086
+ fromSignature: input.preNavigateSignature ?? null,
4087
+ maxMs: 2500
4088
+ });
4089
+ await chunkV3TUIIT2_js.waitForLoadingSettle({
4090
+ pressedComponentId: pressedId,
4091
+ fromScreen: chunkV3TUIIT2_js.getCurrentScreen(),
4092
+ maxMs: 4e3
4093
+ });
4094
+ const afterFingerprint = chunkV3TUIIT2_js.probeLoadingState(pressedId, chunkV3TUIIT2_js.getCurrentScreen()).fingerprint;
4095
+ console.log(
4096
+ `[Appilots] settleTurn: post-list-press settle \u2014 screen="${postPressSettle.screen}" transitioned=${postPressSettle.transitioned} timedOut=${postPressSettle.timedOut} waitedMs=${postPressSettle.waitedMs}`
4097
+ );
4098
+ if (!postPressSettle.transitioned && baselineFingerprint === afterFingerprint) {
4099
+ for (const action of listPressActions) {
4100
+ if (successById.get(action.id)) {
4101
+ toolWithoutEffectIds.add(action.id);
4102
+ }
4103
+ }
4104
+ }
4105
+ }
4106
+ }
4107
+ return { loadingPending, toolWithoutEffectIds };
5236
4108
  }
4109
+ var reactNativeChatAdapter = {
4110
+ buildContext: buildAgentContext,
4111
+ getCurrentScreen: chunkV3TUIIT2_js.getCurrentScreen,
4112
+ getCurrentScreenSignature: chunkV3TUIIT2_js.getCurrentScreenSignature,
4113
+ settleTurn
4114
+ };
5237
4115
  async function runWithConfirmedDestructiveContext(enabled, fn) {
5238
4116
  if (!enabled) return fn();
5239
4117
  const originalAlert = reactNative.Alert.alert;
@@ -5263,321 +4141,120 @@ async function runWithConfirmedDestructiveContext(enabled, fn) {
5263
4141
  reactNative.Alert.alert = originalAlert;
5264
4142
  }
5265
4143
  }
5266
- function useAppilotsActions(options = {}) {
5267
- const { client, subscribe, config, emit } = chunkSIBKF7AA_js.useAppilotsContext();
5268
- const [actions, setActions] = react.useState([]);
5269
- const { navigationRef, autoExecute = false } = options;
5270
- const actionsRef = react.useRef([]);
5271
- actionsRef.current = actions;
5272
- const navRefStable = react.useRef(navigationRef);
5273
- navRefStable.current = navigationRef;
5274
- react.useEffect(() => {
5275
- const unsubscribe = subscribe((event) => {
5276
- if (event.type === "agent:action:start") {
5277
- const action = event.data?.action;
5278
- if (!action?.id) return;
5279
- console.log(
5280
- `[Appilots] useAppilotsActions: received agent:action:start event, action id="${action.id}", type="${action.type}"`
5281
- );
5282
- setActions((prev) => {
5283
- if (prev.some((a) => a.id === action.id)) return prev;
5284
- return [...prev, action];
5285
- });
5286
- }
5287
- });
5288
- return unsubscribe;
5289
- }, [subscribe]);
5290
- const processedRef = react.useRef(/* @__PURE__ */ new Set());
5291
- react.useEffect(() => {
5292
- if (!autoExecute) return;
5293
- const pending = actions.filter(
5294
- (a) => a.status === "pending" && !processedRef.current.has(a.id)
5295
- );
5296
- console.log(`[Appilots] useAppilotsActions: autoExecute check \u2014 ${pending.length} pending action(s) to process`);
5297
- const findGatingConfirm = (target) => {
5298
- return actions.find((a) => {
5299
- if (a.type !== "confirm") return false;
5300
- const payload = a.payload;
5301
- const injectedBy = payload?.injectedBy;
5302
- return payload?.gatedActionId === target.id && (injectedBy === "permissions" || injectedBy === "sdk-local");
5303
- });
5304
- };
5305
- const ensureLocalConfirmIfNeeded = (target) => {
5306
- if (target.type !== "ui_interaction") return false;
5307
- const payload = target.payload;
5308
- const componentId = typeof payload?.componentId === "string" && payload.componentId || typeof payload?.targetId === "string" && payload.targetId || "";
5309
- let policy = payloadRequiresConfirmation(target);
5310
- if (!policy.required && componentId) {
5311
- const screen = chunkSIBKF7AA_js.getCurrentScreen();
5312
- const meta = screen ? chunkSIBKF7AA_js.getScreenMetadata(screen) : void 0;
5313
- const actionsMeta = meta?.actions;
5314
- if (actionsMeta && Array.isArray(actionsMeta)) {
5315
- const match = actionsMeta.find((a) => {
5316
- if (typeof a === "string") return false;
5317
- return metadataMatchesComponentId(a.id, componentId);
5318
- });
5319
- if (match && typeof match !== "string") {
5320
- policy = actionMetadataRequiresConfirmation(match);
5321
- }
5322
- }
5323
- }
5324
- const existingGate = findGatingConfirm(target);
5325
- if (existingGate) {
5326
- if (policy.required && confirmNeedsDestructiveUpgrade(existingGate)) {
5327
- setActions(
5328
- (prev) => prev.map(
5329
- (a) => a.id === existingGate.id ? {
5330
- ...a,
5331
- destructive: true,
5332
- payload: toDestructiveConfirmPayload(
5333
- a,
5334
- policy,
5335
- componentId || target.id
5336
- )
5337
- } : a
5338
- )
5339
- );
5340
- }
5341
- return false;
5342
- }
5343
- if (!policy.required) return false;
5344
- const confirmId = `confirm-local-${target.id}`;
5345
- setActions((prev) => {
5346
- const existingGate2 = prev.some((a) => {
5347
- if (a.type !== "confirm") return false;
5348
- const p = a.payload;
5349
- if (!p || p.gatedActionId !== target.id) return false;
5350
- return p.injectedBy === "permissions" || p.injectedBy === "sdk-local";
5351
- });
5352
- if (existingGate2) {
5353
- const gateToUpgrade = prev.find(
5354
- (a) => isConfirmGateFor(a, target) && confirmNeedsDestructiveUpgrade(a)
5355
- );
5356
- if (!gateToUpgrade) return prev;
5357
- return prev.map(
5358
- (a) => a.id === gateToUpgrade.id ? {
5359
- ...a,
5360
- destructive: true,
5361
- payload: toDestructiveConfirmPayload(
5362
- a,
5363
- policy,
5364
- componentId || target.id
5365
- )
5366
- } : a
5367
- );
5368
- }
5369
- if (prev.some((a) => a.id === confirmId)) return prev;
5370
- console.log(
5371
- `[Appilots] useAppilotsActions: action "${componentId || target.id}" requires confirmation (${policy.source ?? "local-policy"}) \u2014 synthesising local confirm (id="${confirmId}")`
5372
- );
5373
- const synth = {
5374
- id: confirmId,
5375
- type: "confirm",
5376
- payload: toDestructiveConfirmPayload(
5377
- {
5378
- payload: {
5379
- gatedActionId: target.id,
5380
- gatedActionType: target.type,
5381
- injectedBy: "sdk-local"
5382
- },
5383
- messageId: target.messageId
5384
- },
5385
- policy,
5386
- componentId || "esta a\xE7\xE3o"
5387
- ),
5388
- status: "pending",
5389
- messageId: target.messageId
5390
- };
5391
- emit({
5392
- type: "agent:action:start",
5393
- timestamp: Date.now(),
5394
- data: { action: synth }
5395
- });
5396
- const idx = prev.findIndex((a) => a.id === target.id);
5397
- if (idx < 0) return [...prev, synth];
5398
- return [...prev.slice(0, idx), synth, ...prev.slice(idx)];
5399
- });
5400
- return true;
5401
- };
5402
- const executeSequentially = async () => {
5403
- let lastWasNavigate = false;
5404
- let preNavScreen = null;
5405
- let preNavSignature = null;
5406
- for (const action of pending) {
5407
- if (action.type === "confirm") {
5408
- continue;
5409
- }
5410
- if (ensureLocalConfirmIfNeeded(action)) {
5411
- continue;
5412
- }
5413
- const gate = findGatingConfirm(action);
5414
- if (gate) {
5415
- if (gate.status === "pending" || gate.status === "executing") {
5416
- console.log(
5417
- `[Appilots] useAppilotsActions: action id="${action.id}" is gated by confirm id="${gate.id}" (status=${gate.status}); waiting for user decision`
5418
- );
5419
- continue;
5420
- }
5421
- if (gate.status === "failed") {
5422
- console.log(
5423
- `[Appilots] useAppilotsActions: confirm id="${gate.id}" was rejected; skipping gated action id="${action.id}"`
5424
- );
5425
- processedRef.current.add(action.id);
5426
- setActions(
5427
- (prev) => prev.map(
5428
- (a) => a.id === action.id ? { ...a, status: "failed", error: "Confirm canceled by user" } : a
5429
- )
5430
- );
5431
- try {
5432
- await client.completeAction(action.id, false, "Confirm canceled by user");
5433
- } catch {
5434
- }
5435
- emit({
5436
- type: "agent:action:error",
5437
- timestamp: Date.now(),
5438
- data: {
5439
- actionId: action.id,
5440
- actionType: action.type,
5441
- success: false,
5442
- error: "Confirm canceled by user"
5443
- }
5444
- });
5445
- continue;
5446
- }
5447
- }
5448
- if (lastWasNavigate) {
5449
- const settle = await chunkSIBKF7AA_js.waitForScreenSettle({
5450
- expectingChange: true,
5451
- fromScreen: preNavScreen,
5452
- fromSignature: preNavSignature,
5453
- maxMs: 3500
5454
- });
5455
- console.log(
5456
- `[Appilots] useAppilotsActions: post-navigate settle done \u2014 screen="${settle.screen}" transitioned=${settle.transitioned} timedOut=${settle.timedOut} waitedMs=${settle.waitedMs}`
5457
- );
5458
- }
5459
- console.log(`[Appilots] useAppilotsActions: auto-executing action id="${action.id}" type="${action.type}"`);
5460
- processedRef.current.add(action.id);
5461
- if (action.type === "navigate") {
5462
- preNavScreen = chunkSIBKF7AA_js.getCurrentScreen();
5463
- preNavSignature = chunkSIBKF7AA_js.getCurrentScreenSignature();
5464
- }
5465
- const succeeded = await approveActionImpl(action.id);
5466
- if (!succeeded) {
5467
- chunkSIBKF7AA_js.appilotsDebugWarn(
5468
- `useAppilotsActions: stopping current action batch after failed action id="${action.id}"`
5469
- );
5470
- break;
5471
- }
5472
- lastWasNavigate = action.type === "navigate";
5473
- }
5474
- };
5475
- void executeSequentially();
5476
- }, [actions, autoExecute]);
5477
- const approveActionImpl = react.useCallback(
5478
- async (actionId) => {
5479
- const action = actionsRef.current.find((a) => a.id === actionId);
5480
- if (!action) return false;
5481
- console.log(`[Appilots] useAppilotsActions: action status transition: pending \u2192 executing (id="${actionId}", type="${action.type}")`);
5482
- setActions(
5483
- (prev) => prev.map((a) => a.id === actionId ? { ...a, status: "executing" } : a)
4144
+ function createReactNativeActionRunner(getOptions) {
4145
+ return {
4146
+ async execute(action, { confirmedDestructive }) {
4147
+ const { permissions, emit, navigationRef } = getOptions();
4148
+ const navRef = navigationRef?.current ? navigationRef : { current: chunkV3TUIIT2_js.getNavigationRef() };
4149
+ return runWithConfirmedDestructiveContext(
4150
+ confirmedDestructive,
4151
+ () => executeAction(action, {
4152
+ navigationRef: navRef,
4153
+ permissions,
4154
+ emit
4155
+ })
5484
4156
  );
5485
- try {
5486
- const navRef = navRefStable.current?.current ? navRefStable.current : { current: chunkSIBKF7AA_js.getNavigationRef() };
5487
- const confirmedDestructive = actionHasCompletedConfirmGate(
5488
- action,
5489
- actionsRef.current
5490
- );
5491
- const result = await runWithConfirmedDestructiveContext(
5492
- confirmedDestructive,
5493
- () => executeAction(
5494
- { ...action, status: "executing" },
5495
- {
5496
- navigationRef: navRef,
5497
- permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
5498
- emit
5499
- }
5500
- )
5501
- );
5502
- if (result.success) {
5503
- console.log(`[Appilots] useAppilotsActions: action status transition: executing \u2192 completed (id="${actionId}", type="${action.type}")`);
5504
- setActions(
5505
- (prev) => prev.map((a) => a.id === actionId ? { ...a, status: "completed" } : a)
5506
- );
5507
- try {
5508
- await client.completeAction(actionId, true);
5509
- } catch {
5510
- }
5511
- return true;
5512
- } else {
5513
- chunkSIBKF7AA_js.appilotsDebugWarn(
5514
- `useAppilotsActions: action status transition: executing \u2192 failed (id="${actionId}", type="${action.type}", error="${result.error}")`
5515
- );
5516
- setActions(
5517
- (prev) => prev.map(
5518
- (a) => a.id === actionId ? { ...a, status: "failed", error: result.error } : a
5519
- )
5520
- );
5521
- try {
5522
- await client.completeAction(
5523
- actionId,
5524
- false,
5525
- result.error,
5526
- result.diagnose
5527
- );
5528
- } catch {
5529
- }
5530
- return false;
5531
- }
5532
- } catch (err) {
5533
- const errorMsg = err instanceof Error ? err.message : "Action failed";
5534
- chunkSIBKF7AA_js.appilotsDebugWarn(
5535
- `useAppilotsActions: action status transition: executing \u2192 failed (exception) (id="${actionId}", error="${errorMsg}")`
5536
- );
5537
- setActions(
5538
- (prev) => prev.map(
5539
- (a) => a.id === actionId ? { ...a, status: "failed", error: errorMsg } : a
5540
- )
5541
- );
5542
- try {
5543
- await client.completeAction(actionId, false, errorMsg);
5544
- } catch {
5545
- }
5546
- return false;
5547
- }
5548
4157
  },
5549
- [client, config.permissions, emit]
5550
- );
5551
- const rejectAction = react.useCallback(
5552
- async (actionId) => {
5553
- setActions(
5554
- (prev) => prev.map(
5555
- (a) => a.id === actionId ? { ...a, status: "failed", error: "Rejected by user" } : a
5556
- )
5557
- );
5558
- const action = actionsRef.current.find((a) => a.id === actionId);
5559
- emit({
5560
- type: "agent:action:error",
5561
- timestamp: Date.now(),
5562
- data: {
5563
- actionId,
5564
- actionType: action?.type,
5565
- success: false,
5566
- error: "Rejected by user"
5567
- }
5568
- });
5569
- try {
5570
- await client.completeAction(actionId, false, "Rejected by user");
5571
- } catch {
5572
- }
4158
+ getCurrentScreen: chunkV3TUIIT2_js.getCurrentScreen,
4159
+ getCurrentScreenSignature: chunkV3TUIIT2_js.getCurrentScreenSignature,
4160
+ getScreenActionsMetadata(screen) {
4161
+ return chunkV3TUIIT2_js.getScreenMetadata(screen)?.actions;
5573
4162
  },
4163
+ waitForScreenSettle: chunkV3TUIIT2_js.waitForScreenSettle
4164
+ };
4165
+ }
4166
+
4167
+ // src/hooks/useAppilotsChat.ts
4168
+ function useAppilotsChat(options = {}) {
4169
+ const { client, emit, subscribe } = chunkV3TUIIT2_js.useAppilotsContext();
4170
+ const machine = react.useMemo(
4171
+ () => new chunkV3TUIIT2_js.ChatSessionMachine(
4172
+ { client, adapter: reactNativeChatAdapter, emit, warn: chunkV3TUIIT2_js.appilotsDebugWarn },
4173
+ options
4174
+ ),
4175
+ // A new machine per client/provider instance — options are pushed in
4176
+ // below so changing copy never resets the transcript.
4177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
4178
+ [client, emit]
4179
+ );
4180
+ const optionsRef = react.useRef(options);
4181
+ optionsRef.current = options;
4182
+ machine.setOptions(options);
4183
+ const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4184
+ react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4185
+ react.useEffect(() => () => machine.dispose(), [machine]);
4186
+ const requestHuman = react.useCallback(
4187
+ (reason) => machine.requestHuman(reason),
4188
+ [machine]
4189
+ );
4190
+ const sendMessage = react.useCallback((content) => machine.sendMessage(content), [machine]);
4191
+ const cancelMessage = react.useCallback(() => machine.cancelMessage(), [machine]);
4192
+ const clearMessages = react.useCallback(() => machine.clearMessages(), [machine]);
4193
+ const clearError = react.useCallback(() => machine.clearError(), [machine]);
4194
+ return {
4195
+ messages: state.messages,
4196
+ isLoading: state.isLoading,
4197
+ loadingStatusKey: state.loadingStatusKey,
4198
+ error: state.error,
4199
+ pendingActions: state.pendingActions,
4200
+ escalation: state.escalation,
4201
+ requestHuman,
4202
+ sendMessage,
4203
+ cancelMessage,
4204
+ clearMessages,
4205
+ clearError
4206
+ };
4207
+ }
4208
+ var DEFAULT_PERMISSIONS2 = {
4209
+ canNavigate: true,
4210
+ canFillForms: true,
4211
+ canInteractUI: true,
4212
+ canSubmitForms: true
4213
+ };
4214
+ function useAppilotsActions(options = {}) {
4215
+ const { client, subscribe, config, emit } = chunkV3TUIIT2_js.useAppilotsContext();
4216
+ const { navigationRef, autoExecute = false } = options;
4217
+ const runnerOptionsRef = react.useRef({
4218
+ permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
4219
+ emit,
4220
+ navigationRef
4221
+ });
4222
+ runnerOptionsRef.current = {
4223
+ permissions: config.permissions ?? DEFAULT_PERMISSIONS2,
4224
+ emit,
4225
+ navigationRef
4226
+ };
4227
+ const machine = react.useMemo(
4228
+ () => new chunkV3TUIIT2_js.ActionQueueMachine(
4229
+ {
4230
+ client,
4231
+ adapter: createReactNativeActionRunner(() => runnerOptionsRef.current),
4232
+ emit,
4233
+ warn: chunkV3TUIIT2_js.appilotsDebugWarn
4234
+ },
4235
+ { autoExecute }
4236
+ ),
4237
+ // eslint-disable-next-line react-hooks/exhaustive-deps
5574
4238
  [client, emit]
5575
4239
  );
4240
+ machine.setOptions({ autoExecute });
4241
+ const state = react.useSyncExternalStore(machine.subscribeState, machine.getState, machine.getState);
4242
+ react.useEffect(() => subscribe(machine.handleEvent), [subscribe, machine]);
4243
+ react.useEffect(() => {
4244
+ if (autoExecute) machine.scheduleDrain();
4245
+ }, [autoExecute, machine, state.actions]);
4246
+ const approveAction = react.useCallback(
4247
+ (actionId) => machine.approveAction(actionId),
4248
+ [machine]
4249
+ );
4250
+ const rejectAction = react.useCallback((actionId) => machine.rejectAction(actionId), [machine]);
5576
4251
  return {
5577
- pendingActions: actions.filter((a) => a.status === "pending"),
5578
- executingActions: actions.filter((a) => a.status === "executing"),
5579
- completedActions: actions.filter((a) => a.status === "completed" || a.status === "failed"),
5580
- approveAction: approveActionImpl,
4252
+ pendingActions: state.actions.filter((a) => a.status === "pending"),
4253
+ executingActions: state.actions.filter((a) => a.status === "executing"),
4254
+ completedActions: state.actions.filter(
4255
+ (a) => a.status === "completed" || a.status === "failed"
4256
+ ),
4257
+ approveAction,
5581
4258
  rejectAction
5582
4259
  };
5583
4260
  }
@@ -5610,7 +4287,7 @@ function shouldShowSuggestedPrompts(args) {
5610
4287
 
5611
4288
  // src/hooks/useSuggestedPrompts.ts
5612
4289
  function useSuggestedPrompts(options) {
5613
- const { client } = chunkSIBKF7AA_js.useAppilotsContext();
4290
+ const { client } = chunkV3TUIIT2_js.useAppilotsContext();
5614
4291
  const { enabled, limit = 4 } = options;
5615
4292
  const [prompts, setPrompts] = react.useState([]);
5616
4293
  const [isLoading, setIsLoading] = react.useState(false);
@@ -5620,8 +4297,8 @@ function useSuggestedPrompts(options) {
5620
4297
  if (!enabled) return;
5621
4298
  const requestId = ++requestIdRef.current;
5622
4299
  let cancelled = false;
5623
- const screen = chunkSIBKF7AA_js.getCurrentScreen() ?? void 0;
5624
- const localDev = screen ? (chunkSIBKF7AA_js.getScreenMetadata(screen)?.suggestedPrompts ?? []).map((text) => ({
4300
+ const screen = chunkV3TUIIT2_js.getCurrentScreen() ?? void 0;
4301
+ const localDev = screen ? (chunkV3TUIIT2_js.getScreenMetadata(screen)?.suggestedPrompts ?? []).map((text) => ({
5625
4302
  text,
5626
4303
  source: "dev-defined"
5627
4304
  })) : [];
@@ -5646,9 +4323,9 @@ function useSuggestedPrompts(options) {
5646
4323
  }, [client, enabled, limit, refreshTick]);
5647
4324
  react.useEffect(() => {
5648
4325
  if (!enabled) return;
5649
- let lastScreen = chunkSIBKF7AA_js.getCurrentScreen();
4326
+ let lastScreen = chunkV3TUIIT2_js.getCurrentScreen();
5650
4327
  const interval = setInterval(() => {
5651
- const current = chunkSIBKF7AA_js.getCurrentScreen();
4328
+ const current = chunkV3TUIIT2_js.getCurrentScreen();
5652
4329
  if (current !== lastScreen) {
5653
4330
  lastScreen = current;
5654
4331
  setRefreshTick((t) => t + 1);
@@ -5663,14 +4340,14 @@ function useSuggestedPrompts(options) {
5663
4340
  };
5664
4341
  }
5665
4342
  function useAppilotsNavigation() {
5666
- const { emit } = chunkSIBKF7AA_js.useAppilotsContext();
4343
+ const { emit } = chunkV3TUIIT2_js.useAppilotsContext();
5667
4344
  const [currentScreen, setCurrentScreenState] = react.useState(null);
5668
4345
  const [navigationHistory, setNavigationHistory] = react.useState([]);
5669
4346
  const navigationRef = react.useRef(null);
5670
4347
  const setCurrentScreen2 = react.useCallback(
5671
4348
  (screenName) => {
5672
4349
  setCurrentScreenState(screenName);
5673
- chunkSIBKF7AA_js.setCurrentScreen(screenName);
4350
+ chunkV3TUIIT2_js.setCurrentScreen(screenName);
5674
4351
  setNavigationHistory((prev) => [...prev, screenName]);
5675
4352
  emit({
5676
4353
  type: "navigation:change",
@@ -5701,7 +4378,7 @@ function useAppilotsNavigation() {
5701
4378
 
5702
4379
  // src/hooks/useAppilots.ts
5703
4380
  function useAppilots() {
5704
- const { config, client } = chunkSIBKF7AA_js.useAppilotsContext();
4381
+ const { config, client } = chunkV3TUIIT2_js.useAppilotsContext();
5705
4382
  const chat = useAppilotsChat();
5706
4383
  const navigation = useAppilotsNavigation();
5707
4384
  const actions = useAppilotsActions();
@@ -5730,7 +4407,7 @@ function useAppilots() {
5730
4407
  }
5731
4408
  function useAppilotsField(id, options) {
5732
4409
  const { value, onChangeText, ref, fieldType, label, screen } = options;
5733
- const registry = chunkSIBKF7AA_js.useResolvedRegistry();
4410
+ const registry = chunkV3TUIIT2_js.useResolvedRegistry();
5734
4411
  const valueRef = react.useRef(value);
5735
4412
  const onChangeRef = react.useRef(onChangeText);
5736
4413
  valueRef.current = value;
@@ -5758,7 +4435,7 @@ function useAppilotsField(id, options) {
5758
4435
  }
5759
4436
  function useAppilotsTarget(id, options) {
5760
4437
  const { onPress, onLongPress, onScrollTo, label, screen } = options;
5761
- const registry = chunkSIBKF7AA_js.useResolvedRegistry();
4438
+ const registry = chunkV3TUIIT2_js.useResolvedRegistry();
5762
4439
  const onPressRef = react.useRef(onPress);
5763
4440
  const onLongPressRef = react.useRef(onLongPress);
5764
4441
  const onScrollToRef = react.useRef(onScrollTo);
@@ -5785,7 +4462,7 @@ function useAppilotsTarget(id, options) {
5785
4462
  }
5786
4463
  function useAppilotsToggle(id, options) {
5787
4464
  const { value, onValueChange, label, screen } = options;
5788
- const registry = chunkSIBKF7AA_js.useResolvedRegistry();
4465
+ const registry = chunkV3TUIIT2_js.useResolvedRegistry();
5789
4466
  const valueRef = react.useRef(value);
5790
4467
  const onChangeRef = react.useRef(onValueChange);
5791
4468
  valueRef.current = value;
@@ -5808,7 +4485,7 @@ function useAppilotsToggle(id, options) {
5808
4485
  }
5809
4486
  function useAppilotsSlider(id, options) {
5810
4487
  const { value, onValueChange, min, max, step, label, screen } = options;
5811
- const registry = chunkSIBKF7AA_js.useResolvedRegistry();
4488
+ const registry = chunkV3TUIIT2_js.useResolvedRegistry();
5812
4489
  const valueRef = react.useRef(value);
5813
4490
  const onChangeRef = react.useRef(onValueChange);
5814
4491
  valueRef.current = value;