@appilots/sdk 0.2.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/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/chunk-GEM6TPAK.mjs +5834 -0
- package/dist/chunk-HDLZGXNF.mjs +2348 -0
- package/dist/chunk-IASJ7YHC.js +5847 -0
- package/dist/chunk-KCDNL4HV.mjs +61 -0
- package/dist/chunk-KGN3DNGX.js +67 -0
- package/dist/chunk-SIBKF7AA.js +2395 -0
- package/dist/hooks/index.d.mts +2 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.js +43 -0
- package/dist/hooks/index.mjs +2 -0
- package/dist/index-BDb1WVNo.d.mts +1300 -0
- package/dist/index-BDb1WVNo.d.ts +1300 -0
- package/dist/index.d.mts +1156 -0
- package/dist/index.d.ts +1156 -0
- package/dist/index.js +2836 -0
- package/dist/index.mjs +2658 -0
- package/dist/navigation/index.d.mts +43 -0
- package/dist/navigation/index.d.ts +43 -0
- package/dist/navigation/index.js +51 -0
- package/dist/navigation/index.mjs +2 -0
- package/dist/registerScreen-D1oGm28T.d.mts +159 -0
- package/dist/registerScreen-D1oGm28T.d.ts +159 -0
- package/metro.js +158 -0
- package/package.json +90 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export { A as AppilotsNavigationContainer, N as NavigationConfig, S as ScreenActionMetadata, a as ScreenFieldMetadata, b as ScreenMetadata, c as clearScreenRegistry, g as getAllScreens, d as getScreenMetadata, r as registerScreen } from '../registerScreen-D1oGm28T.mjs';
|
|
2
|
+
import 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Global navigation state — lightweight singleton so any part of the SDK
|
|
6
|
+
* can read the current screen without needing a React context or hook.
|
|
7
|
+
*
|
|
8
|
+
* Updated by AppilotsNavigationContainer and read by useAppilotsChat().
|
|
9
|
+
*/
|
|
10
|
+
declare function setCurrentScreen(screen: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Get the current screen name. Prefers a LIVE reading from the navigation
|
|
13
|
+
* ref state (using recursive descent into nested navigators) to ensure
|
|
14
|
+
* accuracy even if onStateChange missed an update.
|
|
15
|
+
* Falls back to the cached value set by onStateChange.
|
|
16
|
+
*/
|
|
17
|
+
declare function getCurrentScreen(): string | null;
|
|
18
|
+
declare function setNavigationRef(ref: any): void;
|
|
19
|
+
declare function getNavigationRef(): any;
|
|
20
|
+
declare function getActiveRouteNames(): string[];
|
|
21
|
+
interface RuntimeNavigationStateSnapshot {
|
|
22
|
+
/** Deepest active route name, same semantic as getCurrentScreen(). */
|
|
23
|
+
currentRouteName?: string;
|
|
24
|
+
/** Active route chain from root to deepest route. */
|
|
25
|
+
activePath: string[];
|
|
26
|
+
/** Route names accepted by the root navigator, when React Navigation exposes them. */
|
|
27
|
+
rootRouteNames: string[];
|
|
28
|
+
/** Route names accepted by the currently active nested navigator. */
|
|
29
|
+
currentRouteNames: string[];
|
|
30
|
+
/** Union of route names exposed anywhere in the mounted navigation tree. */
|
|
31
|
+
routeNames: string[];
|
|
32
|
+
/** Whether React Navigation reports that goBack() can currently run. */
|
|
33
|
+
canGoBack?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Snapshot the runtime navigation tree in a small, serializable shape.
|
|
37
|
+
* This gives the relay route-level facts that the visible UI snapshot
|
|
38
|
+
* cannot provide: mounted sibling tabs, root routes, current stack
|
|
39
|
+
* routes, and whether a back action is possible.
|
|
40
|
+
*/
|
|
41
|
+
declare function getNavigationStateSnapshot(): RuntimeNavigationStateSnapshot | null;
|
|
42
|
+
|
|
43
|
+
export { type RuntimeNavigationStateSnapshot, getActiveRouteNames, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, setCurrentScreen, setNavigationRef };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export { A as AppilotsNavigationContainer, N as NavigationConfig, S as ScreenActionMetadata, a as ScreenFieldMetadata, b as ScreenMetadata, c as clearScreenRegistry, g as getAllScreens, d as getScreenMetadata, r as registerScreen } from '../registerScreen-D1oGm28T.js';
|
|
2
|
+
import 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Global navigation state — lightweight singleton so any part of the SDK
|
|
6
|
+
* can read the current screen without needing a React context or hook.
|
|
7
|
+
*
|
|
8
|
+
* Updated by AppilotsNavigationContainer and read by useAppilotsChat().
|
|
9
|
+
*/
|
|
10
|
+
declare function setCurrentScreen(screen: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Get the current screen name. Prefers a LIVE reading from the navigation
|
|
13
|
+
* ref state (using recursive descent into nested navigators) to ensure
|
|
14
|
+
* accuracy even if onStateChange missed an update.
|
|
15
|
+
* Falls back to the cached value set by onStateChange.
|
|
16
|
+
*/
|
|
17
|
+
declare function getCurrentScreen(): string | null;
|
|
18
|
+
declare function setNavigationRef(ref: any): void;
|
|
19
|
+
declare function getNavigationRef(): any;
|
|
20
|
+
declare function getActiveRouteNames(): string[];
|
|
21
|
+
interface RuntimeNavigationStateSnapshot {
|
|
22
|
+
/** Deepest active route name, same semantic as getCurrentScreen(). */
|
|
23
|
+
currentRouteName?: string;
|
|
24
|
+
/** Active route chain from root to deepest route. */
|
|
25
|
+
activePath: string[];
|
|
26
|
+
/** Route names accepted by the root navigator, when React Navigation exposes them. */
|
|
27
|
+
rootRouteNames: string[];
|
|
28
|
+
/** Route names accepted by the currently active nested navigator. */
|
|
29
|
+
currentRouteNames: string[];
|
|
30
|
+
/** Union of route names exposed anywhere in the mounted navigation tree. */
|
|
31
|
+
routeNames: string[];
|
|
32
|
+
/** Whether React Navigation reports that goBack() can currently run. */
|
|
33
|
+
canGoBack?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Snapshot the runtime navigation tree in a small, serializable shape.
|
|
37
|
+
* This gives the relay route-level facts that the visible UI snapshot
|
|
38
|
+
* cannot provide: mounted sibling tabs, root routes, current stack
|
|
39
|
+
* routes, and whether a back action is possible.
|
|
40
|
+
*/
|
|
41
|
+
declare function getNavigationStateSnapshot(): RuntimeNavigationStateSnapshot | null;
|
|
42
|
+
|
|
43
|
+
export { type RuntimeNavigationStateSnapshot, getActiveRouteNames, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, setCurrentScreen, setNavigationRef };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkKGN3DNGX_js = require('../chunk-KGN3DNGX.js');
|
|
4
|
+
var chunkSIBKF7AA_js = require('../chunk-SIBKF7AA.js');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "AppilotsNavigationContainer", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkKGN3DNGX_js.AppilotsNavigationContainer; }
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "clearScreenRegistry", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () { return chunkSIBKF7AA_js.clearScreenRegistry; }
|
|
15
|
+
});
|
|
16
|
+
Object.defineProperty(exports, "getActiveRouteNames", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return chunkSIBKF7AA_js.getActiveRouteNames; }
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(exports, "getAllScreens", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
get: function () { return chunkSIBKF7AA_js.getAllScreens; }
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "getCurrentScreen", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () { return chunkSIBKF7AA_js.getCurrentScreen; }
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(exports, "getNavigationRef", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return chunkSIBKF7AA_js.getNavigationRef; }
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(exports, "getNavigationStateSnapshot", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
get: function () { return chunkSIBKF7AA_js.getNavigationStateSnapshot; }
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "getScreenMetadata", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () { return chunkSIBKF7AA_js.getScreenMetadata; }
|
|
39
|
+
});
|
|
40
|
+
Object.defineProperty(exports, "registerScreen", {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () { return chunkSIBKF7AA_js.registerScreen; }
|
|
43
|
+
});
|
|
44
|
+
Object.defineProperty(exports, "setCurrentScreen", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return chunkSIBKF7AA_js.setCurrentScreen; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "setNavigationRef", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return chunkSIBKF7AA_js.setNavigationRef; }
|
|
51
|
+
});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { AppilotsNavigationContainer } from '../chunk-KCDNL4HV.mjs';
|
|
2
|
+
export { clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef } from '../chunk-HDLZGXNF.mjs';
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
interface AppilotsNavigationContainerProps {
|
|
4
|
+
children: React__default.ReactElement;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Wraps your NavigationContainer from the outside and automatically
|
|
8
|
+
* injects `ref` and `onStateChange` to track the current screen.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { NavigationContainer } from '@react-navigation/native';
|
|
12
|
+
* import { AppilotsNavigationContainer } from '@appilots/sdk';
|
|
13
|
+
*
|
|
14
|
+
* <AppilotsProvider>
|
|
15
|
+
* <AppilotsNavigationContainer>
|
|
16
|
+
* <NavigationContainer>
|
|
17
|
+
* <Stack.Navigator>...</Stack.Navigator>
|
|
18
|
+
* </NavigationContainer>
|
|
19
|
+
* </AppilotsNavigationContainer>
|
|
20
|
+
* <AppilotsChat />
|
|
21
|
+
* </AppilotsProvider>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function AppilotsNavigationContainer({ children }: AppilotsNavigationContainerProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Navigation-related types for the Appilots SDK.
|
|
28
|
+
*/
|
|
29
|
+
interface ScreenFieldMetadata {
|
|
30
|
+
/** Field identifier (used by AI model to reference this field) */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Human-readable label (must match the UI component's label) */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Field type */
|
|
35
|
+
type: 'text' | 'number' | 'select' | 'toggle' | 'date' | string;
|
|
36
|
+
/** Whether the field is required */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Options for select fields */
|
|
39
|
+
options?: {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
}
|
|
44
|
+
interface ScreenActionMetadata {
|
|
45
|
+
/** Action identifier (used by AI model to reference this action) */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Human-readable label (must match the UI component's label) */
|
|
48
|
+
label: string;
|
|
49
|
+
/** Action type */
|
|
50
|
+
type: 'submit' | 'button' | 'link' | string;
|
|
51
|
+
/** Target screen for navigation/link actions, when known. */
|
|
52
|
+
targetScreen?: string;
|
|
53
|
+
/**
|
|
54
|
+
* When true, the agent MUST present a confirmation card to the user
|
|
55
|
+
* before executing this action. Set at registerScreen time for
|
|
56
|
+
* high-risk or destructive operations.
|
|
57
|
+
*
|
|
58
|
+
* The server's permission policy honours this flag when present in
|
|
59
|
+
* the MCP doc, but a stale MCP can miss it. As defense-in-depth,
|
|
60
|
+
* the SDK also gates such actions locally: when a `ui_interaction`
|
|
61
|
+
* targets an action with `requiresConfirmation: true` and there is
|
|
62
|
+
* NO already-pending confirm action in the queue, the executor
|
|
63
|
+
* synthesises one and waits for user input before pressing.
|
|
64
|
+
*/
|
|
65
|
+
requiresConfirmation?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Structured risk/effect metadata. Prefer these fields over label
|
|
68
|
+
* heuristics for multilingual apps: the runtime can gate the action
|
|
69
|
+
* without trying to infer intent from Portuguese/English/etc. text.
|
|
70
|
+
*/
|
|
71
|
+
effect?: 'read' | 'write' | 'destructive' | string;
|
|
72
|
+
riskLevel?: 'low' | 'medium' | 'high' | string;
|
|
73
|
+
destructive?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Static-analysis hints produced by the MCP generator (Camada B).
|
|
76
|
+
* Present only when the generator could statically prove the
|
|
77
|
+
* handler's async shape — otherwise undefined and the SDK falls
|
|
78
|
+
* back to agnostic runtime signals (ActivityIndicator,
|
|
79
|
+
* pressed-button-still-disabled, fingerprint quiescence).
|
|
80
|
+
*
|
|
81
|
+
* Mirrors `AppilotsInferredAction` from `@appilots/mcp-generator`.
|
|
82
|
+
* Kept as a structural type here to avoid a runtime dependency
|
|
83
|
+
* between sdk and mcp-generator packages.
|
|
84
|
+
*/
|
|
85
|
+
appilotsInferred?: AppilotsInferredAction;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Inferred metadata about an action's expected async behavior.
|
|
89
|
+
* See `packages/mcp-generator/docs/INFERRED_ACTION_FIELDS.md` for
|
|
90
|
+
* the full schema and detection rules.
|
|
91
|
+
*/
|
|
92
|
+
interface AppilotsInferredAction {
|
|
93
|
+
isAsyncTrigger?: boolean;
|
|
94
|
+
expectedOutcome?: 'navigation' | 'inline-feedback' | 'data-arrival' | 'mixed' | 'none';
|
|
95
|
+
loadingStateBindings?: string[];
|
|
96
|
+
}
|
|
97
|
+
interface ScreenMetadata {
|
|
98
|
+
/** Unique screen identifier */
|
|
99
|
+
name: string;
|
|
100
|
+
/** Human-readable title */
|
|
101
|
+
title?: string;
|
|
102
|
+
/** Description of what this screen does */
|
|
103
|
+
description?: string;
|
|
104
|
+
/** Available actions on this screen (legacy: string[], new: ScreenActionMetadata[]) */
|
|
105
|
+
actions?: (string | ScreenActionMetadata)[];
|
|
106
|
+
/** Form fields available on this screen (legacy: string[], new: ScreenFieldMetadata[]) */
|
|
107
|
+
fields?: ScreenFieldMetadata[];
|
|
108
|
+
/** Legacy: simple list of form field names */
|
|
109
|
+
formFields?: string[];
|
|
110
|
+
/** Tags for categorisation */
|
|
111
|
+
tags?: string[];
|
|
112
|
+
/**
|
|
113
|
+
* Dev-defined prompts to surface as chips when the chat opens on this
|
|
114
|
+
* screen. Highest priority — these win over screen-action and global
|
|
115
|
+
* popular prompts. Keep them short and specific to the screen ("Adicionar
|
|
116
|
+
* cliente" beats "Me ajude").
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* registerScreen({
|
|
120
|
+
* name: 'Customers',
|
|
121
|
+
* suggestedPrompts: ['Adicionar cliente', 'Buscar por nome'],
|
|
122
|
+
* });
|
|
123
|
+
*/
|
|
124
|
+
suggestedPrompts?: string[];
|
|
125
|
+
}
|
|
126
|
+
interface NavigationConfig {
|
|
127
|
+
/** Root navigator name */
|
|
128
|
+
rootNavigator?: string;
|
|
129
|
+
/** Map of screen names to metadata */
|
|
130
|
+
screens?: Record<string, ScreenMetadata>;
|
|
131
|
+
/** Navigation linking config */
|
|
132
|
+
linking?: {
|
|
133
|
+
prefixes?: string[];
|
|
134
|
+
config?: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a screen with metadata so the AI agent can understand it.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* registerScreen({
|
|
144
|
+
* name: 'ItemList',
|
|
145
|
+
* title: 'Items',
|
|
146
|
+
* description: 'Lists items available in this app',
|
|
147
|
+
* actions: ['viewDetails', 'addItem'],
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function registerScreen(metadata: ScreenMetadata): void;
|
|
152
|
+
/** Get metadata for a specific screen */
|
|
153
|
+
declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
|
|
154
|
+
/** Get all registered screens */
|
|
155
|
+
declare function getAllScreens(): ScreenMetadata[];
|
|
156
|
+
/** Clear the screen registry (useful for testing) */
|
|
157
|
+
declare function clearScreenRegistry(): void;
|
|
158
|
+
|
|
159
|
+
export { AppilotsNavigationContainer as A, type NavigationConfig as N, type ScreenActionMetadata as S, type ScreenFieldMetadata as a, type ScreenMetadata as b, clearScreenRegistry as c, getScreenMetadata as d, getAllScreens as g, registerScreen as r };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
interface AppilotsNavigationContainerProps {
|
|
4
|
+
children: React__default.ReactElement;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Wraps your NavigationContainer from the outside and automatically
|
|
8
|
+
* injects `ref` and `onStateChange` to track the current screen.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { NavigationContainer } from '@react-navigation/native';
|
|
12
|
+
* import { AppilotsNavigationContainer } from '@appilots/sdk';
|
|
13
|
+
*
|
|
14
|
+
* <AppilotsProvider>
|
|
15
|
+
* <AppilotsNavigationContainer>
|
|
16
|
+
* <NavigationContainer>
|
|
17
|
+
* <Stack.Navigator>...</Stack.Navigator>
|
|
18
|
+
* </NavigationContainer>
|
|
19
|
+
* </AppilotsNavigationContainer>
|
|
20
|
+
* <AppilotsChat />
|
|
21
|
+
* </AppilotsProvider>
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
declare function AppilotsNavigationContainer({ children }: AppilotsNavigationContainerProps): React__default.ReactElement<any, string | React__default.JSXElementConstructor<any>>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Navigation-related types for the Appilots SDK.
|
|
28
|
+
*/
|
|
29
|
+
interface ScreenFieldMetadata {
|
|
30
|
+
/** Field identifier (used by AI model to reference this field) */
|
|
31
|
+
id: string;
|
|
32
|
+
/** Human-readable label (must match the UI component's label) */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Field type */
|
|
35
|
+
type: 'text' | 'number' | 'select' | 'toggle' | 'date' | string;
|
|
36
|
+
/** Whether the field is required */
|
|
37
|
+
required?: boolean;
|
|
38
|
+
/** Options for select fields */
|
|
39
|
+
options?: {
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
}
|
|
44
|
+
interface ScreenActionMetadata {
|
|
45
|
+
/** Action identifier (used by AI model to reference this action) */
|
|
46
|
+
id: string;
|
|
47
|
+
/** Human-readable label (must match the UI component's label) */
|
|
48
|
+
label: string;
|
|
49
|
+
/** Action type */
|
|
50
|
+
type: 'submit' | 'button' | 'link' | string;
|
|
51
|
+
/** Target screen for navigation/link actions, when known. */
|
|
52
|
+
targetScreen?: string;
|
|
53
|
+
/**
|
|
54
|
+
* When true, the agent MUST present a confirmation card to the user
|
|
55
|
+
* before executing this action. Set at registerScreen time for
|
|
56
|
+
* high-risk or destructive operations.
|
|
57
|
+
*
|
|
58
|
+
* The server's permission policy honours this flag when present in
|
|
59
|
+
* the MCP doc, but a stale MCP can miss it. As defense-in-depth,
|
|
60
|
+
* the SDK also gates such actions locally: when a `ui_interaction`
|
|
61
|
+
* targets an action with `requiresConfirmation: true` and there is
|
|
62
|
+
* NO already-pending confirm action in the queue, the executor
|
|
63
|
+
* synthesises one and waits for user input before pressing.
|
|
64
|
+
*/
|
|
65
|
+
requiresConfirmation?: boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Structured risk/effect metadata. Prefer these fields over label
|
|
68
|
+
* heuristics for multilingual apps: the runtime can gate the action
|
|
69
|
+
* without trying to infer intent from Portuguese/English/etc. text.
|
|
70
|
+
*/
|
|
71
|
+
effect?: 'read' | 'write' | 'destructive' | string;
|
|
72
|
+
riskLevel?: 'low' | 'medium' | 'high' | string;
|
|
73
|
+
destructive?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Static-analysis hints produced by the MCP generator (Camada B).
|
|
76
|
+
* Present only when the generator could statically prove the
|
|
77
|
+
* handler's async shape — otherwise undefined and the SDK falls
|
|
78
|
+
* back to agnostic runtime signals (ActivityIndicator,
|
|
79
|
+
* pressed-button-still-disabled, fingerprint quiescence).
|
|
80
|
+
*
|
|
81
|
+
* Mirrors `AppilotsInferredAction` from `@appilots/mcp-generator`.
|
|
82
|
+
* Kept as a structural type here to avoid a runtime dependency
|
|
83
|
+
* between sdk and mcp-generator packages.
|
|
84
|
+
*/
|
|
85
|
+
appilotsInferred?: AppilotsInferredAction;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Inferred metadata about an action's expected async behavior.
|
|
89
|
+
* See `packages/mcp-generator/docs/INFERRED_ACTION_FIELDS.md` for
|
|
90
|
+
* the full schema and detection rules.
|
|
91
|
+
*/
|
|
92
|
+
interface AppilotsInferredAction {
|
|
93
|
+
isAsyncTrigger?: boolean;
|
|
94
|
+
expectedOutcome?: 'navigation' | 'inline-feedback' | 'data-arrival' | 'mixed' | 'none';
|
|
95
|
+
loadingStateBindings?: string[];
|
|
96
|
+
}
|
|
97
|
+
interface ScreenMetadata {
|
|
98
|
+
/** Unique screen identifier */
|
|
99
|
+
name: string;
|
|
100
|
+
/** Human-readable title */
|
|
101
|
+
title?: string;
|
|
102
|
+
/** Description of what this screen does */
|
|
103
|
+
description?: string;
|
|
104
|
+
/** Available actions on this screen (legacy: string[], new: ScreenActionMetadata[]) */
|
|
105
|
+
actions?: (string | ScreenActionMetadata)[];
|
|
106
|
+
/** Form fields available on this screen (legacy: string[], new: ScreenFieldMetadata[]) */
|
|
107
|
+
fields?: ScreenFieldMetadata[];
|
|
108
|
+
/** Legacy: simple list of form field names */
|
|
109
|
+
formFields?: string[];
|
|
110
|
+
/** Tags for categorisation */
|
|
111
|
+
tags?: string[];
|
|
112
|
+
/**
|
|
113
|
+
* Dev-defined prompts to surface as chips when the chat opens on this
|
|
114
|
+
* screen. Highest priority — these win over screen-action and global
|
|
115
|
+
* popular prompts. Keep them short and specific to the screen ("Adicionar
|
|
116
|
+
* cliente" beats "Me ajude").
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* registerScreen({
|
|
120
|
+
* name: 'Customers',
|
|
121
|
+
* suggestedPrompts: ['Adicionar cliente', 'Buscar por nome'],
|
|
122
|
+
* });
|
|
123
|
+
*/
|
|
124
|
+
suggestedPrompts?: string[];
|
|
125
|
+
}
|
|
126
|
+
interface NavigationConfig {
|
|
127
|
+
/** Root navigator name */
|
|
128
|
+
rootNavigator?: string;
|
|
129
|
+
/** Map of screen names to metadata */
|
|
130
|
+
screens?: Record<string, ScreenMetadata>;
|
|
131
|
+
/** Navigation linking config */
|
|
132
|
+
linking?: {
|
|
133
|
+
prefixes?: string[];
|
|
134
|
+
config?: Record<string, unknown>;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Register a screen with metadata so the AI agent can understand it.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* registerScreen({
|
|
144
|
+
* name: 'ItemList',
|
|
145
|
+
* title: 'Items',
|
|
146
|
+
* description: 'Lists items available in this app',
|
|
147
|
+
* actions: ['viewDetails', 'addItem'],
|
|
148
|
+
* });
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare function registerScreen(metadata: ScreenMetadata): void;
|
|
152
|
+
/** Get metadata for a specific screen */
|
|
153
|
+
declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
|
|
154
|
+
/** Get all registered screens */
|
|
155
|
+
declare function getAllScreens(): ScreenMetadata[];
|
|
156
|
+
/** Clear the screen registry (useful for testing) */
|
|
157
|
+
declare function clearScreenRegistry(): void;
|
|
158
|
+
|
|
159
|
+
export { AppilotsNavigationContainer as A, type NavigationConfig as N, type ScreenActionMetadata as S, type ScreenFieldMetadata as a, type ScreenMetadata as b, clearScreenRegistry as c, getScreenMetadata as d, getAllScreens as g, registerScreen as r };
|
package/metro.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @appilots/sdk — Metro plugin
|
|
3
|
+
*
|
|
4
|
+
* Wraps your Metro config so AppilotsProvider auto-loads `.appilotsrc`.
|
|
5
|
+
*
|
|
6
|
+
* How it works:
|
|
7
|
+
* 1. Reads .appilotsrc JSON at Metro startup
|
|
8
|
+
* 2. Creates a tiny JS module that sets `global.__APPILOTS_RC__`
|
|
9
|
+
* 3. Registers it via resolver so the SDK can find it
|
|
10
|
+
* 4. The SDK's AppilotsProvider reads `global.__APPILOTS_RC__` and auto-inits
|
|
11
|
+
*
|
|
12
|
+
* The app's index.js just needs to import the setup module before the app:
|
|
13
|
+
* require('@appilots/auto-init');
|
|
14
|
+
*
|
|
15
|
+
* Or use the `transformerPath` approach for zero-touch setup.
|
|
16
|
+
*
|
|
17
|
+
* Usage in metro.config.js:
|
|
18
|
+
* ```js
|
|
19
|
+
* const { withAppilots } = require('@appilots/sdk/metro');
|
|
20
|
+
* module.exports = withAppilots(mergeConfig(defaultConfig, config));
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
'use strict';
|
|
25
|
+
|
|
26
|
+
const path = require('path');
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
|
|
29
|
+
function parseConfigJSON(raw) {
|
|
30
|
+
const parsed = JSON.parse(raw);
|
|
31
|
+
return JSON.stringify(parsed, null, 2);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createShimSource(configJSON) {
|
|
35
|
+
return (
|
|
36
|
+
'// Auto-generated by @appilots/sdk/metro — do not edit\n' +
|
|
37
|
+
'var _g = typeof globalThis !== "undefined" ? globalThis : global;\n' +
|
|
38
|
+
'var _config = ' + configJSON + ';\n' +
|
|
39
|
+
'_g.__APPILOTS_RC__ = _config;\n' +
|
|
40
|
+
'\n' +
|
|
41
|
+
'// Call initAppilots immediately so auto-tracking patches React.createElement\n' +
|
|
42
|
+
'// BEFORE any app components render.\n' +
|
|
43
|
+
'var _sdk = require("@appilots/sdk");\n' +
|
|
44
|
+
'if (_sdk && _sdk.initAppilots) { _sdk.initAppilots(_config); }\n' +
|
|
45
|
+
'\n' +
|
|
46
|
+
'// Pass JSX runtime modules to the SDK for auto-tracking.\n' +
|
|
47
|
+
'// These requires run in the app context (Metro), so they resolve correctly.\n' +
|
|
48
|
+
'// The SDK cannot require these itself because tsup transforms require() to __require().\n' +
|
|
49
|
+
'if (_sdk && _sdk.enableAppilotsAutoTracking && _sdk.isAutoTrackingEnabled && _sdk.isAutoTrackingEnabled()) {\n' +
|
|
50
|
+
' // Auto-tracking was already enabled by initAppilots, but JSX runtime patches\n' +
|
|
51
|
+
' // need the actual runtime modules from the app context.\n' +
|
|
52
|
+
' try {\n' +
|
|
53
|
+
' var _jsxRuntime = require("react/jsx-runtime");\n' +
|
|
54
|
+
' var _jsxDevRuntime = null;\n' +
|
|
55
|
+
' try { _jsxDevRuntime = require("react/jsx-dev-runtime"); } catch(e) {}\n' +
|
|
56
|
+
' if (_sdk._patchJsxRuntimes) {\n' +
|
|
57
|
+
' _sdk._patchJsxRuntimes(_jsxRuntime, _jsxDevRuntime);\n' +
|
|
58
|
+
' }\n' +
|
|
59
|
+
' } catch(e) {\n' +
|
|
60
|
+
' console.warn("[Appilots] Could not patch JSX runtime: " + e.message);\n' +
|
|
61
|
+
' }\n' +
|
|
62
|
+
'}\n'
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function writeShim(configJSON, shimPath) {
|
|
67
|
+
fs.mkdirSync(path.dirname(shimPath), { recursive: true });
|
|
68
|
+
fs.writeFileSync(shimPath, createShimSource(configJSON));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function withAppilots(metroConfig, options = {}) {
|
|
72
|
+
const projectRoot = metroConfig.projectRoot || process.cwd();
|
|
73
|
+
const configPath = options.configPath || path.resolve(projectRoot, '.appilotsrc');
|
|
74
|
+
|
|
75
|
+
if (!fs.existsSync(configPath)) {
|
|
76
|
+
console.warn('[Appilots] .appilotsrc not found at ' + configPath);
|
|
77
|
+
return metroConfig;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const shimDir = path.resolve(projectRoot, 'node_modules', '.cache', 'appilots');
|
|
81
|
+
const shimPath = path.resolve(shimDir, 'auto-init.js');
|
|
82
|
+
let lastConfigSource = null;
|
|
83
|
+
|
|
84
|
+
const ensureShimFresh = () => {
|
|
85
|
+
const source = fs.readFileSync(configPath, 'utf8').trim();
|
|
86
|
+
if (source === lastConfigSource && fs.existsSync(shimPath)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
writeShim(parseConfigJSON(source), shimPath);
|
|
90
|
+
lastConfigSource = source;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
ensureShimFresh();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const message = error && error.message ? error.message : String(error);
|
|
97
|
+
console.warn('[Appilots] failed to generate auto-init shim from ' + configPath + ': ' + message);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Resolve `@appilots/auto-init` to the shim
|
|
101
|
+
const existingResolveRequest = metroConfig.resolver?.resolveRequest;
|
|
102
|
+
|
|
103
|
+
// Metro < 0.79 does not read package.json "exports" by default
|
|
104
|
+
// (`unstable_enablePackageExports` is off), so deep imports like
|
|
105
|
+
// `@appilots/shared/match` — which the SDK dist emits since the shared
|
|
106
|
+
// element matcher landed — fail to resolve in consumer apps. Map
|
|
107
|
+
// `@appilots/shared/<subpath>` onto the package's built dist layout
|
|
108
|
+
// explicitly. Kept narrow on purpose: flipping
|
|
109
|
+
// unstable_enablePackageExports globally would change resolution for
|
|
110
|
+
// every dependency in the host app.
|
|
111
|
+
const SHARED_SUBPATH_RE = /^@appilots\/shared\/([A-Za-z0-9_-]+)$/;
|
|
112
|
+
function resolveSharedSubpath(moduleName) {
|
|
113
|
+
const match = SHARED_SUBPATH_RE.exec(moduleName);
|
|
114
|
+
if (!match) return null;
|
|
115
|
+
try {
|
|
116
|
+
// require.resolve('@appilots/shared') → <pkg>/dist/index.js; the
|
|
117
|
+
// package root is two levels up. (package.json itself is not in
|
|
118
|
+
// the exports map, so it can't be resolved directly.) __dirname
|
|
119
|
+
// as a fallback path: the SDK always sees shared as a sibling —
|
|
120
|
+
// node_modules/@appilots/{sdk,shared} in apps, workspace packages
|
|
121
|
+
// in the monorepo — even when projectRoot has no resolution
|
|
122
|
+
// chain to it.
|
|
123
|
+
const mainEntry = require.resolve('@appilots/shared', {
|
|
124
|
+
paths: [projectRoot, __dirname],
|
|
125
|
+
});
|
|
126
|
+
const packageRoot = path.dirname(path.dirname(mainEntry));
|
|
127
|
+
const candidate = path.join(packageRoot, 'dist', match[1], 'index.js');
|
|
128
|
+
if (fs.existsSync(candidate)) {
|
|
129
|
+
return { type: 'sourceFile', filePath: candidate };
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
// fall through to the default resolver (its error message names
|
|
133
|
+
// the module, which is more actionable than ours would be)
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
...metroConfig,
|
|
140
|
+
resolver: {
|
|
141
|
+
...(metroConfig.resolver || {}),
|
|
142
|
+
resolveRequest: (context, moduleName, platform) => {
|
|
143
|
+
if (moduleName === '@appilots/auto-init') {
|
|
144
|
+
ensureShimFresh();
|
|
145
|
+
return { type: 'sourceFile', filePath: shimPath };
|
|
146
|
+
}
|
|
147
|
+
const shared = resolveSharedSubpath(moduleName);
|
|
148
|
+
if (shared) return shared;
|
|
149
|
+
if (existingResolveRequest) {
|
|
150
|
+
return existingResolveRequest(context, moduleName, platform);
|
|
151
|
+
}
|
|
152
|
+
return context.resolveRequest(context, moduleName, platform);
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = { withAppilots };
|