@appilots/sdk 0.2.0 → 0.3.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,1300 +0,0 @@
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
- * i18n keys — the canonical list of every translatable string in the
123
- * SDK chat UI. Adding UI copy means adding a key here AND a value in
124
- * every bundle under `./bundles/` (TypeScript will fail the bundle if a
125
- * key is missing). BACKLOG 4.1.
126
- */
127
- interface AppilotsStrings {
128
- /** Default chat header title when the dev hasn't supplied one. */
129
- chatTitle: string;
130
- /** Header button that wipes the conversation. */
131
- clearButton: string;
132
- /** Placeholder for the message input. */
133
- inputPlaceholder: string;
134
- /** Empty state heading. */
135
- emptyTitle: string;
136
- /** Empty state subtitle / one-liner under the heading. */
137
- emptySubtitle: string;
138
- /** "Thinking..." placeholder shown while the assistant is replying. */
139
- thinking: string;
140
- /** Status shown while the assistant is planning from the current screen. */
141
- statusAnalyzing: string;
142
- /** Status shown while the SDK waits for the app to settle after an action. */
143
- statusWaitingApp: string;
144
- /** Status shown while the assistant adjusts after a recoverable failure. */
145
- statusAdjusting: string;
146
- /** Footer line shown when poweredByVisible !== false. */
147
- poweredBy: string;
148
- /** Approve button on a pending action row in the breadcrumb. */
149
- approve: string;
150
- /** Reject button on a pending action row in the breadcrumb. */
151
- reject: string;
152
- /** Generic "cancelled by the user" message after a reject. */
153
- cancelledByUser: string;
154
- /** Fallback humanised name for an unknown action type. */
155
- unknownAction: string;
156
- /** Generic friendly error when nothing else fits. */
157
- somethingWentWrong: string;
158
- /** Open chat accessibility label for the floating bubble. */
159
- openChatA11y: string;
160
- /** Close chat accessibility label. */
161
- closeChatA11y: string;
162
- /** A11y label for the stop-generation button (OKR-008 KR4). */
163
- stopGeneratingA11y: string;
164
- /** A11y label for the "talk to a human" header button. */
165
- talkToHumanA11y: string;
166
- /** Sender label above a human operator's bubble. */
167
- humanAgentLabel: string;
168
- /** System line right after the user (or the offer chip) escalates. */
169
- escalationRequested: string;
170
- /** System line when an operator claims the conversation. */
171
- escalationConnected: string;
172
- /** System line when the operator resolves — AI takes over again. */
173
- escalationResolved: string;
174
- /** System line offering the handoff after the agent gives up. */
175
- escalationOffer: string;
176
- /** Label of the tappable chip under the offer line. */
177
- escalationOfferChip: string;
178
- /** Thin banner under the header while waiting in the queue. */
179
- escalationPendingBanner: string;
180
- /** Thin banner under the header while connected to an operator. */
181
- escalationActiveBanner: string;
182
- }
183
- type AppilotsStringKey = keyof AppilotsStrings;
184
-
185
- /**
186
- * SDK locale code. Adding a locale = adding a bundle file in
187
- * `./bundles/` AND a branch in `BUNDLES` below. BACKLOG 4.1.
188
- */
189
- type AppilotsLocale = 'pt-BR' | 'en' | 'es';
190
- /**
191
- * Best-effort device-locale detection. Returns the closest supported
192
- * locale or `null` if we can't tell. Designed to never throw — RN's
193
- * native modules are platform-specific and can be missing in test
194
- * harnesses.
195
- */
196
- declare function detectDeviceLocale(): AppilotsLocale | null;
197
- /**
198
- * Resolve the locale to use given the prop and the device default.
199
- * Order: explicit prop → device-detected → DEFAULT_LOCALE.
200
- */
201
- declare function resolveLocale(prop?: AppilotsLocale | null): AppilotsLocale;
202
- interface I18nContextValue {
203
- locale: AppilotsLocale;
204
- strings: AppilotsStrings;
205
- /**
206
- * Helper to read a single key. Components can also destructure
207
- * `strings` directly if they need many in one render.
208
- */
209
- t: (key: AppilotsStringKey) => string;
210
- }
211
- interface AppilotsI18nProviderProps {
212
- /** Force a locale. Falls through to device detection when omitted. */
213
- locale?: AppilotsLocale | null;
214
- /**
215
- * Per-key overrides to merge on top of the bundle. Useful when the
216
- * dev wants to rename only "Powered by Appilots" while keeping the
217
- * rest in the default language.
218
- */
219
- overrides?: Partial<AppilotsStrings> | null;
220
- children: React__default.ReactNode;
221
- }
222
- declare function AppilotsI18nProvider({ locale, overrides, children, }: AppilotsI18nProviderProps): React__default.JSX.Element;
223
- /**
224
- * Read the locale + strings from context. Falls back to the default
225
- * locale bundle if no provider is mounted, so components don't need a
226
- * provider to be safe — they just lose the dev's overrides.
227
- */
228
- declare function useAppilotsI18n(): I18nContextValue;
229
-
230
- /**
231
- * Core types for the Appilots SDK.
232
- */
233
-
234
- /**
235
- * Payload of `GET /agent/personalization` — what the dev configured in
236
- * the dashboard under Projects > Personalization. Fetched once on
237
- * `AppilotsProvider` mount and applied by `AppilotsChat` as a fallback
238
- * for any prop the dev did NOT set explicitly in code
239
- * (prop > remote > SDK default).
240
- *
241
- * Only JSON-serializable values travel here: URLs/hex/booleans work,
242
- * React nodes and local `require()` assets can only come via props.
243
- * `null` means "not configured" — fall through to the next source.
244
- */
245
- interface RemotePersonalization {
246
- assistantName: string | null;
247
- /** Avatar URL shown next to assistant turns. */
248
- assistantAvatar: string | null;
249
- /** Emoji or image URL for the empty-state badge. */
250
- emptyStateIcon: string | null;
251
- welcomeMessage: string | null;
252
- chatTitle: string | null;
253
- poweredByVisible: boolean;
254
- /**
255
- * Partial token tree merged onto the SDK defaults. `mode` (when set)
256
- * plays the role of the `themeMode` prop.
257
- */
258
- theme: (PartialThemeTokens & {
259
- mode?: 'auto' | 'light' | 'dark';
260
- }) | null;
261
- defaultLocale: AppilotsLocale | null;
262
- triggerButtonColor: string | null;
263
- triggerButtonImageUrl: string | null;
264
- }
265
- type MessageRole = 'user' | 'assistant' | 'system' | 'human_agent';
266
- interface ChatMessage {
267
- id: string;
268
- role: MessageRole;
269
- content: string;
270
- timestamp: number;
271
- metadata?: Record<string, unknown>;
272
- }
273
- interface AppilotsTraceEntry {
274
- id: string;
275
- timestamp: number;
276
- type: AppilotsEventType | 'agent:trace';
277
- messageId?: string;
278
- actionId?: string;
279
- actionType?: AgentActionType | string;
280
- status?: AgentAction['status'] | 'started' | 'error';
281
- summary?: string;
282
- data: Record<string, unknown>;
283
- }
284
- interface AgentMessage extends ChatMessage {
285
- role: 'assistant';
286
- actions?: AgentAction[];
287
- thinking?: string;
288
- }
289
- type AgentActionType = 'navigate' | 'form_fill' | 'ui_interaction' | 'scroll_list' | 'confirm' | 'custom';
290
- interface AgentAction {
291
- id: string;
292
- type: AgentActionType;
293
- payload: NavigationPayload | FormFillPayload | UIInteractionPayload | ScrollListPayload | Record<string, unknown>;
294
- status: 'pending' | 'executing' | 'completed' | 'failed';
295
- error?: string;
296
- /** ID of the assistant message that triggered this action */
297
- messageId?: string;
298
- /**
299
- * BACKLOG 2.2 — When the server flags an action as destructive,
300
- * the SDK renders any preceding `confirm` action with the danger
301
- * variant and expects the action to be gated by user approval.
302
- */
303
- destructive?: boolean;
304
- }
305
- interface NavigationPayload {
306
- screenName: string;
307
- params?: Record<string, unknown>;
308
- navigationAction: 'push' | 'navigate' | 'replace' | 'goBack' | 'reset';
309
- /**
310
- * Optional path of parent navigator route names for nested screens.
311
- * E.g. ['HomeTab', 'VehiclesTab'] to reach a screen inside
312
- * HomeTab → VehiclesTab → screenName.
313
- *
314
- * React Navigation requires nested navigation params:
315
- * nav.navigate('HomeTab', { screen: 'VehiclesTab', params: { screen: 'VehicleCreate' } })
316
- *
317
- * The AI model provides this based on the MCP document's navigation graph.
318
- */
319
- path?: string[];
320
- }
321
- interface FormFillPayload {
322
- screenName: string;
323
- fields: FormFieldAction[];
324
- /**
325
- * If true, the handler presses the screen's primary submit button
326
- * after all fields are filled. The submit button is resolved via
327
- * `registerScreen({ actions: [{ type: 'submit', ... }] })` first,
328
- * then via the fiber tree and a label heuristic.
329
- *
330
- * Aligned with the `submitAfterFill` field in the LLM tool schema
331
- * (`agentTools.form_fill` in ai-relay.ts).
332
- */
333
- submitAfterFill?: boolean;
334
- }
335
- interface FormFieldAction {
336
- fieldId: string;
337
- fieldType: 'text' | 'select' | 'toggle' | 'date' | 'number' | 'custom';
338
- value: unknown;
339
- label?: string;
340
- }
341
- interface UIInteractionPayload {
342
- componentId: string;
343
- /** Canonical server/LLM identifier. `componentId` is kept as SDK alias. */
344
- targetId?: string;
345
- action: 'press' | 'longPress' | 'scroll' | 'swipe' | 'focus' | 'set_value';
346
- /**
347
- * Numeric value for `set_value` (sliders / adjustable controls).
348
- * The handler clamps to the slider's [min, max] and snaps to its step.
349
- */
350
- value?: number;
351
- params?: Record<string, unknown>;
352
- }
353
- /**
354
- * Scroll a list/collection so virtualized off-screen rows mount and
355
- * show up in the next observation. Mirrors `scrollListPayloadSchema`
356
- * in @appilots/shared. At least one of the fields should be present;
357
- * the handler falls back to paging one viewport down when only a
358
- * listId is given.
359
- */
360
- interface ScrollListPayload {
361
- /** Runtime list id from the observation's "Lists visible" block. */
362
- listId?: string;
363
- /** 1-based index in the list's DATA to scroll to. */
364
- toIndex?: number;
365
- /** Coarse paging when no target index is known. */
366
- direction?: 'up' | 'down';
367
- }
368
- interface AgentPermissions {
369
- canNavigate: boolean;
370
- canFillForms: boolean;
371
- canInteractUI: boolean;
372
- canSubmitForms: boolean;
373
- allowedScreens?: string[];
374
- blockedScreens?: string[];
375
- allowedActions?: AgentActionType[];
376
- }
377
- 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';
378
- interface AppilotsEvent {
379
- type: AppilotsEventType;
380
- timestamp: number;
381
- data: Record<string, unknown>;
382
- }
383
- type AppilotsEventHandler = (event: AppilotsEvent) => void;
384
- /**
385
- * Client-side view of an open escalation. `resolved` never appears
386
- * here — resolution clears the state (after surfacing a system
387
- * message in the transcript).
388
- */
389
- interface EscalationState {
390
- id: string;
391
- status: 'pending' | 'active';
392
- /** Set once an operator claims the conversation. */
393
- operatorName?: string;
394
- }
395
-
396
- interface AppilotsClientOptions {
397
- projectId: string;
398
- apiBaseUrl?: string;
399
- apiKey?: string;
400
- debug?: boolean;
401
- timeout?: number;
402
- headers?: Record<string, string>;
403
- /**
404
- * Version of the MCP doc bundled with this app build. The server
405
- * compares this against the currently-active MCP doc for the
406
- * project and emits a `mcp_version_mismatch` telemetry event when
407
- * they differ — the canonical sign that the dev shipped an app
408
- * update but forgot to regenerate/upload the MCP.
409
- *
410
- * Tip: import this from the MCP file the CLI generates, or read it
411
- * from your app's package.json so it stays in lockstep with releases.
412
- */
413
- mcpVersion?: string;
414
- /**
415
- * The host app's version (e.g. from package.json or
416
- * react-native-device-info). Sent as `X-App-Version` on every request
417
- * so the server can match the compatible MCP document per app build —
418
- * essential for OTA-updated fleets where multiple app versions coexist.
419
- */
420
- appVersion?: string;
421
- /**
422
- * Who the app's current user is. `id` becomes the session's
423
- * externalUserId; `name`/`identifiers` are upserted into the
424
- * workspace's end-users registry (fire-and-forget identify after the
425
- * session opens) so support operators see a person, not an anonymous
426
- * id. Identifiers are dashboard-only — never sent to the LLM.
427
- */
428
- user?: AppilotsUser;
429
- }
430
- interface AppilotsUser {
431
- /** The app's own user id (matches your backend). */
432
- id: string;
433
- name?: string;
434
- /** Free-form lookup keys: { email, phone, cpf, ... }. Max 10. */
435
- identifiers?: Record<string, string>;
436
- }
437
- interface SendMessageResponse {
438
- sessionId: string;
439
- message: ChatMessage;
440
- /** Summary message to show AFTER actions complete */
441
- summaryMessage?: ChatMessage;
442
- actions?: AgentAction[];
443
- usage?: {
444
- tokensUsed: number;
445
- modelUsed: string;
446
- latencyMs: number;
447
- };
448
- }
449
- interface SendMessageStreamOptions {
450
- /**
451
- * Fired per SSE text-delta with the chunk and the accumulated text so
452
- * far — render `fullText` directly; chunks may split words/markdown.
453
- */
454
- onTextDelta?: (chunk: string, fullText: string) => void;
455
- /** Fired once when the server announces the session id. */
456
- onSession?: (sessionId: string) => void;
457
- /** Abort mid-generation (stop button). Rejects with name='AbortError'. */
458
- signal?: AbortSignal;
459
- }
460
- /** Runtime context sent with every user message. */
461
- interface SendMessageContext {
462
- currentScreen?: string;
463
- formState?: Record<string, unknown>;
464
- /** Design-time screen metadata from registerScreen() or the MCP doc */
465
- screenMetadata?: Record<string, unknown>;
466
- /** Runtime React Navigation summary captured by the SDK */
467
- navigationState?: {
468
- currentRouteName?: string;
469
- activePath?: string[];
470
- rootRouteNames?: string[];
471
- currentRouteNames?: string[];
472
- routeNames?: string[];
473
- canGoBack?: boolean;
474
- };
475
- /** Runtime snapshot from captureSnapshot() — what's actually visible */
476
- snapshot?: Record<string, unknown>;
477
- /** Legacy registry snapshot — kept as a fallback signal */
478
- registeredComponents?: Array<{
479
- id: string;
480
- kind: 'field' | 'target' | 'toggle';
481
- screen?: string;
482
- label?: string;
483
- }>;
484
- /** Runtime list registry snapshot — collection metadata even when rows are virtualized. */
485
- registeredLists?: Array<{
486
- kind: 'list';
487
- id: string;
488
- component: string;
489
- itemCount?: number;
490
- label?: string;
491
- screen?: string;
492
- refreshing?: boolean;
493
- empty?: boolean;
494
- }>;
495
- }
496
- declare class AppilotsClient {
497
- private readonly baseUrl;
498
- private readonly projectId;
499
- private readonly headers;
500
- private readonly timeout;
501
- private readonly debug;
502
- private readonly mcpVersion;
503
- private readonly user;
504
- private sessionId;
505
- /** Guard so identify fires at most once per client instance. */
506
- private identified;
507
- constructor(options: AppilotsClientOptions);
508
- private log;
509
- private describeNonJsonResponse;
510
- private request;
511
- createSession(userId?: string, deviceInfo?: Record<string, unknown>): Promise<string>;
512
- /**
513
- * Upsert the configured user into the end-users registry. Fires once
514
- * per client, after the first session opens; fire-and-forget — a
515
- * failed identify must never break the chat.
516
- */
517
- private identifyConfiguredUser;
518
- destroySession(): Promise<void>;
519
- getSessionId(): string | null;
520
- sendMessage(content: string, context?: SendMessageContext): Promise<SendMessageResponse>;
521
- /**
522
- * Streaming variant of `sendMessage` — consumes the server's SSE
523
- * endpoint (`/agent/message/stream`) and fires `onTextDelta` per chunk
524
- * so the UI can render tokens as they arrive (OKR-008 KR1). Resolves
525
- * with the same `SendMessageResponse` shape once the `done` event lands.
526
- *
527
- * Uses XMLHttpRequest because React Native's fetch does not expose
528
- * `response.body` for incremental reads; RN's XHR delivers progressive
529
- * `responseText`, which is the standard SSE transport on RN.
530
- *
531
- * Errors:
532
- * - `StreamTransportError` — transport failed before ANY event; safe
533
- * for the caller to fall back to the non-streaming endpoint.
534
- * - `StreamAbortError` (name='AbortError') — options.signal fired;
535
- * carries `partialContent` so the UI can keep what streamed.
536
- */
537
- sendMessageStream(content: string, context?: SendMessageContext, options?: SendMessageStreamOptions): Promise<SendMessageResponse>;
538
- continueAgent(results: Array<{
539
- actionId: string;
540
- type: string;
541
- success: boolean;
542
- error?: string;
543
- summary?: string;
544
- /** BACKLOG 3.2 — structured failure diagnose, server uses for recovery */
545
- diagnose?: {
546
- category: 'component-not-found' | 'disabled' | 'validation' | 'network-5xx' | 'network-4xx' | 'screen-timeout' | 'ambiguous-target' | 'unknown';
547
- visibleMessage?: string;
548
- fieldId?: string;
549
- targetId?: string;
550
- screen?: string;
551
- httpStatus?: number;
552
- /** Candidate ids when resolution failed due to ambiguity. */
553
- candidates?: string[];
554
- recoverable?: boolean;
555
- requiresUserInput?: boolean;
556
- };
557
- /** BACKLOG 3.2 — how many times this fingerprint has been retried (1 = first retry). */
558
- recoveryAttempt?: number;
559
- /** BACKLOG 3.2 — set when SDK has hit the per-action retry cap. */
560
- recoveryExhausted?: boolean;
561
- /**
562
- * Set when a handler reported success but the expected visible
563
- * side-effect did not happen, e.g. navigate returned but route stayed.
564
- */
565
- toolWithoutEffect?: boolean;
566
- effect?: 'unknown' | 'none' | 'partial' | 'changed' | 'completed';
567
- userVisibleStatusKey?: string;
568
- }>, context: Record<string, unknown>, hop: number): Promise<SendMessageResponse & {
569
- isDone: boolean;
570
- hop: number;
571
- }>;
572
- executeAction(actionId: string): Promise<AgentAction>;
573
- /**
574
- * Rewrite an action's type when the AI used a semantically-misclassified
575
- * action type. The most common case: the LLM emits
576
- * { type: 'ui_interaction', payload: { action: 'select', targetId, value } }
577
- * to mean "set this field's value", which is really a form_fill. We detect
578
- * that here and convert it before normalization, so the executor sees the
579
- * right action shape and the field's setValue() is called instead of a
580
- * meaningless press on a non-pressable component.
581
- */
582
- private rewriteActionTypeIfNeeded;
583
- /**
584
- * Normalize API tool call payloads to match SDK's expected payload types.
585
- * The AI model may return slightly different field names than what the
586
- * SDK executor expects, and may use vocabulary (e.g. "select", "scroll_to",
587
- * "open") that the SDK doesn't natively support — we remap those to the
588
- * nearest equivalent here so the executor never sees an "unknown action".
589
- */
590
- private normalizePayload;
591
- /**
592
- * Legacy per-action status report. The agentic chat loop reports via
593
- * `continueAgent` (which carries diagnose + a fresh snapshot); this
594
- * endpoint remains for apps driving actions manually through
595
- * `useAppilotsActions`. `diagnose` is forwarded when provided so even
596
- * the legacy path gives the server a failure category.
597
- */
598
- completeAction(actionId: string, success: boolean, error?: string, diagnose?: Record<string, unknown>): Promise<void>;
599
- /**
600
- * Fetch actions the server has persisted but that haven't been
601
- * completed yet. Use after an SSE drop or a hard error to recover
602
- * the batch without losing the actions the model already decided.
603
- *
604
- * Returns an empty array if there are no pending actions or if the
605
- * call fails — never throws.
606
- */
607
- recoverPendingActions(sessionId?: string): Promise<AgentAction[]>;
608
- /**
609
- * Fetch dev-defined and empirically-popular prompts to seed the chat
610
- * empty-state with one-tap chips. Cheap (cached server-side for 1h) but
611
- * still a network hit, so callers should debounce around chat-open.
612
- *
613
- * @param screen Optional — when provided, response includes screen-scoped
614
- * popular prompts in addition to globals.
615
- */
616
- getPopularPrompts(screen?: string, limit?: number): Promise<{
617
- devDefined: string[];
618
- screenPopular: string[];
619
- globalPopular: string[];
620
- computedAt: string;
621
- }>;
622
- /**
623
- * Fetch the project's dashboard-configured personalization (theme,
624
- * branding, FAB color/image, locale...). Called by `AppilotsProvider`
625
- * once on mount — cheap (cached server-side for 1h) and applied by
626
- * `AppilotsChat` as a fallback for props not set explicitly in code.
627
- *
628
- * Throws on network/HTTP failure — the provider treats any failure as
629
- * "no remote config" and stays on props/defaults.
630
- */
631
- getPersonalization(): Promise<RemotePersonalization>;
632
- /**
633
- * Ask for a human operator. Idempotent: if the session already has
634
- * an open escalation the server returns it instead of creating a
635
- * duplicate. Creates the session first when the chat had none yet
636
- * (the server sends it back and we adopt it, so the whole
637
- * conversation stays under one sessionId).
638
- */
639
- requestEscalation(reason: 'user_requested' | 'agent_gave_up', note?: string): Promise<{
640
- escalationId: string;
641
- status: 'pending' | 'active';
642
- }>;
643
- /**
644
- * Tell the server the user walked away from the conversation (chat
645
- * cleared) so the escalation is closed instead of leaving the
646
- * operator talking to nobody. Fire-and-forget: never throws — the
647
- * local cleanup must proceed even if the network is gone.
648
- */
649
- abandonEscalation(escalationId: string): Promise<void>;
650
- /** User message routed to the human operator (no LLM involved). */
651
- sendEscalationMessage(escalationId: string, content: string): Promise<void>;
652
- /**
653
- * Poll fallback / reconnect catch-up: status + operator messages
654
- * created after `since` (ISO timestamp of the last one we have).
655
- */
656
- getEscalationUpdates(escalationId: string, since?: string): Promise<{
657
- status: 'pending' | 'active' | 'resolved';
658
- messages: Array<{
659
- id: string;
660
- content: string;
661
- createdAt: string;
662
- }>;
663
- }>;
664
- /**
665
- * Open the escalation SSE channel — operator replies + status
666
- * changes pushed live. Same XHR transport as `sendMessageStream`
667
- * (RN's fetch can't read a body incrementally).
668
- *
669
- * Long-lived by design: no idle watchdog — the server pings every
670
- * 25s, and a genuinely dead connection surfaces as `onClose`, which
671
- * the hook answers with a backoff reconnect + `since` catch-up.
672
- * Returns a close function; closing never fires `onClose`.
673
- */
674
- openEscalationStream(escalationId: string, handlers: {
675
- since?: string;
676
- onHumanMessage: (message: {
677
- id: string;
678
- content: string;
679
- createdAt: string;
680
- }) => void;
681
- onStatus: (status: 'pending' | 'active' | 'resolved', operatorName?: string) => void;
682
- /** Transport ended (error or server close) — caller decides on reconnect. */
683
- onClose: () => void;
684
- }): () => void;
685
- }
686
-
687
- interface AppilotsConfig {
688
- /** Project ID from the Appilots dashboard */
689
- projectId: string;
690
- /** API base URL (defaults to Appilots cloud) */
691
- apiBaseUrl?: string;
692
- /** SDK API key (ak_...) for authenticating with the backend */
693
- apiKey?: string;
694
- /** Agent permissions for this app instance */
695
- permissions?: AgentPermissions;
696
- /** Enable debug logging */
697
- debug?: boolean;
698
- /**
699
- * Host app version (e.g. package.json version). Forwarded to the API
700
- * as `X-App-Version` so the server can serve the MCP document matching
701
- * this app build (OTA fleets run several versions at once).
702
- */
703
- appVersion?: string;
704
- /** Version of the MCP doc bundled with this build (stale-doc telemetry). */
705
- mcpVersion?: string;
706
- /**
707
- * Who the app's current user is. Sessions carry `user.id` as
708
- * externalUserId, and name/identifiers are upserted into the
709
- * end-users registry so the support queue shows a person instead of
710
- * "Usuário anônimo". Identifiers never reach the LLM.
711
- */
712
- user?: AppilotsUser;
713
- /**
714
- * Fetch the dashboard-configured personalization (theme, branding,
715
- * FAB color, locale...) once on provider mount and apply it as a
716
- * fallback for AppilotsChat props not set explicitly in code.
717
- *
718
- * Set to `false` to opt out — this is the SDK's only automatic
719
- * network call before the user interacts, so apps with strict
720
- * network/privacy posture can keep today's 100%-manual behavior.
721
- * @default true
722
- */
723
- fetchPersonalization?: boolean;
724
- }
725
- interface AppilotsProviderProps {
726
- /**
727
- * SDK config. If omitted, auto-loads from `.appilotsrc` via the Metro
728
- * resolver (requires `withAppilots()` in metro.config.js).
729
- */
730
- config?: AppilotsConfig;
731
- children: React__default.ReactNode;
732
- /** Optional custom client instance (if not provided, one is auto-created from config) */
733
- client?: AppilotsClient;
734
- }
735
- interface AppilotsContextValue {
736
- config: AppilotsConfig;
737
- client: AppilotsClient;
738
- subscribe: (handler: AppilotsEventHandler) => () => void;
739
- emit: (event: AppilotsEvent) => void;
740
- /**
741
- * Dashboard-configured personalization fetched on mount. `null` until
742
- * the fetch resolves — and forever, if it fails or is opted out
743
- * (`fetchPersonalization: false`). Consumers must treat `null` as
744
- * "use props/defaults"; the chat renders immediately with defaults
745
- * and re-renders once this lands (accepted cold-start flash).
746
- */
747
- remotePersonalization: RemotePersonalization | null;
748
- }
749
- declare function AppilotsProvider({ config: configProp, children, client: externalClient }: AppilotsProviderProps): React__default.JSX.Element;
750
- declare function useAppilotsContext(): AppilotsContextValue;
751
-
752
- /**
753
- * Convenience hook that combines all Appilots hooks into a single return value.
754
- *
755
- * @example
756
- * ```tsx
757
- * const { messages, sendMessage, currentScreen, pendingActions } = useAppilots();
758
- * ```
759
- */
760
- declare function useAppilots(): {
761
- config: AppilotsConfig;
762
- client: AppilotsClient;
763
- messages: ChatMessage[];
764
- isLoading: boolean;
765
- error: string | null;
766
- sendMessage: (content: string) => Promise<void>;
767
- clearMessages: () => void;
768
- clearError: () => void;
769
- currentScreen: string | null;
770
- navigationHistory: string[];
771
- setCurrentScreen: (screenName: string) => void;
772
- navigationRef: React$1.MutableRefObject<any>;
773
- pendingActions: AgentAction[];
774
- executingActions: AgentAction[];
775
- completedActions: AgentAction[];
776
- approveAction: (actionId: string) => Promise<boolean>;
777
- rejectAction: (actionId: string) => Promise<void>;
778
- };
779
-
780
- interface UseAppilotsNavigationReturn {
781
- currentScreen: string | null;
782
- navigationHistory: string[];
783
- setCurrentScreen: (screenName: string) => void;
784
- /** Navigation ref setter — attach to your NavigationContainer */
785
- navigationRef: React.MutableRefObject<any>;
786
- }
787
- /**
788
- * Hook for tracking navigation state and enabling agent-driven navigation.
789
- *
790
- * @example
791
- * ```tsx
792
- * const { currentScreen, navigationRef } = useAppilotsNavigation();
793
- *
794
- * return (
795
- * <NavigationContainer ref={navigationRef}>
796
- * <Stack.Navigator />
797
- * </NavigationContainer>
798
- * );
799
- * ```
800
- */
801
- declare function useAppilotsNavigation(): UseAppilotsNavigationReturn;
802
-
803
- /**
804
- * Localized copy for escalation system messages, injected by the chat
805
- * surface (the hook has no i18n access — same pattern as errorPrefix).
806
- * When omitted, no system messages are appended but the state machine
807
- * still works.
808
- */
809
- interface EscalationStrings {
810
- /** Appended right after the escalation is created. */
811
- requested: string;
812
- /** Appended when an operator claims the conversation. */
813
- connected: string;
814
- /** Appended when the operator resolves — AI takes over again. */
815
- resolved: string;
816
- /** Content of the offer chip message appended when the agent gives up. */
817
- offer: string;
818
- }
819
- interface UseAppilotsChatReturn {
820
- messages: ChatMessage[];
821
- isLoading: boolean;
822
- loadingStatusKey: 'thinking' | 'statusAnalyzing' | 'statusWaitingApp' | 'statusAdjusting';
823
- error: string | null;
824
- pendingActions: AgentAction[];
825
- /**
826
- * Open escalation, or null. While set, `sendMessage` routes to the
827
- * human channel — the agent session itself is never interrupted.
828
- */
829
- escalation: EscalationState | null;
830
- /**
831
- * Hand the conversation to a human operator (docs/human-escalation.md).
832
- * Idempotent while an escalation is open. `agent_gave_up` is used by
833
- * the auto-offer chip; the header button sends `user_requested`.
834
- */
835
- requestHuman: (reason?: 'user_requested' | 'agent_gave_up') => Promise<void>;
836
- sendMessage: (content: string) => Promise<void>;
837
- /**
838
- * Cancels the in-flight generation (OKR-008 KR4). Streamed partial
839
- * text is kept in the transcript; a no-op when nothing is in flight.
840
- * Cancellation only covers the generation phase — once actions start
841
- * executing on-device they run to completion (interrupting a half-done
842
- * form fill would leave the app in a worse state than finishing it).
843
- */
844
- cancelMessage: () => void;
845
- clearMessages: () => void;
846
- clearError: () => void;
847
- }
848
- interface UseAppilotsChatOptions {
849
- /** User-facing prefix for client-side failures before the relay can answer. */
850
- errorPrefix?: string;
851
- /**
852
- * Stream assistant replies token-by-token via SSE (default true).
853
- * When the streaming transport fails before any output, the hook
854
- * falls back to the non-streaming endpoint transparently.
855
- */
856
- streaming?: boolean;
857
- /** Localized escalation copy — see EscalationStrings. */
858
- escalationStrings?: EscalationStrings;
859
- }
860
- /**
861
- * Hook for managing chat state and sending messages to the Appilots agent.
862
- *
863
- * @example
864
- * ```tsx
865
- * const { messages, sendMessage, isLoading } = useAppilotsChat();
866
- *
867
- * const handleSend = () => {
868
- * sendMessage('Navigate to settings');
869
- * };
870
- * ```
871
- */
872
- declare function useAppilotsChat(options?: UseAppilotsChatOptions): UseAppilotsChatReturn;
873
-
874
- interface UseAppilotsActionsOptions {
875
- /**
876
- * Navigation ref from useAppilotsNavigation().
877
- * Required for navigate actions to work.
878
- */
879
- navigationRef?: React.MutableRefObject<any>;
880
- /**
881
- * If true, actions are executed automatically without user approval.
882
- * Confirm actions always require approval regardless of this setting.
883
- * @default false
884
- */
885
- autoExecute?: boolean;
886
- }
887
- interface UseAppilotsActionsReturn {
888
- pendingActions: AgentAction[];
889
- executingActions: AgentAction[];
890
- completedActions: AgentAction[];
891
- approveAction: (actionId: string) => Promise<boolean>;
892
- rejectAction: (actionId: string) => Promise<void>;
893
- }
894
- /**
895
- * Hook for monitoring and controlling agent actions.
896
- *
897
- * Now integrates with the ActionExecutor to actually execute actions
898
- * against live UI components via the ComponentRegistry.
899
- *
900
- * @example
901
- * ```tsx
902
- * const { navigationRef } = useAppilotsNavigation();
903
- * const { pendingActions, approveAction, rejectAction } = useAppilotsActions({
904
- * navigationRef,
905
- * autoExecute: false,
906
- * });
907
- * ```
908
- */
909
- declare function useAppilotsActions(options?: UseAppilotsActionsOptions): UseAppilotsActionsReturn;
910
-
911
- /**
912
- * ComponentRegistry — Central registry mapping component IDs to their
913
- * refs, callbacks, and metadata so the ActionExecutor can find and
914
- * interact with live UI elements.
915
- *
916
- * Screens register their interactive components via hooks
917
- * (useAppilotsField, useAppilotsTarget, useAppilotsToggle).
918
- * When the AI agent returns an action (e.g. form_fill with fieldId "plate"),
919
- * the executor looks up "plate" here and calls the associated setter.
920
- */
921
- type ComponentKind = 'field' | 'target' | 'toggle' | 'slider';
922
- interface FieldEntry {
923
- kind: 'field';
924
- /** Current value of the field */
925
- getValue: () => string;
926
- /** Set the field value programmatically */
927
- setValue: (value: string) => void;
928
- /** Optional: focus the input */
929
- focus?: () => void;
930
- /** Field type hint for the executor */
931
- fieldType?: 'text' | 'select' | 'toggle' | 'date' | 'number' | 'custom';
932
- /** Human-readable label */
933
- label?: string;
934
- /** Screen where this field is registered */
935
- screen?: string;
936
- }
937
- interface TargetEntry {
938
- kind: 'target';
939
- /** Execute the primary action (press) */
940
- press: () => void;
941
- /** Optional: long press */
942
- longPress?: () => void;
943
- /** Optional: scroll to this element */
944
- scrollTo?: () => void;
945
- /** Human-readable label */
946
- label?: string;
947
- /** Screen where this target is registered */
948
- screen?: string;
949
- }
950
- interface ToggleEntry {
951
- kind: 'toggle';
952
- /** Current value */
953
- getValue: () => boolean;
954
- /** Set the toggle value */
955
- setValue: (value: boolean) => void;
956
- /** Human-readable label */
957
- label?: string;
958
- /** Screen where this toggle is registered */
959
- screen?: string;
960
- }
961
- interface SliderEntry {
962
- kind: 'slider';
963
- /** Current numeric value */
964
- getValue: () => number;
965
- /**
966
- * Set the slider value. The executor clamps to [min, max] and snaps
967
- * to `step` BEFORE calling this, so implementations can trust the
968
- * value — but re-validating is harmless.
969
- */
970
- setValue: (value: number) => void;
971
- /** Lower bound (inclusive) */
972
- min: number;
973
- /** Upper bound (inclusive) */
974
- max: number;
975
- /** Step to snap to (omitted = continuous) */
976
- step?: number;
977
- /** Human-readable label */
978
- label?: string;
979
- /** Screen where this slider is registered */
980
- screen?: string;
981
- }
982
- type ComponentEntry = FieldEntry | TargetEntry | ToggleEntry | SliderEntry;
983
- type Listener = (id: string, entry: ComponentEntry | null) => void;
984
- /**
985
- * Public type for a registry instance. Both the singleton and any
986
- * instance returned by `createComponentRegistry()` satisfy this.
987
- *
988
- * The class itself stays internal — devs construct via the factory
989
- * to keep the surface minimal and future-proof.
990
- */
991
- type ComponentRegistry = ComponentRegistryImpl;
992
- declare class ComponentRegistryImpl {
993
- private components;
994
- private listeners;
995
- /**
996
- * Register a component. If an entry with the same ID already exists,
997
- * it is replaced (this handles re-renders / hot-reload).
998
- */
999
- register(id: string, entry: ComponentEntry): void;
1000
- /**
1001
- * Unregister a component (typically on unmount).
1002
- */
1003
- unregister(id: string): void;
1004
- /**
1005
- * Look up a component by its ID.
1006
- */
1007
- get(id: string): ComponentEntry | undefined;
1008
- /**
1009
- * Get a typed entry or undefined.
1010
- */
1011
- getField(id: string): FieldEntry | undefined;
1012
- getTarget(id: string): TargetEntry | undefined;
1013
- getToggle(id: string): ToggleEntry | undefined;
1014
- getSlider(id: string): SliderEntry | undefined;
1015
- /**
1016
- * Get all components on a given screen.
1017
- */
1018
- getByScreen(screen: string): Map<string, ComponentEntry>;
1019
- /**
1020
- * Get all components of a given kind.
1021
- */
1022
- getByKind(kind: ComponentKind): Map<string, ComponentEntry>;
1023
- /**
1024
- * List all registered component IDs with their kind and screen.
1025
- * Useful for debugging and for the AI to know what's available.
1026
- */
1027
- snapshot(): Array<{
1028
- id: string;
1029
- kind: ComponentKind;
1030
- screen?: string;
1031
- label?: string;
1032
- }>;
1033
- /**
1034
- * Subscribe to registry changes.
1035
- * Returns an unsubscribe function.
1036
- */
1037
- subscribe(listener: Listener): () => void;
1038
- /**
1039
- * Clear all entries (useful for testing or full reset).
1040
- */
1041
- clear(): void;
1042
- /** Number of registered components */
1043
- get size(): number;
1044
- private notify;
1045
- }
1046
- /**
1047
- * Singleton registry instance shared across the entire SDK by default.
1048
- *
1049
- * Apps with a single Appilots session (the overwhelmingly common case)
1050
- * never need anything else — hooks, handlers, and auto-tracking all
1051
- * read from this singleton.
1052
- *
1053
- * For multi-tenant or micro-front-end setups where two Appilots
1054
- * sessions might coexist in the same JS process, use
1055
- * `createComponentRegistry()` to obtain a fresh instance and pass it
1056
- * via `<AppilotsRegistryProvider value={...}>`. Hooks resolve via
1057
- * context first, falling back to this singleton.
1058
- *
1059
- * The singleton stays in place to keep the existing public API stable
1060
- * — pré-mortem 2.8 is "future risk", not "current bug".
1061
- */
1062
- declare const componentRegistry: ComponentRegistry;
1063
- /**
1064
- * Create a fresh, isolated ComponentRegistry instance. Pair with
1065
- * `<AppilotsRegistryProvider value={...}>` to scope auto-tracking and
1066
- * hooks to that registry instead of the global singleton.
1067
- *
1068
- * @example
1069
- * ```tsx
1070
- * const tenantRegistry = createComponentRegistry();
1071
- * <AppilotsRegistryProvider value={tenantRegistry}>
1072
- * <TenantApp />
1073
- * </AppilotsRegistryProvider>
1074
- * ```
1075
- */
1076
- declare function createComponentRegistry(): ComponentRegistry;
1077
-
1078
- /**
1079
- * useAppilotsField — Register a text input (or similar field) with the
1080
- * ComponentRegistry so the AI agent can fill it via form_fill actions.
1081
- *
1082
- * Usage:
1083
- * ```tsx
1084
- * const [plate, setPlate] = useState('');
1085
- * const plateRef = useRef<TextInput>(null);
1086
- *
1087
- * useAppilotsField('plate', {
1088
- * value: plate,
1089
- * onChangeText: setPlate,
1090
- * ref: plateRef, // optional — enables focus()
1091
- * fieldType: 'text', // optional — hint for executor
1092
- * label: 'License Plate', // optional — human-readable name
1093
- * screen: 'VehicleForm', // optional — scoped to screen
1094
- * });
1095
- *
1096
- * return <TextInput ref={plateRef} value={plate} onChangeText={setPlate} />;
1097
- * ```
1098
- */
1099
-
1100
- interface UseAppilotsFieldOptions {
1101
- /** Current value of the field */
1102
- value: string;
1103
- /** Callback to update the value (same signature as TextInput.onChangeText) */
1104
- onChangeText: (text: string) => void;
1105
- /** Optional ref to the TextInput for focus support */
1106
- ref?: React.RefObject<any>;
1107
- /** Field type hint */
1108
- fieldType?: FieldEntry['fieldType'];
1109
- /** Human-readable label */
1110
- label?: string;
1111
- /** Screen name this field belongs to */
1112
- screen?: string;
1113
- }
1114
- /**
1115
- * Register a field with the Appilots ComponentRegistry.
1116
- * Automatically unregisters on unmount.
1117
- *
1118
- * @param id - Unique identifier for this field (e.g. "plate", "customerName")
1119
- * @param options - Field configuration
1120
- */
1121
- declare function useAppilotsField(id: string, options: UseAppilotsFieldOptions): void;
1122
-
1123
- /**
1124
- * useAppilotsTarget — Register a pressable UI element (button, card, link)
1125
- * with the ComponentRegistry so the AI agent can interact with it.
1126
- *
1127
- * Usage:
1128
- * ```tsx
1129
- * const handleSubmit = () => { ... };
1130
- *
1131
- * useAppilotsTarget('submitVehicle', {
1132
- * onPress: handleSubmit,
1133
- * label: 'Submit Vehicle',
1134
- * screen: 'VehicleForm',
1135
- * });
1136
- *
1137
- * return <Button title="Submit" onPress={handleSubmit} />;
1138
- * ```
1139
- */
1140
- interface UseAppilotsTargetOptions {
1141
- /** Primary press handler */
1142
- onPress: () => void;
1143
- /** Optional long-press handler */
1144
- onLongPress?: () => void;
1145
- /** Optional scroll-to handler (scroll this element into view) */
1146
- onScrollTo?: () => void;
1147
- /** Human-readable label */
1148
- label?: string;
1149
- /** Screen name this target belongs to */
1150
- screen?: string;
1151
- }
1152
- /**
1153
- * Register a pressable target with the Appilots ComponentRegistry.
1154
- * Automatically unregisters on unmount.
1155
- *
1156
- * @param id - Unique identifier (e.g. "submitVehicle", "openSettings")
1157
- * @param options - Target configuration
1158
- */
1159
- declare function useAppilotsTarget(id: string, options: UseAppilotsTargetOptions): void;
1160
-
1161
- /**
1162
- * useAppilotsToggle — Register a toggle/switch with the ComponentRegistry
1163
- * so the AI agent can flip it via ui_interaction actions.
1164
- *
1165
- * Usage:
1166
- * ```tsx
1167
- * const [pushEnabled, setPushEnabled] = useState(false);
1168
- *
1169
- * useAppilotsToggle('pushNotifications', {
1170
- * value: pushEnabled,
1171
- * onValueChange: setPushEnabled,
1172
- * label: 'Push Notifications',
1173
- * screen: 'Settings',
1174
- * });
1175
- *
1176
- * return <Switch value={pushEnabled} onValueChange={setPushEnabled} />;
1177
- * ```
1178
- */
1179
- interface UseAppilotsToggleOptions {
1180
- /** Current toggle value */
1181
- value: boolean;
1182
- /** Callback when value changes */
1183
- onValueChange: (value: boolean) => void;
1184
- /** Human-readable label */
1185
- label?: string;
1186
- /** Screen name this toggle belongs to */
1187
- screen?: string;
1188
- }
1189
- /**
1190
- * Register a toggle with the Appilots ComponentRegistry.
1191
- * Automatically unregisters on unmount.
1192
- *
1193
- * @param id - Unique identifier (e.g. "pushNotifications", "darkMode")
1194
- * @param options - Toggle configuration
1195
- */
1196
- declare function useAppilotsToggle(id: string, options: UseAppilotsToggleOptions): void;
1197
-
1198
- /**
1199
- * useAppilotsSlider — Register a slider / adjustable numeric control with
1200
- * the ComponentRegistry so the AI agent can set it via
1201
- * `ui_interaction action="set_value"` actions.
1202
- *
1203
- * Registration is what makes a slider agent-operable end to end:
1204
- * captureSnapshot() reads this entry to advertise the slider (with
1205
- * min/max/step) in the observation, and the executor dispatches
1206
- * set_value through the same entry — clamping to [min, max] and
1207
- * snapping to `step` before calling onValueChange.
1208
- *
1209
- * Usage:
1210
- * ```tsx
1211
- * const [mileage, setMileage] = useState(0);
1212
- *
1213
- * useAppilotsSlider('quilometragem', {
1214
- * value: mileage,
1215
- * onValueChange: setMileage,
1216
- * min: 0,
1217
- * max: 300000,
1218
- * step: 500,
1219
- * label: 'Quilometragem',
1220
- * screen: 'VehicleCreate',
1221
- * });
1222
- *
1223
- * return <MySlider value={mileage} onChange={setMileage} min={0} max={300000} />;
1224
- * ```
1225
- */
1226
- interface UseAppilotsSliderOptions {
1227
- /** Current slider value */
1228
- value: number;
1229
- /** Callback when value changes */
1230
- onValueChange: (value: number) => void;
1231
- /** Lower bound (inclusive) — advertised in the observation and enforced by the executor */
1232
- min: number;
1233
- /** Upper bound (inclusive) — advertised in the observation and enforced by the executor */
1234
- max: number;
1235
- /** Step the executor snaps to (omit for a continuous slider) */
1236
- step?: number;
1237
- /** Human-readable label */
1238
- label?: string;
1239
- /** Screen name this slider belongs to */
1240
- screen?: string;
1241
- }
1242
- /**
1243
- * Register a slider with the Appilots ComponentRegistry.
1244
- * Automatically unregisters on unmount.
1245
- *
1246
- * @param id - Unique identifier (e.g. "quilometragem", "volume")
1247
- * @param options - Slider configuration
1248
- */
1249
- declare function useAppilotsSlider(id: string, options: UseAppilotsSliderOptions): void;
1250
-
1251
- interface SuggestedPrompt {
1252
- /** Display label shown on the chip and inserted into the input on tap. */
1253
- text: string;
1254
- /** Where this prompt came from. Useful for analytics or theming. */
1255
- source: 'dev-defined' | 'screen-popular' | 'global-popular';
1256
- }
1257
- interface UseSuggestedPromptsOptions {
1258
- /**
1259
- * Whether the chat is currently open. Hook only fetches while open, so
1260
- * suggestions don't waste a roundtrip when the chat is minimised.
1261
- */
1262
- enabled: boolean;
1263
- /** Max chips to return. Default 4. */
1264
- limit?: number;
1265
- }
1266
- interface UseSuggestedPromptsReturn {
1267
- prompts: SuggestedPrompt[];
1268
- isLoading: boolean;
1269
- /** Re-runs the fetch — call after navigation so chips refresh. */
1270
- refetch: () => void;
1271
- }
1272
- /**
1273
- * Returns ranked suggested prompts to render as chips in the chat
1274
- * empty-state. Three sources are merged in priority order:
1275
- *
1276
- * 1. **Dev-defined** — from `registerScreen({ suggestedPrompts })` in the
1277
- * current app, read synchronously from the local screen registry.
1278
- * First-class signal, always wins.
1279
- *
1280
- * 2. **Screen-popular** — historical user prompts sent FROM this screen,
1281
- * mined server-side from agentMessages history.
1282
- *
1283
- * 3. **Global-popular** — historical user prompts across the project.
1284
- * Fallback for screens with no history yet.
1285
- *
1286
- * The hook re-fetches whenever the active screen changes so chips always
1287
- * match where the user is right now. Server response is cached 1h, so
1288
- * fetches are cheap.
1289
- *
1290
- * @example
1291
- * ```tsx
1292
- * const { prompts } = useSuggestedPrompts({ enabled: chatVisible });
1293
- * return prompts.map((p) => (
1294
- * <Chip key={p.text} onPress={() => setInput(p.text)}>{p.text}</Chip>
1295
- * ));
1296
- * ```
1297
- */
1298
- declare function useSuggestedPrompts(options: UseSuggestedPromptsOptions): UseSuggestedPromptsReturn;
1299
-
1300
- export { useAppilotsField as $, type AppilotsThemeTokens as A, type UseAppilotsSliderOptions as B, type ComponentRegistry as C, type UseAppilotsTargetOptions as D, type EscalationState as E, type FieldEntry as F, type UseAppilotsToggleOptions as G, type UseSuggestedPromptsOptions as H, type UseSuggestedPromptsReturn as I, componentRegistry as J, createComponentRegistry as K, defaultDarkTheme as L, type MessageRole as M, type NavigationPayload as N, defaultLightTheme as O, type PartialThemeTokens as P, detectDeviceLocale as Q, type RemotePersonalization as R, type SliderEntry as S, type TargetEntry as T, type UIInteractionPayload as U, mergeThemeTokens as V, resolveLocale as W, useAppilots as X, useAppilotsActions as Y, useAppilotsChat as Z, useAppilotsContext as _, type AppilotsLocale as a, useAppilotsI18n as a0, useAppilotsNavigation as a1, useAppilotsSlider as a2, useAppilotsTarget as a3, useAppilotsToggle as a4, useSuggestedPrompts as a5, type AgentAction as b, type AgentPermissions as c, type AppilotsTraceEntry as d, type AppilotsEvent as e, type AgentActionType as f, type AgentMessage as g, AppilotsClient as h, type AppilotsClientOptions as i, type AppilotsConfig as j, type AppilotsEventHandler as k, type AppilotsEventType as l, AppilotsI18nProvider as m, type AppilotsI18nProviderProps as n, AppilotsProvider as o, type AppilotsProviderProps as p, type AppilotsStringKey as q, type AppilotsStrings as r, type AppilotsUser as s, type ChatMessage as t, type ComponentEntry as u, type ComponentKind as v, type FormFillPayload as w, type SuggestedPrompt as x, type ToggleEntry as y, type UseAppilotsFieldOptions as z };