react-native-mcp-kit 4.2.0 → 4.2.1

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.
Files changed (239) hide show
  1. package/dist/babel/testIdPlugin/collectHooks.d.ts +13 -0
  2. package/dist/babel/testIdPlugin/collectHooks.d.ts.map +1 -0
  3. package/dist/babel/testIdPlugin/collectHooks.js +112 -0
  4. package/dist/babel/testIdPlugin/collectHooks.js.map +1 -0
  5. package/dist/babel/testIdPlugin/constants.d.ts +6 -0
  6. package/dist/babel/testIdPlugin/constants.d.ts.map +1 -0
  7. package/dist/babel/testIdPlugin/constants.js +49 -0
  8. package/dist/babel/testIdPlugin/constants.js.map +1 -0
  9. package/dist/babel/testIdPlugin/helpers.d.ts +7 -0
  10. package/dist/babel/testIdPlugin/helpers.d.ts.map +1 -0
  11. package/dist/babel/testIdPlugin/helpers.js +77 -0
  12. package/dist/babel/testIdPlugin/helpers.js.map +1 -0
  13. package/dist/babel/testIdPlugin/hocUnwrap.d.ts +4 -0
  14. package/dist/babel/testIdPlugin/hocUnwrap.d.ts.map +1 -0
  15. package/dist/babel/testIdPlugin/hocUnwrap.js +94 -0
  16. package/dist/babel/testIdPlugin/hocUnwrap.js.map +1 -0
  17. package/dist/babel/{testIdPlugin.d.ts → testIdPlugin/index.d.ts} +1 -1
  18. package/dist/babel/testIdPlugin/index.d.ts.map +1 -0
  19. package/dist/babel/testIdPlugin/index.js +205 -0
  20. package/dist/babel/testIdPlugin/index.js.map +1 -0
  21. package/dist/babel/testIdPlugin/inject.d.ts +7 -0
  22. package/dist/babel/testIdPlugin/inject.d.ts.map +1 -0
  23. package/dist/babel/testIdPlugin/inject.js +86 -0
  24. package/dist/babel/testIdPlugin/inject.js.map +1 -0
  25. package/dist/babel/testIdPlugin/types.d.ts +59 -0
  26. package/dist/babel/testIdPlugin/types.d.ts.map +1 -0
  27. package/dist/babel/testIdPlugin/types.js +3 -0
  28. package/dist/babel/testIdPlugin/types.js.map +1 -0
  29. package/dist/bin/ios-hid +0 -0
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +2 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/modules/fiberTree/hooks/extract.d.ts +6 -0
  35. package/dist/modules/fiberTree/hooks/extract.d.ts.map +1 -0
  36. package/dist/modules/fiberTree/hooks/extract.js +187 -0
  37. package/dist/modules/fiberTree/hooks/extract.js.map +1 -0
  38. package/dist/modules/fiberTree/hooks/flatten.d.ts +4 -0
  39. package/dist/modules/fiberTree/hooks/flatten.d.ts.map +1 -0
  40. package/dist/modules/fiberTree/hooks/flatten.js +81 -0
  41. package/dist/modules/fiberTree/hooks/flatten.js.map +1 -0
  42. package/dist/modules/fiberTree/hooks/index.d.ts +5 -0
  43. package/dist/modules/fiberTree/hooks/index.d.ts.map +1 -0
  44. package/dist/modules/fiberTree/hooks/index.js +10 -0
  45. package/dist/modules/fiberTree/hooks/index.js.map +1 -0
  46. package/dist/modules/fiberTree/hooks/options.d.ts +9 -0
  47. package/dist/modules/fiberTree/hooks/options.d.ts.map +1 -0
  48. package/dist/modules/fiberTree/hooks/options.js +27 -0
  49. package/dist/modules/fiberTree/hooks/options.js.map +1 -0
  50. package/dist/modules/fiberTree/hooks/patterns.d.ts +2 -0
  51. package/dist/modules/fiberTree/hooks/patterns.d.ts.map +1 -0
  52. package/dist/modules/fiberTree/hooks/patterns.js +26 -0
  53. package/dist/modules/fiberTree/hooks/patterns.js.map +1 -0
  54. package/dist/modules/fiberTree/hooks/shape.d.ts +3 -0
  55. package/dist/modules/fiberTree/hooks/shape.d.ts.map +1 -0
  56. package/dist/modules/fiberTree/hooks/shape.js +66 -0
  57. package/dist/modules/fiberTree/hooks/shape.js.map +1 -0
  58. package/dist/modules/fiberTree/hooks/slotCount.d.ts +2 -0
  59. package/dist/modules/fiberTree/hooks/slotCount.d.ts.map +1 -0
  60. package/dist/modules/fiberTree/hooks/slotCount.js +93 -0
  61. package/dist/modules/fiberTree/hooks/slotCount.js.map +1 -0
  62. package/dist/modules/fiberTree/{hooks.d.ts → hooks/types.d.ts} +1 -34
  63. package/dist/modules/fiberTree/hooks/types.d.ts.map +1 -0
  64. package/dist/modules/fiberTree/hooks/types.js +3 -0
  65. package/dist/modules/fiberTree/hooks/types.js.map +1 -0
  66. package/dist/modules/fiberTree/hooks/value.d.ts +2 -0
  67. package/dist/modules/fiberTree/hooks/value.d.ts.map +1 -0
  68. package/dist/modules/fiberTree/hooks/value.js +89 -0
  69. package/dist/modules/fiberTree/hooks/value.js.map +1 -0
  70. package/dist/modules/fiberTree/utils/constants.d.ts +8 -0
  71. package/dist/modules/fiberTree/utils/constants.d.ts.map +1 -0
  72. package/dist/modules/fiberTree/utils/constants.js +15 -0
  73. package/dist/modules/fiberTree/utils/constants.js.map +1 -0
  74. package/dist/modules/fiberTree/utils/index.d.ts +9 -0
  75. package/dist/modules/fiberTree/utils/index.d.ts.map +1 -0
  76. package/dist/modules/fiberTree/utils/index.js +34 -0
  77. package/dist/modules/fiberTree/utils/index.js.map +1 -0
  78. package/dist/modules/fiberTree/utils/match.d.ts +4 -0
  79. package/dist/modules/fiberTree/utils/match.d.ts.map +1 -0
  80. package/dist/modules/fiberTree/utils/match.js +169 -0
  81. package/dist/modules/fiberTree/utils/match.js.map +1 -0
  82. package/dist/modules/fiberTree/utils/naming.d.ts +4 -0
  83. package/dist/modules/fiberTree/utils/naming.d.ts.map +1 -0
  84. package/dist/modules/fiberTree/utils/naming.js +52 -0
  85. package/dist/modules/fiberTree/utils/naming.js.map +1 -0
  86. package/dist/modules/fiberTree/utils/native.d.ts +5 -0
  87. package/dist/modules/fiberTree/utils/native.d.ts.map +1 -0
  88. package/dist/modules/fiberTree/utils/native.js +101 -0
  89. package/dist/modules/fiberTree/utils/native.js.map +1 -0
  90. package/dist/modules/fiberTree/utils/projection.d.ts +9 -0
  91. package/dist/modules/fiberTree/utils/projection.d.ts.map +1 -0
  92. package/dist/modules/fiberTree/utils/projection.js +75 -0
  93. package/dist/modules/fiberTree/utils/projection.js.map +1 -0
  94. package/dist/modules/fiberTree/utils/root.d.ts +4 -0
  95. package/dist/modules/fiberTree/utils/root.d.ts.map +1 -0
  96. package/dist/modules/fiberTree/utils/root.js +30 -0
  97. package/dist/modules/fiberTree/utils/root.js.map +1 -0
  98. package/dist/modules/fiberTree/utils/screen.d.ts +10 -0
  99. package/dist/modules/fiberTree/utils/screen.d.ts.map +1 -0
  100. package/dist/modules/fiberTree/utils/screen.js +39 -0
  101. package/dist/modules/fiberTree/utils/screen.js.map +1 -0
  102. package/dist/modules/fiberTree/utils/serialize.d.ts +4 -0
  103. package/dist/modules/fiberTree/utils/serialize.d.ts.map +1 -0
  104. package/dist/modules/fiberTree/utils/serialize.js +102 -0
  105. package/dist/modules/fiberTree/utils/serialize.js.map +1 -0
  106. package/dist/modules/fiberTree/utils/traverse.d.ts +12 -0
  107. package/dist/modules/fiberTree/utils/traverse.d.ts.map +1 -0
  108. package/dist/modules/fiberTree/utils/traverse.js +107 -0
  109. package/dist/modules/fiberTree/utils/traverse.js.map +1 -0
  110. package/dist/server/dispatch.d.ts +15 -0
  111. package/dist/server/dispatch.d.ts.map +1 -0
  112. package/dist/server/dispatch.js +121 -0
  113. package/dist/server/dispatch.js.map +1 -0
  114. package/dist/server/helpers.d.ts +97 -0
  115. package/dist/server/helpers.d.ts.map +1 -0
  116. package/dist/server/helpers.js +162 -0
  117. package/dist/server/helpers.js.map +1 -0
  118. package/dist/server/host/deviceResolver/byClient.d.ts +5 -0
  119. package/dist/server/host/deviceResolver/byClient.d.ts.map +1 -0
  120. package/dist/server/host/deviceResolver/byClient.js +171 -0
  121. package/dist/server/host/deviceResolver/byClient.js.map +1 -0
  122. package/dist/server/host/deviceResolver/byId.d.ts +5 -0
  123. package/dist/server/host/deviceResolver/byId.d.ts.map +1 -0
  124. package/dist/server/host/deviceResolver/byId.js +81 -0
  125. package/dist/server/host/deviceResolver/byId.js.map +1 -0
  126. package/dist/server/host/deviceResolver/enrich.d.ts +5 -0
  127. package/dist/server/host/deviceResolver/enrich.d.ts.map +1 -0
  128. package/dist/server/host/deviceResolver/enrich.js +123 -0
  129. package/dist/server/host/deviceResolver/enrich.js.map +1 -0
  130. package/dist/server/host/deviceResolver/index.d.ts +13 -0
  131. package/dist/server/host/deviceResolver/index.d.ts.map +1 -0
  132. package/dist/server/host/deviceResolver/index.js +65 -0
  133. package/dist/server/host/deviceResolver/index.js.map +1 -0
  134. package/dist/server/host/deviceResolver/list.d.ts +10 -0
  135. package/dist/server/host/deviceResolver/list.d.ts.map +1 -0
  136. package/dist/server/host/deviceResolver/list.js +119 -0
  137. package/dist/server/host/deviceResolver/list.js.map +1 -0
  138. package/dist/server/host/deviceResolver/scan.d.ts +4 -0
  139. package/dist/server/host/deviceResolver/scan.d.ts.map +1 -0
  140. package/dist/server/host/deviceResolver/scan.js +102 -0
  141. package/dist/server/host/deviceResolver/scan.js.map +1 -0
  142. package/dist/server/host/{deviceResolver.d.ts → deviceResolver/types.d.ts} +1 -16
  143. package/dist/server/host/deviceResolver/types.d.ts.map +1 -0
  144. package/dist/server/host/deviceResolver/types.js +3 -0
  145. package/dist/server/host/deviceResolver/types.js.map +1 -0
  146. package/dist/server/host/tools/input/android.d.ts +15 -0
  147. package/dist/server/host/tools/input/android.d.ts.map +1 -0
  148. package/dist/server/host/tools/input/android.js +88 -0
  149. package/dist/server/host/tools/input/android.js.map +1 -0
  150. package/dist/server/host/tools/input/constants.d.ts +14 -0
  151. package/dist/server/host/tools/input/constants.d.ts.map +1 -0
  152. package/dist/server/host/tools/input/constants.js +41 -0
  153. package/dist/server/host/tools/input/constants.js.map +1 -0
  154. package/dist/server/host/tools/input/drag.d.ts +4 -0
  155. package/dist/server/host/tools/input/drag.d.ts.map +1 -0
  156. package/dist/server/host/tools/input/drag.js +76 -0
  157. package/dist/server/host/tools/input/drag.js.map +1 -0
  158. package/dist/server/host/tools/input/index.d.ts +8 -0
  159. package/dist/server/host/tools/input/index.d.ts.map +1 -0
  160. package/dist/server/host/tools/input/index.js +18 -0
  161. package/dist/server/host/tools/input/index.js.map +1 -0
  162. package/dist/server/host/tools/input/longPress.d.ts +4 -0
  163. package/dist/server/host/tools/input/longPress.d.ts.map +1 -0
  164. package/dist/server/host/tools/input/longPress.js +49 -0
  165. package/dist/server/host/tools/input/longPress.js.map +1 -0
  166. package/dist/server/host/tools/input/pressKey.d.ts +4 -0
  167. package/dist/server/host/tools/input/pressKey.d.ts.map +1 -0
  168. package/dist/server/host/tools/input/pressKey.js +42 -0
  169. package/dist/server/host/tools/input/pressKey.js.map +1 -0
  170. package/dist/server/host/tools/input/swipe.d.ts +4 -0
  171. package/dist/server/host/tools/input/swipe.d.ts.map +1 -0
  172. package/dist/server/host/tools/input/swipe.js +71 -0
  173. package/dist/server/host/tools/input/swipe.js.map +1 -0
  174. package/dist/server/host/tools/input/tap.d.ts +4 -0
  175. package/dist/server/host/tools/input/tap.d.ts.map +1 -0
  176. package/dist/server/host/tools/input/tap.js +49 -0
  177. package/dist/server/host/tools/input/tap.js.map +1 -0
  178. package/dist/server/host/tools/input/typeText.d.ts +4 -0
  179. package/dist/server/host/tools/input/typeText.d.ts.map +1 -0
  180. package/dist/server/host/tools/input/typeText.js +52 -0
  181. package/dist/server/host/tools/input/typeText.js.map +1 -0
  182. package/dist/server/host/tools/input/typeTextBatch.d.ts +4 -0
  183. package/dist/server/host/tools/input/typeTextBatch.d.ts.map +1 -0
  184. package/dist/server/host/tools/input/typeTextBatch.js +106 -0
  185. package/dist/server/host/tools/input/typeTextBatch.js.map +1 -0
  186. package/dist/server/instructions.d.ts +2 -0
  187. package/dist/server/instructions.d.ts.map +1 -0
  188. package/dist/server/instructions.js +74 -0
  189. package/dist/server/instructions.js.map +1 -0
  190. package/dist/server/mcpServer.d.ts +0 -12
  191. package/dist/server/mcpServer.d.ts.map +1 -1
  192. package/dist/server/mcpServer.js +26 -877
  193. package/dist/server/mcpServer.js.map +1 -1
  194. package/dist/server/predicate.d.ts +31 -0
  195. package/dist/server/predicate.d.ts.map +1 -0
  196. package/dist/server/predicate.js +104 -0
  197. package/dist/server/predicate.js.map +1 -0
  198. package/dist/server/tools/assert.d.ts +4 -0
  199. package/dist/server/tools/assert.d.ts.map +1 -0
  200. package/dist/server/tools/assert.js +79 -0
  201. package/dist/server/tools/assert.js.map +1 -0
  202. package/dist/server/tools/call.d.ts +4 -0
  203. package/dist/server/tools/call.d.ts.map +1 -0
  204. package/dist/server/tools/call.js +38 -0
  205. package/dist/server/tools/call.js.map +1 -0
  206. package/dist/server/tools/connectionStatus.d.ts +4 -0
  207. package/dist/server/tools/connectionStatus.d.ts.map +1 -0
  208. package/dist/server/tools/connectionStatus.js +41 -0
  209. package/dist/server/tools/connectionStatus.js.map +1 -0
  210. package/dist/server/tools/describeTool.d.ts +4 -0
  211. package/dist/server/tools/describeTool.d.ts.map +1 -0
  212. package/dist/server/tools/describeTool.js +130 -0
  213. package/dist/server/tools/describeTool.js.map +1 -0
  214. package/dist/server/tools/listTools.d.ts +4 -0
  215. package/dist/server/tools/listTools.d.ts.map +1 -0
  216. package/dist/server/tools/listTools.js +109 -0
  217. package/dist/server/tools/listTools.js.map +1 -0
  218. package/dist/server/tools/waitUntil.d.ts +4 -0
  219. package/dist/server/tools/waitUntil.d.ts.map +1 -0
  220. package/dist/server/tools/waitUntil.js +119 -0
  221. package/dist/server/tools/waitUntil.js.map +1 -0
  222. package/package.json +2 -2
  223. package/dist/babel/testIdPlugin.d.ts.map +0 -1
  224. package/dist/babel/testIdPlugin.js +0 -585
  225. package/dist/babel/testIdPlugin.js.map +0 -1
  226. package/dist/modules/fiberTree/hooks.d.ts.map +0 -1
  227. package/dist/modules/fiberTree/hooks.js +0 -550
  228. package/dist/modules/fiberTree/hooks.js.map +0 -1
  229. package/dist/modules/fiberTree/utils.d.ts +0 -39
  230. package/dist/modules/fiberTree/utils.d.ts.map +0 -1
  231. package/dist/modules/fiberTree/utils.js +0 -641
  232. package/dist/modules/fiberTree/utils.js.map +0 -1
  233. package/dist/server/host/deviceResolver.d.ts.map +0 -1
  234. package/dist/server/host/deviceResolver.js +0 -621
  235. package/dist/server/host/deviceResolver.js.map +0 -1
  236. package/dist/server/host/tools/input.d.ts +0 -10
  237. package/dist/server/host/tools/input.d.ts.map +0 -1
  238. package/dist/server/host/tools/input.js +0 -503
  239. package/dist/server/host/tools/input.js.map +0 -1
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serializeFiber = exports.getTextContent = void 0;
4
+ const constants_1 = require("./constants");
5
+ const naming_1 = require("./naming");
6
+ const getTextContent = (fiber) => {
7
+ if (fiber.tag === constants_1.HOST_TEXT) {
8
+ return fiber.memoizedProps;
9
+ }
10
+ // Check children for text
11
+ let text = '';
12
+ let child = fiber.child;
13
+ while (child) {
14
+ if (child.tag === constants_1.HOST_TEXT && typeof child.memoizedProps === 'string') {
15
+ text += child.memoizedProps;
16
+ }
17
+ child = child.sibling;
18
+ }
19
+ return text || undefined;
20
+ };
21
+ exports.getTextContent = getTextContent;
22
+ // Host components that are just native mirrors of composite wrappers (e.g. RCTView for View)
23
+ const HOST_PASSTHROUGH = new Set(['RCTView', 'RCTText', 'RCTScrollView', 'RCTSafeAreaView']);
24
+ const shouldSkipFiber = (fiber) => {
25
+ const componentType = (0, naming_1.getComponentType)(fiber);
26
+ // Skip internal React wrapper nodes (providers, contexts, etc.)
27
+ if (componentType === 'other' && fiber.tag !== constants_1.HOST_TEXT)
28
+ return true;
29
+ // Skip native host mirrors — their composite parent already represents the same component
30
+ if (componentType === 'host' && HOST_PASSTHROUGH.has((0, naming_1.getComponentName)(fiber)))
31
+ return true;
32
+ return false;
33
+ };
34
+ const collectChildren = (fiber, maxDepth, currentDepth) => {
35
+ const children = [];
36
+ let child = fiber.child;
37
+ while (child) {
38
+ if (shouldSkipFiber(child)) {
39
+ // Skip this node but collect its children at the same depth
40
+ children.push(...collectChildren(child, maxDepth, currentDepth));
41
+ }
42
+ else {
43
+ const serialized = (0, exports.serializeFiber)(child, maxDepth, currentDepth + 1);
44
+ if (serialized) {
45
+ children.push(serialized);
46
+ }
47
+ }
48
+ child = child.sibling;
49
+ }
50
+ return children;
51
+ };
52
+ const serializeFiberUnsafe = (fiber, maxDepth, currentDepth) => {
53
+ if (shouldSkipFiber(fiber)) {
54
+ const children = collectChildren(fiber, maxDepth, currentDepth);
55
+ if (children.length === 1)
56
+ return children[0];
57
+ if (children.length > 1) {
58
+ return {
59
+ children,
60
+ name: 'Fragment',
61
+ props: {},
62
+ type: 'other',
63
+ };
64
+ }
65
+ return null;
66
+ }
67
+ const name = (0, naming_1.getComponentName)(fiber);
68
+ // Pass raw memoizedProps through — handler-level `applyProjection` runs the
69
+ // single canonical projectValue walk on the final response, including this
70
+ // tree. Projecting here would cause double-projection and break path drill.
71
+ const props = (fiber.memoizedProps ?? {});
72
+ const mcpId = fiber.memoizedProps?.['data-mcp-id'];
73
+ const testID = fiber.memoizedProps?.testID;
74
+ const text = (0, exports.getTextContent)(fiber);
75
+ const children = collectChildren(fiber, maxDepth, currentDepth);
76
+ return {
77
+ children,
78
+ mcpId,
79
+ name,
80
+ props,
81
+ testID,
82
+ text,
83
+ type: (0, naming_1.getComponentType)(fiber),
84
+ };
85
+ };
86
+ const serializeFiber = (fiber, maxDepth, currentDepth = 0) => {
87
+ if (!fiber || currentDepth > maxDepth)
88
+ return null;
89
+ try {
90
+ return serializeFiberUnsafe(fiber, maxDepth, currentDepth);
91
+ }
92
+ catch {
93
+ return {
94
+ children: [],
95
+ name: (0, naming_1.getComponentName)(fiber),
96
+ props: { __error: 'Failed to serialize' },
97
+ type: (0, naming_1.getComponentType)(fiber),
98
+ };
99
+ }
100
+ };
101
+ exports.serializeFiber = serializeFiber;
102
+ //# sourceMappingURL=serialize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serialize.js","sourceRoot":"","sources":["../../../../src/modules/fiberTree/utils/serialize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type Fiber } from '../../../modules/fiberTree/types';
2
+ export declare const findFiber: (root: Fiber, predicate: (fiber: Fiber) => boolean) => Fiber | null;
3
+ export declare const findAllFibers: (root: Fiber, predicate: (fiber: Fiber) => boolean) => Fiber[];
4
+ export declare const findByMcpId: (root: Fiber, mcpId: string) => Fiber | null;
5
+ export declare const findByTestID: (root: Fiber, testID: string) => Fiber | null;
6
+ export declare const findByName: (root: Fiber, name: string) => Fiber | null;
7
+ export declare const findByText: (root: Fiber, text: string) => Fiber | null;
8
+ export declare const getDirectChildren: (fiber: Fiber) => Fiber[];
9
+ export declare const getSiblings: (fiber: Fiber) => Fiber[];
10
+ export declare const getAncestors: (fiber: Fiber) => Fiber[];
11
+ export declare const findHostFiber: (fiber: Fiber) => Fiber | null;
12
+ //# sourceMappingURL=traverse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.d.ts","sourceRoot":"","sources":["../../../../src/modules/fiberTree/utils/traverse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAMvD,eAAO,MAAM,SAAS,SAAU,KAAK,aAAa,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,KAAG,KAAK,GAAG,IAWrF,CAAC;AAEF,eAAO,MAAM,aAAa,SAAU,KAAK,aAAa,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,KAAG,KAAK,EAgBtF,CAAC;AAEF,eAAO,MAAM,WAAW,SAAU,KAAK,SAAS,MAAM,KAAG,KAAK,GAAG,IAIhE,CAAC;AAEF,eAAO,MAAM,YAAY,SAAU,KAAK,UAAU,MAAM,KAAG,KAAK,GAAG,IAIlE,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,KAAK,QAAQ,MAAM,KAAG,KAAK,GAAG,IAI9D,CAAC;AAEF,eAAO,MAAM,UAAU,SAAU,KAAK,QAAQ,MAAM,KAAG,KAAK,GAAG,IAK9D,CAAC;AAGF,eAAO,MAAM,iBAAiB,UAAW,KAAK,KAAG,KAAK,EAQrD,CAAC;AAGF,eAAO,MAAM,WAAW,UAAW,KAAK,KAAG,KAAK,EAM/C,CAAC;AAGF,eAAO,MAAM,YAAY,UAAW,KAAK,KAAG,KAAK,EAQhD,CAAC;AAGF,eAAO,MAAM,aAAa,UAAW,KAAK,KAAG,KAAK,GAAG,IAUpD,CAAC"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findHostFiber = exports.getAncestors = exports.getSiblings = exports.getDirectChildren = exports.findByText = exports.findByName = exports.findByTestID = exports.findByMcpId = exports.findAllFibers = exports.findFiber = void 0;
4
+ const constants_1 = require("./constants");
5
+ const naming_1 = require("./naming");
6
+ const serialize_1 = require("./serialize");
7
+ const findFiber = (root, predicate) => {
8
+ if (predicate(root))
9
+ return root;
10
+ let child = root.child;
11
+ while (child) {
12
+ const found = (0, exports.findFiber)(child, predicate);
13
+ if (found)
14
+ return found;
15
+ child = child.sibling;
16
+ }
17
+ return null;
18
+ };
19
+ exports.findFiber = findFiber;
20
+ const findAllFibers = (root, predicate) => {
21
+ const results = [];
22
+ const walk = (fiber) => {
23
+ if (predicate(fiber)) {
24
+ results.push(fiber);
25
+ }
26
+ let child = fiber.child;
27
+ while (child) {
28
+ walk(child);
29
+ child = child.sibling;
30
+ }
31
+ };
32
+ walk(root);
33
+ return results;
34
+ };
35
+ exports.findAllFibers = findAllFibers;
36
+ const findByMcpId = (root, mcpId) => {
37
+ return (0, exports.findFiber)(root, (fiber) => {
38
+ return fiber.memoizedProps?.['data-mcp-id'] === mcpId;
39
+ });
40
+ };
41
+ exports.findByMcpId = findByMcpId;
42
+ const findByTestID = (root, testID) => {
43
+ return (0, exports.findFiber)(root, (fiber) => {
44
+ return fiber.memoizedProps?.testID === testID;
45
+ });
46
+ };
47
+ exports.findByTestID = findByTestID;
48
+ const findByName = (root, name) => {
49
+ return (0, exports.findFiber)(root, (fiber) => {
50
+ return (0, naming_1.getComponentName)(fiber) === name;
51
+ });
52
+ };
53
+ exports.findByName = findByName;
54
+ const findByText = (root, text) => {
55
+ return (0, exports.findFiber)(root, (fiber) => {
56
+ const content = (0, serialize_1.getTextContent)(fiber);
57
+ return content !== undefined && content.includes(text);
58
+ });
59
+ };
60
+ exports.findByText = findByText;
61
+ // Direct children of a fiber (one level down, not descendants).
62
+ const getDirectChildren = (fiber) => {
63
+ const out = [];
64
+ let child = fiber.child;
65
+ while (child) {
66
+ out.push(child);
67
+ child = child.sibling;
68
+ }
69
+ return out;
70
+ };
71
+ exports.getDirectChildren = getDirectChildren;
72
+ // Sibling fibers at the same level, excluding `fiber` itself.
73
+ const getSiblings = (fiber) => {
74
+ const parent = fiber.return;
75
+ if (!parent)
76
+ return [];
77
+ return (0, exports.getDirectChildren)(parent).filter((f) => {
78
+ return f !== fiber;
79
+ });
80
+ };
81
+ exports.getSiblings = getSiblings;
82
+ // Ancestors walked upward via `fiber.return`, nearest first.
83
+ const getAncestors = (fiber) => {
84
+ const out = [];
85
+ let current = fiber.return;
86
+ while (current) {
87
+ out.push(current);
88
+ current = current.return;
89
+ }
90
+ return out;
91
+ };
92
+ exports.getAncestors = getAncestors;
93
+ // Find the nearest host fiber (native component) from a given fiber.
94
+ const findHostFiber = (fiber) => {
95
+ if (fiber.tag === constants_1.HOST_COMPONENT)
96
+ return fiber;
97
+ let child = fiber.child;
98
+ while (child) {
99
+ const found = (0, exports.findHostFiber)(child);
100
+ if (found)
101
+ return found;
102
+ child = child.sibling;
103
+ }
104
+ return null;
105
+ };
106
+ exports.findHostFiber = findHostFiber;
107
+ //# sourceMappingURL=traverse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"traverse.js","sourceRoot":"","sources":["../../../../src/modules/fiberTree/utils/traverse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type Bridge } from './bridge';
2
+ import { type DispatchResult, type HostToolEntry } from './helpers';
3
+ import { type HostModule } from './host/types';
4
+ /**
5
+ * Pre-indexes host tools by full name so dispatch is O(1).
6
+ */
7
+ export declare const buildHostToolMap: (hostModules: HostModule[]) => Map<string, HostToolEntry>;
8
+ /**
9
+ * Creates the tool dispatcher used by `call`, `wait_until`, `assert`, and host
10
+ * tools that chain (`host__tap_fiber` → `fiber_tree__query` + `host__tap`). The
11
+ * returned function closes over `bridge` + `hostToolMap` so the host context's
12
+ * own `dispatch` callback can re-enter without losing the original clientId.
13
+ */
14
+ export declare const createDispatcher: (bridge: Bridge, hostToolMap: Map<string, HostToolEntry>) => ((tool: string, args: Record<string, unknown>, clientId?: string) => Promise<DispatchResult>);
15
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/server/dispatch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,gBAAgB,gBAAiB,UAAU,EAAE,KAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAcrF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,WACnB,MAAM,eACD,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,KACtC,CAAC,CACF,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,cAAc,CAAC,CA8F3B,CAAC"}
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDispatcher = exports.buildHostToolMap = void 0;
4
+ const protocol_1 = require("../shared/protocol");
5
+ /**
6
+ * Pre-indexes host tools by full name so dispatch is O(1).
7
+ */
8
+ const buildHostToolMap = (hostModules) => {
9
+ const map = new Map();
10
+ for (const mod of hostModules) {
11
+ for (const [toolName, tool] of Object.entries(mod.tools)) {
12
+ const fullName = `${mod.name}${protocol_1.MODULE_SEPARATOR}${toolName}`;
13
+ map.set(fullName, {
14
+ handler: tool.handler,
15
+ moduleName: mod.name,
16
+ timeout: tool.timeout,
17
+ toolName,
18
+ });
19
+ }
20
+ }
21
+ return map;
22
+ };
23
+ exports.buildHostToolMap = buildHostToolMap;
24
+ /**
25
+ * Creates the tool dispatcher used by `call`, `wait_until`, `assert`, and host
26
+ * tools that chain (`host__tap_fiber` → `fiber_tree__query` + `host__tap`). The
27
+ * returned function closes over `bridge` + `hostToolMap` so the host context's
28
+ * own `dispatch` callback can re-enter without losing the original clientId.
29
+ */
30
+ const createDispatcher = (bridge, hostToolMap) => {
31
+ const dispatch = async (tool, args, clientId) => {
32
+ const hostEntry = hostToolMap.get(tool);
33
+ if (hostEntry) {
34
+ try {
35
+ const result = await hostEntry.handler(args, {
36
+ bridge,
37
+ dispatch: (nextTool, nextArgs, nextClientId) => {
38
+ return dispatch(nextTool, nextArgs, nextClientId ?? clientId);
39
+ },
40
+ requestedClientId: clientId,
41
+ });
42
+ return { ok: true, result };
43
+ }
44
+ catch (err) {
45
+ return { error: `Host tool "${tool}" threw: ${err.message}`, ok: false };
46
+ }
47
+ }
48
+ const resolution = bridge.resolveClient(clientId);
49
+ if (!resolution.ok)
50
+ return { error: resolution.error, ok: false };
51
+ const client = resolution.client;
52
+ let mod;
53
+ let moduleName = '';
54
+ let methodName = '';
55
+ for (const m of client.modules) {
56
+ const prefix = `${m.name}${protocol_1.MODULE_SEPARATOR}`;
57
+ if (tool.startsWith(prefix)) {
58
+ mod = m;
59
+ moduleName = m.name;
60
+ methodName = tool.slice(prefix.length);
61
+ break;
62
+ }
63
+ }
64
+ if (!mod) {
65
+ if (tool.startsWith(protocol_1.DYNAMIC_PREFIX)) {
66
+ moduleName = `${protocol_1.MODULE_SEPARATOR}dynamic`;
67
+ methodName = tool.slice(protocol_1.DYNAMIC_PREFIX.length);
68
+ }
69
+ else {
70
+ const idx = tool.indexOf(protocol_1.MODULE_SEPARATOR);
71
+ if (idx <= 0) {
72
+ return {
73
+ error: `Invalid tool name "${tool}". Use "module${protocol_1.MODULE_SEPARATOR}method" format.`,
74
+ ok: false,
75
+ };
76
+ }
77
+ moduleName = tool.slice(0, idx);
78
+ methodName = tool.slice(idx + protocol_1.MODULE_SEPARATOR.length);
79
+ }
80
+ try {
81
+ const result = await bridge.call(client.id, moduleName, methodName, args);
82
+ return { ok: true, result };
83
+ }
84
+ catch {
85
+ const allModules = client.modules
86
+ .map((m) => {
87
+ return m.name;
88
+ })
89
+ .join(', ');
90
+ const dynNames = [...client.dynamicTools.keys()].join(', ');
91
+ return {
92
+ error: `Tool "${tool}" not found on client '${client.id}'. Modules: ${allModules || '(none)'}. Dynamic: ${dynNames || '(none)'}`,
93
+ ok: false,
94
+ };
95
+ }
96
+ }
97
+ const toolDef = mod.tools.find((t) => {
98
+ return t.name === methodName;
99
+ });
100
+ if (!toolDef) {
101
+ return {
102
+ error: `Tool "${methodName}" not found in module "${moduleName}" on client '${client.id}'. Available: ${mod.tools
103
+ .map((t) => {
104
+ return t.name;
105
+ })
106
+ .join(', ')}`,
107
+ ok: false,
108
+ };
109
+ }
110
+ try {
111
+ const result = await bridge.call(client.id, moduleName, methodName, args, toolDef.timeout);
112
+ return { ok: true, result };
113
+ }
114
+ catch (err) {
115
+ return { error: err.message, ok: false };
116
+ }
117
+ };
118
+ return dispatch;
119
+ };
120
+ exports.createDispatcher = createDispatcher;
121
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/server/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ import { type Bridge, type ClientEntry } from './bridge';
2
+ import { type HostModule, type HostToolHandler } from './host/types';
3
+ export type TextContent = {
4
+ text: string;
5
+ type: 'text';
6
+ };
7
+ export type ImageContent = {
8
+ data: string;
9
+ mimeType: string;
10
+ type: 'image';
11
+ };
12
+ export interface HostToolEntry {
13
+ handler: HostToolHandler['handler'];
14
+ moduleName: string;
15
+ toolName: string;
16
+ timeout?: number;
17
+ }
18
+ export interface ToolDescriptorShape {
19
+ description: string;
20
+ name: string;
21
+ inputSchema?: Record<string, unknown>;
22
+ }
23
+ export interface ToolGroup {
24
+ description: string | undefined;
25
+ module: string;
26
+ tools: Array<{
27
+ description: string;
28
+ name: string;
29
+ inputSchema?: Record<string, unknown>;
30
+ }>;
31
+ }
32
+ export type DispatchResult = {
33
+ ok: true;
34
+ result: unknown;
35
+ } | {
36
+ error: string;
37
+ ok: false;
38
+ };
39
+ /**
40
+ * Shared state passed to every MCP tool registration in `src/server/tools/`.
41
+ * The McpServerWrapper constructs one and hands it to each `register<Tool>`
42
+ * function so the tool files stay decoupled from the class.
43
+ */
44
+ export interface ServerContext {
45
+ bridge: Bridge;
46
+ dispatchTool: (tool: string, args: Record<string, unknown>, clientId?: string) => Promise<DispatchResult>;
47
+ formatResult: (result: unknown) => Array<TextContent | ImageContent>;
48
+ hostModules: HostModule[];
49
+ hostToolMap: Map<string, HostToolEntry>;
50
+ listToolGroups: (client: ClientEntry) => ToolGroup[];
51
+ }
52
+ export declare const jsonError: (msg: string) => {
53
+ content: TextContent[];
54
+ };
55
+ /**
56
+ * Parse a `call`-style args argument that may arrive as a JSON string (older
57
+ * clients) or a plain object (new form). Returns { ok, args } or { ok: false,
58
+ * error } on malformed JSON.
59
+ */
60
+ export declare const parseCallArgs: (raw: unknown) => {
61
+ args: Record<string, unknown>;
62
+ ok: true;
63
+ } | {
64
+ error: string;
65
+ ok: false;
66
+ };
67
+ /**
68
+ * Recursively serializes a value to JSON with sorted object keys, producing a
69
+ * stable canonical form that's safe to use as a dedup Map key. Arrays keep
70
+ * their original order — caller is responsible for normalizing them when
71
+ * order-independence is desired.
72
+ */
73
+ export declare const canonicalize: (value: unknown) => string;
74
+ /**
75
+ * Produces a canonical key for a ToolGroup that's independent of tool
76
+ * registration order. Two modules with the same name + tools (regardless of
77
+ * order) + descriptions + schemas produce the same key.
78
+ */
79
+ export declare const canonicalizeGroup: (group: ToolGroup) => string;
80
+ /**
81
+ * Looks up a full tool descriptor on a client by its full name
82
+ * (`module__method`). Checks both static modules and dynamic tools registered
83
+ * via useMcpTool. Returns null if the tool is not on this client.
84
+ */
85
+ export declare const findToolInClient: (client: ClientEntry, toolFullName: string) => ToolDescriptorShape | null;
86
+ /**
87
+ * Builds the per-client list of ToolGroup entries that `list_tools` deduplicates
88
+ * across clients. Static modules are passed through; dynamic tools are grouped
89
+ * under a synthetic `<module> (dynamic)` group per source module.
90
+ */
91
+ export declare const buildToolGroups: (client: ClientEntry) => ToolGroup[];
92
+ /**
93
+ * Detects image-content payloads (from host__screenshot) and passes them
94
+ * through as MCP image blocks; everything else is JSON-serialized text.
95
+ */
96
+ export declare const formatResult: (result: unknown) => Array<TextContent | ImageContent>;
97
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/server/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatResult = exports.buildToolGroups = exports.findToolInClient = exports.canonicalizeGroup = exports.canonicalize = exports.parseCallArgs = exports.jsonError = void 0;
4
+ const protocol_1 = require("../shared/protocol");
5
+ const jsonError = (msg) => {
6
+ return {
7
+ content: [{ text: JSON.stringify({ error: msg }), type: 'text' }],
8
+ };
9
+ };
10
+ exports.jsonError = jsonError;
11
+ /**
12
+ * Parse a `call`-style args argument that may arrive as a JSON string (older
13
+ * clients) or a plain object (new form). Returns { ok, args } or { ok: false,
14
+ * error } on malformed JSON.
15
+ */
16
+ const parseCallArgs = (raw) => {
17
+ if (raw === undefined || raw === null)
18
+ return { args: {}, ok: true };
19
+ if (typeof raw === 'string') {
20
+ if (raw.length === 0)
21
+ return { args: {}, ok: true };
22
+ try {
23
+ const parsed = JSON.parse(raw);
24
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
25
+ return { args: parsed, ok: true };
26
+ }
27
+ return { error: 'Parsed args must be an object.', ok: false };
28
+ }
29
+ catch {
30
+ return { error: 'Invalid JSON in args.', ok: false };
31
+ }
32
+ }
33
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
34
+ return { args: raw, ok: true };
35
+ }
36
+ return { error: 'args must be an object or a JSON string.', ok: false };
37
+ };
38
+ exports.parseCallArgs = parseCallArgs;
39
+ /**
40
+ * Recursively serializes a value to JSON with sorted object keys, producing a
41
+ * stable canonical form that's safe to use as a dedup Map key. Arrays keep
42
+ * their original order — caller is responsible for normalizing them when
43
+ * order-independence is desired.
44
+ */
45
+ const canonicalize = (value) => {
46
+ return JSON.stringify(value, (_key, v) => {
47
+ if (v && typeof v === 'object' && !Array.isArray(v)) {
48
+ const sorted = {};
49
+ for (const k of Object.keys(v).sort()) {
50
+ sorted[k] = v[k];
51
+ }
52
+ return sorted;
53
+ }
54
+ return v;
55
+ });
56
+ };
57
+ exports.canonicalize = canonicalize;
58
+ /**
59
+ * Produces a canonical key for a ToolGroup that's independent of tool
60
+ * registration order. Two modules with the same name + tools (regardless of
61
+ * order) + descriptions + schemas produce the same key.
62
+ */
63
+ const canonicalizeGroup = (group) => {
64
+ const normalized = {
65
+ description: group.description,
66
+ module: group.module,
67
+ tools: [...group.tools].sort((a, b) => {
68
+ return a.name.localeCompare(b.name);
69
+ }),
70
+ };
71
+ return (0, exports.canonicalize)(normalized);
72
+ };
73
+ exports.canonicalizeGroup = canonicalizeGroup;
74
+ /**
75
+ * Looks up a full tool descriptor on a client by its full name
76
+ * (`module__method`). Checks both static modules and dynamic tools registered
77
+ * via useMcpTool. Returns null if the tool is not on this client.
78
+ */
79
+ const findToolInClient = (client, toolFullName) => {
80
+ for (const mod of client.modules) {
81
+ const prefix = `${mod.name}${protocol_1.MODULE_SEPARATOR}`;
82
+ if (toolFullName.startsWith(prefix)) {
83
+ const methodName = toolFullName.slice(prefix.length);
84
+ const toolDef = mod.tools.find((t) => {
85
+ return t.name === methodName;
86
+ });
87
+ if (toolDef) {
88
+ return {
89
+ description: toolDef.description,
90
+ inputSchema: toolDef.inputSchema,
91
+ name: toolFullName,
92
+ };
93
+ }
94
+ }
95
+ }
96
+ const dynamicEntry = client.dynamicTools.get(toolFullName);
97
+ if (dynamicEntry) {
98
+ return {
99
+ description: dynamicEntry.description,
100
+ inputSchema: dynamicEntry.inputSchema,
101
+ name: toolFullName,
102
+ };
103
+ }
104
+ return null;
105
+ };
106
+ exports.findToolInClient = findToolInClient;
107
+ /**
108
+ * Builds the per-client list of ToolGroup entries that `list_tools` deduplicates
109
+ * across clients. Static modules are passed through; dynamic tools are grouped
110
+ * under a synthetic `<module> (dynamic)` group per source module.
111
+ */
112
+ const buildToolGroups = (client) => {
113
+ const groups = client.modules.map((mod) => {
114
+ return {
115
+ description: mod.description,
116
+ module: mod.name,
117
+ tools: mod.tools.map((t) => {
118
+ return {
119
+ description: t.description,
120
+ inputSchema: t.inputSchema,
121
+ name: `${mod.name}${protocol_1.MODULE_SEPARATOR}${t.name}`,
122
+ };
123
+ }),
124
+ };
125
+ });
126
+ if (client.dynamicTools.size > 0) {
127
+ const dynamicByModule = new Map();
128
+ for (const [fullName, info] of client.dynamicTools) {
129
+ const existing = dynamicByModule.get(info.module) ?? [];
130
+ existing.push({
131
+ description: info.description,
132
+ inputSchema: info.inputSchema,
133
+ name: fullName,
134
+ });
135
+ dynamicByModule.set(info.module, existing);
136
+ }
137
+ for (const [module, dynTools] of dynamicByModule) {
138
+ groups.push({
139
+ description: 'Dynamically registered tools from useMcpTool hooks',
140
+ module: `${module} (dynamic)`,
141
+ tools: dynTools,
142
+ });
143
+ }
144
+ }
145
+ return groups;
146
+ };
147
+ exports.buildToolGroups = buildToolGroups;
148
+ /**
149
+ * Detects image-content payloads (from host__screenshot) and passes them
150
+ * through as MCP image blocks; everything else is JSON-serialized text.
151
+ */
152
+ const formatResult = (result) => {
153
+ if (Array.isArray(result) && result.length > 0) {
154
+ const first = result[0];
155
+ if (typeof first === 'object' && first !== null && 'type' in first && first.type === 'image') {
156
+ return result;
157
+ }
158
+ }
159
+ return [{ text: JSON.stringify(result, null, 2), type: 'text' }];
160
+ };
161
+ exports.formatResult = formatResult;
162
+ //# sourceMappingURL=helpers.js.map