@appilots/sdk 0.11.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -176,7 +176,28 @@ interface NavigationConfig {
176
176
  * ```
177
177
  */
178
178
  declare function registerScreen(metadata: ScreenMetadata): void;
179
- /** Get metadata for a specific screen */
179
+ /**
180
+ * Get metadata for a specific screen.
181
+ *
182
+ * Exact name first, then the SAME fold the server applies.
183
+ *
184
+ * The asymmetry this closes: the backend routes by
185
+ * `normalizeRouteIdentity`, so `HomeTab`, `HomeScreen` and `Home` are
186
+ * one screen to it, while this lookup was a bare `Map.get` and they were
187
+ * three. An app whose navigator names a tab `HomeTab` and whose
188
+ * `registerScreen` says `Home` — the ordinary React Navigation shape,
189
+ * since the tab and the screen inside it cannot share a name — served
190
+ * the agent a described screen from the map and `undefined` here, so the
191
+ * title, the description and the declared risk of the screen it was
192
+ * standing on all went missing. Nothing reported an error; the metadata
193
+ * was simply absent.
194
+ *
195
+ * Folded matching only resolves an UNAMBIGUOUS hit. Two screens that
196
+ * fold together (`Orders` and `OrdersTab` both registered) are a real
197
+ * ambiguity, and guessing between them would be worse than the miss:
198
+ * the caller gets `undefined` and the app keeps the exact-name contract
199
+ * it already had.
200
+ */
180
201
  declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
181
202
  /** Get all registered screens */
182
203
  declare function getAllScreens(): ScreenMetadata[];
@@ -176,7 +176,28 @@ interface NavigationConfig {
176
176
  * ```
177
177
  */
178
178
  declare function registerScreen(metadata: ScreenMetadata): void;
179
- /** Get metadata for a specific screen */
179
+ /**
180
+ * Get metadata for a specific screen.
181
+ *
182
+ * Exact name first, then the SAME fold the server applies.
183
+ *
184
+ * The asymmetry this closes: the backend routes by
185
+ * `normalizeRouteIdentity`, so `HomeTab`, `HomeScreen` and `Home` are
186
+ * one screen to it, while this lookup was a bare `Map.get` and they were
187
+ * three. An app whose navigator names a tab `HomeTab` and whose
188
+ * `registerScreen` says `Home` — the ordinary React Navigation shape,
189
+ * since the tab and the screen inside it cannot share a name — served
190
+ * the agent a described screen from the map and `undefined` here, so the
191
+ * title, the description and the declared risk of the screen it was
192
+ * standing on all went missing. Nothing reported an error; the metadata
193
+ * was simply absent.
194
+ *
195
+ * Folded matching only resolves an UNAMBIGUOUS hit. Two screens that
196
+ * fold together (`Orders` and `OrdersTab` both registered) are a real
197
+ * ambiguity, and guessing between them would be worse than the miss:
198
+ * the caller gets `undefined` and the app keeps the exact-name contract
199
+ * it already had.
200
+ */
180
201
  declare function getScreenMetadata(name: string): ScreenMetadata | undefined;
181
202
  /** Get all registered screens */
182
203
  declare function getAllScreens(): ScreenMetadata[];
@@ -1,51 +1,51 @@
1
1
  'use strict';
2
2
 
3
- var chunk5UVMNKPT_js = require('../chunk-5UVMNKPT.js');
4
- var chunkSUMIABJK_js = require('../chunk-SUMIABJK.js');
3
+ var chunkALJGKORS_js = require('../chunk-ALJGKORS.js');
4
+ var chunkUZ2D4BVX_js = require('../chunk-UZ2D4BVX.js');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "AppilotsNavigationContainer", {
9
9
  enumerable: true,
10
- get: function () { return chunk5UVMNKPT_js.AppilotsNavigationContainer; }
10
+ get: function () { return chunkALJGKORS_js.AppilotsNavigationContainer; }
11
11
  });
12
12
  Object.defineProperty(exports, "clearScreenRegistry", {
13
13
  enumerable: true,
14
- get: function () { return chunkSUMIABJK_js.clearScreenRegistry; }
14
+ get: function () { return chunkUZ2D4BVX_js.clearScreenRegistry; }
15
15
  });
16
16
  Object.defineProperty(exports, "getActiveRouteNames", {
17
17
  enumerable: true,
18
- get: function () { return chunkSUMIABJK_js.getActiveRouteNames; }
18
+ get: function () { return chunkUZ2D4BVX_js.getActiveRouteNames; }
19
19
  });
20
20
  Object.defineProperty(exports, "getAllScreens", {
21
21
  enumerable: true,
22
- get: function () { return chunkSUMIABJK_js.getAllScreens; }
22
+ get: function () { return chunkUZ2D4BVX_js.getAllScreens; }
23
23
  });
24
24
  Object.defineProperty(exports, "getCurrentScreen", {
25
25
  enumerable: true,
26
- get: function () { return chunkSUMIABJK_js.getCurrentScreen; }
26
+ get: function () { return chunkUZ2D4BVX_js.getCurrentScreen; }
27
27
  });
28
28
  Object.defineProperty(exports, "getNavigationRef", {
29
29
  enumerable: true,
30
- get: function () { return chunkSUMIABJK_js.getNavigationRef; }
30
+ get: function () { return chunkUZ2D4BVX_js.getNavigationRef; }
31
31
  });
32
32
  Object.defineProperty(exports, "getNavigationStateSnapshot", {
33
33
  enumerable: true,
34
- get: function () { return chunkSUMIABJK_js.getNavigationStateSnapshot; }
34
+ get: function () { return chunkUZ2D4BVX_js.getNavigationStateSnapshot; }
35
35
  });
36
36
  Object.defineProperty(exports, "getScreenMetadata", {
37
37
  enumerable: true,
38
- get: function () { return chunkSUMIABJK_js.getScreenMetadata; }
38
+ get: function () { return chunkUZ2D4BVX_js.getScreenMetadata; }
39
39
  });
40
40
  Object.defineProperty(exports, "registerScreen", {
41
41
  enumerable: true,
42
- get: function () { return chunkSUMIABJK_js.registerScreen; }
42
+ get: function () { return chunkUZ2D4BVX_js.registerScreen; }
43
43
  });
44
44
  Object.defineProperty(exports, "setCurrentScreen", {
45
45
  enumerable: true,
46
- get: function () { return chunkSUMIABJK_js.setCurrentScreen; }
46
+ get: function () { return chunkUZ2D4BVX_js.setCurrentScreen; }
47
47
  });
48
48
  Object.defineProperty(exports, "setNavigationRef", {
49
49
  enumerable: true,
50
- get: function () { return chunkSUMIABJK_js.setNavigationRef; }
50
+ get: function () { return chunkUZ2D4BVX_js.setNavigationRef; }
51
51
  });
@@ -1,2 +1,2 @@
1
- export { AppilotsNavigationContainer } from '../chunk-JKLE5SLN.mjs';
2
- export { clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef } from '../chunk-ROXXCDIG.mjs';
1
+ export { AppilotsNavigationContainer } from '../chunk-L3SY3Q4K.mjs';
2
+ export { clearScreenRegistry, getActiveRouteNames, getAllScreens, getCurrentScreen, getNavigationRef, getNavigationStateSnapshot, getScreenMetadata, registerScreen, setCurrentScreen, setNavigationRef } from '../chunk-HRWBK35Y.mjs';
package/metro.d.ts CHANGED
@@ -13,17 +13,15 @@
13
13
  export interface MetroConfigLike {
14
14
  projectRoot?: string;
15
15
  resolver?: {
16
- resolveRequest?: (
17
- context: unknown,
18
- moduleName: string,
19
- platform: string | null,
20
- ) => unknown;
16
+ resolveRequest?: (context: unknown, moduleName: string, platform: string | null) => unknown;
21
17
  [option: string]: unknown;
22
18
  };
23
19
  [option: string]: unknown;
24
20
  }
25
21
 
26
22
  export interface WithAppilotsOptions {
23
+ /** CLI output directory containing control-evidence.json. Defaults to .appilots. */
24
+ outputDir?: string;
27
25
  /**
28
26
  * Path to the `.appilotsrc` file.
29
27
  *
package/metro.js CHANGED
@@ -65,13 +65,16 @@ function missingConfigError(configPath) {
65
65
  );
66
66
  }
67
67
 
68
- function createShimSource(configJSON) {
68
+ function createShimSource(configJSON, sessionStorageAvailable) {
69
69
  return (
70
70
  '// Auto-generated by @appilots/sdk/metro — do not edit\n' +
71
71
  'var _g = typeof globalThis !== "undefined" ? globalThis : global;\n' +
72
72
  'var _config = ' +
73
73
  configJSON +
74
74
  ';\n' +
75
+ (sessionStorageAvailable
76
+ ? 'try { var _storage = require("@react-native-async-storage/async-storage");\n_config.sessionStorage = _storage.default || _storage; } catch (_storageError) {}\n'
77
+ : '') +
75
78
  '_g.__APPILOTS_RC__ = _config;\n' +
76
79
  '\n' +
77
80
  '// Call initAppilots immediately so auto-tracking patches React.createElement\n' +
@@ -99,9 +102,9 @@ function createShimSource(configJSON) {
99
102
  );
100
103
  }
101
104
 
102
- function writeShim(configJSON, shimPath) {
105
+ function writeShim(configJSON, shimPath, sessionStorageAvailable) {
103
106
  fs.mkdirSync(path.dirname(shimPath), { recursive: true });
104
- fs.writeFileSync(shimPath, createShimSource(configJSON));
107
+ fs.writeFileSync(shimPath, createShimSource(configJSON, sessionStorageAvailable));
105
108
  }
106
109
 
107
110
  function withAppilots(metroConfig, options = {}) {
@@ -136,12 +139,47 @@ function withAppilots(metroConfig, options = {}) {
136
139
  // A malformed .appilotsrc throws from JSON.parse and is NOT downgraded to
137
140
  // a warning either: the shim would be stale or absent, and the failure
138
141
  // would resurface later as an unresolvable module.
139
- writeShim(parseConfigJSON(source), shimPath);
142
+ // Reuse an existing host dependency; never add a native dependency to the app.
143
+ let sessionStorageAvailable = false;
144
+ if (JSON.parse(source).sessionPersistence !== false) {
145
+ try {
146
+ require.resolve('@react-native-async-storage/async-storage', { paths: [projectRoot] });
147
+ sessionStorageAvailable = true;
148
+ } catch {
149
+ /* Hosts without storage keep in-memory sessions. */
150
+ }
151
+ }
152
+ writeShim(parseConfigJSON(source), shimPath, sessionStorageAvailable);
140
153
  lastConfigSource = source;
141
154
  };
142
155
 
143
156
  ensureShimFresh();
144
157
 
158
+ // The existing Metro integration consumes the CLI's revision-bound evidence.
159
+ // Client JSX files remain unchanged; chain the original transformer.
160
+ const upstream = metroConfig.transformer?.babelTransformerPath;
161
+ let transformerPath;
162
+ if (upstream) {
163
+ transformerPath = path.join(shimDir, 'control-transformer.js');
164
+ const evidencePath = path.resolve(
165
+ projectRoot,
166
+ options.outputDir || '.appilots',
167
+ 'control-evidence.json',
168
+ );
169
+ fs.writeFileSync(
170
+ transformerPath,
171
+ 'module.exports = require(' +
172
+ JSON.stringify(path.join(__dirname, 'control-transformer.js')) +
173
+ ').createControlTransformer(' +
174
+ JSON.stringify(upstream) +
175
+ ',' +
176
+ JSON.stringify(evidencePath) +
177
+ ',' +
178
+ JSON.stringify(projectRoot) +
179
+ ');\n',
180
+ );
181
+ }
182
+
145
183
  // Resolve `@appilots/auto-init` to the shim
146
184
  const existingResolveRequest = metroConfig.resolver?.resolveRequest;
147
185
 
@@ -160,7 +198,10 @@ function withAppilots(metroConfig, options = {}) {
160
198
  return context.resolveRequest(context, moduleName, platform);
161
199
  },
162
200
  },
163
- transformer: withPreservedNames(metroConfig.transformer),
201
+ transformer: {
202
+ ...withPreservedNames(metroConfig.transformer),
203
+ ...(transformerPath ? { babelTransformerPath: transformerPath } : {}),
204
+ },
164
205
  };
165
206
  }
166
207
 
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@appilots/sdk",
3
- "version": "0.11.3",
3
+ "version": "0.13.0",
4
4
  "description": "AI-powered chat component and navigation SDK for React Native apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
+ "react-native": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
10
14
  "import": {
11
15
  "types": "./dist/index.d.mts",
12
16
  "default": "./dist/index.mjs"
@@ -17,6 +21,10 @@
17
21
  }
18
22
  },
19
23
  "./navigation": {
24
+ "react-native": {
25
+ "types": "./dist/navigation/index.d.ts",
26
+ "default": "./dist/navigation/index.js"
27
+ },
20
28
  "import": {
21
29
  "types": "./dist/navigation/index.d.mts",
22
30
  "default": "./dist/navigation/index.mjs"
@@ -27,6 +35,10 @@
27
35
  }
28
36
  },
29
37
  "./hooks": {
38
+ "react-native": {
39
+ "types": "./dist/hooks/index.d.ts",
40
+ "default": "./dist/hooks/index.js"
41
+ },
30
42
  "import": {
31
43
  "types": "./dist/hooks/index.d.mts",
32
44
  "default": "./dist/hooks/index.mjs"
@@ -44,6 +56,7 @@
44
56
  "files": [
45
57
  "dist",
46
58
  "metro.js",
59
+ "control-transformer.js",
47
60
  "metro.d.ts",
48
61
  "navigation",
49
62
  "hooks",
@@ -105,16 +118,17 @@
105
118
  "@types/react": "^18.3.0",
106
119
  "@types/react-native": "^0.73.0",
107
120
  "@types/react-test-renderer": "^18.3.0",
121
+ "@vitest/coverage-v8": "^2.1.0",
108
122
  "react": "^18.3.0",
109
123
  "react-19": "npm:react@^19.0.0",
110
124
  "react-native": "^0.76.0",
125
+ "react-native-paper": "5.14.5",
111
126
  "react-native-safe-area-context": "^5.0.0",
112
127
  "react-native-svg": "15.8.0",
113
128
  "react-test-renderer": "^18.3.1",
114
129
  "react-test-renderer-19": "npm:react-test-renderer@^19.0.0",
115
130
  "tsup": "^8.3.0",
116
131
  "typescript": "^5.6.0",
117
- "@vitest/coverage-v8": "^2.1.0",
118
132
  "vitest": "^2.1.0"
119
133
  }
120
134
  }