@appilots/sdk 0.13.0 → 0.14.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,5 +1,5 @@
1
1
  {
2
- "sourceHash": "1f64a760bbfbeb0a",
3
- "gitSha": "3ad9efcac370eee38bf12ad76fda10bfd2e1e482",
4
- "builtAt": "2026-09-24T22:22:24.138Z"
2
+ "sourceHash": "50ebfc923d19527d",
3
+ "gitSha": "d4cb61e26667dffb8f7fa9ad46b18914e06866d6",
4
+ "builtAt": "2026-09-27T06:35:27.818Z"
5
5
  }
@@ -1,4 +1,4 @@
1
- import { createSnapshotDeltaTracker, normalizeAppilotsLocale, getFiberRoot, appilotsDebugWarn, recordIntrospectionFailure, getCurrentScreen, walkFiber, getActiveRouteNames, clampSnapshotToWireLimits, deriveInteractionElements, rectForNode, toWireElement, attachElementIdsToChoiceGroups, elementRegistry, appilotsDebugLog, getLastWalkDiagnostics, SDK_VERSION, geometryStats, geometryAvailability, getNameManglingProbe, emptyDetectorCounts, getAutoTrackingState, getIntrospectionDiagnostics, getGeometryHost, isRectOnScreen, listRegistry, resolveAgentPermissions, getDefaultRegistry, useAppilotsContext, ChatSessionMachine, getCurrentScreenSignature, ActionQueueMachine, getScreenMetadata, setCurrentScreen, useResolvedRegistry, totalDetectorHits, getOpenNativeDialog, componentRegistry, permissionDeniedMessage, probeLoadingState, getLastAnsweredNativeDialog, isListItemPressTarget, waitForLoadingSettle, describeValue, waitForScreenSettle, screenDepartedBaseline, routesBelongToSameFeature, actionPressTargetId, getNavigationStateSnapshot, getNavigationRef, isOptionalStepAutomationFailure, OPTIONAL_STEP_AUTOMATION_HINT, isSourceControlId, resolveTarget, isSwitchLike, sourceControlTarget, rectOfFiber, idLooselyMatches, normalize3, matchScore, FORM_VALIDATION_TEXT_RE, parseStableElementId, shouldSkipSubtree, isAlwaysListContainer, isHeuristicListContainer, findListItems, getTypeName, foldForCompare, isModalFiber, sourceControlId, endTextInputEditing, switchValue, getAllScreens, snapshotShowsOpenCreateForm, isReferenceable, looksDestructiveActionLabel, isGenericSelectValue, SUBMIT_CONTROL_RE, isVisibleValidationText, FORM_WRITE_SUCCESS_TEXT_RE, TOUCHABLE_NAMES } from './chunk-HRWBK35Y.mjs';
1
+ import { createSnapshotDeltaTracker, normalizeAppilotsLocale, getFiberRoot, appilotsDebugWarn, recordIntrospectionFailure, getCurrentScreen, walkFiber, getActiveRouteNames, clampSnapshotToWireLimits, deriveInteractionElements, rectForNode, toWireElement, attachElementIdsToChoiceGroups, elementRegistry, appilotsDebugLog, getLastWalkDiagnostics, SDK_VERSION, geometryStats, geometryAvailability, getNameManglingProbe, emptyDetectorCounts, getAutoTrackingState, getIntrospectionDiagnostics, getGeometryHost, isRectOnScreen, listRegistry, resolveAgentPermissions, getDefaultRegistry, useAppilotsContext, ChatSessionMachine, getCurrentScreenSignature, ActionQueueMachine, getScreenMetadata, setCurrentScreen, useResolvedRegistry, totalDetectorHits, getOpenNativeDialog, componentRegistry, permissionDeniedMessage, probeLoadingState, getLastAnsweredNativeDialog, isListItemPressTarget, waitForLoadingSettle, describeValue, waitForScreenSettle, screenDepartedBaseline, routesBelongToSameFeature, actionPressTargetId, getNavigationStateSnapshot, getNavigationRef, isOptionalStepAutomationFailure, OPTIONAL_STEP_AUTOMATION_HINT, isSourceControlId, resolveTarget, isSwitchLike, sourceControlTarget, rectOfFiber, idLooselyMatches, normalize3, matchScore, FORM_VALIDATION_TEXT_RE, parseStableElementId, shouldSkipSubtree, isAlwaysListContainer, isHeuristicListContainer, findListItems, getTypeName, foldForCompare, isModalFiber, sourceControlId, endTextInputEditing, switchValue, getAllScreens, snapshotShowsOpenCreateForm, isReferenceable, looksDestructiveActionLabel, isAppilotsSensitiveMarked, isGenericSelectValue, SUBMIT_CONTROL_RE, isVisibleValidationText, FORM_WRITE_SUCCESS_TEXT_RE, TOUCHABLE_NAMES } from './chunk-AKAMWKO6.mjs';
2
2
  import React, { createContext, useMemo, useContext, useRef, useSyncExternalStore, useEffect, useCallback, useState } from 'react';
3
3
  import { Platform, NativeModules, AppState, Alert } from 'react-native';
4
4
 
@@ -13,6 +13,7 @@ var ptBR = {
13
13
  statusAnalyzing: "Analisando a tela...",
14
14
  statusWaitingApp: "Aguardando o app responder...",
15
15
  statusAdjusting: "Ajustando o plano...",
16
+ stillWorking: "Ainda trabalhando\u2026 {seconds} s",
16
17
  poweredBy: "Powered by Appilots",
17
18
  approve: "Aprovar",
18
19
  reject: "Rejeitar",
@@ -24,6 +25,7 @@ var ptBR = {
24
25
  confirmApprove: "Confirmar",
25
26
  confirmCancel: "Cancelar",
26
27
  confirmThisAction: "esta a\xE7\xE3o",
28
+ confirmExpired: "Esta confirma\xE7\xE3o expirou. Pe\xE7a de novo ao assistente para continuar.",
27
29
  unknownAction: "A\xE7\xE3o desconhecida",
28
30
  somethingWentWrong: "Algo deu errado",
29
31
  openChatA11y: "Abrir chat do assistente",
@@ -46,6 +48,8 @@ var ptBR = {
46
48
  missionCancel: "Cancelar tarefa",
47
49
  missionPaused: "Pausada",
48
50
  pillDone: "Pronto \u2014 toque para ver",
51
+ a11yAwaitingApproval: "O assistente precisa da sua confirma\xE7\xE3o para continuar.",
52
+ a11yTurnDone: "O assistente terminou.",
49
53
  micStartA11y: "Segurar para falar",
50
54
  micStopA11y: "Soltar para enviar",
51
55
  micListening: "Ouvindo..."
@@ -62,6 +66,7 @@ var en = {
62
66
  statusAnalyzing: "Reading the screen...",
63
67
  statusWaitingApp: "Waiting for the app...",
64
68
  statusAdjusting: "Adjusting the plan...",
69
+ stillWorking: "Still working\u2026 {seconds} s",
65
70
  poweredBy: "Powered by Appilots",
66
71
  approve: "Approve",
67
72
  reject: "Reject",
@@ -73,6 +78,7 @@ var en = {
73
78
  confirmApprove: "Confirm",
74
79
  confirmCancel: "Cancel",
75
80
  confirmThisAction: "this action",
81
+ confirmExpired: "This confirmation expired. Ask the assistant again to continue.",
76
82
  unknownAction: "Unknown action",
77
83
  somethingWentWrong: "Something went wrong",
78
84
  openChatA11y: "Open assistant chat",
@@ -95,6 +101,8 @@ var en = {
95
101
  missionCancel: "Cancel task",
96
102
  missionPaused: "Paused",
97
103
  pillDone: "Done \u2014 tap to read",
104
+ a11yAwaitingApproval: "The assistant needs your confirmation to continue.",
105
+ a11yTurnDone: "The assistant finished.",
98
106
  micStartA11y: "Hold to talk",
99
107
  micStopA11y: "Release to send",
100
108
  micListening: "Listening..."
@@ -111,6 +119,7 @@ var es = {
111
119
  statusAnalyzing: "Analizando la pantalla...",
112
120
  statusWaitingApp: "Esperando a la app...",
113
121
  statusAdjusting: "Ajustando el plan...",
122
+ stillWorking: "Sigo trabajando\u2026 {seconds} s",
114
123
  poweredBy: "Hecho con Appilots",
115
124
  approve: "Aprobar",
116
125
  reject: "Rechazar",
@@ -122,6 +131,7 @@ var es = {
122
131
  confirmApprove: "Confirmar",
123
132
  confirmCancel: "Cancelar",
124
133
  confirmThisAction: "esta acci\xF3n",
134
+ confirmExpired: "Esta confirmaci\xF3n expir\xF3. Pide de nuevo al asistente para continuar.",
125
135
  unknownAction: "Acci\xF3n desconocida",
126
136
  somethingWentWrong: "Algo sali\xF3 mal",
127
137
  openChatA11y: "Abrir chat del asistente",
@@ -144,6 +154,8 @@ var es = {
144
154
  missionCancel: "Cancelar tarea",
145
155
  missionPaused: "Pausada",
146
156
  pillDone: "Listo \u2014 toca para ver",
157
+ a11yAwaitingApproval: "El asistente necesita tu confirmaci\xF3n para continuar.",
158
+ a11yTurnDone: "El asistente termin\xF3.",
147
159
  micStartA11y: "Mantener para hablar",
148
160
  micStopA11y: "Soltar para enviar",
149
161
  micListening: "Escuchando..."
@@ -160,6 +172,7 @@ var fr = {
160
172
  statusAnalyzing: "Lecture de l\u2019\xE9cran\u2026",
161
173
  statusWaitingApp: "En attente de l\u2019application\u2026",
162
174
  statusAdjusting: "Ajustement du plan\u2026",
175
+ stillWorking: "Toujours en cours\u2026 {seconds} s",
163
176
  poweredBy: "Propuls\xE9 par Appilots",
164
177
  approve: "Approuver",
165
178
  reject: "Refuser",
@@ -171,6 +184,7 @@ var fr = {
171
184
  confirmApprove: "Confirmer",
172
185
  confirmCancel: "Annuler",
173
186
  confirmThisAction: "cette action",
187
+ confirmExpired: "Cette confirmation a expir\xE9. Redemandez \xE0 l\u2019assistant pour continuer.",
174
188
  unknownAction: "Action inconnue",
175
189
  somethingWentWrong: "Une erreur est survenue",
176
190
  openChatA11y: "Ouvrir la conversation avec l\u2019assistant",
@@ -193,6 +207,8 @@ var fr = {
193
207
  missionCancel: "Annuler la t\xE2che",
194
208
  missionPaused: "En pause",
195
209
  pillDone: "Termin\xE9 \u2014 touchez pour lire",
210
+ a11yAwaitingApproval: "L\u2019assistant a besoin de votre confirmation pour continuer.",
211
+ a11yTurnDone: "L\u2019assistant a termin\xE9.",
196
212
  micStartA11y: "Maintenez pour parler",
197
213
  micStopA11y: "Rel\xE2chez pour envoyer",
198
214
  micListening: "\xC9coute en cours\u2026"
@@ -701,6 +717,9 @@ function shouldSkipSubtree2(fiber) {
701
717
  }
702
718
  return false;
703
719
  }
720
+ function isSecureInput(props) {
721
+ return !!props.secureTextEntry || isAppilotsSensitiveMarked(props);
722
+ }
704
723
  var normalize = foldForCompare;
705
724
  function scoreMatchDetail(fiber, queryNorm, queryRaw) {
706
725
  const props = fiber.memoizedProps ?? {};
@@ -722,14 +741,20 @@ function scoreMatchDetail(fiber, queryNorm, queryRaw) {
722
741
  if (childText) candidates.push({ val: childText, weight: 80 });
723
742
  }
724
743
  let best = 0;
744
+ let exact = false;
725
745
  for (const { val, weight } of candidates) {
726
746
  const vNorm = normalize(val);
727
747
  if (!vNorm) continue;
728
- if (val === queryRaw) best = Math.max(best, weight + 20);
729
- else if (vNorm === queryNorm) best = Math.max(best, weight + 10);
730
- else if (!isPositionalControlId(queryRaw) && queryNorm && (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)))
748
+ if (val === queryRaw) {
749
+ best = Math.max(best, weight + 20);
750
+ exact = true;
751
+ } else if (vNorm === queryNorm) {
752
+ best = Math.max(best, weight + 10);
753
+ exact = true;
754
+ } else if (!isPositionalControlId(queryRaw) && queryNorm && (vNorm.includes(queryNorm) || queryNorm.includes(vNorm)))
731
755
  best = Math.max(best, weight - 20);
732
756
  }
757
+ if (!exact && isSecureInput(props)) best = 0;
733
758
  const named = best >= IDENTITY_MATCH_SCORE;
734
759
  const disabledProp = props.disabled === true || props.editable === false || props.readOnly === true;
735
760
  const disabledA11y = typeof props.accessibilityState === "object" && props.accessibilityState !== null && props.accessibilityState.disabled === true;
@@ -928,6 +953,7 @@ function findInteractiveByIdentifier(query, options = {}) {
928
953
 
929
954
  // src/introspection/spotlightTarget.ts
930
955
  var listeners = /* @__PURE__ */ new Set();
956
+ var announcementListeners = /* @__PURE__ */ new Set();
931
957
  var current = null;
932
958
  var seq = 0;
933
959
  var expiry = null;
@@ -942,7 +968,8 @@ function getSpotlightMode() {
942
968
  function emit() {
943
969
  for (const listener of listeners) listener(current);
944
970
  }
945
- function setSpotlightTarget(rect, label) {
971
+ function setSpotlightTarget(rect, label, verb) {
972
+ if (label && verb) for (const listener of announcementListeners) listener(label, verb);
946
973
  if (expiry) {
947
974
  clearTimeout(expiry);
948
975
  expiry = null;
@@ -976,6 +1003,12 @@ function subscribeSpotlight(listener) {
976
1003
  listeners.delete(listener);
977
1004
  };
978
1005
  }
1006
+ function subscribeSpotlightAnnouncement(listener) {
1007
+ announcementListeners.add(listener);
1008
+ return () => {
1009
+ announcementListeners.delete(listener);
1010
+ };
1011
+ }
979
1012
 
980
1013
  // src/introspection/scrollIntoView.ts
981
1014
  var REVEAL_MARGIN = 24;
@@ -1913,10 +1946,11 @@ function dispatchFiberTarget(targetId, action) {
1913
1946
  };
1914
1947
  }
1915
1948
  const measured = handle.measure?.() ?? null;
1949
+ const verb = action === "scroll" ? void 0 : action === "toggle" || action === "focus" ? action : "press";
1916
1950
  if (measured && getSpotlightMode() === "guided") {
1917
- setSpotlightTarget(revealTarget(measured).rect, handle.label);
1951
+ setSpotlightTarget(revealTarget(measured).rect, handle.label, verb);
1918
1952
  } else {
1919
- setSpotlightTarget(measured, handle.label);
1953
+ setSpotlightTarget(measured, handle.label, verb);
1920
1954
  }
1921
1955
  try {
1922
1956
  if (isPressLike(action) && handle.kind === "target" && handle.press) {
@@ -2183,19 +2217,9 @@ function collectKnownFormFields(registry) {
2183
2217
  }
2184
2218
  return registryFields;
2185
2219
  }
2186
- function isMisplacedFieldId(fieldId, knownIds) {
2220
+ function isMisplacedFieldId(fieldId) {
2187
2221
  const trimmed = fieldId.trim();
2188
- if (!trimmed) return true;
2189
- if (LIST_ORDINAL_RE.test(trimmed)) return true;
2190
- if (/^\d+$/.test(trimmed)) return true;
2191
- const normalized = normalize4(trimmed);
2192
- if (knownIds.has(normalized)) return false;
2193
- for (const known of knownIds) {
2194
- if (known.length >= 4 && (known.includes(normalized) || normalized.includes(known))) {
2195
- return false;
2196
- }
2197
- }
2198
- return true;
2222
+ return !trimmed || LIST_ORDINAL_RE.test(trimmed) || /^\d+$/.test(trimmed);
2199
2223
  }
2200
2224
  function valueMatchesOption(field, rawValue) {
2201
2225
  const value = normalize4(String(rawValue ?? ""));
@@ -2252,6 +2276,7 @@ function fieldTypeMatchesShape(field, shape) {
2252
2276
  function fieldAcceptsFreeText(field, shape) {
2253
2277
  const type = normalize4(field.type ?? "text");
2254
2278
  if (CHOICE_FIELD_TYPES.has(type)) return false;
2279
+ if (type === "password") return false;
2255
2280
  if (NUMERIC_FIELD_TYPES.has(type)) return shape === "number";
2256
2281
  if (DATE_FIELD_TYPES.has(type)) return shape === "date";
2257
2282
  if (EMAIL_FIELD_TYPES.has(type)) return shape === "email";
@@ -2272,12 +2297,11 @@ function inferFieldIdForValue(rawValue, fields, used) {
2272
2297
  function rewriteMisplacedFormFillFields(fields, registry) {
2273
2298
  const knownFields = collectKnownFormFields(registry);
2274
2299
  if (knownFields.length === 0) return fields;
2275
- const knownIds = new Set(knownFields.map((field) => normalize4(field.id)));
2276
- const needsRewrite = fields.some((field) => isMisplacedFieldId(field.fieldId, knownIds));
2300
+ const needsRewrite = fields.some((field) => isMisplacedFieldId(field.fieldId));
2277
2301
  if (!needsRewrite) return fields;
2278
2302
  const used = /* @__PURE__ */ new Set();
2279
2303
  return fields.map((field) => {
2280
- if (!isMisplacedFieldId(field.fieldId, knownIds)) {
2304
+ if (!isMisplacedFieldId(field.fieldId)) {
2281
2305
  used.add(field.fieldId);
2282
2306
  return field;
2283
2307
  }
@@ -3446,6 +3470,10 @@ function findField(fieldId, registry) {
3446
3470
  return registry.getField(comp.id);
3447
3471
  }
3448
3472
  }
3473
+ if (findInteractiveByIdentifier(fieldId, { kind: "field", minScore: IDENTITY_MATCH_SCORE })) {
3474
+ appilotsDebugLog(`findField: "${fieldId}" names a live input \u2014 not guessing in the registry`);
3475
+ return void 0;
3476
+ }
3449
3477
  const currentScreenForTieBreak = getCurrentScreen();
3450
3478
  const needle = normalize3(fieldId);
3451
3479
  let bestComp;
@@ -3842,7 +3870,7 @@ async function formFillHandler(payload, context) {
3842
3870
  allSuccess = false;
3843
3871
  continue;
3844
3872
  }
3845
- setSpotlightTarget(handle.measure?.() ?? null, handle.label);
3873
+ setSpotlightTarget(handle.measure?.() ?? null, handle.label, "fill");
3846
3874
  handle.focus?.();
3847
3875
  handle.setValue(value);
3848
3876
  if (handle.kind === "field" && !await completeTextEdit(fieldId, value, void 0, handle)) {
@@ -5255,4 +5283,4 @@ function useAppilotsSlider(id, options) {
5255
5283
  return useAppilotsElementProps(id);
5256
5284
  }
5257
5285
 
5258
- export { AppilotsI18nProvider, REVEAL_MARGIN, SPOTLIGHT_TTL_MS, appilotsSelfCheck, captureSnapshot, detectDeviceLocale, executeAction, getSpotlightMode, getSpotlightTarget, offsetToReveal, resolveLocale, revealTarget, setSpotlightMode, setSpotlightTarget, shouldShowSuggestedPrompts, subscribeSpotlight, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsI18n, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts };
5286
+ export { AppilotsI18nProvider, REVEAL_MARGIN, SPOTLIGHT_TTL_MS, appilotsSelfCheck, captureSnapshot, detectDeviceLocale, executeAction, getSpotlightMode, getSpotlightTarget, offsetToReveal, resolveLocale, revealTarget, setSpotlightMode, setSpotlightTarget, shouldShowSuggestedPrompts, subscribeSpotlight, subscribeSpotlightAnnouncement, useAppilots, useAppilotsActions, useAppilotsChat, useAppilotsField, useAppilotsI18n, useAppilotsNavigation, useAppilotsSlider, useAppilotsTarget, useAppilotsToggle, useSuggestedPrompts };
@@ -4592,18 +4592,27 @@ var WRITE_SUCCESS = {
4592
4592
  "a\\s+[e\xE9]t[e\xE9]\\s+(?:enregistr|cr[e\xE9]|ajout|sauvegard)[e\xE9]e?"
4593
4593
  ]
4594
4594
  };
4595
+ var SENTENCE_START = "(?:^|[.!?:;*\\n]\\s*)";
4595
4596
  var COMPLETION_CLAIM = {
4596
4597
  pt: [
4597
4598
  "j[a\xE1]\\s+(?:cadastrei|registrei|salvei|criei)",
4598
4599
  "conclu[i\xED]\\s+o\\s+cadastro",
4599
- "cadastro\\s+(?:foi\\s+)?(?:conclu[i\xED]do|realizado|feito)"
4600
+ "cadastro\\s+(?:foi\\s+)?(?:conclu[i\xED]do|realizado|feito)",
4601
+ `${SENTENCE_START}(?:eu\\s+)?(?:cadastrei|registrei|salvei|criei|adicionei|enviei)\\b`
4600
4602
  ],
4601
4603
  en: [
4602
4604
  "i(?:'|\u2019)?ve\\s+(?:registered|saved|created|added)",
4603
- "i\\s+have\\s+(?:registered|saved|created|added)"
4605
+ "i\\s+have\\s+(?:registered|saved|created|added)",
4606
+ `${SENTENCE_START}i\\s+(?:registered|saved|created|added|submitted)\\b`
4604
4607
  ],
4605
- es: ["ya\\s+(?:lo\\s+|la\\s+)?(?:registr[e\xE9]|guard[e\xE9]|cre[e\xE9])"],
4606
- fr: ["j(?:e\\s+l(?:'|\u2019)ai|(?:'|\u2019)ai)\\s+(?:enregistr|cr[e\xE9]|ajout|sauvegard)[e\xE9]"]
4608
+ es: [
4609
+ "ya\\s+(?:lo\\s+|la\\s+)?(?:registr[e\xE9]|guard[e\xE9]|cre[e\xE9])",
4610
+ `${SENTENCE_START}(?:ya\\s+)?he\\s+(?:registrado|guardado|creado|enviado|a[\xF1n]adido)\\b`
4611
+ ],
4612
+ fr: [
4613
+ "j(?:e\\s+l(?:'|\u2019)ai|(?:'|\u2019)ai)\\s+(?:enregistr|cr[e\xE9]|ajout|sauvegard)[e\xE9]",
4614
+ `${SENTENCE_START}c(?:'|\u2019)est\\s+(?:enregistr|cr[e\xE9]|ajout|sauvegard)[e\xE9]`
4615
+ ]
4607
4616
  };
4608
4617
  var SUBMIT_CONTROL = {
4609
4618
  pt: ["cadastrar", "registrar", "salvar", "enviar", "confirmar"],
@@ -4738,6 +4747,7 @@ var AppilotsClient = class {
4738
4747
  mcpVersion;
4739
4748
  introspectionReporter;
4740
4749
  user;
4750
+ plainLanguage;
4741
4751
  sessionId = null;
4742
4752
  mission = null;
4743
4753
  missionDispatchPaused = false;
@@ -4756,6 +4766,7 @@ var AppilotsClient = class {
4756
4766
  this.mcpVersion = options.mcpVersion;
4757
4767
  this.introspectionReporter = options.introspectionReporter;
4758
4768
  this.user = options.user;
4769
+ this.plainLanguage = options.plainLanguage;
4759
4770
  this.headers = {
4760
4771
  "Content-Type": "application/json",
4761
4772
  // Version telemetry: lets the server correlate behavior per SDK
@@ -4905,6 +4916,19 @@ var AppilotsClient = class {
4905
4916
  return {};
4906
4917
  }
4907
4918
  }
4919
+ /**
4920
+ * Per-session plain-language override — e.g. from the signed-in user's
4921
+ * accessibility profile. `undefined` hands the decision back to the
4922
+ * project setting. Applies from the next request on.
4923
+ */
4924
+ setPlainLanguage(value) {
4925
+ this.plainLanguage = value;
4926
+ }
4927
+ /** Every relay-bound context carries the reply-style preference. */
4928
+ withPreferences(context) {
4929
+ if (this.plainLanguage === void 0) return context;
4930
+ return { ...context ?? {}, plainLanguage: this.plainLanguage };
4931
+ }
4908
4932
  // ── Messages ──────────────────────────────────────────────────
4909
4933
  async sendMessage(content, context) {
4910
4934
  if (this.sessionStorage && !this.sessionId) await this.loadStoredSession();
@@ -4918,7 +4942,7 @@ var AppilotsClient = class {
4918
4942
  body: JSON.stringify({
4919
4943
  content,
4920
4944
  sessionId: this.sessionId,
4921
- context,
4945
+ context: this.withPreferences(context),
4922
4946
  // Optional MCP version bundled with this app build. Server
4923
4947
  // compares vs the active MCP doc to detect stale uploads.
4924
4948
  ...this.mcpVersion ? { mcpVersion: this.mcpVersion } : {},
@@ -5183,7 +5207,7 @@ var AppilotsClient = class {
5183
5207
  JSON.stringify({
5184
5208
  content,
5185
5209
  sessionId: this.sessionId,
5186
- context,
5210
+ context: this.withPreferences(context),
5187
5211
  ...this.mcpVersion ? { mcpVersion: this.mcpVersion } : {},
5188
5212
  ...this.introspectionFragment()
5189
5213
  })
@@ -5202,7 +5226,9 @@ var AppilotsClient = class {
5202
5226
  body: JSON.stringify({
5203
5227
  sessionId: this.sessionId,
5204
5228
  results,
5205
- context: this.mission ? { ...context, missionProtocol: 1, missionId: this.mission.scope.id } : context,
5229
+ context: this.withPreferences(
5230
+ this.mission ? { ...context, missionProtocol: 1, missionId: this.mission.scope.id } : context
5231
+ ),
5206
5232
  hop
5207
5233
  })
5208
5234
  },
@@ -5290,7 +5316,7 @@ var AppilotsClient = class {
5290
5316
  body: JSON.stringify({
5291
5317
  command,
5292
5318
  missionId: this.mission.scope.id,
5293
- context
5319
+ context: this.withPreferences(context)
5294
5320
  })
5295
5321
  });
5296
5322
  if (command === "resume") this.missionDispatchPaused = false;
@@ -5677,6 +5703,11 @@ var AppilotsClient = class {
5677
5703
  };
5678
5704
  }
5679
5705
  };
5706
+ function isSpeechHost(value) {
5707
+ if (!value || typeof value !== "object") return false;
5708
+ const candidate = value;
5709
+ return typeof candidate.start === "function" && typeof candidate.stop === "function" && typeof candidate.cancel === "function";
5710
+ }
5680
5711
  var defaultLightTheme = {
5681
5712
  colors: {
5682
5713
  primary: "#6366f1",
@@ -6937,6 +6968,10 @@ function actionHasCompletedConfirmGate(action, actions) {
6937
6968
  return payload.destructive === true || payload.severity === "danger";
6938
6969
  });
6939
6970
  }
6971
+ function confirmExpiresAt(confirm) {
6972
+ const scope = readPayload(confirm).missionApproval;
6973
+ return typeof scope?.expiresAt === "number" ? scope.expiresAt : void 0;
6974
+ }
6940
6975
  var ActionQueueMachine = class {
6941
6976
  deps;
6942
6977
  options;
@@ -7442,6 +7477,17 @@ var ActionQueueMachine = class {
7442
7477
  return this.state.actions.filter((a) => a.status === "completed" || a.status === "failed");
7443
7478
  }
7444
7479
  };
7480
+ var STILL_WORKING_FIRST_MS = 1e4;
7481
+ var STILL_WORKING_EVERY_MS = 2e4;
7482
+ function startStillWorkingTimer(onTick) {
7483
+ let elapsedMs = STILL_WORKING_FIRST_MS;
7484
+ let timer = setTimeout(function tick() {
7485
+ onTick(Math.round(elapsedMs / 1e3));
7486
+ elapsedMs += STILL_WORKING_EVERY_MS;
7487
+ timer = setTimeout(tick, STILL_WORKING_EVERY_MS);
7488
+ }, STILL_WORKING_FIRST_MS);
7489
+ return () => clearTimeout(timer);
7490
+ }
7445
7491
  function normalize3(s) {
7446
7492
  return s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
7447
7493
  }
@@ -11262,7 +11308,7 @@ async function waitForLoadingSettle(opts = {}) {
11262
11308
  }
11263
11309
 
11264
11310
  // src/version.ts
11265
- var SDK_VERSION2 = "0.13.0";
11311
+ var SDK_VERSION2 = "0.14.0";
11266
11312
  var FiberSentinel = class extends React2.Component {
11267
11313
  componentDidMount() {
11268
11314
  const fiber = this._reactInternals ?? this._reactInternalFiber ?? null;
@@ -11611,12 +11657,14 @@ function AppilotsProviderInner({
11611
11657
  apiBaseUrl: config.apiBaseUrl,
11612
11658
  apiKey: config.apiKey,
11613
11659
  debug: config.debug,
11660
+ timeout: config.timeout,
11614
11661
  appVersion: config.appVersion,
11615
11662
  mcpVersion: config.mcpVersion,
11616
11663
  // This package's published version, so the server knows which
11617
11664
  // SDK is actually in the field (issue #312).
11618
11665
  sdkVersion: SDK_VERSION2,
11619
11666
  user: config.user,
11667
+ plainLanguage: config.plainLanguage,
11620
11668
  // Only reports a FAILED reading; the happy path sends nothing.
11621
11669
  introspectionReporter: getIntrospectionDiagnostics
11622
11670
  }),
@@ -11632,6 +11680,9 @@ function AppilotsProviderInner({
11632
11680
  externalClient
11633
11681
  ]
11634
11682
  );
11683
+ useEffect(() => {
11684
+ client.setPlainLanguage?.(config.plainLanguage);
11685
+ }, [client, config.plainLanguage]);
11635
11686
  const fetchPersonalizationEnabled = config.fetchPersonalization !== false;
11636
11687
  const [remotePersonalization, setRemotePersonalization] = useState(
11637
11688
  null
@@ -11686,4 +11737,4 @@ function clearScreenRegistry() {
11686
11737
  screenRegistry.clear();
11687
11738
  }
11688
11739
 
11689
- export { ActionQueueMachine, AppilotsClient, AppilotsErrorBoundary, AppilotsProvider, AppilotsRegistryProvider, ChatSessionMachine, FORM_VALIDATION_TEXT_RE, FORM_WRITE_SUCCESS_TEXT_RE, OPTIONAL_STEP_AUTOMATION_HINT, RateLimitedError, SDK_VERSION2 as SDK_VERSION, SUBMIT_CONTROL_RE, TOUCHABLE_NAMES, _patchJsxRuntimes, actionPressTargetId, appilotsDebugLog, appilotsDebugWarn, attachElementIdsToChoiceGroups, clampSnapshotToWireLimits, clearAppilotsDebugTraces, clearScreenRegistry, componentRegistry, createComponentRegistry, createElementRegistry, createListRegistry, createSnapshotDeltaTracker, defaultDarkTheme, defaultLightTheme, deriveInteractionElements, describeAction, describeValue, elementRegistry, emptyDetectorCounts, enableAppilotsAutoTracking, endTextInputEditing, enhancePlainAssistantContent, findListItems, foldForCompare, geometryAvailability, geometryStats, getActiveRouteNames, getAllScreens, getAppilotsDebugTraces, getAutoTrackingState, getCurrentScreen, getCurrentScreenSignature, getDefaultRegistry, getFiberRoot, getGeometryHost, getGlobalConfig, getIntrospectionDiagnostics, getLastAnsweredNativeDialog, getLastWalkDiagnostics, getNameManglingProbe, getNavigationRef, getNavigationStateSnapshot, getOpenNativeDialog, getScreenMetadata, getTypeName, humanizeError, idLooselyMatches, initAppilots, isAlwaysListContainer, isAutoTrackingEnabled, isGenericSelectValue, isGeometryResolved, isHeuristicListContainer, isListItemPressTarget, isModalFiber, isOptionalStepAutomationFailure, isRectOnScreen, isReferenceable, isSourceControlId, isSwitchLike, isVisibleValidationText, listRegistry, looksDestructiveActionLabel, looksLikeMarkdown, matchScore, mergeThemeTokens, needsWideChatLayout, normalize3, normalizeAppilotsLocale, parseInlineMarkdown, parseMarkdownBlocks, parseStableElementId, permissionDeniedMessage, probeLoadingState, recordAppilotsDebugTrace, recordIntrospectionFailure, rectForNode, rectOfFiber, registerScreen, resolveAgentPermissions, resolveBaseTheme, resolveTarget, routesBelongToSameFeature, screenDepartedBaseline, setCurrentScreen, setNavigationRef, shouldSkipSubtree, snapshotShowsOpenCreateForm, sourceControlId, sourceControlTarget, subscribeAppilotsDebugTraces, subscribeGeometryHost, switchValue, toWireElement, totalDetectorHits, useAppilotsContext, useResolvedRegistry, waitForLoadingSettle, waitForScreenSettle, walkFiber };
11740
+ export { ActionQueueMachine, AppilotsClient, AppilotsErrorBoundary, AppilotsProvider, AppilotsRegistryProvider, ChatSessionMachine, FORM_VALIDATION_TEXT_RE, FORM_WRITE_SUCCESS_TEXT_RE, OPTIONAL_STEP_AUTOMATION_HINT, RateLimitedError, SDK_VERSION2 as SDK_VERSION, SUBMIT_CONTROL_RE, TOUCHABLE_NAMES, _patchJsxRuntimes, actionPressTargetId, appilotsDebugLog, appilotsDebugWarn, attachElementIdsToChoiceGroups, clampSnapshotToWireLimits, clearAppilotsDebugTraces, clearScreenRegistry, componentRegistry, confirmExpiresAt, createComponentRegistry, createElementRegistry, createListRegistry, createSnapshotDeltaTracker, defaultDarkTheme, defaultLightTheme, deriveInteractionElements, describeAction, describeValue, elementRegistry, emptyDetectorCounts, enableAppilotsAutoTracking, endTextInputEditing, enhancePlainAssistantContent, findListItems, foldForCompare, geometryAvailability, geometryStats, getActiveRouteNames, getAllScreens, getAppilotsDebugTraces, getAutoTrackingState, getCurrentScreen, getCurrentScreenSignature, getDefaultRegistry, getFiberRoot, getGeometryHost, getGlobalConfig, getIntrospectionDiagnostics, getLastAnsweredNativeDialog, getLastWalkDiagnostics, getNameManglingProbe, getNavigationRef, getNavigationStateSnapshot, getOpenNativeDialog, getScreenMetadata, getTypeName, humanizeError, idLooselyMatches, initAppilots, isAlwaysListContainer, isAppilotsSensitiveMarked, isAutoTrackingEnabled, isGenericSelectValue, isGeometryResolved, isHeuristicListContainer, isListItemPressTarget, isModalFiber, isOptionalStepAutomationFailure, isRectOnScreen, isReferenceable, isSourceControlId, isSpeechHost, isSwitchLike, isVisibleValidationText, listRegistry, looksDestructiveActionLabel, looksLikeMarkdown, matchScore, mergeThemeTokens, needsWideChatLayout, normalize3, normalizeAppilotsLocale, parseInlineMarkdown, parseMarkdownBlocks, parseStableElementId, permissionDeniedMessage, probeLoadingState, recordAppilotsDebugTrace, recordIntrospectionFailure, rectForNode, rectOfFiber, registerScreen, resolveAgentPermissions, resolveBaseTheme, resolveTarget, routesBelongToSameFeature, screenDepartedBaseline, setCurrentScreen, setNavigationRef, shouldSkipSubtree, snapshotShowsOpenCreateForm, sourceControlId, sourceControlTarget, startStillWorkingTimer, subscribeAppilotsDebugTraces, subscribeGeometryHost, switchValue, toWireElement, totalDetectorHits, useAppilotsContext, useResolvedRegistry, waitForLoadingSettle, waitForScreenSettle, walkFiber };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkUZ2D4BVX_js = require('./chunk-UZ2D4BVX.js');
3
+ var chunkQAZ4TN3Z_js = require('./chunk-QAZ4TN3Z.js');
4
4
  var React = require('react');
5
5
 
6
6
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -15,17 +15,17 @@ function getActiveRouteName(state) {
15
15
  return route.name;
16
16
  }
17
17
  function AppilotsNavigationContainer({ children }) {
18
- const { emit } = chunkUZ2D4BVX_js.useAppilotsContext();
18
+ const { emit } = chunkQAZ4TN3Z_js.useAppilotsContext();
19
19
  const internalRef = React.useRef(null);
20
20
  const handleRef = React.useCallback(
21
21
  (instance) => {
22
22
  internalRef.current = instance;
23
- chunkUZ2D4BVX_js.setNavigationRef(instance);
23
+ chunkQAZ4TN3Z_js.setNavigationRef(instance);
24
24
  const childRef = children.ref;
25
25
  if (typeof childRef === "function") childRef(instance);
26
26
  else if (childRef && typeof childRef === "object") childRef.current = instance;
27
27
  if (instance) {
28
- chunkUZ2D4BVX_js.appilotsDebugLog("NavigationContainer ref captured");
28
+ chunkQAZ4TN3Z_js.appilotsDebugLog("NavigationContainer ref captured");
29
29
  }
30
30
  },
31
31
  [children]
@@ -34,8 +34,8 @@ function AppilotsNavigationContainer({ children }) {
34
34
  (state) => {
35
35
  const routeName = getActiveRouteName(state);
36
36
  if (routeName) {
37
- chunkUZ2D4BVX_js.appilotsDebugLog(`Screen changed \u2192 "${routeName}"`);
38
- chunkUZ2D4BVX_js.setCurrentScreen(routeName);
37
+ chunkQAZ4TN3Z_js.appilotsDebugLog(`Screen changed \u2192 "${routeName}"`);
38
+ chunkQAZ4TN3Z_js.setCurrentScreen(routeName);
39
39
  emit({
40
40
  type: "navigation:change",
41
41
  timestamp: Date.now(),
@@ -50,8 +50,8 @@ function AppilotsNavigationContainer({ children }) {
50
50
  const timer = setTimeout(() => {
51
51
  const route = internalRef.current?.getCurrentRoute?.();
52
52
  if (route?.name) {
53
- chunkUZ2D4BVX_js.appilotsDebugLog(`Initial screen \u2192 "${route.name}"`);
54
- chunkUZ2D4BVX_js.setCurrentScreen(route.name);
53
+ chunkQAZ4TN3Z_js.appilotsDebugLog(`Initial screen \u2192 "${route.name}"`);
54
+ chunkQAZ4TN3Z_js.setCurrentScreen(route.name);
55
55
  emit({
56
56
  type: "navigation:change",
57
57
  timestamp: Date.now(),