@appilots/sdk 0.11.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,33 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default from 'react';
3
3
 
4
+ /** Customer conversation/UI locales. Map text and host-app labels may use other languages. */
5
+ declare const SUPPORTED_APPILOTS_LOCALES: readonly ["pt-BR", "en", "es", "fr"];
6
+ type SupportedAppilotsLocale = (typeof SUPPORTED_APPILOTS_LOCALES)[number];
7
+
8
+ type MissionStatus = 'awaiting_approval' | 'running' | 'paused' | 'blocked' | 'completed' | 'cancelled';
9
+ interface MissionScope {
10
+ id: string;
11
+ revision: number;
12
+ operation: 'delete';
13
+ screen: string;
14
+ listId: string;
15
+ items: Array<{
16
+ key: string;
17
+ label: string;
18
+ }>;
19
+ expiresAt: number;
20
+ }
21
+ interface MissionView {
22
+ scope: MissionScope;
23
+ objective: string;
24
+ status: MissionStatus;
25
+ completed: number;
26
+ total: number;
27
+ reason?: string;
28
+ progressText: string;
29
+ }
30
+
4
31
  /**
5
32
  * Theme tokens — the source of truth for any color, font, radius or
6
33
  * shadow used inside the SDK's chat UI. Components must read from these
@@ -132,7 +159,7 @@ declare function mergeThemeTokens(base: AppilotsThemeTokens, partial?: PartialTh
132
159
  * `i18n/bundles/` AND a branch in `i18n/I18nProvider.tsx`'s `BUNDLES`
133
160
  * map AND a variant here. BACKLOG 4.1.
134
161
  */
135
- type AppilotsLocale = 'pt-BR' | 'en' | 'es';
162
+ type AppilotsLocale = SupportedAppilotsLocale;
136
163
 
137
164
  /**
138
165
  * Core types for the Appilots SDK.
@@ -282,7 +309,9 @@ interface AgentPermissions {
282
309
  blockedScreens?: string[];
283
310
  allowedActions?: AgentActionType[];
284
311
  }
285
- type AppilotsEventType = 'agent:action:start' | 'agent:action:complete' | 'agent:action:error' | 'agent:message' | 'navigation:change' | 'chat:open' | 'chat:close' | 'chat:escalation:start' | 'chat:escalation:message' | 'chat:escalation:end' | 'sdk:introspection:unavailable';
312
+ type AppilotsEventType = 'agent:action:start'
313
+ /** Queue dispatch, after approval; distinct from a proposed action. */
314
+ | 'agent:action:executing' | 'agent:action:complete' | 'agent:action:error' | 'agent:message' | 'navigation:change' | 'chat:open' | 'chat:close' | 'chat:cancel' | 'chat:escalation:start' | 'chat:escalation:message' | 'chat:escalation:end' | 'sdk:introspection:unavailable';
286
315
  interface AppilotsEvent {
287
316
  type: AppilotsEventType;
288
317
  timestamp: number;
@@ -301,6 +330,12 @@ interface EscalationState {
301
330
  operatorName?: string;
302
331
  }
303
332
 
333
+ /** Optional host storage; only a session handle is stored, never screen contents. */
334
+ interface AppilotsSessionStorage {
335
+ getItem(key: string): Promise<string | null>;
336
+ setItem(key: string, value: string): Promise<void>;
337
+ removeItem(key: string): Promise<void>;
338
+ }
304
339
  /**
305
340
  * Mirrors `introspectionDiagnosticsSchema` on the wire. Declared here
306
341
  * rather than imported so client-core stays free of the server's
@@ -315,6 +350,7 @@ interface IntrospectionDiagnosticsInput {
315
350
  failureCount?: number;
316
351
  }
317
352
  interface AppilotsClientOptions {
353
+ sessionStorage?: AppilotsSessionStorage;
318
354
  projectId: string;
319
355
  apiBaseUrl?: string;
320
356
  apiKey?: string;
@@ -381,6 +417,8 @@ interface AppilotsUser {
381
417
  identifiers?: Record<string, string>;
382
418
  }
383
419
  interface SendMessageResponse {
420
+ mission?: MissionView;
421
+ replyLocale?: SupportedAppilotsLocale;
384
422
  sessionId: string;
385
423
  message: ChatMessage;
386
424
  /** Summary message to show AFTER actions complete */
@@ -400,6 +438,7 @@ interface SendMessageStreamOptions {
400
438
  onTextDelta?: (chunk: string, fullText: string) => void;
401
439
  /** Fired once when the server announces the session id. */
402
440
  onSession?: (sessionId: string) => void;
441
+ onReplyLocale?: (locale: SupportedAppilotsLocale) => void;
403
442
  /** Abort mid-generation (stop button). Rejects with name='AbortError'. */
404
443
  signal?: AbortSignal;
405
444
  }
@@ -429,6 +468,10 @@ declare class RateLimitedError extends Error {
429
468
  }
430
469
  /** Runtime context sent with every user message. */
431
470
  interface SendMessageContext {
471
+ missionProtocol?: 1;
472
+ missionId?: string;
473
+ /** Supported device language, independent of the app/map/visible UI locale. */
474
+ deviceLocale?: SupportedAppilotsLocale;
432
475
  /**
433
476
  * Which client platform this observation came from — `'react-native'`,
434
477
  * `'web'`, `'android'`, `'ios'`, or any other client-defined string.
@@ -484,6 +527,11 @@ declare class AppilotsClient {
484
527
  private readonly introspectionReporter;
485
528
  private readonly user;
486
529
  private sessionId;
530
+ private mission;
531
+ private missionDispatchPaused;
532
+ private readonly sessionStorage;
533
+ private readonly sessionStorageKey;
534
+ private sessionLoad;
487
535
  /** Guard so identify fires at most once per client instance. */
488
536
  private identified;
489
537
  constructor(options: AppilotsClientOptions);
@@ -570,6 +618,23 @@ declare class AppilotsClient {
570
618
  isDone: boolean;
571
619
  hop: number;
572
620
  }>;
621
+ private acceptMission;
622
+ getMission(): MissionView | null;
623
+ pauseMissionLocally(): void;
624
+ missionApprovalAllowed(action: AgentAction): boolean;
625
+ missionScopeForAction(action: AgentAction): MissionScope | undefined;
626
+ claimMissionAction(action: AgentAction, context: Record<string, unknown>): Promise<{
627
+ allowed: boolean;
628
+ scope: MissionScope;
629
+ expiresAt: number;
630
+ }>;
631
+ controlMission(command: 'observe' | 'pause' | 'resume' | 'cancel', context: Record<string, unknown>): Promise<SendMessageResponse & {
632
+ isDone: boolean;
633
+ hop: number;
634
+ }>;
635
+ private persistSession;
636
+ private loadStoredSession;
637
+ restoreMission(): Promise<MissionView | null>;
573
638
  executeAction(actionId: string): Promise<AgentAction>;
574
639
  /**
575
640
  * Rewrite an action's type when the AI used a semantically-misclassified
@@ -685,600 +750,6 @@ declare class AppilotsClient {
685
750
  }): () => void;
686
751
  }
687
752
 
688
- /**
689
- * Snapshot types — the platform-agnostic "view model" of what the user
690
- * is currently seeing on screen, sent to the AI agent so it has
691
- * accurate visible state.
692
- *
693
- * Every platform walker (React Native fiber walk, web DOM walk, ...)
694
- * produces this same shape; the wire contract it feeds is
695
- * `agentSnapshotSchema` in `@appilots/shared`.
696
- */
697
- /**
698
- * How much the walker actually knows about an element's identifier.
699
- *
700
- * The observation used to say nothing here, so `btn-3` — an ordinal the
701
- * walker invented — read to the model exactly like `testID="submit-order"`,
702
- * which a developer wrote down on purpose. That is how a confident press on
703
- * the wrong control happens.
704
- *
705
- * - `declared` the app named it: `testID` / `data-testid` /
706
- * `accessibilityLabel` / `aria-label`. Stable across renders
707
- * and across releases; safe to copy into a tool call.
708
- * - `derived` folded from what the user can see — the button's own text,
709
- * a `label` or `placeholder` prop. Stable as long as the copy
710
- * does not change, and it changes with the app's language.
711
- * - `positional` nothing but an ordinal in the current snapshot. Valid for
712
- * this observation only: a re-render, a scroll or an inserted
713
- * sibling moves it.
714
- *
715
- * ABSENT means unknown, NOT `declared` — clients published before this field
716
- * existed send no provenance at all, and a missing value must never be read
717
- * as the most trustworthy one.
718
- */
719
- type IdentityProvenance = 'declared' | 'derived' | 'positional';
720
- interface InputSnapshot {
721
- /** Best identifier — testID/data-testid, accessibilityLabel/aria-label, or placeholder */
722
- id?: string;
723
- /** How `id` was obtained. See {@link IdentityProvenance}. */
724
- provenance?: IdentityProvenance;
725
- /**
726
- * False when the control is mounted but currently outside the window —
727
- * below the fold of a ScrollView, scrolled off the top, pushed sideways
728
- * by a carousel.
729
- *
730
- * ABSENT MEANS UNKNOWN. The old React Native architecture cannot report a
731
- * synchronous window-relative rect, and no SDK published before this
732
- * field existed reports one at all; reading absence as `false` would make
733
- * the agent refuse to press a control the user is looking at.
734
- */
735
- onScreen?: boolean;
736
- /** Human-readable label inferred from accessibility metadata or sibling text */
737
- label?: string;
738
- /** Current value (only present for controlled inputs) */
739
- value?: string;
740
- /** Placeholder text */
741
- placeholder?: string;
742
- /** Whether the input is editable */
743
- editable?: boolean;
744
- /** Whether the input is secure (password field) */
745
- secure?: boolean;
746
- /** Inferred type based on the platform's input-type metadata */
747
- type?: 'text' | 'email' | 'number' | 'phone' | 'password';
748
- /**
749
- * True when pressing return on this field submits — RN's
750
- * `onSubmitEditing`, the web's implicit form submit.
751
- *
752
- * On a search box, a one-field login or a chat composer this IS the
753
- * submit; the screen has no button and never will. Absent means the
754
- * field declares no such handler, so the form needs a button.
755
- */
756
- submitsOnReturn?: boolean;
757
- /**
758
- * The app is asking for this field before the form can be submitted.
759
- *
760
- * ABSENT MEANS UNKNOWN, not optional: most apps never declare it, and
761
- * reading absence as "not required" would let the agent submit a form
762
- * it could have known was incomplete.
763
- */
764
- required?: boolean;
765
- /**
766
- * The app is currently rejecting this field's value.
767
- *
768
- * This is the fact the agent used to recover by READING — the error
769
- * copy next to the input ("Campo obrigatório", "Formato inválido").
770
- * Carrying the fact as a boolean is what lets a redacted observation
771
- * still support recovery, and it is cheaper than the sentence even
772
- * when nothing is redacted.
773
- *
774
- * Absent means the app declares no validity state — never that the
775
- * field is valid.
776
- */
777
- invalid?: boolean;
778
- /**
779
- * Whether the field currently holds anything.
780
- *
781
- * Deliberately its own field rather than an inference over `value`.
782
- * The value belongs to the user and is the first thing a privacy
783
- * policy withholds; the EXISTENCE of a value belongs to the agent and
784
- * is what stops it from filling the same field twice on a later hop.
785
- * Separating them is what lets the second survive without the first.
786
- */
787
- filled?: boolean;
788
- /**
789
- * This input has keyboard focus right now.
790
- *
791
- * Tells apart "empty because nobody typed" from "empty because the
792
- * user is typing in it at this moment" — the difference between
793
- * completing a form and interrupting someone mid-sentence.
794
- */
795
- focused?: boolean;
796
- /**
797
- * True when this input lives inside a currently-visible modal. When a
798
- * modal is open, only inModal elements can actually receive input —
799
- * everything else is behind the overlay.
800
- */
801
- inModal?: boolean;
802
- }
803
- interface ButtonSnapshot {
804
- /** Best identifier — testID/data-testid, accessibilityLabel/aria-label, or inferred from child text */
805
- id?: string;
806
- /** How `id` was obtained. See {@link IdentityProvenance}. */
807
- provenance?: IdentityProvenance;
808
- /**
809
- * False when the control is mounted but currently outside the window —
810
- * below the fold of a ScrollView, scrolled off the top, pushed sideways
811
- * by a carousel.
812
- *
813
- * ABSENT MEANS UNKNOWN. The old React Native architecture cannot report a
814
- * synchronous window-relative rect, and no SDK published before this
815
- * field existed reports one at all; reading absence as `false` would make
816
- * the agent refuse to press a control the user is looking at.
817
- */
818
- onScreen?: boolean;
819
- /** Human-readable label — usually the visible text inside the button */
820
- label?: string;
821
- /** Whether the button is disabled */
822
- disabled?: boolean;
823
- /**
824
- * Whether this control is currently in its ON state.
825
- *
826
- * Covers both accessibility states that mean it, because the agent
827
- * needs the same thing from either: `accessibilityState.selected`
828
- * (grouped, mutually-exclusive controls — segmented controls, radio
829
- * groups, each option its own pressable target) and
830
- * `accessibilityState.checked` (an independent checkbox).
831
- *
832
- * Absent means "not on OR not observable" — the walker cannot tell a
833
- * custom checkbox that declares no a11y state from an ordinary button,
834
- * so absence is never proof that a box is unticked.
835
- */
836
- selected?: boolean;
837
- /** True when this button lives inside a currently-visible modal. */
838
- inModal?: boolean;
839
- }
840
- interface ToggleSnapshot {
841
- /** Best identifier */
842
- id?: string;
843
- /** How `id` was obtained. See {@link IdentityProvenance}. */
844
- provenance?: IdentityProvenance;
845
- /**
846
- * False when the control is mounted but currently outside the window —
847
- * below the fold of a ScrollView, scrolled off the top, pushed sideways
848
- * by a carousel.
849
- *
850
- * ABSENT MEANS UNKNOWN. The old React Native architecture cannot report a
851
- * synchronous window-relative rect, and no SDK published before this
852
- * field existed reports one at all; reading absence as `false` would make
853
- * the agent refuse to press a control the user is looking at.
854
- */
855
- onScreen?: boolean;
856
- /** Human-readable label */
857
- label?: string;
858
- /** Current on/off state */
859
- value?: boolean;
860
- /** True when this toggle lives inside a currently-visible modal. */
861
- inModal?: boolean;
862
- }
863
- interface SliderSnapshot {
864
- /** Registry id — the executable handle. */
865
- id?: string;
866
- /** How `id` was obtained. See {@link IdentityProvenance}. */
867
- provenance?: IdentityProvenance;
868
- /**
869
- * False when the control is mounted but currently outside the window —
870
- * below the fold of a ScrollView, scrolled off the top, pushed sideways
871
- * by a carousel.
872
- *
873
- * ABSENT MEANS UNKNOWN. The old React Native architecture cannot report a
874
- * synchronous window-relative rect, and no SDK published before this
875
- * field existed reports one at all; reading absence as `false` would make
876
- * the agent refuse to press a control the user is looking at.
877
- */
878
- onScreen?: boolean;
879
- /** Human-readable label */
880
- label?: string;
881
- /** Current numeric value */
882
- value?: number;
883
- /** Lower bound the executor clamps to */
884
- min?: number;
885
- /** Upper bound the executor clamps to */
886
- max?: number;
887
- /** Step the executor snaps to (omitted = continuous) */
888
- step?: number;
889
- /** Whether the slider is currently disabled */
890
- disabled?: boolean;
891
- /** True when this slider lives inside a currently-visible modal. */
892
- inModal?: boolean;
893
- }
894
- interface ListItemSnapshot {
895
- /** 1-indexed position within the parent list (matches "selecione o terceiro"). */
896
- index: number;
897
- /**
898
- * 0-based index of this row in the list's backing DATA, when known.
899
- * For scrolled/virtualized lists this differs from `index`.
900
- */
901
- dataIndex?: number;
902
- /** Framework key of the row, if present (typically the item's domain id). */
903
- reactKey?: string;
904
- /** Runtime key supplied by list tracking, if available. */
905
- itemKey?: string;
906
- /** Texts captured from this item's subtree, preserving row association. */
907
- texts: string[];
908
- /** Buttons inside this item — e.g. an inline "Edit" button on a row. */
909
- buttons: ButtonSnapshot[];
910
- /** Inputs inside this item — rare but possible (inline edit row). */
911
- inputs: InputSnapshot[];
912
- /** Toggles inside this item. */
913
- toggles: ToggleSnapshot[];
914
- /**
915
- * Synthetic id assigned by the walker. Stable within a single
916
- * snapshot; format `list-<L>-item-<I>` (0-indexed L, 1-indexed I).
917
- * Used by tap-by-ordinal resolution in the executor.
918
- */
919
- syntheticId: string;
920
- }
921
- interface ListSnapshot {
922
- /** 0-indexed list ordinal — multiple lists on one screen get 0, 1, 2... */
923
- index: number;
924
- /** Runtime list id when tracking or explicit props provide one. */
925
- id?: string;
926
- /** The container component/tag name as observed by the walker. */
927
- containerType: string;
928
- /**
929
- * Source that identified this list. `'fiber'`/`'auto-tracked'` are
930
- * the walker's own discovery tags (a DOM walker reports
931
- * `'auto-tracked'` for app-annotated lists and omits the field for
932
- * heuristically-detected ones); `'registry'` means the list came
933
- * from the SDK's list registry rather than the tree walk.
934
- */
935
- source?: 'fiber' | 'auto-tracked' | 'registry';
936
- /** Total data-set count when the list exposes it. */
937
- itemCount?: number;
938
- /** Number of row items captured in this snapshot. */
939
- visibleItemCount?: number;
940
- /** True when the list reports a refresh/loading state. */
941
- refreshing?: boolean;
942
- /** True when total item count is known and zero. */
943
- empty?: boolean;
944
- /** Human-readable label if the app supplied one. */
945
- label?: string;
946
- /** Items in visible order. */
947
- items: ListItemSnapshot[];
948
- /**
949
- * Lightweight text projection of the list's FULL data set (capped),
950
- * so the agent can see/search rows that virtualization keeps
951
- * unmounted. Each entry: 0-based data index, stable key, short text.
952
- */
953
- dataPreview?: ListDataPreviewEntry[];
954
- /** Current vertical scroll offset in px, when readable. */
955
- scrollOffsetY?: number;
956
- /** True when there is scrollable content above the viewport. */
957
- canScrollUp?: boolean;
958
- /** True when there is scrollable content below the viewport. */
959
- canScrollDown?: boolean;
960
- }
961
- interface ListDataPreviewEntry {
962
- /** 0-based index in the list's backing data. */
963
- index: number;
964
- /** Stable key from the item's domain id when available. */
965
- key?: string;
966
- /** Short human-readable projection of the item (capped length). */
967
- text: string;
968
- }
969
- /**
970
- * A scrollable surface that is NOT a collection — a long form, a detail
971
- * page, a settings screen inside a `ScrollView`.
972
- *
973
- * It exists as its own concept, and not as a `ListSnapshot` with zero
974
- * rows, because everything the agent knows how to do with a list
975
- * (ordinals, totals, "select the third one") is meaningless here. The
976
- * only affordance is paging toward content below the fold — and without
977
- * it, a screen taller than the viewport ends at the fold.
978
- */
979
- interface ScrollableSnapshot {
980
- /** Runtime id — the handle `scroll_list` addresses. */
981
- id: string;
982
- /** The container component as observed: ScrollView, ... */
983
- containerType: string;
984
- /** Human-readable label if the app supplied one. */
985
- label?: string;
986
- /** Current scroll offset in px. */
987
- scrollOffsetY?: number;
988
- /** True when there is content above the viewport. */
989
- canScrollUp?: boolean;
990
- /** True when there is content below the viewport. */
991
- canScrollDown?: boolean;
992
- /** True when the surface scrolls sideways rather than vertically. */
993
- horizontal?: boolean;
994
- }
995
- /**
996
- * A platform dialog covering the screen — React Native's `Alert.alert`,
997
- * an action sheet, an OS permission prompt.
998
- *
999
- * It renders outside React, so no amount of tree walking finds it. It
1000
- * has to be reported separately or the agent keeps operating the app
1001
- * underneath a dialog that blocks every real finger.
1002
- */
1003
- interface NativeDialogSnapshot {
1004
- /** Stable for as long as this dialog is open. */
1005
- id: string;
1006
- title?: string;
1007
- message?: string;
1008
- /** The buttons the user can press. Never empty. */
1009
- buttons: Array<{
1010
- label: string;
1011
- style?: 'default' | 'cancel' | 'destructive';
1012
- }>;
1013
- }
1014
- interface ChoiceOptionSnapshot {
1015
- /** 1-indexed option position within this group. */
1016
- index: number;
1017
- /** Stable-enough id for the current snapshot/action turn. */
1018
- syntheticId: string;
1019
- /** Best target id if this option is backed by a pressable component. */
1020
- targetId?: string;
1021
- /** Human-readable option label. */
1022
- label?: string;
1023
- /** Text segments that belong to this option. */
1024
- texts: string[];
1025
- /** Whether this option appears selected. */
1026
- selected?: boolean;
1027
- /** Whether this option appears disabled. */
1028
- disabled?: boolean;
1029
- }
1030
- interface ChoiceGroupSnapshot {
1031
- /** 0-indexed group ordinal on the current screen. */
1032
- index: number;
1033
- /** Runtime id when known, usually inherited from a list/collection. */
1034
- id?: string;
1035
- /** Human-readable label when known. */
1036
- label?: string;
1037
- /** Source that produced this choice group. */
1038
- source?: 'list' | 'buttons' | 'heuristic';
1039
- /** Visible options in order. */
1040
- options: ChoiceOptionSnapshot[];
1041
- }
1042
- interface InteractionElementListContext {
1043
- listIndex?: number;
1044
- listId?: string;
1045
- listLabel?: string;
1046
- itemIndex?: number;
1047
- itemKey?: string;
1048
- reactKey?: string;
1049
- syntheticId?: string;
1050
- }
1051
- interface InteractionElementSnapshot {
1052
- /** Stable id for the current screen/content, preferred for tool calls. */
1053
- id: string;
1054
- /** Semantic UI role. */
1055
- role: 'option' | 'button' | 'input' | 'toggle' | 'slider' | 'listItem';
1056
- /** Human-readable label. */
1057
- label?: string;
1058
- /** Text segments associated with this element. */
1059
- texts: string[];
1060
- /** Actions supported by this element. */
1061
- actions: Array<'press' | 'focus' | 'toggle' | 'setValue'>;
1062
- /** Whether the element is currently disabled. */
1063
- disabled?: boolean;
1064
- /** Whether the element appears selected. */
1065
- selected?: boolean;
1066
- /** Source that produced the element. */
1067
- source?: 'list' | 'button' | 'input' | 'toggle' | 'slider' | 'choice';
1068
- /**
1069
- * How the underlying control's identifier was obtained. Carried up from
1070
- * the snapshot entry this element was derived from, so a consumer that
1071
- * only reads `elements` still knows what it is trusting. See
1072
- * {@link IdentityProvenance}.
1073
- */
1074
- provenance?: IdentityProvenance;
1075
- /**
1076
- * False when the control is mounted but currently outside the window —
1077
- * below the fold of a ScrollView, scrolled off the top, pushed sideways
1078
- * by a carousel.
1079
- *
1080
- * ABSENT MEANS UNKNOWN. The old React Native architecture cannot report a
1081
- * synchronous window-relative rect, and no SDK published before this
1082
- * field existed reports one at all; reading absence as `false` would make
1083
- * the agent refuse to press a control the user is looking at.
1084
- */
1085
- onScreen?: boolean;
1086
- /** Legacy/fallback target id, if any. */
1087
- targetId?: string;
1088
- /** Context for row/list options. */
1089
- listContext?: InteractionElementListContext;
1090
- /**
1091
- * True when the underlying component lives inside a currently-visible
1092
- * modal — the only targets actually touchable while the overlay is up.
1093
- */
1094
- inModal?: boolean;
1095
- }
1096
- /** Window-relative box, in the coordinate space the platform reports. */
1097
- interface ElementRect {
1098
- x: number;
1099
- y: number;
1100
- width: number;
1101
- height: number;
1102
- }
1103
- /**
1104
- * What the CLIENT keeps about an element, which is strictly more than what
1105
- * the model is told about it.
1106
- *
1107
- * The wire shape (`InteractionElementSnapshot`) is sized for a language
1108
- * model: names, roles, state, everything it needs to decide. This one adds
1109
- * what only the executor needs — coordinates it will never read aloud —
1110
- * and it exists because that data was being measured and then discarded
1111
- * for want of somewhere to put it that wasn't the wire.
1112
- *
1113
- * The split is the point. Anything added here is free: it never reaches
1114
- * `agentSnapshotSchema`, never crosses the network, and never costs a
1115
- * token. Anything added to the wire type is paid for on every observation
1116
- * of every session, so it has to earn the model's attention.
1117
- */
1118
- interface InteractionElementEntry extends InteractionElementSnapshot {
1119
- /**
1120
- * Where the control was on screen when the snapshot was taken. Absent
1121
- * when the platform cannot measure synchronously (React Native's old
1122
- * architecture) or when the element came from a source with no fiber
1123
- * behind it.
1124
- */
1125
- rect?: ElementRect;
1126
- }
1127
- /**
1128
- * What changed between the previous observation and this one.
1129
- *
1130
- * The client holds both snapshots; the server only ever sees one. So the
1131
- * question the agent loop asks most often — "did the action I just took
1132
- * do anything?" — is one the client can answer as a FACT and the server
1133
- * can only guess at. Today it guesses: `effect: 'none'` on the turn trail
1134
- * is derived server-side from heuristics over a single snapshot.
1135
- *
1136
- * Everything here is shape, never content: counts, booleans, and field
1137
- * ids that the app declared itself. That is not an accident of design —
1138
- * it is what lets this survive a redacted or content-free observation
1139
- * intact, and it is why the most useful signal in the observation is also
1140
- * the cheapest one to send.
1141
- *
1142
- * ABSENT vs `unchanged: true` is the load-bearing distinction, and it is
1143
- * the same one `truncated` exists to make. Absent means there was no
1144
- * previous observation to compare against (the first capture of a
1145
- * mission). `unchanged: true` means we DID compare and nothing moved —
1146
- * which is the strongest evidence there is that an action did nothing.
1147
- */
1148
- interface SnapshotDelta {
1149
- /** The active route is not the one the previous observation reported. */
1150
- routeChanged?: boolean;
1151
- /** A modal or native dialog is up now and was not before. */
1152
- modalOpened?: boolean;
1153
- /** A modal or native dialog was up before and is gone now. */
1154
- modalClosed?: boolean;
1155
- /** A loading indicator appeared. */
1156
- loadingStarted?: boolean;
1157
- /** A loading indicator that was showing is gone. */
1158
- loadingFinished?: boolean;
1159
- /** How many distinct visible texts are present now that were not before. */
1160
- textsAdded?: number;
1161
- /** How many distinct visible texts are gone. */
1162
- textsRemoved?: number;
1163
- /** Net change in mounted list rows, summed across every list. */
1164
- visibleRowsDelta?: number;
1165
- /**
1166
- * Net change in the lists' reported DATA totals, summed. This is the
1167
- * one that answers "did the record actually get created", because it
1168
- * moves even when virtualization keeps the new row unmounted.
1169
- */
1170
- totalRowsDelta?: number;
1171
- /**
1172
- * Fields that went from empty to filled. Declared ids only — a
1173
- * `derived` id is folded from visible copy, so publishing it here
1174
- * would smuggle content through a field that claims to carry none.
1175
- */
1176
- fieldsNewlyFilled?: string[];
1177
- /** Fields that went from filled to empty. Declared ids only. */
1178
- fieldsCleared?: string[];
1179
- /** Some field is reporting invalid that was not reporting it before. */
1180
- invalidAppeared?: boolean;
1181
- /**
1182
- * Nothing above fired: we compared two observations and the screen is
1183
- * structurally identical. Present only when every other field is
1184
- * absent, so a reader never has to check all of them to know.
1185
- */
1186
- unchanged?: boolean;
1187
- }
1188
- interface ScreenSnapshot {
1189
- /** The currently active route name, if known */
1190
- route: string | null;
1191
- /** All visible static text */
1192
- texts: string[];
1193
- /** All text inputs currently rendered (and visible) */
1194
- inputs: InputSnapshot[];
1195
- /** All button-like components */
1196
- buttons: ButtonSnapshot[];
1197
- /** All toggle components */
1198
- toggles: ToggleSnapshot[];
1199
- /** Sliders / adjustable numeric controls. */
1200
- sliders: SliderSnapshot[];
1201
- /** Whether a loading indicator is visible */
1202
- loading: boolean;
1203
- /** Whether a modal is currently open */
1204
- modalOpen: boolean;
1205
- /**
1206
- * A native dialog covering the screen, when the SDK could observe one.
1207
- *
1208
- * Its presence also forces `modalOpen`, because for every purpose the
1209
- * agent cares about it IS a modal — nothing behind it is touchable.
1210
- * Absence is not proof there is no dialog: an OS permission prompt or
1211
- * a share sheet cannot be instrumented at all.
1212
- */
1213
- nativeDialog?: NativeDialogSnapshot;
1214
- /**
1215
- * Lists detected in the visible tree. Each list's items have their
1216
- * own per-item texts/buttons/inputs/toggles, NOT duplicated in the
1217
- * flat top-level arrays — preserving the row association the flat
1218
- * shape destroys.
1219
- */
1220
- lists: ListSnapshot[];
1221
- /**
1222
- * Choice groups detected from visible cards/rows/chips/buttons, used
1223
- * for select-like flows where no text input exists.
1224
- */
1225
- choiceGroups: ChoiceGroupSnapshot[];
1226
- /**
1227
- * Scrollable surfaces that carry no rows. Absent/empty means either
1228
- * the screen does not scroll or the SDK could not observe that it
1229
- * does — never that the visible content is all the content.
1230
- */
1231
- scrollables?: ScrollableSnapshot[];
1232
- /**
1233
- * Interaction graph: visible actionable elements with stable ids,
1234
- * semantic roles, labels, and execution fallbacks. Agents should
1235
- * prefer these ids over synthetic ordinal handles.
1236
- */
1237
- elements: InteractionElementSnapshot[];
1238
- /**
1239
- * Set when the walker's output exceeded the wire contract and
1240
- * `clampSnapshotToWireLimits` dropped part of it (see
1241
- * `introspection/wireLimits.ts`). Absent means the observation is
1242
- * complete.
1243
- *
1244
- * The server surfaces this to the model: a screen whose text was cut
1245
- * at 500 entries must not be read as a screen with only 500 things on
1246
- * it. Without the flag a truncated observation is indistinguishable
1247
- * from a short one.
1248
- */
1249
- truncated?: boolean;
1250
- /**
1251
- * What moved since the previous observation. See {@link SnapshotDelta}
1252
- * — absent means there was nothing to compare against, which is a
1253
- * different statement from "nothing changed".
1254
- *
1255
- * Attached by the platform adapter rather than by the walker: the
1256
- * baseline has to be the last snapshot that was actually SENT, and
1257
- * `captureSnapshot` is also called for internal probes that never
1258
- * leave the device.
1259
- */
1260
- delta?: SnapshotDelta;
1261
- /** Diagnostic counts for debugging */
1262
- stats?: {
1263
- visitedFibers: number;
1264
- skippedHidden: number;
1265
- /**
1266
- * How many controls the walker could name, and how well.
1267
- *
1268
- * `WalkDetectorCounts` counts RECOGNITIONS, not emissions, so a screen
1269
- * whose controls were all silently dropped still reported healthy
1270
- * detector numbers. This is the emission side: `positional` climbing is
1271
- * the signal that an app needs annotating, and comparing it between a
1272
- * debug and a release build is the first real measurement of what
1273
- * minification costs the agent.
1274
- */
1275
- identity?: {
1276
- declared: number;
1277
- derived: number;
1278
- positional: number;
1279
- };
1280
- };
1281
- }
1282
753
  /**
1283
754
  * Localized copy for escalation system messages, injected by the chat
1284
755
  * surface (the machine has no i18n access — same pattern as errorPrefix).
@@ -1296,69 +767,25 @@ interface EscalationStrings {
1296
767
  offer: string;
1297
768
  }
1298
769
 
1299
- type TraceListener = (entries: AppilotsTraceEntry[]) => void;
1300
- declare function recordAppilotsDebugTrace(entry: Omit<AppilotsTraceEntry, 'id'> & {
1301
- id?: string;
1302
- }): void;
1303
- declare function getAppilotsDebugTraces(): AppilotsTraceEntry[];
1304
- declare function clearAppilotsDebugTraces(): void;
1305
- declare function subscribeAppilotsDebugTraces(listener: TraceListener): () => void;
1306
-
1307
- /**
1308
- * Human-readable labels and error messages for the action breadcrumb.
1309
- *
1310
- * Strings are PT-BR hardcoded for now. i18n is planned for backlog item
1311
- * 4.1 (Personalização) — when that lands, these strings move into the
1312
- * locale bundles.
1313
- *
1314
- * Two responsibilities:
1315
- * 1. `describeAction(action)` — turns a typed AgentAction into a label
1316
- * that varies by lifecycle state (pending/running/done/failed).
1317
- * 2. `humanizeError(raw, action)` — sanitises the raw error string from
1318
- * the executor into a short user-facing reason. Stack traces and
1319
- * protocol errors are collapsed into "algo deu errado" so users
1320
- * aren't shown technical noise.
1321
- */
1322
-
1323
- type BreadcrumbState = 'pending' | 'running' | 'success' | 'failed';
1324
- interface BreadcrumbItem {
1325
- /** What to render on the line. */
1326
- label: string;
1327
- /** Lifecycle state — drives icon + colour in the breadcrumb. */
1328
- state: BreadcrumbState;
1329
- }
1330
- /**
1331
- * Map an AgentAction + its current status to a breadcrumb item ready to
1332
- * render. The function is intentionally defensive — both the native-tools
1333
- * and JSON-fallback code paths feed actions through here, and the JSON
1334
- * path is loose with payload shapes, so every field access has to assume
1335
- * `unknown`.
1336
- */
1337
- declare function describeAction(action: AgentAction): BreadcrumbItem;
1338
- /**
1339
- * Convert the executor's raw error string into a short, user-facing
1340
- * reason that fits inside parentheses on the breadcrumb line. Returns
1341
- * `undefined` when there's no useful information to show — caller can
1342
- * then drop the parenthetical entirely.
1343
- *
1344
- * Heuristics:
1345
- * - Apply known-pattern rewrites (rejected, not found, network, etc.)
1346
- * - If the result looks technical (stack frame, HTTP status, JSON
1347
- * dump) or is suspiciously long, fall back to "algo deu errado".
1348
- * - Trim and lowercase the first letter so it reads naturally inside
1349
- * the parens after the action verb.
1350
- */
1351
- declare function humanizeError(raw: string | undefined, _action?: AgentAction): string | undefined;
1352
-
1353
770
  interface AppilotsConfig {
771
+ /** Persist the session handle to resume a mission after an app restart. */
772
+ sessionStorage?: AppilotsSessionStorage;
1354
773
  /** Project ID from the Appilots dashboard */
1355
774
  projectId: string;
1356
775
  /** API base URL (defaults to Appilots cloud) */
1357
776
  apiBaseUrl?: string;
1358
777
  /** SDK API key (ak_...) for authenticating with the backend */
1359
778
  apiKey?: string;
1360
- /** Agent permissions for this app instance */
1361
- permissions?: AgentPermissions;
779
+ /**
780
+ * Agent permissions for this app instance.
781
+ *
782
+ * PARTIAL: name only the flags you want to change. Every flag you
783
+ * omit takes its default (see `DEFAULT_AGENT_PERMISSIONS`), which is
784
+ * also what a config with no `permissions` key at all gets — the two
785
+ * used to disagree, and a `.appilotsrc` naming three of the four
786
+ * flags silently denied the fourth.
787
+ */
788
+ permissions?: Partial<AgentPermissions>;
1362
789
  /** Enable debug logging */
1363
790
  debug?: boolean;
1364
791
  /**
@@ -1516,6 +943,12 @@ interface UseAppilotsNavigationReturn {
1516
943
  declare function useAppilotsNavigation(): UseAppilotsNavigationReturn;
1517
944
 
1518
945
  interface UseAppilotsChatReturn {
946
+ mission?: MissionView | null;
947
+ pauseMission: () => Promise<void>;
948
+ resumeMission: () => Promise<void>;
949
+ cancelMission: () => Promise<void>;
950
+ hasStartedActing: boolean;
951
+ replyLocale: AppilotsLocale | null;
1519
952
  messages: ChatMessage[];
1520
953
  isLoading: boolean;
1521
954
  loadingStatusKey: 'thinking' | 'statusAnalyzing' | 'statusWaitingApp' | 'statusAdjusting';
@@ -1536,9 +969,8 @@ interface UseAppilotsChatReturn {
1536
969
  /**
1537
970
  * Cancels the in-flight generation (OKR-008 KR4). Streamed partial
1538
971
  * text is kept in the transcript; a no-op when nothing is in flight.
1539
- * Cancellation only covers the generation phase — once actions start
1540
- * executing on-device they run to completion (interrupting a half-done
1541
- * form fill would leave the app in a worse state than finishing it).
972
+ * Pending actions and later continuation responses are discarded; an
973
+ * action already dispatched on-device is allowed to finish.
1542
974
  */
1543
975
  cancelMessage: () => void;
1544
976
  clearMessages: () => void;
@@ -1616,6 +1048,45 @@ interface UseAppilotsActionsReturn {
1616
1048
  */
1617
1049
  declare function useAppilotsActions(options?: UseAppilotsActionsOptions): UseAppilotsActionsReturn;
1618
1050
 
1051
+ /**
1052
+ * What a registration hook hands back for the app to spread.
1053
+ *
1054
+ * The registration hooks (`useAppilotsField`, `useAppilotsTarget`,
1055
+ * `useAppilotsToggle`, `useAppilotsSlider`) returned `void`. They put the
1056
+ * declared id in the ComponentRegistry, where the EXECUTOR looks it up,
1057
+ * and nothing carried that id to the rendered element — so the control
1058
+ * ended up with two identities: the declared one, which is what the
1059
+ * application map shows the agent, and one `walkFiber` derives from the
1060
+ * visible label (`testID ?? accessibilityLabel`, then `labelToId`, then
1061
+ * position).
1062
+ *
1063
+ * The two agree only while the label spells the id. A translated app, an
1064
+ * icon-only control, a reworded button or a label composed at runtime
1065
+ * breaks the coincidence, and the agent then asks for something the
1066
+ * snapshot does not contain.
1067
+ *
1068
+ * Spreading the return value closes it:
1069
+ *
1070
+ * ```tsx
1071
+ * <Switch {...useAppilotsToggle('pushEnabled', { value, onValueChange })} />
1072
+ * ```
1073
+ *
1074
+ * Ignoring it is still valid — every existing call site keeps compiling
1075
+ * and behaving exactly as before, which is why this is additive rather
1076
+ * than a new required argument.
1077
+ */
1078
+ interface AppilotsElementProps {
1079
+ /**
1080
+ * The declared id, published where the identity chain looks FIRST.
1081
+ *
1082
+ * Spread it last if the component also takes a `testID` of its own and
1083
+ * you want yours to win; spread it first if you want the declared id
1084
+ * to win. The SDK does not decide that for you here, because unlike
1085
+ * the HOC path there is no way to see what else you are passing.
1086
+ */
1087
+ testID: string;
1088
+ }
1089
+
1619
1090
  /**
1620
1091
  * ComponentRegistry — Central registry mapping component IDs to their
1621
1092
  * refs, callbacks, and metadata so the ActionExecutor can find and
@@ -1635,6 +1106,8 @@ interface FieldEntry {
1635
1106
  setValue: (value: string) => void;
1636
1107
  /** Optional: focus the input */
1637
1108
  focus?: () => void;
1109
+ /** End editing after the latest render, without submitting the form. */
1110
+ finishEditing?: () => void;
1638
1111
  /** Field type hint for the executor */
1639
1112
  fieldType?: 'text' | 'select' | 'toggle' | 'date' | 'number' | 'custom';
1640
1113
  /** Human-readable label */
@@ -1826,7 +1299,7 @@ interface UseAppilotsFieldOptions {
1826
1299
  * @param id - Unique identifier for this field (e.g. "plate", "customerName")
1827
1300
  * @param options - Field configuration
1828
1301
  */
1829
- declare function useAppilotsField(id: string, options: UseAppilotsFieldOptions): void;
1302
+ declare function useAppilotsField(id: string, options: UseAppilotsFieldOptions): AppilotsElementProps;
1830
1303
 
1831
1304
  /**
1832
1305
  * useAppilotsTarget — Register a pressable UI element (button, card, link)
@@ -1845,6 +1318,7 @@ declare function useAppilotsField(id: string, options: UseAppilotsFieldOptions):
1845
1318
  * return <Button title="Submit" onPress={handleSubmit} />;
1846
1319
  * ```
1847
1320
  */
1321
+
1848
1322
  interface UseAppilotsTargetOptions {
1849
1323
  /** Primary press handler */
1850
1324
  onPress: () => void;
@@ -1864,7 +1338,7 @@ interface UseAppilotsTargetOptions {
1864
1338
  * @param id - Unique identifier (e.g. "submitVehicle", "openSettings")
1865
1339
  * @param options - Target configuration
1866
1340
  */
1867
- declare function useAppilotsTarget(id: string, options: UseAppilotsTargetOptions): void;
1341
+ declare function useAppilotsTarget(id: string, options: UseAppilotsTargetOptions): AppilotsElementProps;
1868
1342
 
1869
1343
  /**
1870
1344
  * useAppilotsToggle — Register a toggle/switch with the ComponentRegistry
@@ -1884,6 +1358,7 @@ declare function useAppilotsTarget(id: string, options: UseAppilotsTargetOptions
1884
1358
  * return <Switch value={pushEnabled} onValueChange={setPushEnabled} />;
1885
1359
  * ```
1886
1360
  */
1361
+
1887
1362
  interface UseAppilotsToggleOptions {
1888
1363
  /** Current toggle value */
1889
1364
  value: boolean;
@@ -1901,7 +1376,7 @@ interface UseAppilotsToggleOptions {
1901
1376
  * @param id - Unique identifier (e.g. "pushNotifications", "darkMode")
1902
1377
  * @param options - Toggle configuration
1903
1378
  */
1904
- declare function useAppilotsToggle(id: string, options: UseAppilotsToggleOptions): void;
1379
+ declare function useAppilotsToggle(id: string, options: UseAppilotsToggleOptions): AppilotsElementProps;
1905
1380
 
1906
1381
  /**
1907
1382
  * useAppilotsSlider — Register a slider / adjustable numeric control with
@@ -1931,6 +1406,7 @@ declare function useAppilotsToggle(id: string, options: UseAppilotsToggleOptions
1931
1406
  * return <MySlider value={mileage} onChange={setMileage} min={0} max={300000} />;
1932
1407
  * ```
1933
1408
  */
1409
+
1934
1410
  interface UseAppilotsSliderOptions {
1935
1411
  /** Current slider value */
1936
1412
  value: number;
@@ -1954,7 +1430,7 @@ interface UseAppilotsSliderOptions {
1954
1430
  * @param id - Unique identifier (e.g. "quilometragem", "volume")
1955
1431
  * @param options - Slider configuration
1956
1432
  */
1957
- declare function useAppilotsSlider(id: string, options: UseAppilotsSliderOptions): void;
1433
+ declare function useAppilotsSlider(id: string, options: UseAppilotsSliderOptions): AppilotsElementProps;
1958
1434
 
1959
1435
  interface SuggestedPrompt {
1960
1436
  /** Display label shown on the chip and inserted into the input on tap. */
@@ -2005,4 +1481,4 @@ interface UseSuggestedPromptsReturn {
2005
1481
  */
2006
1482
  declare function useSuggestedPrompts(options: UseSuggestedPromptsOptions): UseSuggestedPromptsReturn;
2007
1483
 
2008
- export { componentRegistry as $, type AppilotsThemeTokens as A, type BreadcrumbItem as B, type ComponentRegistry as C, type ListSnapshot as D, type EscalationState as E, type FieldEntry as F, type RemotePersonalization as G, type SliderEntry as H, type InteractionElementEntry as I, type SuggestedPrompt as J, type ToggleEntry as K, type ListItemSnapshot as L, type MessageRole as M, type NavigationPayload as N, type ToggleSnapshot as O, type PartialThemeTokens as P, type UseAppilotsFieldOptions as Q, RateLimitedError as R, type ScreenSnapshot as S, type TargetEntry as T, type UIInteractionPayload as U, type UseAppilotsSliderOptions as V, type UseAppilotsTargetOptions as W, type UseAppilotsToggleOptions as X, type UseSuggestedPromptsOptions as Y, type UseSuggestedPromptsReturn as Z, clearAppilotsDebugTraces as _, type AppilotsLocale as a, createComponentRegistry as a0, defaultDarkTheme as a1, defaultLightTheme as a2, describeAction as a3, getAppilotsDebugTraces as a4, humanizeError as a5, mergeThemeTokens as a6, recordAppilotsDebugTrace as a7, subscribeAppilotsDebugTraces as a8, useAppilots as a9, useAppilotsActions as aa, useAppilotsChat as ab, useAppilotsContext as ac, useAppilotsField as ad, useAppilotsNavigation as ae, useAppilotsSlider as af, useAppilotsTarget as ag, useAppilotsToggle as ah, useSuggestedPrompts as ai, type AgentAction as b, type AgentPermissions as c, type AppilotsEvent as d, type AgentActionType as e, type AgentMessage as f, AppilotsClient as g, type AppilotsClientOptions as h, type AppilotsConfig as i, type AppilotsEventHandler as j, type AppilotsEventType as k, AppilotsProvider as l, type AppilotsProviderProps as m, type AppilotsTraceEntry as n, type AppilotsUser as o, type BreadcrumbState as p, type ButtonSnapshot as q, type ChatMessage as r, type ChoiceGroupSnapshot as s, type ChoiceOptionSnapshot as t, type ComponentEntry as u, type ComponentKind as v, type FormFillPayload as w, type InputSnapshot as x, type InteractionElementListContext as y, type InteractionElementSnapshot as z };
1484
+ export { useAppilotsTarget as $, type AppilotsTraceEntry as A, type UseAppilotsTargetOptions as B, type ComponentRegistry as C, type UseAppilotsToggleOptions as D, type EscalationState as E, type FieldEntry as F, type UseSuggestedPromptsOptions as G, type UseSuggestedPromptsReturn as H, componentRegistry as I, createComponentRegistry as J, defaultDarkTheme as K, defaultLightTheme as L, type MessageRole as M, type NavigationPayload as N, mergeThemeTokens as O, type PartialThemeTokens as P, useAppilots as Q, RateLimitedError as R, type SliderEntry as S, type TargetEntry as T, type UIInteractionPayload as U, useAppilotsActions as V, useAppilotsChat as W, useAppilotsContext as X, useAppilotsField as Y, useAppilotsNavigation as Z, useAppilotsSlider as _, type AgentAction as a, useAppilotsToggle as a0, useSuggestedPrompts as a1, type AppilotsLocale as b, type AppilotsThemeTokens as c, type AppilotsSessionStorage as d, type AgentPermissions as e, type AppilotsEvent as f, type AgentActionType as g, type AgentMessage as h, AppilotsClient as i, type AppilotsClientOptions as j, type AppilotsConfig as k, type AppilotsElementProps as l, type AppilotsEventHandler as m, type AppilotsEventType as n, AppilotsProvider as o, type AppilotsProviderProps as p, type AppilotsUser as q, type ChatMessage as r, type ComponentEntry as s, type ComponentKind as t, type FormFillPayload as u, type RemotePersonalization as v, type SuggestedPrompt as w, type ToggleEntry as x, type UseAppilotsFieldOptions as y, type UseAppilotsSliderOptions as z };