@appilots/sdk 0.3.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.
- package/dist/{chunk-BKFO4DHW.mjs → chunk-42WI3UDB.mjs} +322 -1479
- package/dist/{chunk-N2I3CA7Q.js → chunk-CHY5D2PV.js} +5 -5
- package/dist/{chunk-DUSYQXAQ.mjs → chunk-GEKCGVJN.mjs} +1 -1
- package/dist/{chunk-QMSMXTED.mjs → chunk-JBOLV5AM.mjs} +1435 -51
- package/dist/{chunk-MCY5YFYD.js → chunk-V3TUIIT2.js} +1442 -57
- package/dist/{chunk-XNKPS7W3.js → chunk-Y7EA6R2G.js} +394 -1551
- package/dist/hooks/index.d.mts +1 -2
- package/dist/hooks/index.d.ts +1 -2
- package/dist/hooks/index.js +11 -11
- package/dist/hooks/index.mjs +2 -2
- package/dist/index-Cb0D6uKH.d.mts +1543 -0
- package/dist/index-Cb0D6uKH.d.ts +1543 -0
- package/dist/index.d.mts +5 -282
- package/dist/index.d.ts +5 -282
- package/dist/index.js +65 -65
- package/dist/index.mjs +5 -5
- package/dist/navigation/index.js +13 -13
- package/dist/navigation/index.mjs +2 -2
- package/hooks/package.json +9 -0
- package/metro.d.ts +49 -0
- package/metro.js +0 -37
- package/navigation/package.json +9 -0
- package/package.json +31 -12
- package/dist/index-BYVRBzjJ.d.mts +0 -619
- package/dist/index-BYVRBzjJ.d.ts +0 -619
|
@@ -0,0 +1,1543 @@
|
|
|
1
|
+
import * as React$1 from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Theme tokens — the source of truth for any color, font, radius or
|
|
6
|
+
* shadow used inside the SDK's chat UI. Components must read from these
|
|
7
|
+
* tokens (via {@link useAppilotsTheme}) rather than hardcoding values, so
|
|
8
|
+
* a developer who sets a `theme` prop or dashboard config can re-skin
|
|
9
|
+
* the whole chat without forking the SDK.
|
|
10
|
+
*
|
|
11
|
+
* BACKLOG 4.1.
|
|
12
|
+
*
|
|
13
|
+
* Adding a new token:
|
|
14
|
+
* 1. Add a field to `AppilotsThemeTokens` below.
|
|
15
|
+
* 2. Set a value in BOTH `defaultLight` and `defaultDark` (and ideally
|
|
16
|
+
* keep them visually consistent — e.g. dark text on light bg ↔
|
|
17
|
+
* light text on dark bg).
|
|
18
|
+
* 3. Use it in components via `useAppilotsTheme()`.
|
|
19
|
+
* 4. Mirror the field on `themeTokensSchema` in `@appilots/shared` if
|
|
20
|
+
* it should be settable from the dashboard.
|
|
21
|
+
*
|
|
22
|
+
* Removing a token is a breaking change — bump the SDK minor.
|
|
23
|
+
*/
|
|
24
|
+
interface AppilotsThemeTokens {
|
|
25
|
+
/** Hex color values. The 8-digit form (#RRGGBBAA) is allowed. */
|
|
26
|
+
colors: {
|
|
27
|
+
/** Brand color — send button, FAB, header dot, links. */
|
|
28
|
+
primary: string;
|
|
29
|
+
/** Secondary brand accent — used sparingly (e.g. the human-agent/operator icon accent in message rows). */
|
|
30
|
+
secondary: string;
|
|
31
|
+
/** Page/modal background, behind the messages list. */
|
|
32
|
+
background: string;
|
|
33
|
+
/** Surface color for assistant message bubbles, input field, chips. */
|
|
34
|
+
surface: string;
|
|
35
|
+
/** Default text color (high contrast on background). */
|
|
36
|
+
text: string;
|
|
37
|
+
/** Muted text — placeholders, secondary labels, "Powered by". */
|
|
38
|
+
textSecondary: string;
|
|
39
|
+
/** 1px hairlines under header, around chips. */
|
|
40
|
+
border: string;
|
|
41
|
+
/** Success state — completed action checks in the breadcrumb (ActionBreadcrumb `success` tone). */
|
|
42
|
+
success: string;
|
|
43
|
+
/**
|
|
44
|
+
* Warning / caution state — drives the breadcrumb's `pending` tone
|
|
45
|
+
* (queued, not-yet-run actions). The default is a neutral gray, not
|
|
46
|
+
* amber, so it renders pixel-identical to the SDK's pre-4.2 hardcoded
|
|
47
|
+
* palette out of the box; set an amber/yellow here to make queued
|
|
48
|
+
* actions visually louder.
|
|
49
|
+
*/
|
|
50
|
+
warning: string;
|
|
51
|
+
/** Error state — failed action rows (ActionBreadcrumb `failed` tone) and destructive badges/CTAs (confirm card, reject button). */
|
|
52
|
+
error: string;
|
|
53
|
+
/** Text color for chip/button labels (e.g. suggested prompts). */
|
|
54
|
+
buttonText: string;
|
|
55
|
+
/** Text color inside the assistant's message bubble (not the user's — that stays white on `primary`). */
|
|
56
|
+
bubbleText: string;
|
|
57
|
+
/**
|
|
58
|
+
* Text color inside the USER's message bubble (on `primary`). Optional
|
|
59
|
+
* mirror of `bubbleText` for the user side — falls back to white,
|
|
60
|
+
* matching the SDK's pre-4.2 hardcoded value, when unset.
|
|
61
|
+
*/
|
|
62
|
+
userBubbleText: string;
|
|
63
|
+
};
|
|
64
|
+
typography: {
|
|
65
|
+
/** Font family applied to ALL chat text. Falls back to system. */
|
|
66
|
+
fontFamily: string;
|
|
67
|
+
fontSizeXs: number;
|
|
68
|
+
fontSizeSm: number;
|
|
69
|
+
fontSizeBase: number;
|
|
70
|
+
fontSizeLg: number;
|
|
71
|
+
};
|
|
72
|
+
radii: {
|
|
73
|
+
/** Tight corners — chips, small badges. */
|
|
74
|
+
sm: number;
|
|
75
|
+
/** Default — input field, send button, secondary buttons. */
|
|
76
|
+
md: number;
|
|
77
|
+
/** Generous — chat sheet, message bubbles. */
|
|
78
|
+
lg: number;
|
|
79
|
+
};
|
|
80
|
+
/** Optional drop-shadows (RN-shaped, applied via View style). */
|
|
81
|
+
shadows: {
|
|
82
|
+
/** Tells the developer's dark/light intent. Components don't read
|
|
83
|
+
* this directly — they read tokens — but `mode` is forwarded so
|
|
84
|
+
* status bar / image color choices can branch on it. */
|
|
85
|
+
appearance: 'light' | 'dark';
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Default LIGHT theme — used when the device is in light mode and the
|
|
90
|
+
* developer hasn't overridden anything. Visually matches the SDK's
|
|
91
|
+
* pre-4.1 hardcoded palette so existing apps don't change look on
|
|
92
|
+
* upgrade.
|
|
93
|
+
*/
|
|
94
|
+
declare const defaultLightTheme: AppilotsThemeTokens;
|
|
95
|
+
/**
|
|
96
|
+
* Default DARK theme — used when the device is in dark mode and the
|
|
97
|
+
* developer hasn't overridden anything. Picked to roughly mirror the
|
|
98
|
+
* light theme: same hue family, inverted background/text, slightly
|
|
99
|
+
* cooler border/surface tones.
|
|
100
|
+
*/
|
|
101
|
+
declare const defaultDarkTheme: AppilotsThemeTokens;
|
|
102
|
+
/**
|
|
103
|
+
* Deep-partial of the token tree — what a developer hands to the SDK
|
|
104
|
+
* via the `theme` prop or dashboard config. Every field optional;
|
|
105
|
+
* unspecified fields fall through to the default.
|
|
106
|
+
*/
|
|
107
|
+
type PartialThemeTokens = {
|
|
108
|
+
colors?: Partial<AppilotsThemeTokens['colors']>;
|
|
109
|
+
typography?: Partial<AppilotsThemeTokens['typography']>;
|
|
110
|
+
radii?: Partial<AppilotsThemeTokens['radii']>;
|
|
111
|
+
shadows?: Partial<AppilotsThemeTokens['shadows']>;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Merge a partial token tree on top of a base. Keys present in the
|
|
115
|
+
* partial win; missing keys keep the base value. Two levels deep is
|
|
116
|
+
* enough for the current token shape, so we don't need a generic deep
|
|
117
|
+
* merge — keeps tree-shaking friendly.
|
|
118
|
+
*/
|
|
119
|
+
declare function mergeThemeTokens(base: AppilotsThemeTokens, partial?: PartialThemeTokens | null): AppilotsThemeTokens;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* SDK locale code. Canonical source of truth for `AppilotsLocale` — moved
|
|
123
|
+
* here (out of the React Native-coupled `i18n/I18nProvider`) so that
|
|
124
|
+
* platform-agnostic contract types (`RemotePersonalization.defaultLocale`)
|
|
125
|
+
* don't pull in a React/React Native import just for a string union type.
|
|
126
|
+
*
|
|
127
|
+
* `@appilots/sdk`'s `i18n/I18nProvider.tsx` re-exports this type from its
|
|
128
|
+
* original public path (`@appilots/sdk`'s `./i18n` barrel) so nothing
|
|
129
|
+
* downstream of the SDK's public API changes.
|
|
130
|
+
*
|
|
131
|
+
* Adding a locale = adding a bundle file in `@appilots/sdk`'s
|
|
132
|
+
* `i18n/bundles/` AND a branch in `i18n/I18nProvider.tsx`'s `BUNDLES`
|
|
133
|
+
* map AND a variant here. BACKLOG 4.1.
|
|
134
|
+
*/
|
|
135
|
+
type AppilotsLocale = 'pt-BR' | 'en' | 'es';
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Core types for the Appilots SDK.
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Payload of `GET /agent/personalization` — what the dev configured in
|
|
143
|
+
* the dashboard under Projects > Personalization. Fetched once on
|
|
144
|
+
* `AppilotsProvider` mount and applied by `AppilotsChat` as a fallback
|
|
145
|
+
* for any prop the dev did NOT set explicitly in code
|
|
146
|
+
* (prop > remote > SDK default).
|
|
147
|
+
*
|
|
148
|
+
* Only JSON-serializable values travel here: URLs/hex/booleans work,
|
|
149
|
+
* React nodes and local `require()` assets can only come via props.
|
|
150
|
+
* `null` means "not configured" — fall through to the next source.
|
|
151
|
+
*/
|
|
152
|
+
interface RemotePersonalization {
|
|
153
|
+
assistantName: string | null;
|
|
154
|
+
/** Avatar URL shown next to assistant turns. */
|
|
155
|
+
assistantAvatar: string | null;
|
|
156
|
+
/** Emoji or image URL for the empty-state badge. */
|
|
157
|
+
emptyStateIcon: string | null;
|
|
158
|
+
welcomeMessage: string | null;
|
|
159
|
+
chatTitle: string | null;
|
|
160
|
+
poweredByVisible: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Partial token tree merged onto the SDK defaults. `mode` (when set)
|
|
163
|
+
* plays the role of the `themeMode` prop.
|
|
164
|
+
*/
|
|
165
|
+
theme: (PartialThemeTokens & {
|
|
166
|
+
mode?: 'auto' | 'light' | 'dark';
|
|
167
|
+
}) | null;
|
|
168
|
+
defaultLocale: AppilotsLocale | null;
|
|
169
|
+
triggerButtonColor: string | null;
|
|
170
|
+
triggerButtonImageUrl: string | null;
|
|
171
|
+
}
|
|
172
|
+
type MessageRole = 'user' | 'assistant' | 'system' | 'human_agent';
|
|
173
|
+
interface ChatMessage {
|
|
174
|
+
id: string;
|
|
175
|
+
role: MessageRole;
|
|
176
|
+
content: string;
|
|
177
|
+
timestamp: number;
|
|
178
|
+
metadata?: Record<string, unknown>;
|
|
179
|
+
}
|
|
180
|
+
interface AppilotsTraceEntry {
|
|
181
|
+
id: string;
|
|
182
|
+
timestamp: number;
|
|
183
|
+
type: AppilotsEventType | 'agent:trace';
|
|
184
|
+
messageId?: string;
|
|
185
|
+
actionId?: string;
|
|
186
|
+
actionType?: AgentActionType | string;
|
|
187
|
+
status?: AgentAction['status'] | 'started' | 'error';
|
|
188
|
+
summary?: string;
|
|
189
|
+
data: Record<string, unknown>;
|
|
190
|
+
}
|
|
191
|
+
interface AgentMessage extends ChatMessage {
|
|
192
|
+
role: 'assistant';
|
|
193
|
+
actions?: AgentAction[];
|
|
194
|
+
thinking?: string;
|
|
195
|
+
}
|
|
196
|
+
type AgentActionType = 'navigate' | 'form_fill' | 'ui_interaction' | 'scroll_list' | 'confirm' | 'custom';
|
|
197
|
+
interface AgentAction {
|
|
198
|
+
id: string;
|
|
199
|
+
type: AgentActionType;
|
|
200
|
+
payload: NavigationPayload | FormFillPayload | UIInteractionPayload | ScrollListPayload | Record<string, unknown>;
|
|
201
|
+
status: 'pending' | 'executing' | 'completed' | 'failed';
|
|
202
|
+
error?: string;
|
|
203
|
+
/** ID of the assistant message that triggered this action */
|
|
204
|
+
messageId?: string;
|
|
205
|
+
/**
|
|
206
|
+
* BACKLOG 2.2 — When the server flags an action as destructive,
|
|
207
|
+
* the SDK renders any preceding `confirm` action with the danger
|
|
208
|
+
* variant and expects the action to be gated by user approval.
|
|
209
|
+
*/
|
|
210
|
+
destructive?: boolean;
|
|
211
|
+
}
|
|
212
|
+
interface NavigationPayload {
|
|
213
|
+
screenName: string;
|
|
214
|
+
params?: Record<string, unknown>;
|
|
215
|
+
navigationAction: 'push' | 'navigate' | 'replace' | 'goBack' | 'reset';
|
|
216
|
+
/**
|
|
217
|
+
* Optional path of parent navigator route names for nested screens.
|
|
218
|
+
* E.g. ['HomeTab', 'VehiclesTab'] to reach a screen inside
|
|
219
|
+
* HomeTab → VehiclesTab → screenName.
|
|
220
|
+
*
|
|
221
|
+
* React Navigation requires nested navigation params:
|
|
222
|
+
* nav.navigate('HomeTab', { screen: 'VehiclesTab', params: { screen: 'VehicleCreate' } })
|
|
223
|
+
*
|
|
224
|
+
* The AI model provides this based on the MCP document's navigation graph.
|
|
225
|
+
*/
|
|
226
|
+
path?: string[];
|
|
227
|
+
}
|
|
228
|
+
interface FormFillPayload {
|
|
229
|
+
screenName: string;
|
|
230
|
+
fields: FormFieldAction[];
|
|
231
|
+
/**
|
|
232
|
+
* If true, the handler presses the screen's primary submit button
|
|
233
|
+
* after all fields are filled. The submit button is resolved via
|
|
234
|
+
* `registerScreen({ actions: [{ type: 'submit', ... }] })` first,
|
|
235
|
+
* then via the fiber tree and a label heuristic.
|
|
236
|
+
*
|
|
237
|
+
* Aligned with the `submitAfterFill` field in the LLM tool schema
|
|
238
|
+
* (`agentTools.form_fill` in ai-relay.ts).
|
|
239
|
+
*/
|
|
240
|
+
submitAfterFill?: boolean;
|
|
241
|
+
}
|
|
242
|
+
interface FormFieldAction {
|
|
243
|
+
fieldId: string;
|
|
244
|
+
fieldType: 'text' | 'select' | 'toggle' | 'date' | 'number' | 'custom';
|
|
245
|
+
value: unknown;
|
|
246
|
+
label?: string;
|
|
247
|
+
}
|
|
248
|
+
interface UIInteractionPayload {
|
|
249
|
+
componentId: string;
|
|
250
|
+
/** Canonical server/LLM identifier. `componentId` is kept as SDK alias. */
|
|
251
|
+
targetId?: string;
|
|
252
|
+
action: 'press' | 'longPress' | 'scroll' | 'swipe' | 'focus' | 'set_value';
|
|
253
|
+
/**
|
|
254
|
+
* Numeric value for `set_value` (sliders / adjustable controls).
|
|
255
|
+
* The handler clamps to the slider's [min, max] and snaps to its step.
|
|
256
|
+
*/
|
|
257
|
+
value?: number;
|
|
258
|
+
params?: Record<string, unknown>;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Scroll a list/collection so virtualized off-screen rows mount and
|
|
262
|
+
* show up in the next observation. Mirrors `scrollListPayloadSchema`
|
|
263
|
+
* in @appilots/shared. At least one of the fields should be present;
|
|
264
|
+
* the handler falls back to paging one viewport down when only a
|
|
265
|
+
* listId is given.
|
|
266
|
+
*/
|
|
267
|
+
interface ScrollListPayload {
|
|
268
|
+
/** Runtime list id from the observation's "Lists visible" block. */
|
|
269
|
+
listId?: string;
|
|
270
|
+
/** 1-based index in the list's DATA to scroll to. */
|
|
271
|
+
toIndex?: number;
|
|
272
|
+
/** Coarse paging when no target index is known. */
|
|
273
|
+
direction?: 'up' | 'down';
|
|
274
|
+
}
|
|
275
|
+
interface AgentPermissions {
|
|
276
|
+
canNavigate: boolean;
|
|
277
|
+
canFillForms: boolean;
|
|
278
|
+
canInteractUI: boolean;
|
|
279
|
+
canSubmitForms: boolean;
|
|
280
|
+
allowedScreens?: string[];
|
|
281
|
+
blockedScreens?: string[];
|
|
282
|
+
allowedActions?: AgentActionType[];
|
|
283
|
+
}
|
|
284
|
+
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';
|
|
285
|
+
interface AppilotsEvent {
|
|
286
|
+
type: AppilotsEventType;
|
|
287
|
+
timestamp: number;
|
|
288
|
+
data: Record<string, unknown>;
|
|
289
|
+
}
|
|
290
|
+
type AppilotsEventHandler = (event: AppilotsEvent) => void;
|
|
291
|
+
/**
|
|
292
|
+
* Client-side view of an open escalation. `resolved` never appears
|
|
293
|
+
* here — resolution clears the state (after surfacing a system
|
|
294
|
+
* message in the transcript).
|
|
295
|
+
*/
|
|
296
|
+
interface EscalationState {
|
|
297
|
+
id: string;
|
|
298
|
+
status: 'pending' | 'active';
|
|
299
|
+
/** Set once an operator claims the conversation. */
|
|
300
|
+
operatorName?: string;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
interface AppilotsClientOptions {
|
|
304
|
+
projectId: string;
|
|
305
|
+
apiBaseUrl?: string;
|
|
306
|
+
apiKey?: string;
|
|
307
|
+
debug?: boolean;
|
|
308
|
+
timeout?: number;
|
|
309
|
+
headers?: Record<string, string>;
|
|
310
|
+
/**
|
|
311
|
+
* Version of the MCP doc bundled with this app build. The server
|
|
312
|
+
* compares this against the currently-active MCP doc for the
|
|
313
|
+
* project and emits a `mcp_version_mismatch` telemetry event when
|
|
314
|
+
* they differ — the canonical sign that the dev shipped an app
|
|
315
|
+
* update but forgot to regenerate/upload the MCP.
|
|
316
|
+
*
|
|
317
|
+
* Tip: import this from the MCP file the CLI generates, or read it
|
|
318
|
+
* from your app's package.json so it stays in lockstep with releases.
|
|
319
|
+
*/
|
|
320
|
+
mcpVersion?: string;
|
|
321
|
+
/**
|
|
322
|
+
* The host app's version (e.g. from package.json or
|
|
323
|
+
* react-native-device-info). Sent as `X-App-Version` on every request
|
|
324
|
+
* so the server can match the compatible MCP document per app build —
|
|
325
|
+
* essential for OTA-updated fleets where multiple app versions coexist.
|
|
326
|
+
*/
|
|
327
|
+
appVersion?: string;
|
|
328
|
+
/**
|
|
329
|
+
* Who the app's current user is. `id` becomes the session's
|
|
330
|
+
* externalUserId; `name`/`identifiers` are upserted into the
|
|
331
|
+
* workspace's end-users registry (fire-and-forget identify after the
|
|
332
|
+
* session opens) so support operators see a person, not an anonymous
|
|
333
|
+
* id. Identifiers are dashboard-only — never sent to the LLM.
|
|
334
|
+
*/
|
|
335
|
+
user?: AppilotsUser;
|
|
336
|
+
}
|
|
337
|
+
interface AppilotsUser {
|
|
338
|
+
/** The app's own user id (matches your backend). */
|
|
339
|
+
id: string;
|
|
340
|
+
name?: string;
|
|
341
|
+
/** Free-form lookup keys: { email, phone, cpf, ... }. Max 10. */
|
|
342
|
+
identifiers?: Record<string, string>;
|
|
343
|
+
}
|
|
344
|
+
interface SendMessageResponse {
|
|
345
|
+
sessionId: string;
|
|
346
|
+
message: ChatMessage;
|
|
347
|
+
/** Summary message to show AFTER actions complete */
|
|
348
|
+
summaryMessage?: ChatMessage;
|
|
349
|
+
actions?: AgentAction[];
|
|
350
|
+
usage?: {
|
|
351
|
+
tokensUsed: number;
|
|
352
|
+
modelUsed: string;
|
|
353
|
+
latencyMs: number;
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
interface SendMessageStreamOptions {
|
|
357
|
+
/**
|
|
358
|
+
* Fired per SSE text-delta with the chunk and the accumulated text so
|
|
359
|
+
* far — render `fullText` directly; chunks may split words/markdown.
|
|
360
|
+
*/
|
|
361
|
+
onTextDelta?: (chunk: string, fullText: string) => void;
|
|
362
|
+
/** Fired once when the server announces the session id. */
|
|
363
|
+
onSession?: (sessionId: string) => void;
|
|
364
|
+
/** Abort mid-generation (stop button). Rejects with name='AbortError'. */
|
|
365
|
+
signal?: AbortSignal;
|
|
366
|
+
}
|
|
367
|
+
/** Runtime context sent with every user message. */
|
|
368
|
+
interface SendMessageContext {
|
|
369
|
+
/**
|
|
370
|
+
* Which client platform this observation came from — `'react-native'`,
|
|
371
|
+
* `'web'`, `'android'`, `'ios'`, or any other client-defined string.
|
|
372
|
+
* The server treats an absent value as `'react-native'` (see
|
|
373
|
+
* `docs/agent-contract.md`'s "The `platform` field" section), so
|
|
374
|
+
* setting it is optional but forward-compatible: a client that sends
|
|
375
|
+
* it explicitly isn't relying on that default staying `'react-native'`
|
|
376
|
+
* forever.
|
|
377
|
+
*/
|
|
378
|
+
platform?: string;
|
|
379
|
+
currentScreen?: string;
|
|
380
|
+
formState?: Record<string, unknown>;
|
|
381
|
+
/** Design-time screen metadata from registerScreen() or the MCP doc */
|
|
382
|
+
screenMetadata?: Record<string, unknown>;
|
|
383
|
+
/** Runtime React Navigation summary captured by the SDK */
|
|
384
|
+
navigationState?: {
|
|
385
|
+
currentRouteName?: string;
|
|
386
|
+
activePath?: string[];
|
|
387
|
+
rootRouteNames?: string[];
|
|
388
|
+
currentRouteNames?: string[];
|
|
389
|
+
routeNames?: string[];
|
|
390
|
+
canGoBack?: boolean;
|
|
391
|
+
};
|
|
392
|
+
/** Runtime snapshot from captureSnapshot() — what's actually visible */
|
|
393
|
+
snapshot?: Record<string, unknown>;
|
|
394
|
+
/** Legacy registry snapshot — kept as a fallback signal */
|
|
395
|
+
registeredComponents?: Array<{
|
|
396
|
+
id: string;
|
|
397
|
+
kind: 'field' | 'target' | 'toggle';
|
|
398
|
+
screen?: string;
|
|
399
|
+
label?: string;
|
|
400
|
+
}>;
|
|
401
|
+
/** Runtime list registry snapshot — collection metadata even when rows are virtualized. */
|
|
402
|
+
registeredLists?: Array<{
|
|
403
|
+
kind: 'list';
|
|
404
|
+
id: string;
|
|
405
|
+
component: string;
|
|
406
|
+
itemCount?: number;
|
|
407
|
+
label?: string;
|
|
408
|
+
screen?: string;
|
|
409
|
+
refreshing?: boolean;
|
|
410
|
+
empty?: boolean;
|
|
411
|
+
}>;
|
|
412
|
+
}
|
|
413
|
+
declare class AppilotsClient {
|
|
414
|
+
private readonly baseUrl;
|
|
415
|
+
private readonly projectId;
|
|
416
|
+
private readonly headers;
|
|
417
|
+
private readonly timeout;
|
|
418
|
+
private readonly debug;
|
|
419
|
+
private readonly mcpVersion;
|
|
420
|
+
private readonly user;
|
|
421
|
+
private sessionId;
|
|
422
|
+
/** Guard so identify fires at most once per client instance. */
|
|
423
|
+
private identified;
|
|
424
|
+
constructor(options: AppilotsClientOptions);
|
|
425
|
+
private log;
|
|
426
|
+
private describeNonJsonResponse;
|
|
427
|
+
private request;
|
|
428
|
+
createSession(userId?: string, deviceInfo?: Record<string, unknown>): Promise<string>;
|
|
429
|
+
/**
|
|
430
|
+
* Upsert the configured user into the end-users registry. Fires once
|
|
431
|
+
* per client, after the first session opens; fire-and-forget — a
|
|
432
|
+
* failed identify must never break the chat.
|
|
433
|
+
*/
|
|
434
|
+
private identifyConfiguredUser;
|
|
435
|
+
destroySession(): Promise<void>;
|
|
436
|
+
getSessionId(): string | null;
|
|
437
|
+
sendMessage(content: string, context?: SendMessageContext): Promise<SendMessageResponse>;
|
|
438
|
+
/**
|
|
439
|
+
* Streaming variant of `sendMessage` — consumes the server's SSE
|
|
440
|
+
* endpoint (`/agent/message/stream`) and fires `onTextDelta` per chunk
|
|
441
|
+
* so the UI can render tokens as they arrive (OKR-008 KR1). Resolves
|
|
442
|
+
* with the same `SendMessageResponse` shape once the `done` event lands.
|
|
443
|
+
*
|
|
444
|
+
* Uses XMLHttpRequest because React Native's fetch does not expose
|
|
445
|
+
* `response.body` for incremental reads; RN's XHR delivers progressive
|
|
446
|
+
* `responseText`, which is the standard SSE transport on RN.
|
|
447
|
+
*
|
|
448
|
+
* Errors:
|
|
449
|
+
* - `StreamTransportError` — transport failed before ANY event; safe
|
|
450
|
+
* for the caller to fall back to the non-streaming endpoint.
|
|
451
|
+
* - `StreamAbortError` (name='AbortError') — options.signal fired;
|
|
452
|
+
* carries `partialContent` so the UI can keep what streamed.
|
|
453
|
+
*/
|
|
454
|
+
sendMessageStream(content: string, context?: SendMessageContext, options?: SendMessageStreamOptions): Promise<SendMessageResponse>;
|
|
455
|
+
continueAgent(results: Array<{
|
|
456
|
+
actionId: string;
|
|
457
|
+
type: string;
|
|
458
|
+
success: boolean;
|
|
459
|
+
error?: string;
|
|
460
|
+
summary?: string;
|
|
461
|
+
/** BACKLOG 3.2 — structured failure diagnose, server uses for recovery */
|
|
462
|
+
diagnose?: {
|
|
463
|
+
category: 'component-not-found' | 'disabled' | 'validation' | 'network-5xx' | 'network-4xx' | 'screen-timeout' | 'ambiguous-target' | 'unknown';
|
|
464
|
+
visibleMessage?: string;
|
|
465
|
+
fieldId?: string;
|
|
466
|
+
targetId?: string;
|
|
467
|
+
screen?: string;
|
|
468
|
+
httpStatus?: number;
|
|
469
|
+
/** Candidate ids when resolution failed due to ambiguity. */
|
|
470
|
+
candidates?: string[];
|
|
471
|
+
recoverable?: boolean;
|
|
472
|
+
requiresUserInput?: boolean;
|
|
473
|
+
};
|
|
474
|
+
/** BACKLOG 3.2 — how many times this fingerprint has been retried (1 = first retry). */
|
|
475
|
+
recoveryAttempt?: number;
|
|
476
|
+
/** BACKLOG 3.2 — set when SDK has hit the per-action retry cap. */
|
|
477
|
+
recoveryExhausted?: boolean;
|
|
478
|
+
/**
|
|
479
|
+
* Set when a handler reported success but the expected visible
|
|
480
|
+
* side-effect did not happen, e.g. navigate returned but route stayed.
|
|
481
|
+
*/
|
|
482
|
+
toolWithoutEffect?: boolean;
|
|
483
|
+
effect?: 'unknown' | 'none' | 'partial' | 'changed' | 'completed';
|
|
484
|
+
userVisibleStatusKey?: string;
|
|
485
|
+
}>, context: Record<string, unknown>, hop: number): Promise<SendMessageResponse & {
|
|
486
|
+
isDone: boolean;
|
|
487
|
+
hop: number;
|
|
488
|
+
}>;
|
|
489
|
+
executeAction(actionId: string): Promise<AgentAction>;
|
|
490
|
+
/**
|
|
491
|
+
* Rewrite an action's type when the AI used a semantically-misclassified
|
|
492
|
+
* action type. The most common case: the LLM emits
|
|
493
|
+
* { type: 'ui_interaction', payload: { action: 'select', targetId, value } }
|
|
494
|
+
* to mean "set this field's value", which is really a form_fill. We detect
|
|
495
|
+
* that here and convert it before normalization, so the executor sees the
|
|
496
|
+
* right action shape and the field's setValue() is called instead of a
|
|
497
|
+
* meaningless press on a non-pressable component.
|
|
498
|
+
*/
|
|
499
|
+
private rewriteActionTypeIfNeeded;
|
|
500
|
+
/**
|
|
501
|
+
* Normalize API tool call payloads to match SDK's expected payload types.
|
|
502
|
+
* The AI model may return slightly different field names than what the
|
|
503
|
+
* SDK executor expects, and may use vocabulary (e.g. "select", "scroll_to",
|
|
504
|
+
* "open") that the SDK doesn't natively support — we remap those to the
|
|
505
|
+
* nearest equivalent here so the executor never sees an "unknown action".
|
|
506
|
+
*/
|
|
507
|
+
private normalizePayload;
|
|
508
|
+
/**
|
|
509
|
+
* Legacy per-action status report. The agentic chat loop reports via
|
|
510
|
+
* `continueAgent` (which carries diagnose + a fresh snapshot); this
|
|
511
|
+
* endpoint remains for apps driving actions manually through
|
|
512
|
+
* `useAppilotsActions`. `diagnose` is forwarded when provided so even
|
|
513
|
+
* the legacy path gives the server a failure category.
|
|
514
|
+
*/
|
|
515
|
+
completeAction(actionId: string, success: boolean, error?: string, diagnose?: Record<string, unknown>): Promise<void>;
|
|
516
|
+
/**
|
|
517
|
+
* Fetch actions the server has persisted but that haven't been
|
|
518
|
+
* completed yet. Use after an SSE drop or a hard error to recover
|
|
519
|
+
* the batch without losing the actions the model already decided.
|
|
520
|
+
*
|
|
521
|
+
* Returns an empty array if there are no pending actions or if the
|
|
522
|
+
* call fails — never throws.
|
|
523
|
+
*/
|
|
524
|
+
recoverPendingActions(sessionId?: string): Promise<AgentAction[]>;
|
|
525
|
+
/**
|
|
526
|
+
* Fetch dev-defined and empirically-popular prompts to seed the chat
|
|
527
|
+
* empty-state with one-tap chips. Cheap (cached server-side for 1h) but
|
|
528
|
+
* still a network hit, so callers should debounce around chat-open.
|
|
529
|
+
*
|
|
530
|
+
* @param screen Optional — when provided, response includes screen-scoped
|
|
531
|
+
* popular prompts in addition to globals.
|
|
532
|
+
*/
|
|
533
|
+
getPopularPrompts(screen?: string, limit?: number): Promise<{
|
|
534
|
+
devDefined: string[];
|
|
535
|
+
screenPopular: string[];
|
|
536
|
+
globalPopular: string[];
|
|
537
|
+
computedAt: string;
|
|
538
|
+
}>;
|
|
539
|
+
/**
|
|
540
|
+
* Fetch the project's dashboard-configured personalization (theme,
|
|
541
|
+
* branding, FAB color/image, locale...). Called by `AppilotsProvider`
|
|
542
|
+
* once on mount — cheap (cached server-side for 1h) and applied by
|
|
543
|
+
* `AppilotsChat` as a fallback for props not set explicitly in code.
|
|
544
|
+
*
|
|
545
|
+
* Throws on network/HTTP failure — the provider treats any failure as
|
|
546
|
+
* "no remote config" and stays on props/defaults.
|
|
547
|
+
*/
|
|
548
|
+
getPersonalization(): Promise<RemotePersonalization>;
|
|
549
|
+
/**
|
|
550
|
+
* Ask for a human operator. Idempotent: if the session already has
|
|
551
|
+
* an open escalation the server returns it instead of creating a
|
|
552
|
+
* duplicate. Creates the session first when the chat had none yet
|
|
553
|
+
* (the server sends it back and we adopt it, so the whole
|
|
554
|
+
* conversation stays under one sessionId).
|
|
555
|
+
*/
|
|
556
|
+
requestEscalation(reason: 'user_requested' | 'agent_gave_up', note?: string): Promise<{
|
|
557
|
+
escalationId: string;
|
|
558
|
+
status: 'pending' | 'active';
|
|
559
|
+
}>;
|
|
560
|
+
/**
|
|
561
|
+
* Tell the server the user walked away from the conversation (chat
|
|
562
|
+
* cleared) so the escalation is closed instead of leaving the
|
|
563
|
+
* operator talking to nobody. Fire-and-forget: never throws — the
|
|
564
|
+
* local cleanup must proceed even if the network is gone.
|
|
565
|
+
*/
|
|
566
|
+
abandonEscalation(escalationId: string): Promise<void>;
|
|
567
|
+
/** User message routed to the human operator (no LLM involved). */
|
|
568
|
+
sendEscalationMessage(escalationId: string, content: string): Promise<void>;
|
|
569
|
+
/**
|
|
570
|
+
* Poll fallback / reconnect catch-up: status + operator messages
|
|
571
|
+
* created after `since` (ISO timestamp of the last one we have).
|
|
572
|
+
*/
|
|
573
|
+
getEscalationUpdates(escalationId: string, since?: string): Promise<{
|
|
574
|
+
status: 'pending' | 'active' | 'resolved';
|
|
575
|
+
messages: Array<{
|
|
576
|
+
id: string;
|
|
577
|
+
content: string;
|
|
578
|
+
createdAt: string;
|
|
579
|
+
}>;
|
|
580
|
+
}>;
|
|
581
|
+
/**
|
|
582
|
+
* Open the escalation SSE channel — operator replies + status
|
|
583
|
+
* changes pushed live. Same XHR transport as `sendMessageStream`
|
|
584
|
+
* (RN's fetch can't read a body incrementally).
|
|
585
|
+
*
|
|
586
|
+
* Long-lived by design: no idle watchdog — the server pings every
|
|
587
|
+
* 25s, and a genuinely dead connection surfaces as `onClose`, which
|
|
588
|
+
* the hook answers with a backoff reconnect + `since` catch-up.
|
|
589
|
+
* Returns a close function; closing never fires `onClose`.
|
|
590
|
+
*/
|
|
591
|
+
openEscalationStream(escalationId: string, handlers: {
|
|
592
|
+
since?: string;
|
|
593
|
+
onHumanMessage: (message: {
|
|
594
|
+
id: string;
|
|
595
|
+
content: string;
|
|
596
|
+
createdAt: string;
|
|
597
|
+
}) => void;
|
|
598
|
+
onStatus: (status: 'pending' | 'active' | 'resolved', operatorName?: string) => void;
|
|
599
|
+
/** Transport ended (error or server close) — caller decides on reconnect. */
|
|
600
|
+
onClose: () => void;
|
|
601
|
+
}): () => void;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Snapshot types — the platform-agnostic "view model" of what the user
|
|
606
|
+
* is currently seeing on screen, sent to the AI agent so it has
|
|
607
|
+
* accurate visible state.
|
|
608
|
+
*
|
|
609
|
+
* Every platform walker (React Native fiber walk, web DOM walk, ...)
|
|
610
|
+
* produces this same shape; the wire contract it feeds is
|
|
611
|
+
* `agentSnapshotSchema` in `@appilots/shared`.
|
|
612
|
+
*/
|
|
613
|
+
interface InputSnapshot {
|
|
614
|
+
/** Best identifier — testID/data-testid, accessibilityLabel/aria-label, or placeholder */
|
|
615
|
+
id?: string;
|
|
616
|
+
/** Human-readable label inferred from accessibility metadata or sibling text */
|
|
617
|
+
label?: string;
|
|
618
|
+
/** Current value (only present for controlled inputs) */
|
|
619
|
+
value?: string;
|
|
620
|
+
/** Placeholder text */
|
|
621
|
+
placeholder?: string;
|
|
622
|
+
/** Whether the input is editable */
|
|
623
|
+
editable?: boolean;
|
|
624
|
+
/** Whether the input is secure (password field) */
|
|
625
|
+
secure?: boolean;
|
|
626
|
+
/** Inferred type based on the platform's input-type metadata */
|
|
627
|
+
type?: 'text' | 'email' | 'number' | 'phone' | 'password';
|
|
628
|
+
/**
|
|
629
|
+
* True when this input lives inside a currently-visible modal. When a
|
|
630
|
+
* modal is open, only inModal elements can actually receive input —
|
|
631
|
+
* everything else is behind the overlay.
|
|
632
|
+
*/
|
|
633
|
+
inModal?: boolean;
|
|
634
|
+
}
|
|
635
|
+
interface ButtonSnapshot {
|
|
636
|
+
/** Best identifier — testID/data-testid, accessibilityLabel/aria-label, or inferred from child text */
|
|
637
|
+
id?: string;
|
|
638
|
+
/** Human-readable label — usually the visible text inside the button */
|
|
639
|
+
label?: string;
|
|
640
|
+
/** Whether the button is disabled */
|
|
641
|
+
disabled?: boolean;
|
|
642
|
+
/**
|
|
643
|
+
* Whether the button currently appears selected/active — set by
|
|
644
|
+
* grouped, mutually-exclusive controls (segmented controls, radio
|
|
645
|
+
* groups) where each option is its own pressable target.
|
|
646
|
+
*/
|
|
647
|
+
selected?: boolean;
|
|
648
|
+
/** True when this button lives inside a currently-visible modal. */
|
|
649
|
+
inModal?: boolean;
|
|
650
|
+
}
|
|
651
|
+
interface ToggleSnapshot {
|
|
652
|
+
/** Best identifier */
|
|
653
|
+
id?: string;
|
|
654
|
+
/** Human-readable label */
|
|
655
|
+
label?: string;
|
|
656
|
+
/** Current on/off state */
|
|
657
|
+
value?: boolean;
|
|
658
|
+
/** True when this toggle lives inside a currently-visible modal. */
|
|
659
|
+
inModal?: boolean;
|
|
660
|
+
}
|
|
661
|
+
interface SliderSnapshot {
|
|
662
|
+
/** Registry id — the executable handle. */
|
|
663
|
+
id?: string;
|
|
664
|
+
/** Human-readable label */
|
|
665
|
+
label?: string;
|
|
666
|
+
/** Current numeric value */
|
|
667
|
+
value?: number;
|
|
668
|
+
/** Lower bound the executor clamps to */
|
|
669
|
+
min?: number;
|
|
670
|
+
/** Upper bound the executor clamps to */
|
|
671
|
+
max?: number;
|
|
672
|
+
/** Step the executor snaps to (omitted = continuous) */
|
|
673
|
+
step?: number;
|
|
674
|
+
/** Whether the slider is currently disabled */
|
|
675
|
+
disabled?: boolean;
|
|
676
|
+
/** True when this slider lives inside a currently-visible modal. */
|
|
677
|
+
inModal?: boolean;
|
|
678
|
+
}
|
|
679
|
+
interface ListItemSnapshot {
|
|
680
|
+
/** 1-indexed position within the parent list (matches "selecione o terceiro"). */
|
|
681
|
+
index: number;
|
|
682
|
+
/**
|
|
683
|
+
* 0-based index of this row in the list's backing DATA, when known.
|
|
684
|
+
* For scrolled/virtualized lists this differs from `index`.
|
|
685
|
+
*/
|
|
686
|
+
dataIndex?: number;
|
|
687
|
+
/** Framework key of the row, if present (typically the item's domain id). */
|
|
688
|
+
reactKey?: string;
|
|
689
|
+
/** Runtime key supplied by list tracking, if available. */
|
|
690
|
+
itemKey?: string;
|
|
691
|
+
/** Texts captured from this item's subtree, preserving row association. */
|
|
692
|
+
texts: string[];
|
|
693
|
+
/** Buttons inside this item — e.g. an inline "Edit" button on a row. */
|
|
694
|
+
buttons: ButtonSnapshot[];
|
|
695
|
+
/** Inputs inside this item — rare but possible (inline edit row). */
|
|
696
|
+
inputs: InputSnapshot[];
|
|
697
|
+
/** Toggles inside this item. */
|
|
698
|
+
toggles: ToggleSnapshot[];
|
|
699
|
+
/**
|
|
700
|
+
* Synthetic id assigned by the walker. Stable within a single
|
|
701
|
+
* snapshot; format `list-<L>-item-<I>` (0-indexed L, 1-indexed I).
|
|
702
|
+
* Used by tap-by-ordinal resolution in the executor.
|
|
703
|
+
*/
|
|
704
|
+
syntheticId: string;
|
|
705
|
+
}
|
|
706
|
+
interface ListSnapshot {
|
|
707
|
+
/** 0-indexed list ordinal — multiple lists on one screen get 0, 1, 2... */
|
|
708
|
+
index: number;
|
|
709
|
+
/** Runtime list id when tracking or explicit props provide one. */
|
|
710
|
+
id?: string;
|
|
711
|
+
/** The container component/tag name as observed by the walker. */
|
|
712
|
+
containerType: string;
|
|
713
|
+
/**
|
|
714
|
+
* Source that identified this list. `'fiber'`/`'auto-tracked'` are
|
|
715
|
+
* the walker's own discovery tags (a DOM walker reports
|
|
716
|
+
* `'auto-tracked'` for app-annotated lists and omits the field for
|
|
717
|
+
* heuristically-detected ones); `'registry'` means the list came
|
|
718
|
+
* from the SDK's list registry rather than the tree walk.
|
|
719
|
+
*/
|
|
720
|
+
source?: 'fiber' | 'auto-tracked' | 'registry';
|
|
721
|
+
/** Total data-set count when the list exposes it. */
|
|
722
|
+
itemCount?: number;
|
|
723
|
+
/** Number of row items captured in this snapshot. */
|
|
724
|
+
visibleItemCount?: number;
|
|
725
|
+
/** True when the list reports a refresh/loading state. */
|
|
726
|
+
refreshing?: boolean;
|
|
727
|
+
/** True when total item count is known and zero. */
|
|
728
|
+
empty?: boolean;
|
|
729
|
+
/** Human-readable label if the app supplied one. */
|
|
730
|
+
label?: string;
|
|
731
|
+
/** Items in visible order. */
|
|
732
|
+
items: ListItemSnapshot[];
|
|
733
|
+
/**
|
|
734
|
+
* Lightweight text projection of the list's FULL data set (capped),
|
|
735
|
+
* so the agent can see/search rows that virtualization keeps
|
|
736
|
+
* unmounted. Each entry: 0-based data index, stable key, short text.
|
|
737
|
+
*/
|
|
738
|
+
dataPreview?: ListDataPreviewEntry[];
|
|
739
|
+
/** Current vertical scroll offset in px, when readable. */
|
|
740
|
+
scrollOffsetY?: number;
|
|
741
|
+
/** True when there is scrollable content above the viewport. */
|
|
742
|
+
canScrollUp?: boolean;
|
|
743
|
+
/** True when there is scrollable content below the viewport. */
|
|
744
|
+
canScrollDown?: boolean;
|
|
745
|
+
}
|
|
746
|
+
interface ListDataPreviewEntry {
|
|
747
|
+
/** 0-based index in the list's backing data. */
|
|
748
|
+
index: number;
|
|
749
|
+
/** Stable key from the item's domain id when available. */
|
|
750
|
+
key?: string;
|
|
751
|
+
/** Short human-readable projection of the item (capped length). */
|
|
752
|
+
text: string;
|
|
753
|
+
}
|
|
754
|
+
interface ChoiceOptionSnapshot {
|
|
755
|
+
/** 1-indexed option position within this group. */
|
|
756
|
+
index: number;
|
|
757
|
+
/** Stable-enough id for the current snapshot/action turn. */
|
|
758
|
+
syntheticId: string;
|
|
759
|
+
/** Best target id if this option is backed by a pressable component. */
|
|
760
|
+
targetId?: string;
|
|
761
|
+
/** Human-readable option label. */
|
|
762
|
+
label?: string;
|
|
763
|
+
/** Text segments that belong to this option. */
|
|
764
|
+
texts: string[];
|
|
765
|
+
/** Whether this option appears selected. */
|
|
766
|
+
selected?: boolean;
|
|
767
|
+
/** Whether this option appears disabled. */
|
|
768
|
+
disabled?: boolean;
|
|
769
|
+
}
|
|
770
|
+
interface ChoiceGroupSnapshot {
|
|
771
|
+
/** 0-indexed group ordinal on the current screen. */
|
|
772
|
+
index: number;
|
|
773
|
+
/** Runtime id when known, usually inherited from a list/collection. */
|
|
774
|
+
id?: string;
|
|
775
|
+
/** Human-readable label when known. */
|
|
776
|
+
label?: string;
|
|
777
|
+
/** Source that produced this choice group. */
|
|
778
|
+
source?: 'list' | 'buttons' | 'heuristic';
|
|
779
|
+
/** Visible options in order. */
|
|
780
|
+
options: ChoiceOptionSnapshot[];
|
|
781
|
+
}
|
|
782
|
+
interface InteractionElementListContext {
|
|
783
|
+
listIndex?: number;
|
|
784
|
+
listId?: string;
|
|
785
|
+
listLabel?: string;
|
|
786
|
+
itemIndex?: number;
|
|
787
|
+
itemKey?: string;
|
|
788
|
+
reactKey?: string;
|
|
789
|
+
syntheticId?: string;
|
|
790
|
+
}
|
|
791
|
+
interface InteractionElementSnapshot {
|
|
792
|
+
/** Stable id for the current screen/content, preferred for tool calls. */
|
|
793
|
+
id: string;
|
|
794
|
+
/** Semantic UI role. */
|
|
795
|
+
role: 'option' | 'button' | 'input' | 'toggle' | 'slider' | 'listItem';
|
|
796
|
+
/** Human-readable label. */
|
|
797
|
+
label?: string;
|
|
798
|
+
/** Text segments associated with this element. */
|
|
799
|
+
texts: string[];
|
|
800
|
+
/** Actions supported by this element. */
|
|
801
|
+
actions: Array<'press' | 'focus' | 'toggle' | 'setValue'>;
|
|
802
|
+
/** Whether the element is currently disabled. */
|
|
803
|
+
disabled?: boolean;
|
|
804
|
+
/** Whether the element appears selected. */
|
|
805
|
+
selected?: boolean;
|
|
806
|
+
/** Source that produced the element. */
|
|
807
|
+
source?: 'list' | 'button' | 'input' | 'toggle' | 'slider' | 'choice';
|
|
808
|
+
/** Legacy/fallback target id, if any. */
|
|
809
|
+
targetId?: string;
|
|
810
|
+
/** Context for row/list options. */
|
|
811
|
+
listContext?: InteractionElementListContext;
|
|
812
|
+
/**
|
|
813
|
+
* True when the underlying component lives inside a currently-visible
|
|
814
|
+
* modal — the only targets actually touchable while the overlay is up.
|
|
815
|
+
*/
|
|
816
|
+
inModal?: boolean;
|
|
817
|
+
}
|
|
818
|
+
interface ScreenSnapshot {
|
|
819
|
+
/** The currently active route name, if known */
|
|
820
|
+
route: string | null;
|
|
821
|
+
/** All visible static text */
|
|
822
|
+
texts: string[];
|
|
823
|
+
/** All text inputs currently rendered (and visible) */
|
|
824
|
+
inputs: InputSnapshot[];
|
|
825
|
+
/** All button-like components */
|
|
826
|
+
buttons: ButtonSnapshot[];
|
|
827
|
+
/** All toggle components */
|
|
828
|
+
toggles: ToggleSnapshot[];
|
|
829
|
+
/** Sliders / adjustable numeric controls. */
|
|
830
|
+
sliders: SliderSnapshot[];
|
|
831
|
+
/** Whether a loading indicator is visible */
|
|
832
|
+
loading: boolean;
|
|
833
|
+
/** Whether a modal is currently open */
|
|
834
|
+
modalOpen: boolean;
|
|
835
|
+
/**
|
|
836
|
+
* Lists detected in the visible tree. Each list's items have their
|
|
837
|
+
* own per-item texts/buttons/inputs/toggles, NOT duplicated in the
|
|
838
|
+
* flat top-level arrays — preserving the row association the flat
|
|
839
|
+
* shape destroys.
|
|
840
|
+
*/
|
|
841
|
+
lists: ListSnapshot[];
|
|
842
|
+
/**
|
|
843
|
+
* Choice groups detected from visible cards/rows/chips/buttons, used
|
|
844
|
+
* for select-like flows where no text input exists.
|
|
845
|
+
*/
|
|
846
|
+
choiceGroups: ChoiceGroupSnapshot[];
|
|
847
|
+
/**
|
|
848
|
+
* Interaction graph: visible actionable elements with stable ids,
|
|
849
|
+
* semantic roles, labels, and execution fallbacks. Agents should
|
|
850
|
+
* prefer these ids over synthetic ordinal handles.
|
|
851
|
+
*/
|
|
852
|
+
elements: InteractionElementSnapshot[];
|
|
853
|
+
/** Diagnostic counts for debugging */
|
|
854
|
+
stats?: {
|
|
855
|
+
visitedFibers: number;
|
|
856
|
+
skippedHidden: number;
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Localized copy for escalation system messages, injected by the chat
|
|
861
|
+
* surface (the machine has no i18n access — same pattern as errorPrefix).
|
|
862
|
+
* When omitted, no system messages are appended but the state machine
|
|
863
|
+
* still works.
|
|
864
|
+
*/
|
|
865
|
+
interface EscalationStrings {
|
|
866
|
+
/** Appended right after the escalation is created. */
|
|
867
|
+
requested: string;
|
|
868
|
+
/** Appended when an operator claims the conversation. */
|
|
869
|
+
connected: string;
|
|
870
|
+
/** Appended when the operator resolves — AI takes over again. */
|
|
871
|
+
resolved: string;
|
|
872
|
+
/** Content of the offer chip message appended when the agent gives up. */
|
|
873
|
+
offer: string;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
type TraceListener = (entries: AppilotsTraceEntry[]) => void;
|
|
877
|
+
declare function recordAppilotsDebugTrace(entry: Omit<AppilotsTraceEntry, 'id'> & {
|
|
878
|
+
id?: string;
|
|
879
|
+
}): void;
|
|
880
|
+
declare function getAppilotsDebugTraces(): AppilotsTraceEntry[];
|
|
881
|
+
declare function clearAppilotsDebugTraces(): void;
|
|
882
|
+
declare function subscribeAppilotsDebugTraces(listener: TraceListener): () => void;
|
|
883
|
+
|
|
884
|
+
/**
|
|
885
|
+
* Human-readable labels and error messages for the action breadcrumb.
|
|
886
|
+
*
|
|
887
|
+
* Strings are PT-BR hardcoded for now. i18n is planned for backlog item
|
|
888
|
+
* 4.1 (Personalização) — when that lands, these strings move into the
|
|
889
|
+
* locale bundles.
|
|
890
|
+
*
|
|
891
|
+
* Two responsibilities:
|
|
892
|
+
* 1. `describeAction(action)` — turns a typed AgentAction into a label
|
|
893
|
+
* that varies by lifecycle state (pending/running/done/failed).
|
|
894
|
+
* 2. `humanizeError(raw, action)` — sanitises the raw error string from
|
|
895
|
+
* the executor into a short user-facing reason. Stack traces and
|
|
896
|
+
* protocol errors are collapsed into "algo deu errado" so users
|
|
897
|
+
* aren't shown technical noise.
|
|
898
|
+
*/
|
|
899
|
+
|
|
900
|
+
type BreadcrumbState = 'pending' | 'running' | 'success' | 'failed';
|
|
901
|
+
interface BreadcrumbItem {
|
|
902
|
+
/** What to render on the line. */
|
|
903
|
+
label: string;
|
|
904
|
+
/** Lifecycle state — drives icon + colour in the breadcrumb. */
|
|
905
|
+
state: BreadcrumbState;
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Map an AgentAction + its current status to a breadcrumb item ready to
|
|
909
|
+
* render. The function is intentionally defensive — both the native-tools
|
|
910
|
+
* and JSON-fallback code paths feed actions through here, and the JSON
|
|
911
|
+
* path is loose with payload shapes, so every field access has to assume
|
|
912
|
+
* `unknown`.
|
|
913
|
+
*/
|
|
914
|
+
declare function describeAction(action: AgentAction): BreadcrumbItem;
|
|
915
|
+
/**
|
|
916
|
+
* Convert the executor's raw error string into a short, user-facing
|
|
917
|
+
* reason that fits inside parentheses on the breadcrumb line. Returns
|
|
918
|
+
* `undefined` when there's no useful information to show — caller can
|
|
919
|
+
* then drop the parenthetical entirely.
|
|
920
|
+
*
|
|
921
|
+
* Heuristics:
|
|
922
|
+
* - Apply known-pattern rewrites (rejected, not found, network, etc.)
|
|
923
|
+
* - If the result looks technical (stack frame, HTTP status, JSON
|
|
924
|
+
* dump) or is suspiciously long, fall back to "algo deu errado".
|
|
925
|
+
* - Trim and lowercase the first letter so it reads naturally inside
|
|
926
|
+
* the parens after the action verb.
|
|
927
|
+
*/
|
|
928
|
+
declare function humanizeError(raw: string | undefined, _action?: AgentAction): string | undefined;
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* SDK version — bumped by changesets on release. Lives in its own module
|
|
932
|
+
* so runtime code (AppilotsClient) can import it without pulling the whole
|
|
933
|
+
* public barrel in and creating an import cycle.
|
|
934
|
+
*/
|
|
935
|
+
declare const SDK_VERSION = "0.1.0";
|
|
936
|
+
|
|
937
|
+
interface AppilotsConfig {
|
|
938
|
+
/** Project ID from the Appilots dashboard */
|
|
939
|
+
projectId: string;
|
|
940
|
+
/** API base URL (defaults to Appilots cloud) */
|
|
941
|
+
apiBaseUrl?: string;
|
|
942
|
+
/** SDK API key (ak_...) for authenticating with the backend */
|
|
943
|
+
apiKey?: string;
|
|
944
|
+
/** Agent permissions for this app instance */
|
|
945
|
+
permissions?: AgentPermissions;
|
|
946
|
+
/** Enable debug logging */
|
|
947
|
+
debug?: boolean;
|
|
948
|
+
/**
|
|
949
|
+
* Host app version (e.g. package.json version). Forwarded to the API
|
|
950
|
+
* as `X-App-Version` so the server can serve the MCP document matching
|
|
951
|
+
* this app build (OTA fleets run several versions at once).
|
|
952
|
+
*/
|
|
953
|
+
appVersion?: string;
|
|
954
|
+
/** Version of the MCP doc bundled with this build (stale-doc telemetry). */
|
|
955
|
+
mcpVersion?: string;
|
|
956
|
+
/**
|
|
957
|
+
* Who the app's current user is. Sessions carry `user.id` as
|
|
958
|
+
* externalUserId, and name/identifiers are upserted into the
|
|
959
|
+
* end-users registry so the support queue shows a person instead of
|
|
960
|
+
* "Usuário anônimo". Identifiers never reach the LLM.
|
|
961
|
+
*/
|
|
962
|
+
user?: AppilotsUser;
|
|
963
|
+
/**
|
|
964
|
+
* Fetch the dashboard-configured personalization (theme, branding,
|
|
965
|
+
* FAB color, locale...) once on provider mount and apply it as a
|
|
966
|
+
* fallback for AppilotsChat props not set explicitly in code.
|
|
967
|
+
*
|
|
968
|
+
* Set to `false` to opt out — this is the SDK's only automatic
|
|
969
|
+
* network call before the user interacts, so apps with strict
|
|
970
|
+
* network/privacy posture can keep today's 100%-manual behavior.
|
|
971
|
+
* @default true
|
|
972
|
+
*/
|
|
973
|
+
fetchPersonalization?: boolean;
|
|
974
|
+
}
|
|
975
|
+
interface AppilotsProviderProps {
|
|
976
|
+
/**
|
|
977
|
+
* SDK config. If omitted, auto-loads from `.appilotsrc` via the Metro
|
|
978
|
+
* resolver (requires `withAppilots()` in metro.config.js).
|
|
979
|
+
*/
|
|
980
|
+
config?: AppilotsConfig;
|
|
981
|
+
children: React__default.ReactNode;
|
|
982
|
+
/** Optional custom client instance (if not provided, one is auto-created from config) */
|
|
983
|
+
client?: AppilotsClient;
|
|
984
|
+
}
|
|
985
|
+
interface AppilotsContextValue {
|
|
986
|
+
config: AppilotsConfig;
|
|
987
|
+
client: AppilotsClient;
|
|
988
|
+
subscribe: (handler: AppilotsEventHandler) => () => void;
|
|
989
|
+
emit: (event: AppilotsEvent) => void;
|
|
990
|
+
/**
|
|
991
|
+
* Dashboard-configured personalization fetched on mount. `null` until
|
|
992
|
+
* the fetch resolves — and forever, if it fails or is opted out
|
|
993
|
+
* (`fetchPersonalization: false`). Consumers must treat `null` as
|
|
994
|
+
* "use props/defaults"; the chat renders immediately with defaults
|
|
995
|
+
* and re-renders once this lands (accepted cold-start flash).
|
|
996
|
+
*/
|
|
997
|
+
remotePersonalization: RemotePersonalization | null;
|
|
998
|
+
}
|
|
999
|
+
declare function AppilotsProvider({ config: configProp, children, client: externalClient }: AppilotsProviderProps): React__default.JSX.Element;
|
|
1000
|
+
declare function useAppilotsContext(): AppilotsContextValue;
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* Convenience hook that combines all Appilots hooks into a single return value.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* ```tsx
|
|
1007
|
+
* const { messages, sendMessage, currentScreen, pendingActions } = useAppilots();
|
|
1008
|
+
* ```
|
|
1009
|
+
*/
|
|
1010
|
+
declare function useAppilots(): {
|
|
1011
|
+
config: AppilotsConfig;
|
|
1012
|
+
client: AppilotsClient;
|
|
1013
|
+
messages: ChatMessage[];
|
|
1014
|
+
isLoading: boolean;
|
|
1015
|
+
error: string | null;
|
|
1016
|
+
sendMessage: (content: string) => Promise<void>;
|
|
1017
|
+
clearMessages: () => void;
|
|
1018
|
+
clearError: () => void;
|
|
1019
|
+
currentScreen: string | null;
|
|
1020
|
+
navigationHistory: string[];
|
|
1021
|
+
setCurrentScreen: (screenName: string) => void;
|
|
1022
|
+
navigationRef: React$1.MutableRefObject<any>;
|
|
1023
|
+
pendingActions: AgentAction[];
|
|
1024
|
+
executingActions: AgentAction[];
|
|
1025
|
+
completedActions: AgentAction[];
|
|
1026
|
+
approveAction: (actionId: string) => Promise<boolean>;
|
|
1027
|
+
rejectAction: (actionId: string) => Promise<void>;
|
|
1028
|
+
};
|
|
1029
|
+
|
|
1030
|
+
interface UseAppilotsNavigationReturn {
|
|
1031
|
+
currentScreen: string | null;
|
|
1032
|
+
navigationHistory: string[];
|
|
1033
|
+
setCurrentScreen: (screenName: string) => void;
|
|
1034
|
+
/** Navigation ref setter — attach to your NavigationContainer */
|
|
1035
|
+
navigationRef: React.MutableRefObject<any>;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Hook for tracking navigation state and enabling agent-driven navigation.
|
|
1039
|
+
*
|
|
1040
|
+
* @example
|
|
1041
|
+
* ```tsx
|
|
1042
|
+
* const { currentScreen, navigationRef } = useAppilotsNavigation();
|
|
1043
|
+
*
|
|
1044
|
+
* return (
|
|
1045
|
+
* <NavigationContainer ref={navigationRef}>
|
|
1046
|
+
* <Stack.Navigator />
|
|
1047
|
+
* </NavigationContainer>
|
|
1048
|
+
* );
|
|
1049
|
+
* ```
|
|
1050
|
+
*/
|
|
1051
|
+
declare function useAppilotsNavigation(): UseAppilotsNavigationReturn;
|
|
1052
|
+
|
|
1053
|
+
interface UseAppilotsChatReturn {
|
|
1054
|
+
messages: ChatMessage[];
|
|
1055
|
+
isLoading: boolean;
|
|
1056
|
+
loadingStatusKey: 'thinking' | 'statusAnalyzing' | 'statusWaitingApp' | 'statusAdjusting';
|
|
1057
|
+
error: string | null;
|
|
1058
|
+
pendingActions: AgentAction[];
|
|
1059
|
+
/**
|
|
1060
|
+
* Open escalation, or null. While set, `sendMessage` routes to the
|
|
1061
|
+
* human channel — the agent session itself is never interrupted.
|
|
1062
|
+
*/
|
|
1063
|
+
escalation: EscalationState | null;
|
|
1064
|
+
/**
|
|
1065
|
+
* Hand the conversation to a human operator (docs/human-escalation.md).
|
|
1066
|
+
* Idempotent while an escalation is open. `agent_gave_up` is used by
|
|
1067
|
+
* the auto-offer chip; the header button sends `user_requested`.
|
|
1068
|
+
*/
|
|
1069
|
+
requestHuman: (reason?: 'user_requested' | 'agent_gave_up') => Promise<void>;
|
|
1070
|
+
sendMessage: (content: string) => Promise<void>;
|
|
1071
|
+
/**
|
|
1072
|
+
* Cancels the in-flight generation (OKR-008 KR4). Streamed partial
|
|
1073
|
+
* text is kept in the transcript; a no-op when nothing is in flight.
|
|
1074
|
+
* Cancellation only covers the generation phase — once actions start
|
|
1075
|
+
* executing on-device they run to completion (interrupting a half-done
|
|
1076
|
+
* form fill would leave the app in a worse state than finishing it).
|
|
1077
|
+
*/
|
|
1078
|
+
cancelMessage: () => void;
|
|
1079
|
+
clearMessages: () => void;
|
|
1080
|
+
clearError: () => void;
|
|
1081
|
+
}
|
|
1082
|
+
interface UseAppilotsChatOptions {
|
|
1083
|
+
/** User-facing prefix for client-side failures before the relay can answer. */
|
|
1084
|
+
errorPrefix?: string;
|
|
1085
|
+
/**
|
|
1086
|
+
* Stream assistant replies token-by-token via SSE (default true).
|
|
1087
|
+
* When the streaming transport fails before any output, the hook
|
|
1088
|
+
* falls back to the non-streaming endpoint transparently.
|
|
1089
|
+
*/
|
|
1090
|
+
streaming?: boolean;
|
|
1091
|
+
/** Localized escalation copy — see EscalationStrings. */
|
|
1092
|
+
escalationStrings?: EscalationStrings;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Hook for managing chat state and sending messages to the Appilots agent.
|
|
1096
|
+
*
|
|
1097
|
+
* This is a thin React binding over `ChatSessionMachine` from
|
|
1098
|
+
* `@appilots/client-core` — the turn/continuation/recovery orchestration
|
|
1099
|
+
* itself is platform-agnostic and shared with the web client. Everything
|
|
1100
|
+
* React Native-specific (Fiber snapshotting, React Navigation settling)
|
|
1101
|
+
* enters through `reactNativeChatAdapter`.
|
|
1102
|
+
*
|
|
1103
|
+
* @example
|
|
1104
|
+
* ```tsx
|
|
1105
|
+
* const { messages, sendMessage, isLoading } = useAppilotsChat();
|
|
1106
|
+
*
|
|
1107
|
+
* const handleSend = () => {
|
|
1108
|
+
* sendMessage('Navigate to settings');
|
|
1109
|
+
* };
|
|
1110
|
+
* ```
|
|
1111
|
+
*/
|
|
1112
|
+
declare function useAppilotsChat(options?: UseAppilotsChatOptions): UseAppilotsChatReturn;
|
|
1113
|
+
|
|
1114
|
+
interface UseAppilotsActionsOptions {
|
|
1115
|
+
/**
|
|
1116
|
+
* Navigation ref from useAppilotsNavigation().
|
|
1117
|
+
* Required for navigate actions to work.
|
|
1118
|
+
*/
|
|
1119
|
+
navigationRef?: React.MutableRefObject<any>;
|
|
1120
|
+
/**
|
|
1121
|
+
* If true, actions are executed automatically without user approval.
|
|
1122
|
+
* Confirm actions always require approval regardless of this setting.
|
|
1123
|
+
* @default false
|
|
1124
|
+
*/
|
|
1125
|
+
autoExecute?: boolean;
|
|
1126
|
+
}
|
|
1127
|
+
interface UseAppilotsActionsReturn {
|
|
1128
|
+
pendingActions: AgentAction[];
|
|
1129
|
+
executingActions: AgentAction[];
|
|
1130
|
+
completedActions: AgentAction[];
|
|
1131
|
+
approveAction: (actionId: string) => Promise<boolean>;
|
|
1132
|
+
rejectAction: (actionId: string) => Promise<void>;
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Hook for monitoring and controlling agent actions.
|
|
1136
|
+
*
|
|
1137
|
+
* A thin React binding over `ActionQueueMachine` from
|
|
1138
|
+
* `@appilots/client-core`: the queue, its status transitions, the
|
|
1139
|
+
* confirm gate (server-injected and locally synthesized) and sequential
|
|
1140
|
+
* auto-execution are platform-agnostic. React Native execution goes
|
|
1141
|
+
* through the ActionExecutor via `createReactNativeActionRunner`.
|
|
1142
|
+
*
|
|
1143
|
+
* @example
|
|
1144
|
+
* ```tsx
|
|
1145
|
+
* const { navigationRef } = useAppilotsNavigation();
|
|
1146
|
+
* const { pendingActions, approveAction, rejectAction } = useAppilotsActions({
|
|
1147
|
+
* navigationRef,
|
|
1148
|
+
* autoExecute: false,
|
|
1149
|
+
* });
|
|
1150
|
+
* ```
|
|
1151
|
+
*/
|
|
1152
|
+
declare function useAppilotsActions(options?: UseAppilotsActionsOptions): UseAppilotsActionsReturn;
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* ComponentRegistry — Central registry mapping component IDs to their
|
|
1156
|
+
* refs, callbacks, and metadata so the ActionExecutor can find and
|
|
1157
|
+
* interact with live UI elements.
|
|
1158
|
+
*
|
|
1159
|
+
* Screens register their interactive components via hooks
|
|
1160
|
+
* (useAppilotsField, useAppilotsTarget, useAppilotsToggle).
|
|
1161
|
+
* When the AI agent returns an action (e.g. form_fill with fieldId "plate"),
|
|
1162
|
+
* the executor looks up "plate" here and calls the associated setter.
|
|
1163
|
+
*/
|
|
1164
|
+
type ComponentKind = 'field' | 'target' | 'toggle' | 'slider';
|
|
1165
|
+
interface FieldEntry {
|
|
1166
|
+
kind: 'field';
|
|
1167
|
+
/** Current value of the field */
|
|
1168
|
+
getValue: () => string;
|
|
1169
|
+
/** Set the field value programmatically */
|
|
1170
|
+
setValue: (value: string) => void;
|
|
1171
|
+
/** Optional: focus the input */
|
|
1172
|
+
focus?: () => void;
|
|
1173
|
+
/** Field type hint for the executor */
|
|
1174
|
+
fieldType?: 'text' | 'select' | 'toggle' | 'date' | 'number' | 'custom';
|
|
1175
|
+
/** Human-readable label */
|
|
1176
|
+
label?: string;
|
|
1177
|
+
/** Screen where this field is registered */
|
|
1178
|
+
screen?: string;
|
|
1179
|
+
}
|
|
1180
|
+
interface TargetEntry {
|
|
1181
|
+
kind: 'target';
|
|
1182
|
+
/** Execute the primary action (press) */
|
|
1183
|
+
press: () => void;
|
|
1184
|
+
/** Optional: long press */
|
|
1185
|
+
longPress?: () => void;
|
|
1186
|
+
/** Optional: scroll to this element */
|
|
1187
|
+
scrollTo?: () => void;
|
|
1188
|
+
/** Human-readable label */
|
|
1189
|
+
label?: string;
|
|
1190
|
+
/** Screen where this target is registered */
|
|
1191
|
+
screen?: string;
|
|
1192
|
+
}
|
|
1193
|
+
interface ToggleEntry {
|
|
1194
|
+
kind: 'toggle';
|
|
1195
|
+
/** Current value */
|
|
1196
|
+
getValue: () => boolean;
|
|
1197
|
+
/** Set the toggle value */
|
|
1198
|
+
setValue: (value: boolean) => void;
|
|
1199
|
+
/** Human-readable label */
|
|
1200
|
+
label?: string;
|
|
1201
|
+
/** Screen where this toggle is registered */
|
|
1202
|
+
screen?: string;
|
|
1203
|
+
}
|
|
1204
|
+
interface SliderEntry {
|
|
1205
|
+
kind: 'slider';
|
|
1206
|
+
/** Current numeric value */
|
|
1207
|
+
getValue: () => number;
|
|
1208
|
+
/**
|
|
1209
|
+
* Set the slider value. The executor clamps to [min, max] and snaps
|
|
1210
|
+
* to `step` BEFORE calling this, so implementations can trust the
|
|
1211
|
+
* value — but re-validating is harmless.
|
|
1212
|
+
*/
|
|
1213
|
+
setValue: (value: number) => void;
|
|
1214
|
+
/** Lower bound (inclusive) */
|
|
1215
|
+
min: number;
|
|
1216
|
+
/** Upper bound (inclusive) */
|
|
1217
|
+
max: number;
|
|
1218
|
+
/** Step to snap to (omitted = continuous) */
|
|
1219
|
+
step?: number;
|
|
1220
|
+
/** Human-readable label */
|
|
1221
|
+
label?: string;
|
|
1222
|
+
/** Screen where this slider is registered */
|
|
1223
|
+
screen?: string;
|
|
1224
|
+
}
|
|
1225
|
+
type ComponentEntry = FieldEntry | TargetEntry | ToggleEntry | SliderEntry;
|
|
1226
|
+
type Listener = (id: string, entry: ComponentEntry | null) => void;
|
|
1227
|
+
/**
|
|
1228
|
+
* Public type for a registry instance. Both the singleton and any
|
|
1229
|
+
* instance returned by `createComponentRegistry()` satisfy this.
|
|
1230
|
+
*
|
|
1231
|
+
* The class itself stays internal — devs construct via the factory
|
|
1232
|
+
* to keep the surface minimal and future-proof.
|
|
1233
|
+
*/
|
|
1234
|
+
type ComponentRegistry = ComponentRegistryImpl;
|
|
1235
|
+
declare class ComponentRegistryImpl {
|
|
1236
|
+
private components;
|
|
1237
|
+
private listeners;
|
|
1238
|
+
/**
|
|
1239
|
+
* Register a component. If an entry with the same ID already exists,
|
|
1240
|
+
* it is replaced (this handles re-renders / hot-reload).
|
|
1241
|
+
*/
|
|
1242
|
+
register(id: string, entry: ComponentEntry): void;
|
|
1243
|
+
/**
|
|
1244
|
+
* Unregister a component (typically on unmount).
|
|
1245
|
+
*/
|
|
1246
|
+
unregister(id: string): void;
|
|
1247
|
+
/**
|
|
1248
|
+
* Look up a component by its ID.
|
|
1249
|
+
*/
|
|
1250
|
+
get(id: string): ComponentEntry | undefined;
|
|
1251
|
+
/**
|
|
1252
|
+
* Get a typed entry or undefined.
|
|
1253
|
+
*/
|
|
1254
|
+
getField(id: string): FieldEntry | undefined;
|
|
1255
|
+
getTarget(id: string): TargetEntry | undefined;
|
|
1256
|
+
getToggle(id: string): ToggleEntry | undefined;
|
|
1257
|
+
getSlider(id: string): SliderEntry | undefined;
|
|
1258
|
+
/**
|
|
1259
|
+
* Get all components on a given screen.
|
|
1260
|
+
*/
|
|
1261
|
+
getByScreen(screen: string): Map<string, ComponentEntry>;
|
|
1262
|
+
/**
|
|
1263
|
+
* Get all components of a given kind.
|
|
1264
|
+
*/
|
|
1265
|
+
getByKind(kind: ComponentKind): Map<string, ComponentEntry>;
|
|
1266
|
+
/**
|
|
1267
|
+
* List all registered component IDs with their kind and screen.
|
|
1268
|
+
* Useful for debugging and for the AI to know what's available.
|
|
1269
|
+
*/
|
|
1270
|
+
snapshot(): Array<{
|
|
1271
|
+
id: string;
|
|
1272
|
+
kind: ComponentKind;
|
|
1273
|
+
screen?: string;
|
|
1274
|
+
label?: string;
|
|
1275
|
+
}>;
|
|
1276
|
+
/**
|
|
1277
|
+
* Subscribe to registry changes.
|
|
1278
|
+
* Returns an unsubscribe function.
|
|
1279
|
+
*/
|
|
1280
|
+
subscribe(listener: Listener): () => void;
|
|
1281
|
+
/**
|
|
1282
|
+
* Clear all entries (useful for testing or full reset).
|
|
1283
|
+
*/
|
|
1284
|
+
clear(): void;
|
|
1285
|
+
/** Number of registered components */
|
|
1286
|
+
get size(): number;
|
|
1287
|
+
private notify;
|
|
1288
|
+
}
|
|
1289
|
+
/**
|
|
1290
|
+
* Singleton registry instance shared across the entire SDK by default.
|
|
1291
|
+
*
|
|
1292
|
+
* Apps with a single Appilots session (the overwhelmingly common case)
|
|
1293
|
+
* never need anything else — hooks, handlers, and auto-tracking all
|
|
1294
|
+
* read from this singleton.
|
|
1295
|
+
*
|
|
1296
|
+
* For multi-tenant or micro-front-end setups where two Appilots
|
|
1297
|
+
* sessions might coexist in the same JS process, use
|
|
1298
|
+
* `createComponentRegistry()` to obtain a fresh instance and pass it
|
|
1299
|
+
* via `<AppilotsRegistryProvider value={...}>`. Hooks resolve via
|
|
1300
|
+
* context first, falling back to this singleton.
|
|
1301
|
+
*
|
|
1302
|
+
* The singleton stays in place to keep the existing public API stable
|
|
1303
|
+
* — pré-mortem 2.8 is "future risk", not "current bug".
|
|
1304
|
+
*/
|
|
1305
|
+
declare const componentRegistry: ComponentRegistry;
|
|
1306
|
+
/**
|
|
1307
|
+
* Create a fresh, isolated ComponentRegistry instance. Pair with
|
|
1308
|
+
* `<AppilotsRegistryProvider value={...}>` to scope auto-tracking and
|
|
1309
|
+
* hooks to that registry instead of the global singleton.
|
|
1310
|
+
*
|
|
1311
|
+
* @example
|
|
1312
|
+
* ```tsx
|
|
1313
|
+
* const tenantRegistry = createComponentRegistry();
|
|
1314
|
+
* <AppilotsRegistryProvider value={tenantRegistry}>
|
|
1315
|
+
* <TenantApp />
|
|
1316
|
+
* </AppilotsRegistryProvider>
|
|
1317
|
+
* ```
|
|
1318
|
+
*/
|
|
1319
|
+
declare function createComponentRegistry(): ComponentRegistry;
|
|
1320
|
+
|
|
1321
|
+
/**
|
|
1322
|
+
* useAppilotsField — Register a text input (or similar field) with the
|
|
1323
|
+
* ComponentRegistry so the AI agent can fill it via form_fill actions.
|
|
1324
|
+
*
|
|
1325
|
+
* Usage:
|
|
1326
|
+
* ```tsx
|
|
1327
|
+
* const [plate, setPlate] = useState('');
|
|
1328
|
+
* const plateRef = useRef<TextInput>(null);
|
|
1329
|
+
*
|
|
1330
|
+
* useAppilotsField('plate', {
|
|
1331
|
+
* value: plate,
|
|
1332
|
+
* onChangeText: setPlate,
|
|
1333
|
+
* ref: plateRef, // optional — enables focus()
|
|
1334
|
+
* fieldType: 'text', // optional — hint for executor
|
|
1335
|
+
* label: 'License Plate', // optional — human-readable name
|
|
1336
|
+
* screen: 'VehicleForm', // optional — scoped to screen
|
|
1337
|
+
* });
|
|
1338
|
+
*
|
|
1339
|
+
* return <TextInput ref={plateRef} value={plate} onChangeText={setPlate} />;
|
|
1340
|
+
* ```
|
|
1341
|
+
*/
|
|
1342
|
+
|
|
1343
|
+
interface UseAppilotsFieldOptions {
|
|
1344
|
+
/** Current value of the field */
|
|
1345
|
+
value: string;
|
|
1346
|
+
/** Callback to update the value (same signature as TextInput.onChangeText) */
|
|
1347
|
+
onChangeText: (text: string) => void;
|
|
1348
|
+
/** Optional ref to the TextInput for focus support */
|
|
1349
|
+
ref?: React.RefObject<any>;
|
|
1350
|
+
/** Field type hint */
|
|
1351
|
+
fieldType?: FieldEntry['fieldType'];
|
|
1352
|
+
/** Human-readable label */
|
|
1353
|
+
label?: string;
|
|
1354
|
+
/** Screen name this field belongs to */
|
|
1355
|
+
screen?: string;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Register a field with the Appilots ComponentRegistry.
|
|
1359
|
+
* Automatically unregisters on unmount.
|
|
1360
|
+
*
|
|
1361
|
+
* @param id - Unique identifier for this field (e.g. "plate", "customerName")
|
|
1362
|
+
* @param options - Field configuration
|
|
1363
|
+
*/
|
|
1364
|
+
declare function useAppilotsField(id: string, options: UseAppilotsFieldOptions): void;
|
|
1365
|
+
|
|
1366
|
+
/**
|
|
1367
|
+
* useAppilotsTarget — Register a pressable UI element (button, card, link)
|
|
1368
|
+
* with the ComponentRegistry so the AI agent can interact with it.
|
|
1369
|
+
*
|
|
1370
|
+
* Usage:
|
|
1371
|
+
* ```tsx
|
|
1372
|
+
* const handleSubmit = () => { ... };
|
|
1373
|
+
*
|
|
1374
|
+
* useAppilotsTarget('submitVehicle', {
|
|
1375
|
+
* onPress: handleSubmit,
|
|
1376
|
+
* label: 'Submit Vehicle',
|
|
1377
|
+
* screen: 'VehicleForm',
|
|
1378
|
+
* });
|
|
1379
|
+
*
|
|
1380
|
+
* return <Button title="Submit" onPress={handleSubmit} />;
|
|
1381
|
+
* ```
|
|
1382
|
+
*/
|
|
1383
|
+
interface UseAppilotsTargetOptions {
|
|
1384
|
+
/** Primary press handler */
|
|
1385
|
+
onPress: () => void;
|
|
1386
|
+
/** Optional long-press handler */
|
|
1387
|
+
onLongPress?: () => void;
|
|
1388
|
+
/** Optional scroll-to handler (scroll this element into view) */
|
|
1389
|
+
onScrollTo?: () => void;
|
|
1390
|
+
/** Human-readable label */
|
|
1391
|
+
label?: string;
|
|
1392
|
+
/** Screen name this target belongs to */
|
|
1393
|
+
screen?: string;
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* Register a pressable target with the Appilots ComponentRegistry.
|
|
1397
|
+
* Automatically unregisters on unmount.
|
|
1398
|
+
*
|
|
1399
|
+
* @param id - Unique identifier (e.g. "submitVehicle", "openSettings")
|
|
1400
|
+
* @param options - Target configuration
|
|
1401
|
+
*/
|
|
1402
|
+
declare function useAppilotsTarget(id: string, options: UseAppilotsTargetOptions): void;
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* useAppilotsToggle — Register a toggle/switch with the ComponentRegistry
|
|
1406
|
+
* so the AI agent can flip it via ui_interaction actions.
|
|
1407
|
+
*
|
|
1408
|
+
* Usage:
|
|
1409
|
+
* ```tsx
|
|
1410
|
+
* const [pushEnabled, setPushEnabled] = useState(false);
|
|
1411
|
+
*
|
|
1412
|
+
* useAppilotsToggle('pushNotifications', {
|
|
1413
|
+
* value: pushEnabled,
|
|
1414
|
+
* onValueChange: setPushEnabled,
|
|
1415
|
+
* label: 'Push Notifications',
|
|
1416
|
+
* screen: 'Settings',
|
|
1417
|
+
* });
|
|
1418
|
+
*
|
|
1419
|
+
* return <Switch value={pushEnabled} onValueChange={setPushEnabled} />;
|
|
1420
|
+
* ```
|
|
1421
|
+
*/
|
|
1422
|
+
interface UseAppilotsToggleOptions {
|
|
1423
|
+
/** Current toggle value */
|
|
1424
|
+
value: boolean;
|
|
1425
|
+
/** Callback when value changes */
|
|
1426
|
+
onValueChange: (value: boolean) => void;
|
|
1427
|
+
/** Human-readable label */
|
|
1428
|
+
label?: string;
|
|
1429
|
+
/** Screen name this toggle belongs to */
|
|
1430
|
+
screen?: string;
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Register a toggle with the Appilots ComponentRegistry.
|
|
1434
|
+
* Automatically unregisters on unmount.
|
|
1435
|
+
*
|
|
1436
|
+
* @param id - Unique identifier (e.g. "pushNotifications", "darkMode")
|
|
1437
|
+
* @param options - Toggle configuration
|
|
1438
|
+
*/
|
|
1439
|
+
declare function useAppilotsToggle(id: string, options: UseAppilotsToggleOptions): void;
|
|
1440
|
+
|
|
1441
|
+
/**
|
|
1442
|
+
* useAppilotsSlider — Register a slider / adjustable numeric control with
|
|
1443
|
+
* the ComponentRegistry so the AI agent can set it via
|
|
1444
|
+
* `ui_interaction action="set_value"` actions.
|
|
1445
|
+
*
|
|
1446
|
+
* Registration is what makes a slider agent-operable end to end:
|
|
1447
|
+
* captureSnapshot() reads this entry to advertise the slider (with
|
|
1448
|
+
* min/max/step) in the observation, and the executor dispatches
|
|
1449
|
+
* set_value through the same entry — clamping to [min, max] and
|
|
1450
|
+
* snapping to `step` before calling onValueChange.
|
|
1451
|
+
*
|
|
1452
|
+
* Usage:
|
|
1453
|
+
* ```tsx
|
|
1454
|
+
* const [mileage, setMileage] = useState(0);
|
|
1455
|
+
*
|
|
1456
|
+
* useAppilotsSlider('quilometragem', {
|
|
1457
|
+
* value: mileage,
|
|
1458
|
+
* onValueChange: setMileage,
|
|
1459
|
+
* min: 0,
|
|
1460
|
+
* max: 300000,
|
|
1461
|
+
* step: 500,
|
|
1462
|
+
* label: 'Quilometragem',
|
|
1463
|
+
* screen: 'VehicleCreate',
|
|
1464
|
+
* });
|
|
1465
|
+
*
|
|
1466
|
+
* return <MySlider value={mileage} onChange={setMileage} min={0} max={300000} />;
|
|
1467
|
+
* ```
|
|
1468
|
+
*/
|
|
1469
|
+
interface UseAppilotsSliderOptions {
|
|
1470
|
+
/** Current slider value */
|
|
1471
|
+
value: number;
|
|
1472
|
+
/** Callback when value changes */
|
|
1473
|
+
onValueChange: (value: number) => void;
|
|
1474
|
+
/** Lower bound (inclusive) — advertised in the observation and enforced by the executor */
|
|
1475
|
+
min: number;
|
|
1476
|
+
/** Upper bound (inclusive) — advertised in the observation and enforced by the executor */
|
|
1477
|
+
max: number;
|
|
1478
|
+
/** Step the executor snaps to (omit for a continuous slider) */
|
|
1479
|
+
step?: number;
|
|
1480
|
+
/** Human-readable label */
|
|
1481
|
+
label?: string;
|
|
1482
|
+
/** Screen name this slider belongs to */
|
|
1483
|
+
screen?: string;
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Register a slider with the Appilots ComponentRegistry.
|
|
1487
|
+
* Automatically unregisters on unmount.
|
|
1488
|
+
*
|
|
1489
|
+
* @param id - Unique identifier (e.g. "quilometragem", "volume")
|
|
1490
|
+
* @param options - Slider configuration
|
|
1491
|
+
*/
|
|
1492
|
+
declare function useAppilotsSlider(id: string, options: UseAppilotsSliderOptions): void;
|
|
1493
|
+
|
|
1494
|
+
interface SuggestedPrompt {
|
|
1495
|
+
/** Display label shown on the chip and inserted into the input on tap. */
|
|
1496
|
+
text: string;
|
|
1497
|
+
/** Where this prompt came from. Useful for analytics or theming. */
|
|
1498
|
+
source: 'dev-defined' | 'screen-popular' | 'global-popular';
|
|
1499
|
+
}
|
|
1500
|
+
interface UseSuggestedPromptsOptions {
|
|
1501
|
+
/**
|
|
1502
|
+
* Whether the chat is currently open. Hook only fetches while open, so
|
|
1503
|
+
* suggestions don't waste a roundtrip when the chat is minimised.
|
|
1504
|
+
*/
|
|
1505
|
+
enabled: boolean;
|
|
1506
|
+
/** Max chips to return. Default 4. */
|
|
1507
|
+
limit?: number;
|
|
1508
|
+
}
|
|
1509
|
+
interface UseSuggestedPromptsReturn {
|
|
1510
|
+
prompts: SuggestedPrompt[];
|
|
1511
|
+
isLoading: boolean;
|
|
1512
|
+
/** Re-runs the fetch — call after navigation so chips refresh. */
|
|
1513
|
+
refetch: () => void;
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Returns ranked suggested prompts to render as chips in the chat
|
|
1517
|
+
* empty-state. Three sources are merged in priority order:
|
|
1518
|
+
*
|
|
1519
|
+
* 1. **Dev-defined** — from `registerScreen({ suggestedPrompts })` in the
|
|
1520
|
+
* current app, read synchronously from the local screen registry.
|
|
1521
|
+
* First-class signal, always wins.
|
|
1522
|
+
*
|
|
1523
|
+
* 2. **Screen-popular** — historical user prompts sent FROM this screen,
|
|
1524
|
+
* mined server-side from agentMessages history.
|
|
1525
|
+
*
|
|
1526
|
+
* 3. **Global-popular** — historical user prompts across the project.
|
|
1527
|
+
* Fallback for screens with no history yet.
|
|
1528
|
+
*
|
|
1529
|
+
* The hook re-fetches whenever the active screen changes so chips always
|
|
1530
|
+
* match where the user is right now. Server response is cached 1h, so
|
|
1531
|
+
* fetches are cheap.
|
|
1532
|
+
*
|
|
1533
|
+
* @example
|
|
1534
|
+
* ```tsx
|
|
1535
|
+
* const { prompts } = useSuggestedPrompts({ enabled: chatVisible });
|
|
1536
|
+
* return prompts.map((p) => (
|
|
1537
|
+
* <Chip key={p.text} onPress={() => setInput(p.text)}>{p.text}</Chip>
|
|
1538
|
+
* ));
|
|
1539
|
+
* ```
|
|
1540
|
+
*/
|
|
1541
|
+
declare function useSuggestedPrompts(options: UseSuggestedPromptsOptions): UseSuggestedPromptsReturn;
|
|
1542
|
+
|
|
1543
|
+
export { createComponentRegistry as $, type AppilotsThemeTokens as A, type BreadcrumbItem as B, type ComponentRegistry as C, SDK_VERSION as D, type EscalationState as E, type FieldEntry as F, type SliderEntry as G, type SuggestedPrompt as H, type InteractionElementSnapshot as I, type ToggleEntry as J, type ToggleSnapshot as K, type ListItemSnapshot as L, type MessageRole as M, type NavigationPayload as N, type UseAppilotsFieldOptions as O, type PartialThemeTokens as P, type UseAppilotsSliderOptions as Q, type RemotePersonalization as R, type ScreenSnapshot as S, type TargetEntry as T, type UIInteractionPayload as U, type UseAppilotsTargetOptions as V, type UseAppilotsToggleOptions as W, type UseSuggestedPromptsOptions as X, type UseSuggestedPromptsReturn as Y, clearAppilotsDebugTraces as Z, componentRegistry as _, type AppilotsLocale as a, defaultDarkTheme as a0, defaultLightTheme as a1, describeAction as a2, getAppilotsDebugTraces as a3, humanizeError as a4, mergeThemeTokens as a5, recordAppilotsDebugTrace as a6, subscribeAppilotsDebugTraces as a7, useAppilots as a8, useAppilotsActions as a9, useAppilotsChat as aa, useAppilotsContext as ab, useAppilotsField as ac, useAppilotsNavigation as ad, useAppilotsSlider as ae, useAppilotsTarget as af, useAppilotsToggle as ag, useSuggestedPrompts as ah, 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 ListSnapshot as z };
|