@intentcomputing/koko-agent-sdk 1.0.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 (622) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/CODE_OF_CONDUCT.md +3 -0
  3. package/CONTRIBUTING.md +9 -0
  4. package/LICENSE +21 -0
  5. package/README.md +65 -0
  6. package/README.zh-CN.md +50 -0
  7. package/SECURITY.md +5 -0
  8. package/android/build.gradle +40 -0
  9. package/android/src/main/AndroidManifest.xml +2 -0
  10. package/android/src/main/java/cn/intentcomputing/kokoagentsdk/KokoAgentSdkModule.java +1356 -0
  11. package/android/src/main/java/cn/intentcomputing/kokoagentsdk/KokoAgentSdkPackage.java +23 -0
  12. package/docs/INTEGRATION.md +168 -0
  13. package/docs/INTEGRATION.zh-CN.md +140 -0
  14. package/docs/PRIVACY.md +11 -0
  15. package/docs/PRIVACY.zh-CN.md +11 -0
  16. package/docs/PUBLISH.md +11 -0
  17. package/docs/PUBLISH.zh-CN.md +11 -0
  18. package/ios/KokoAgentSdk/KokoAgentSdk.h +5 -0
  19. package/ios/KokoAgentSdk/KokoAgentSdk.m +2464 -0
  20. package/ios/KokoAgentSdk/KokoOcrBounds.h +20 -0
  21. package/ios/KokoAgentSdk/KokoScrollBounds.h +21 -0
  22. package/koko-agent-sdk.podspec +23 -0
  23. package/lib/commonjs/KokoAgent.js +1427 -0
  24. package/lib/commonjs/KokoAgent.js.map +1 -0
  25. package/lib/commonjs/assist/OnDeviceAssist.js +94 -0
  26. package/lib/commonjs/assist/OnDeviceAssist.js.map +1 -0
  27. package/lib/commonjs/assist/intentClassify.js +100 -0
  28. package/lib/commonjs/assist/intentClassify.js.map +1 -0
  29. package/lib/commonjs/assist/nodeRank.js +120 -0
  30. package/lib/commonjs/assist/nodeRank.js.map +1 -0
  31. package/lib/commonjs/assist/ocrTarget.js +135 -0
  32. package/lib/commonjs/assist/ocrTarget.js.map +1 -0
  33. package/lib/commonjs/assist/webVisualChange.js +29 -0
  34. package/lib/commonjs/assist/webVisualChange.js.map +1 -0
  35. package/lib/commonjs/client/ActionOutcomeUnknownError.js +28 -0
  36. package/lib/commonjs/client/ActionOutcomeUnknownError.js.map +1 -0
  37. package/lib/commonjs/client/AgentSession.js +858 -0
  38. package/lib/commonjs/client/AgentSession.js.map +1 -0
  39. package/lib/commonjs/client/GatewayClient.js +302 -0
  40. package/lib/commonjs/client/GatewayClient.js.map +1 -0
  41. package/lib/commonjs/client/OperationReplayGuard.js +62 -0
  42. package/lib/commonjs/client/OperationReplayGuard.js.map +1 -0
  43. package/lib/commonjs/client/RunCheckpoint.js +139 -0
  44. package/lib/commonjs/client/RunCheckpoint.js.map +1 -0
  45. package/lib/commonjs/client/loopDetect.js +184 -0
  46. package/lib/commonjs/client/loopDetect.js.map +1 -0
  47. package/lib/commonjs/client/recentSearch.js +50 -0
  48. package/lib/commonjs/client/recentSearch.js.map +1 -0
  49. package/lib/commonjs/client/walletChoiceGuard.js +18 -0
  50. package/lib/commonjs/client/walletChoiceGuard.js.map +1 -0
  51. package/lib/commonjs/client/webResultCategory.js +38 -0
  52. package/lib/commonjs/client/webResultCategory.js.map +1 -0
  53. package/lib/commonjs/commercial/AccountStore.js +78 -0
  54. package/lib/commonjs/commercial/AccountStore.js.map +1 -0
  55. package/lib/commonjs/commercial/AgentDebug.js +104 -0
  56. package/lib/commonjs/commercial/AgentDebug.js.map +1 -0
  57. package/lib/commonjs/commercial/ExecutionGuard.js +53 -0
  58. package/lib/commonjs/commercial/ExecutionGuard.js.map +1 -0
  59. package/lib/commonjs/commercial/UsageBus.js +42 -0
  60. package/lib/commonjs/commercial/UsageBus.js.map +1 -0
  61. package/lib/commonjs/commercial/branding.js +69 -0
  62. package/lib/commonjs/commercial/branding.js.map +1 -0
  63. package/lib/commonjs/commercial/devMode.js +52 -0
  64. package/lib/commonjs/commercial/devMode.js.map +1 -0
  65. package/lib/commonjs/commercial/trust.js +69 -0
  66. package/lib/commonjs/commercial/trust.js.map +1 -0
  67. package/lib/commonjs/confirmation/gate.js +62 -0
  68. package/lib/commonjs/confirmation/gate.js.map +1 -0
  69. package/lib/commonjs/cursor/CursorOverlay.js +141 -0
  70. package/lib/commonjs/cursor/CursorOverlay.js.map +1 -0
  71. package/lib/commonjs/cursor/PointerHand.js +51 -0
  72. package/lib/commonjs/cursor/PointerHand.js.map +1 -0
  73. package/lib/commonjs/cursor/controller.js +91 -0
  74. package/lib/commonjs/cursor/controller.js.map +1 -0
  75. package/lib/commonjs/cursor/pointer.js +49 -0
  76. package/lib/commonjs/cursor/pointer.js.map +1 -0
  77. package/lib/commonjs/debug/KokoRemoteSmoke.js +611 -0
  78. package/lib/commonjs/debug/KokoRemoteSmoke.js.map +1 -0
  79. package/lib/commonjs/explore/ExplorationGraph.js +418 -0
  80. package/lib/commonjs/explore/ExplorationGraph.js.map +1 -0
  81. package/lib/commonjs/explore/bootstrapExplore.js +59 -0
  82. package/lib/commonjs/explore/bootstrapExplore.js.map +1 -0
  83. package/lib/commonjs/host/HostActions.js +266 -0
  84. package/lib/commonjs/host/HostActions.js.map +1 -0
  85. package/lib/commonjs/i18n/index.js +169 -0
  86. package/lib/commonjs/i18n/index.js.map +1 -0
  87. package/lib/commonjs/i18n/runtimeMessages.js +184 -0
  88. package/lib/commonjs/i18n/runtimeMessages.js.map +1 -0
  89. package/lib/commonjs/index.js +640 -0
  90. package/lib/commonjs/index.js.map +1 -0
  91. package/lib/commonjs/native/NativeBridge.js +132 -0
  92. package/lib/commonjs/native/NativeBridge.js.map +1 -0
  93. package/lib/commonjs/native/navigationLabel.js +16 -0
  94. package/lib/commonjs/native/navigationLabel.js.map +1 -0
  95. package/lib/commonjs/native/normalizeViewTree.js +28 -0
  96. package/lib/commonjs/native/normalizeViewTree.js.map +1 -0
  97. package/lib/commonjs/native/pruneOffscreen.js +76 -0
  98. package/lib/commonjs/native/pruneOffscreen.js.map +1 -0
  99. package/lib/commonjs/native/scrollViewport.js +69 -0
  100. package/lib/commonjs/native/scrollViewport.js.map +1 -0
  101. package/lib/commonjs/package.json +1 -0
  102. package/lib/commonjs/privacy/redact.js +108 -0
  103. package/lib/commonjs/privacy/redact.js.map +1 -0
  104. package/lib/commonjs/privacy/screenEvidence.js +59 -0
  105. package/lib/commonjs/privacy/screenEvidence.js.map +1 -0
  106. package/lib/commonjs/privacy/screenModel.js +404 -0
  107. package/lib/commonjs/privacy/screenModel.js.map +1 -0
  108. package/lib/commonjs/privacy/sensitiveScreen.js +58 -0
  109. package/lib/commonjs/privacy/sensitiveScreen.js.map +1 -0
  110. package/lib/commonjs/privacy/userGate.js +213 -0
  111. package/lib/commonjs/privacy/userGate.js.map +1 -0
  112. package/lib/commonjs/protocol/actions.js +112 -0
  113. package/lib/commonjs/protocol/actions.js.map +1 -0
  114. package/lib/commonjs/provider/HostAppearanceStore.js +111 -0
  115. package/lib/commonjs/provider/HostAppearanceStore.js.map +1 -0
  116. package/lib/commonjs/provider/KokoProvider.js +81 -0
  117. package/lib/commonjs/provider/KokoProvider.js.map +1 -0
  118. package/lib/commonjs/provider/KokoUiContext.js +102 -0
  119. package/lib/commonjs/provider/KokoUiContext.js.map +1 -0
  120. package/lib/commonjs/selector/match.js +378 -0
  121. package/lib/commonjs/selector/match.js.map +1 -0
  122. package/lib/commonjs/task/TaskStore.js +361 -0
  123. package/lib/commonjs/task/TaskStore.js.map +1 -0
  124. package/lib/commonjs/task/types.js +2 -0
  125. package/lib/commonjs/task/types.js.map +1 -0
  126. package/lib/commonjs/task/useTaskStore.js +14 -0
  127. package/lib/commonjs/task/useTaskStore.js.map +1 -0
  128. package/lib/commonjs/types.js +2 -0
  129. package/lib/commonjs/types.js.map +1 -0
  130. package/lib/commonjs/ui/KokoChatSheet.js +885 -0
  131. package/lib/commonjs/ui/KokoChatSheet.js.map +1 -0
  132. package/lib/commonjs/ui/KokoComposer.js +161 -0
  133. package/lib/commonjs/ui/KokoComposer.js.map +1 -0
  134. package/lib/commonjs/ui/KokoDialogHost.js +254 -0
  135. package/lib/commonjs/ui/KokoDialogHost.js.map +1 -0
  136. package/lib/commonjs/ui/KokoEntryButton.js +81 -0
  137. package/lib/commonjs/ui/KokoEntryButton.js.map +1 -0
  138. package/lib/commonjs/ui/KokoObserver.js +522 -0
  139. package/lib/commonjs/ui/KokoObserver.js.map +1 -0
  140. package/lib/commonjs/ui/KokoOverlayLayer.js +45 -0
  141. package/lib/commonjs/ui/KokoOverlayLayer.js.map +1 -0
  142. package/lib/commonjs/ui/KokoSubtitle.js +95 -0
  143. package/lib/commonjs/ui/KokoSubtitle.js.map +1 -0
  144. package/lib/commonjs/ui/KokoTaskPanel.js +322 -0
  145. package/lib/commonjs/ui/KokoTaskPanel.js.map +1 -0
  146. package/lib/commonjs/ui/hostOverlay.js +126 -0
  147. package/lib/commonjs/ui/hostOverlay.js.map +1 -0
  148. package/lib/commonjs/ui/icons.js +132 -0
  149. package/lib/commonjs/ui/icons.js.map +1 -0
  150. package/lib/commonjs/ui/progressChrome.js +66 -0
  151. package/lib/commonjs/ui/progressChrome.js.map +1 -0
  152. package/lib/commonjs/ui/safeArea.js +96 -0
  153. package/lib/commonjs/ui/safeArea.js.map +1 -0
  154. package/lib/commonjs/ui/useOverlayOrigin.js +40 -0
  155. package/lib/commonjs/ui/useOverlayOrigin.js.map +1 -0
  156. package/lib/module/KokoAgent.js +1418 -0
  157. package/lib/module/KokoAgent.js.map +1 -0
  158. package/lib/module/assist/OnDeviceAssist.js +89 -0
  159. package/lib/module/assist/OnDeviceAssist.js.map +1 -0
  160. package/lib/module/assist/intentClassify.js +95 -0
  161. package/lib/module/assist/intentClassify.js.map +1 -0
  162. package/lib/module/assist/nodeRank.js +115 -0
  163. package/lib/module/assist/nodeRank.js.map +1 -0
  164. package/lib/module/assist/ocrTarget.js +123 -0
  165. package/lib/module/assist/ocrTarget.js.map +1 -0
  166. package/lib/module/assist/webVisualChange.js +24 -0
  167. package/lib/module/assist/webVisualChange.js.map +1 -0
  168. package/lib/module/client/ActionOutcomeUnknownError.js +23 -0
  169. package/lib/module/client/ActionOutcomeUnknownError.js.map +1 -0
  170. package/lib/module/client/AgentSession.js +854 -0
  171. package/lib/module/client/AgentSession.js.map +1 -0
  172. package/lib/module/client/GatewayClient.js +293 -0
  173. package/lib/module/client/GatewayClient.js.map +1 -0
  174. package/lib/module/client/OperationReplayGuard.js +58 -0
  175. package/lib/module/client/OperationReplayGuard.js.map +1 -0
  176. package/lib/module/client/RunCheckpoint.js +135 -0
  177. package/lib/module/client/RunCheckpoint.js.map +1 -0
  178. package/lib/module/client/loopDetect.js +177 -0
  179. package/lib/module/client/loopDetect.js.map +1 -0
  180. package/lib/module/client/recentSearch.js +46 -0
  181. package/lib/module/client/recentSearch.js.map +1 -0
  182. package/lib/module/client/walletChoiceGuard.js +14 -0
  183. package/lib/module/client/walletChoiceGuard.js.map +1 -0
  184. package/lib/module/client/webResultCategory.js +34 -0
  185. package/lib/module/client/webResultCategory.js.map +1 -0
  186. package/lib/module/commercial/AccountStore.js +75 -0
  187. package/lib/module/commercial/AccountStore.js.map +1 -0
  188. package/lib/module/commercial/AgentDebug.js +99 -0
  189. package/lib/module/commercial/AgentDebug.js.map +1 -0
  190. package/lib/module/commercial/ExecutionGuard.js +49 -0
  191. package/lib/module/commercial/ExecutionGuard.js.map +1 -0
  192. package/lib/module/commercial/UsageBus.js +38 -0
  193. package/lib/module/commercial/UsageBus.js.map +1 -0
  194. package/lib/module/commercial/branding.js +63 -0
  195. package/lib/module/commercial/branding.js.map +1 -0
  196. package/lib/module/commercial/devMode.js +45 -0
  197. package/lib/module/commercial/devMode.js.map +1 -0
  198. package/lib/module/commercial/trust.js +62 -0
  199. package/lib/module/commercial/trust.js.map +1 -0
  200. package/lib/module/confirmation/gate.js +54 -0
  201. package/lib/module/confirmation/gate.js.map +1 -0
  202. package/lib/module/cursor/CursorOverlay.js +136 -0
  203. package/lib/module/cursor/CursorOverlay.js.map +1 -0
  204. package/lib/module/cursor/PointerHand.js +47 -0
  205. package/lib/module/cursor/PointerHand.js.map +1 -0
  206. package/lib/module/cursor/controller.js +87 -0
  207. package/lib/module/cursor/controller.js.map +1 -0
  208. package/lib/module/cursor/pointer.js +45 -0
  209. package/lib/module/cursor/pointer.js.map +1 -0
  210. package/lib/module/debug/KokoRemoteSmoke.js +608 -0
  211. package/lib/module/debug/KokoRemoteSmoke.js.map +1 -0
  212. package/lib/module/explore/ExplorationGraph.js +406 -0
  213. package/lib/module/explore/ExplorationGraph.js.map +1 -0
  214. package/lib/module/explore/bootstrapExplore.js +55 -0
  215. package/lib/module/explore/bootstrapExplore.js.map +1 -0
  216. package/lib/module/host/HostActions.js +255 -0
  217. package/lib/module/host/HostActions.js.map +1 -0
  218. package/lib/module/i18n/index.js +159 -0
  219. package/lib/module/i18n/index.js.map +1 -0
  220. package/lib/module/i18n/runtimeMessages.js +180 -0
  221. package/lib/module/i18n/runtimeMessages.js.map +1 -0
  222. package/lib/module/index.js +44 -0
  223. package/lib/module/index.js.map +1 -0
  224. package/lib/module/native/NativeBridge.js +128 -0
  225. package/lib/module/native/NativeBridge.js.map +1 -0
  226. package/lib/module/native/navigationLabel.js +12 -0
  227. package/lib/module/native/navigationLabel.js.map +1 -0
  228. package/lib/module/native/normalizeViewTree.js +25 -0
  229. package/lib/module/native/normalizeViewTree.js.map +1 -0
  230. package/lib/module/native/pruneOffscreen.js +72 -0
  231. package/lib/module/native/pruneOffscreen.js.map +1 -0
  232. package/lib/module/native/scrollViewport.js +63 -0
  233. package/lib/module/native/scrollViewport.js.map +1 -0
  234. package/lib/module/package.json +1 -0
  235. package/lib/module/privacy/redact.js +103 -0
  236. package/lib/module/privacy/redact.js.map +1 -0
  237. package/lib/module/privacy/screenEvidence.js +50 -0
  238. package/lib/module/privacy/screenEvidence.js.map +1 -0
  239. package/lib/module/privacy/screenModel.js +397 -0
  240. package/lib/module/privacy/screenModel.js.map +1 -0
  241. package/lib/module/privacy/sensitiveScreen.js +52 -0
  242. package/lib/module/privacy/sensitiveScreen.js.map +1 -0
  243. package/lib/module/privacy/userGate.js +202 -0
  244. package/lib/module/privacy/userGate.js.map +1 -0
  245. package/lib/module/protocol/actions.js +108 -0
  246. package/lib/module/protocol/actions.js.map +1 -0
  247. package/lib/module/provider/HostAppearanceStore.js +101 -0
  248. package/lib/module/provider/HostAppearanceStore.js.map +1 -0
  249. package/lib/module/provider/KokoProvider.js +74 -0
  250. package/lib/module/provider/KokoProvider.js.map +1 -0
  251. package/lib/module/provider/KokoUiContext.js +96 -0
  252. package/lib/module/provider/KokoUiContext.js.map +1 -0
  253. package/lib/module/selector/match.js +366 -0
  254. package/lib/module/selector/match.js.map +1 -0
  255. package/lib/module/task/TaskStore.js +356 -0
  256. package/lib/module/task/TaskStore.js.map +1 -0
  257. package/lib/module/task/types.js +2 -0
  258. package/lib/module/task/types.js.map +1 -0
  259. package/lib/module/task/useTaskStore.js +10 -0
  260. package/lib/module/task/useTaskStore.js.map +1 -0
  261. package/lib/module/types.js +2 -0
  262. package/lib/module/types.js.map +1 -0
  263. package/lib/module/ui/KokoChatSheet.js +879 -0
  264. package/lib/module/ui/KokoChatSheet.js.map +1 -0
  265. package/lib/module/ui/KokoComposer.js +155 -0
  266. package/lib/module/ui/KokoComposer.js.map +1 -0
  267. package/lib/module/ui/KokoDialogHost.js +247 -0
  268. package/lib/module/ui/KokoDialogHost.js.map +1 -0
  269. package/lib/module/ui/KokoEntryButton.js +74 -0
  270. package/lib/module/ui/KokoEntryButton.js.map +1 -0
  271. package/lib/module/ui/KokoObserver.js +516 -0
  272. package/lib/module/ui/KokoObserver.js.map +1 -0
  273. package/lib/module/ui/KokoOverlayLayer.js +39 -0
  274. package/lib/module/ui/KokoOverlayLayer.js.map +1 -0
  275. package/lib/module/ui/KokoSubtitle.js +90 -0
  276. package/lib/module/ui/KokoSubtitle.js.map +1 -0
  277. package/lib/module/ui/KokoTaskPanel.js +316 -0
  278. package/lib/module/ui/KokoTaskPanel.js.map +1 -0
  279. package/lib/module/ui/hostOverlay.js +120 -0
  280. package/lib/module/ui/hostOverlay.js.map +1 -0
  281. package/lib/module/ui/icons.js +124 -0
  282. package/lib/module/ui/icons.js.map +1 -0
  283. package/lib/module/ui/progressChrome.js +58 -0
  284. package/lib/module/ui/progressChrome.js.map +1 -0
  285. package/lib/module/ui/safeArea.js +92 -0
  286. package/lib/module/ui/safeArea.js.map +1 -0
  287. package/lib/module/ui/useOverlayOrigin.js +36 -0
  288. package/lib/module/ui/useOverlayOrigin.js.map +1 -0
  289. package/lib/typescript/commonjs/KokoAgent.d.ts +167 -0
  290. package/lib/typescript/commonjs/KokoAgent.d.ts.map +1 -0
  291. package/lib/typescript/commonjs/assist/OnDeviceAssist.d.ts +31 -0
  292. package/lib/typescript/commonjs/assist/OnDeviceAssist.d.ts.map +1 -0
  293. package/lib/typescript/commonjs/assist/intentClassify.d.ts +18 -0
  294. package/lib/typescript/commonjs/assist/intentClassify.d.ts.map +1 -0
  295. package/lib/typescript/commonjs/assist/nodeRank.d.ts +32 -0
  296. package/lib/typescript/commonjs/assist/nodeRank.d.ts.map +1 -0
  297. package/lib/typescript/commonjs/assist/ocrTarget.d.ts +25 -0
  298. package/lib/typescript/commonjs/assist/ocrTarget.d.ts.map +1 -0
  299. package/lib/typescript/commonjs/assist/webVisualChange.d.ts +6 -0
  300. package/lib/typescript/commonjs/assist/webVisualChange.d.ts.map +1 -0
  301. package/lib/typescript/commonjs/client/ActionOutcomeUnknownError.d.ts +13 -0
  302. package/lib/typescript/commonjs/client/ActionOutcomeUnknownError.d.ts.map +1 -0
  303. package/lib/typescript/commonjs/client/AgentSession.d.ts +56 -0
  304. package/lib/typescript/commonjs/client/AgentSession.d.ts.map +1 -0
  305. package/lib/typescript/commonjs/client/GatewayClient.d.ts +149 -0
  306. package/lib/typescript/commonjs/client/GatewayClient.d.ts.map +1 -0
  307. package/lib/typescript/commonjs/client/OperationReplayGuard.d.ts +13 -0
  308. package/lib/typescript/commonjs/client/OperationReplayGuard.d.ts.map +1 -0
  309. package/lib/typescript/commonjs/client/RunCheckpoint.d.ts +57 -0
  310. package/lib/typescript/commonjs/client/RunCheckpoint.d.ts.map +1 -0
  311. package/lib/typescript/commonjs/client/loopDetect.d.ts +15 -0
  312. package/lib/typescript/commonjs/client/loopDetect.d.ts.map +1 -0
  313. package/lib/typescript/commonjs/client/recentSearch.d.ts +5 -0
  314. package/lib/typescript/commonjs/client/recentSearch.d.ts.map +1 -0
  315. package/lib/typescript/commonjs/client/walletChoiceGuard.d.ts +4 -0
  316. package/lib/typescript/commonjs/client/walletChoiceGuard.d.ts.map +1 -0
  317. package/lib/typescript/commonjs/client/webResultCategory.d.ts +5 -0
  318. package/lib/typescript/commonjs/client/webResultCategory.d.ts.map +1 -0
  319. package/lib/typescript/commonjs/commercial/AccountStore.d.ts +17 -0
  320. package/lib/typescript/commonjs/commercial/AccountStore.d.ts.map +1 -0
  321. package/lib/typescript/commonjs/commercial/AgentDebug.d.ts +25 -0
  322. package/lib/typescript/commonjs/commercial/AgentDebug.d.ts.map +1 -0
  323. package/lib/typescript/commonjs/commercial/ExecutionGuard.d.ts +18 -0
  324. package/lib/typescript/commonjs/commercial/ExecutionGuard.d.ts.map +1 -0
  325. package/lib/typescript/commonjs/commercial/UsageBus.d.ts +18 -0
  326. package/lib/typescript/commonjs/commercial/UsageBus.d.ts.map +1 -0
  327. package/lib/typescript/commonjs/commercial/branding.d.ts +25 -0
  328. package/lib/typescript/commonjs/commercial/branding.d.ts.map +1 -0
  329. package/lib/typescript/commonjs/commercial/devMode.d.ts +26 -0
  330. package/lib/typescript/commonjs/commercial/devMode.d.ts.map +1 -0
  331. package/lib/typescript/commonjs/commercial/trust.d.ts +21 -0
  332. package/lib/typescript/commonjs/commercial/trust.d.ts.map +1 -0
  333. package/lib/typescript/commonjs/confirmation/gate.d.ts +18 -0
  334. package/lib/typescript/commonjs/confirmation/gate.d.ts.map +1 -0
  335. package/lib/typescript/commonjs/cursor/CursorOverlay.d.ts +13 -0
  336. package/lib/typescript/commonjs/cursor/CursorOverlay.d.ts.map +1 -0
  337. package/lib/typescript/commonjs/cursor/PointerHand.d.ts +16 -0
  338. package/lib/typescript/commonjs/cursor/PointerHand.d.ts.map +1 -0
  339. package/lib/typescript/commonjs/cursor/controller.d.ts +30 -0
  340. package/lib/typescript/commonjs/cursor/controller.d.ts.map +1 -0
  341. package/lib/typescript/commonjs/cursor/pointer.d.ts +23 -0
  342. package/lib/typescript/commonjs/cursor/pointer.d.ts.map +1 -0
  343. package/lib/typescript/commonjs/debug/KokoRemoteSmoke.d.ts +96 -0
  344. package/lib/typescript/commonjs/debug/KokoRemoteSmoke.d.ts.map +1 -0
  345. package/lib/typescript/commonjs/explore/ExplorationGraph.d.ts +96 -0
  346. package/lib/typescript/commonjs/explore/ExplorationGraph.d.ts.map +1 -0
  347. package/lib/typescript/commonjs/explore/bootstrapExplore.d.ts +40 -0
  348. package/lib/typescript/commonjs/explore/bootstrapExplore.d.ts.map +1 -0
  349. package/lib/typescript/commonjs/host/HostActions.d.ts +101 -0
  350. package/lib/typescript/commonjs/host/HostActions.d.ts.map +1 -0
  351. package/lib/typescript/commonjs/i18n/index.d.ts +20 -0
  352. package/lib/typescript/commonjs/i18n/index.d.ts.map +1 -0
  353. package/lib/typescript/commonjs/i18n/runtimeMessages.d.ts +178 -0
  354. package/lib/typescript/commonjs/i18n/runtimeMessages.d.ts.map +1 -0
  355. package/lib/typescript/commonjs/index.d.ts +66 -0
  356. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  357. package/lib/typescript/commonjs/native/NativeBridge.d.ts +70 -0
  358. package/lib/typescript/commonjs/native/NativeBridge.d.ts.map +1 -0
  359. package/lib/typescript/commonjs/native/navigationLabel.d.ts +4 -0
  360. package/lib/typescript/commonjs/native/navigationLabel.d.ts.map +1 -0
  361. package/lib/typescript/commonjs/native/normalizeViewTree.d.ts +4 -0
  362. package/lib/typescript/commonjs/native/normalizeViewTree.d.ts.map +1 -0
  363. package/lib/typescript/commonjs/native/pruneOffscreen.d.ts +3 -0
  364. package/lib/typescript/commonjs/native/pruneOffscreen.d.ts.map +1 -0
  365. package/lib/typescript/commonjs/native/scrollViewport.d.ts +13 -0
  366. package/lib/typescript/commonjs/native/scrollViewport.d.ts.map +1 -0
  367. package/lib/typescript/commonjs/package.json +1 -0
  368. package/lib/typescript/commonjs/privacy/redact.d.ts +9 -0
  369. package/lib/typescript/commonjs/privacy/redact.d.ts.map +1 -0
  370. package/lib/typescript/commonjs/privacy/screenEvidence.d.ts +14 -0
  371. package/lib/typescript/commonjs/privacy/screenEvidence.d.ts.map +1 -0
  372. package/lib/typescript/commonjs/privacy/screenModel.d.ts +26 -0
  373. package/lib/typescript/commonjs/privacy/screenModel.d.ts.map +1 -0
  374. package/lib/typescript/commonjs/privacy/sensitiveScreen.d.ts +8 -0
  375. package/lib/typescript/commonjs/privacy/sensitiveScreen.d.ts.map +1 -0
  376. package/lib/typescript/commonjs/privacy/userGate.d.ts +58 -0
  377. package/lib/typescript/commonjs/privacy/userGate.d.ts.map +1 -0
  378. package/lib/typescript/commonjs/protocol/actions.d.ts +7 -0
  379. package/lib/typescript/commonjs/protocol/actions.d.ts.map +1 -0
  380. package/lib/typescript/commonjs/provider/HostAppearanceStore.d.ts +64 -0
  381. package/lib/typescript/commonjs/provider/HostAppearanceStore.d.ts.map +1 -0
  382. package/lib/typescript/commonjs/provider/KokoProvider.d.ts +39 -0
  383. package/lib/typescript/commonjs/provider/KokoProvider.d.ts.map +1 -0
  384. package/lib/typescript/commonjs/provider/KokoUiContext.d.ts +22 -0
  385. package/lib/typescript/commonjs/provider/KokoUiContext.d.ts.map +1 -0
  386. package/lib/typescript/commonjs/selector/match.d.ts +27 -0
  387. package/lib/typescript/commonjs/selector/match.d.ts.map +1 -0
  388. package/lib/typescript/commonjs/task/TaskStore.d.ts +65 -0
  389. package/lib/typescript/commonjs/task/TaskStore.d.ts.map +1 -0
  390. package/lib/typescript/commonjs/task/types.d.ts +66 -0
  391. package/lib/typescript/commonjs/task/types.d.ts.map +1 -0
  392. package/lib/typescript/commonjs/task/useTaskStore.d.ts +3 -0
  393. package/lib/typescript/commonjs/task/useTaskStore.d.ts.map +1 -0
  394. package/lib/typescript/commonjs/types.d.ts +372 -0
  395. package/lib/typescript/commonjs/types.d.ts.map +1 -0
  396. package/lib/typescript/commonjs/ui/KokoChatSheet.d.ts +8 -0
  397. package/lib/typescript/commonjs/ui/KokoChatSheet.d.ts.map +1 -0
  398. package/lib/typescript/commonjs/ui/KokoComposer.d.ts +13 -0
  399. package/lib/typescript/commonjs/ui/KokoComposer.d.ts.map +1 -0
  400. package/lib/typescript/commonjs/ui/KokoDialogHost.d.ts +32 -0
  401. package/lib/typescript/commonjs/ui/KokoDialogHost.d.ts.map +1 -0
  402. package/lib/typescript/commonjs/ui/KokoEntryButton.d.ts +18 -0
  403. package/lib/typescript/commonjs/ui/KokoEntryButton.d.ts.map +1 -0
  404. package/lib/typescript/commonjs/ui/KokoObserver.d.ts +13 -0
  405. package/lib/typescript/commonjs/ui/KokoObserver.d.ts.map +1 -0
  406. package/lib/typescript/commonjs/ui/KokoOverlayLayer.d.ts +35 -0
  407. package/lib/typescript/commonjs/ui/KokoOverlayLayer.d.ts.map +1 -0
  408. package/lib/typescript/commonjs/ui/KokoSubtitle.d.ts +7 -0
  409. package/lib/typescript/commonjs/ui/KokoSubtitle.d.ts.map +1 -0
  410. package/lib/typescript/commonjs/ui/KokoTaskPanel.d.ts +7 -0
  411. package/lib/typescript/commonjs/ui/KokoTaskPanel.d.ts.map +1 -0
  412. package/lib/typescript/commonjs/ui/hostOverlay.d.ts +28 -0
  413. package/lib/typescript/commonjs/ui/hostOverlay.d.ts.map +1 -0
  414. package/lib/typescript/commonjs/ui/icons.d.ts +26 -0
  415. package/lib/typescript/commonjs/ui/icons.d.ts.map +1 -0
  416. package/lib/typescript/commonjs/ui/progressChrome.d.ts +21 -0
  417. package/lib/typescript/commonjs/ui/progressChrome.d.ts.map +1 -0
  418. package/lib/typescript/commonjs/ui/safeArea.d.ts +12 -0
  419. package/lib/typescript/commonjs/ui/safeArea.d.ts.map +1 -0
  420. package/lib/typescript/commonjs/ui/useOverlayOrigin.d.ts +22 -0
  421. package/lib/typescript/commonjs/ui/useOverlayOrigin.d.ts.map +1 -0
  422. package/lib/typescript/module/KokoAgent.d.ts +167 -0
  423. package/lib/typescript/module/KokoAgent.d.ts.map +1 -0
  424. package/lib/typescript/module/assist/OnDeviceAssist.d.ts +31 -0
  425. package/lib/typescript/module/assist/OnDeviceAssist.d.ts.map +1 -0
  426. package/lib/typescript/module/assist/intentClassify.d.ts +18 -0
  427. package/lib/typescript/module/assist/intentClassify.d.ts.map +1 -0
  428. package/lib/typescript/module/assist/nodeRank.d.ts +32 -0
  429. package/lib/typescript/module/assist/nodeRank.d.ts.map +1 -0
  430. package/lib/typescript/module/assist/ocrTarget.d.ts +25 -0
  431. package/lib/typescript/module/assist/ocrTarget.d.ts.map +1 -0
  432. package/lib/typescript/module/assist/webVisualChange.d.ts +6 -0
  433. package/lib/typescript/module/assist/webVisualChange.d.ts.map +1 -0
  434. package/lib/typescript/module/client/ActionOutcomeUnknownError.d.ts +13 -0
  435. package/lib/typescript/module/client/ActionOutcomeUnknownError.d.ts.map +1 -0
  436. package/lib/typescript/module/client/AgentSession.d.ts +56 -0
  437. package/lib/typescript/module/client/AgentSession.d.ts.map +1 -0
  438. package/lib/typescript/module/client/GatewayClient.d.ts +149 -0
  439. package/lib/typescript/module/client/GatewayClient.d.ts.map +1 -0
  440. package/lib/typescript/module/client/OperationReplayGuard.d.ts +13 -0
  441. package/lib/typescript/module/client/OperationReplayGuard.d.ts.map +1 -0
  442. package/lib/typescript/module/client/RunCheckpoint.d.ts +57 -0
  443. package/lib/typescript/module/client/RunCheckpoint.d.ts.map +1 -0
  444. package/lib/typescript/module/client/loopDetect.d.ts +15 -0
  445. package/lib/typescript/module/client/loopDetect.d.ts.map +1 -0
  446. package/lib/typescript/module/client/recentSearch.d.ts +5 -0
  447. package/lib/typescript/module/client/recentSearch.d.ts.map +1 -0
  448. package/lib/typescript/module/client/walletChoiceGuard.d.ts +4 -0
  449. package/lib/typescript/module/client/walletChoiceGuard.d.ts.map +1 -0
  450. package/lib/typescript/module/client/webResultCategory.d.ts +5 -0
  451. package/lib/typescript/module/client/webResultCategory.d.ts.map +1 -0
  452. package/lib/typescript/module/commercial/AccountStore.d.ts +17 -0
  453. package/lib/typescript/module/commercial/AccountStore.d.ts.map +1 -0
  454. package/lib/typescript/module/commercial/AgentDebug.d.ts +25 -0
  455. package/lib/typescript/module/commercial/AgentDebug.d.ts.map +1 -0
  456. package/lib/typescript/module/commercial/ExecutionGuard.d.ts +18 -0
  457. package/lib/typescript/module/commercial/ExecutionGuard.d.ts.map +1 -0
  458. package/lib/typescript/module/commercial/UsageBus.d.ts +18 -0
  459. package/lib/typescript/module/commercial/UsageBus.d.ts.map +1 -0
  460. package/lib/typescript/module/commercial/branding.d.ts +25 -0
  461. package/lib/typescript/module/commercial/branding.d.ts.map +1 -0
  462. package/lib/typescript/module/commercial/devMode.d.ts +26 -0
  463. package/lib/typescript/module/commercial/devMode.d.ts.map +1 -0
  464. package/lib/typescript/module/commercial/trust.d.ts +21 -0
  465. package/lib/typescript/module/commercial/trust.d.ts.map +1 -0
  466. package/lib/typescript/module/confirmation/gate.d.ts +18 -0
  467. package/lib/typescript/module/confirmation/gate.d.ts.map +1 -0
  468. package/lib/typescript/module/cursor/CursorOverlay.d.ts +13 -0
  469. package/lib/typescript/module/cursor/CursorOverlay.d.ts.map +1 -0
  470. package/lib/typescript/module/cursor/PointerHand.d.ts +16 -0
  471. package/lib/typescript/module/cursor/PointerHand.d.ts.map +1 -0
  472. package/lib/typescript/module/cursor/controller.d.ts +30 -0
  473. package/lib/typescript/module/cursor/controller.d.ts.map +1 -0
  474. package/lib/typescript/module/cursor/pointer.d.ts +23 -0
  475. package/lib/typescript/module/cursor/pointer.d.ts.map +1 -0
  476. package/lib/typescript/module/debug/KokoRemoteSmoke.d.ts +96 -0
  477. package/lib/typescript/module/debug/KokoRemoteSmoke.d.ts.map +1 -0
  478. package/lib/typescript/module/explore/ExplorationGraph.d.ts +96 -0
  479. package/lib/typescript/module/explore/ExplorationGraph.d.ts.map +1 -0
  480. package/lib/typescript/module/explore/bootstrapExplore.d.ts +40 -0
  481. package/lib/typescript/module/explore/bootstrapExplore.d.ts.map +1 -0
  482. package/lib/typescript/module/host/HostActions.d.ts +101 -0
  483. package/lib/typescript/module/host/HostActions.d.ts.map +1 -0
  484. package/lib/typescript/module/i18n/index.d.ts +20 -0
  485. package/lib/typescript/module/i18n/index.d.ts.map +1 -0
  486. package/lib/typescript/module/i18n/runtimeMessages.d.ts +178 -0
  487. package/lib/typescript/module/i18n/runtimeMessages.d.ts.map +1 -0
  488. package/lib/typescript/module/index.d.ts +66 -0
  489. package/lib/typescript/module/index.d.ts.map +1 -0
  490. package/lib/typescript/module/native/NativeBridge.d.ts +70 -0
  491. package/lib/typescript/module/native/NativeBridge.d.ts.map +1 -0
  492. package/lib/typescript/module/native/navigationLabel.d.ts +4 -0
  493. package/lib/typescript/module/native/navigationLabel.d.ts.map +1 -0
  494. package/lib/typescript/module/native/normalizeViewTree.d.ts +4 -0
  495. package/lib/typescript/module/native/normalizeViewTree.d.ts.map +1 -0
  496. package/lib/typescript/module/native/pruneOffscreen.d.ts +3 -0
  497. package/lib/typescript/module/native/pruneOffscreen.d.ts.map +1 -0
  498. package/lib/typescript/module/native/scrollViewport.d.ts +13 -0
  499. package/lib/typescript/module/native/scrollViewport.d.ts.map +1 -0
  500. package/lib/typescript/module/package.json +1 -0
  501. package/lib/typescript/module/privacy/redact.d.ts +9 -0
  502. package/lib/typescript/module/privacy/redact.d.ts.map +1 -0
  503. package/lib/typescript/module/privacy/screenEvidence.d.ts +14 -0
  504. package/lib/typescript/module/privacy/screenEvidence.d.ts.map +1 -0
  505. package/lib/typescript/module/privacy/screenModel.d.ts +26 -0
  506. package/lib/typescript/module/privacy/screenModel.d.ts.map +1 -0
  507. package/lib/typescript/module/privacy/sensitiveScreen.d.ts +8 -0
  508. package/lib/typescript/module/privacy/sensitiveScreen.d.ts.map +1 -0
  509. package/lib/typescript/module/privacy/userGate.d.ts +58 -0
  510. package/lib/typescript/module/privacy/userGate.d.ts.map +1 -0
  511. package/lib/typescript/module/protocol/actions.d.ts +7 -0
  512. package/lib/typescript/module/protocol/actions.d.ts.map +1 -0
  513. package/lib/typescript/module/provider/HostAppearanceStore.d.ts +64 -0
  514. package/lib/typescript/module/provider/HostAppearanceStore.d.ts.map +1 -0
  515. package/lib/typescript/module/provider/KokoProvider.d.ts +39 -0
  516. package/lib/typescript/module/provider/KokoProvider.d.ts.map +1 -0
  517. package/lib/typescript/module/provider/KokoUiContext.d.ts +22 -0
  518. package/lib/typescript/module/provider/KokoUiContext.d.ts.map +1 -0
  519. package/lib/typescript/module/selector/match.d.ts +27 -0
  520. package/lib/typescript/module/selector/match.d.ts.map +1 -0
  521. package/lib/typescript/module/task/TaskStore.d.ts +65 -0
  522. package/lib/typescript/module/task/TaskStore.d.ts.map +1 -0
  523. package/lib/typescript/module/task/types.d.ts +66 -0
  524. package/lib/typescript/module/task/types.d.ts.map +1 -0
  525. package/lib/typescript/module/task/useTaskStore.d.ts +3 -0
  526. package/lib/typescript/module/task/useTaskStore.d.ts.map +1 -0
  527. package/lib/typescript/module/types.d.ts +372 -0
  528. package/lib/typescript/module/types.d.ts.map +1 -0
  529. package/lib/typescript/module/ui/KokoChatSheet.d.ts +8 -0
  530. package/lib/typescript/module/ui/KokoChatSheet.d.ts.map +1 -0
  531. package/lib/typescript/module/ui/KokoComposer.d.ts +13 -0
  532. package/lib/typescript/module/ui/KokoComposer.d.ts.map +1 -0
  533. package/lib/typescript/module/ui/KokoDialogHost.d.ts +32 -0
  534. package/lib/typescript/module/ui/KokoDialogHost.d.ts.map +1 -0
  535. package/lib/typescript/module/ui/KokoEntryButton.d.ts +18 -0
  536. package/lib/typescript/module/ui/KokoEntryButton.d.ts.map +1 -0
  537. package/lib/typescript/module/ui/KokoObserver.d.ts +13 -0
  538. package/lib/typescript/module/ui/KokoObserver.d.ts.map +1 -0
  539. package/lib/typescript/module/ui/KokoOverlayLayer.d.ts +35 -0
  540. package/lib/typescript/module/ui/KokoOverlayLayer.d.ts.map +1 -0
  541. package/lib/typescript/module/ui/KokoSubtitle.d.ts +7 -0
  542. package/lib/typescript/module/ui/KokoSubtitle.d.ts.map +1 -0
  543. package/lib/typescript/module/ui/KokoTaskPanel.d.ts +7 -0
  544. package/lib/typescript/module/ui/KokoTaskPanel.d.ts.map +1 -0
  545. package/lib/typescript/module/ui/hostOverlay.d.ts +28 -0
  546. package/lib/typescript/module/ui/hostOverlay.d.ts.map +1 -0
  547. package/lib/typescript/module/ui/icons.d.ts +26 -0
  548. package/lib/typescript/module/ui/icons.d.ts.map +1 -0
  549. package/lib/typescript/module/ui/progressChrome.d.ts +21 -0
  550. package/lib/typescript/module/ui/progressChrome.d.ts.map +1 -0
  551. package/lib/typescript/module/ui/safeArea.d.ts +12 -0
  552. package/lib/typescript/module/ui/safeArea.d.ts.map +1 -0
  553. package/lib/typescript/module/ui/useOverlayOrigin.d.ts +22 -0
  554. package/lib/typescript/module/ui/useOverlayOrigin.d.ts.map +1 -0
  555. package/package.json +153 -0
  556. package/react-native.config.js +12 -0
  557. package/src/KokoAgent.ts +1415 -0
  558. package/src/assist/OnDeviceAssist.ts +133 -0
  559. package/src/assist/intentClassify.ts +122 -0
  560. package/src/assist/nodeRank.ts +167 -0
  561. package/src/assist/ocrTarget.ts +146 -0
  562. package/src/assist/webVisualChange.ts +24 -0
  563. package/src/client/ActionOutcomeUnknownError.ts +18 -0
  564. package/src/client/AgentSession.ts +952 -0
  565. package/src/client/GatewayClient.ts +439 -0
  566. package/src/client/OperationReplayGuard.ts +61 -0
  567. package/src/client/RunCheckpoint.ts +154 -0
  568. package/src/client/loopDetect.ts +213 -0
  569. package/src/client/recentSearch.ts +47 -0
  570. package/src/client/walletChoiceGuard.ts +15 -0
  571. package/src/client/webResultCategory.ts +28 -0
  572. package/src/commercial/AccountStore.ts +85 -0
  573. package/src/commercial/AgentDebug.ts +142 -0
  574. package/src/commercial/ExecutionGuard.ts +67 -0
  575. package/src/commercial/UsageBus.ts +44 -0
  576. package/src/commercial/branding.ts +97 -0
  577. package/src/commercial/devMode.ts +48 -0
  578. package/src/commercial/trust.ts +67 -0
  579. package/src/confirmation/gate.ts +82 -0
  580. package/src/cursor/CursorOverlay.tsx +138 -0
  581. package/src/cursor/PointerHand.tsx +49 -0
  582. package/src/cursor/controller.ts +98 -0
  583. package/src/cursor/pointer.ts +40 -0
  584. package/src/debug/KokoRemoteSmoke.tsx +561 -0
  585. package/src/explore/ExplorationGraph.ts +518 -0
  586. package/src/explore/bootstrapExplore.ts +89 -0
  587. package/src/host/HostActions.ts +349 -0
  588. package/src/i18n/index.ts +229 -0
  589. package/src/i18n/runtimeMessages.ts +180 -0
  590. package/src/index.ts +203 -0
  591. package/src/native/NativeBridge.ts +207 -0
  592. package/src/native/navigationLabel.ts +11 -0
  593. package/src/native/normalizeViewTree.ts +16 -0
  594. package/src/native/pruneOffscreen.ts +72 -0
  595. package/src/native/scrollViewport.ts +51 -0
  596. package/src/privacy/redact.ts +115 -0
  597. package/src/privacy/screenEvidence.ts +55 -0
  598. package/src/privacy/screenModel.ts +504 -0
  599. package/src/privacy/sensitiveScreen.ts +55 -0
  600. package/src/privacy/userGate.ts +233 -0
  601. package/src/protocol/actions.ts +66 -0
  602. package/src/provider/HostAppearanceStore.ts +148 -0
  603. package/src/provider/KokoProvider.tsx +118 -0
  604. package/src/provider/KokoUiContext.tsx +162 -0
  605. package/src/selector/match.ts +417 -0
  606. package/src/task/TaskStore.ts +387 -0
  607. package/src/task/types.ts +82 -0
  608. package/src/task/useTaskStore.ts +9 -0
  609. package/src/types.ts +318 -0
  610. package/src/ui/KokoChatSheet.tsx +930 -0
  611. package/src/ui/KokoComposer.tsx +174 -0
  612. package/src/ui/KokoDialogHost.tsx +249 -0
  613. package/src/ui/KokoEntryButton.tsx +74 -0
  614. package/src/ui/KokoObserver.tsx +587 -0
  615. package/src/ui/KokoOverlayLayer.tsx +53 -0
  616. package/src/ui/KokoSubtitle.tsx +80 -0
  617. package/src/ui/KokoTaskPanel.tsx +299 -0
  618. package/src/ui/hostOverlay.tsx +148 -0
  619. package/src/ui/icons.tsx +145 -0
  620. package/src/ui/progressChrome.ts +73 -0
  621. package/src/ui/safeArea.ts +95 -0
  622. package/src/ui/useOverlayOrigin.ts +29 -0
@@ -0,0 +1,1418 @@
1
+ "use strict";
2
+
3
+ import { Platform } from 'react-native';
4
+ import { CursorController } from "./cursor/controller.js";
5
+ import { isSensitiveLabel, runConfirmationGate } from "./confirmation/gate.js";
6
+ import { NativeBridge } from "./native/NativeBridge.js";
7
+ import { executeAgentAction } from "./protocol/actions.js";
8
+ import { centerOf, centerOfLabel, find, findAll, findBySoftLabel, findNodeById, flattenTree } from "./selector/match.js";
9
+ import { sensitiveScreenKind } from "./privacy/sensitiveScreen.js";
10
+ import { boundedScrollGesture, scrollViewports } from "./native/scrollViewport.js";
11
+ import { canRunHostActionForNode, HostActionsStore, runHostAction } from "./host/HostActions.js";
12
+ import { screenSnapshotLine } from "./privacy/screenModel.js";
13
+ import { TaskStore } from "./task/TaskStore.js";
14
+ import { AgentSession } from "./client/AgentSession.js";
15
+ import { RunCheckpoint } from "./client/RunCheckpoint.js";
16
+ import { ActionOutcomeUnknownError, ActionValidationError } from "./client/ActionOutcomeUnknownError.js";
17
+ import { ExplorationGraph } from "./explore/ExplorationGraph.js";
18
+ import { DialogBus } from "./ui/KokoDialogHost.js";
19
+ import { pointsOverlapProgressChrome } from "./ui/progressChrome.js";
20
+ import { UsageBus } from "./commercial/UsageBus.js";
21
+ import { AccountStore } from "./commercial/AccountStore.js";
22
+ import { ExecutionGuard } from "./commercial/ExecutionGuard.js";
23
+ import { AgentDebug } from "./commercial/AgentDebug.js";
24
+ import { gatewayLocale, currentLocale, t, runtimeText, message } from "./i18n/index.js";
25
+ import { findOcrTextHit, ocrHitInFrames, visibleWebViewFrames } from "./assist/ocrTarget.js";
26
+ /**
27
+ * Koko Agent SDK runtime — dump / find / tap / swipe / pinch / type + cursor + confirm gate + task log.
28
+ */
29
+ export class KokoAgent {
30
+ lastTree = null;
31
+ planningTree = null;
32
+ // OCR ids are local references to observed text, never caller-supplied points.
33
+ ocrTargets = new Map();
34
+ nextOcrTargetId = 0;
35
+ /** Labels already confirmed in the current runGoal — avoid repeat dialogs on retry. */
36
+ confirmedSensitive = new Set();
37
+ /** Last tap used a host `run` callback (tab/CTA) — skip false tap_noop. */
38
+ lastTapViaHost = null;
39
+ /** Current NL goal; direct SDK callers may opt into visible scroll search. */
40
+
41
+ constructor(config = {}) {
42
+ this.config = {
43
+ dumpMaxDepth: 80,
44
+ dumpSkipInvisible: true,
45
+ cursorDurationMs: 480,
46
+ observer: true,
47
+ ...config,
48
+ confirmation: {
49
+ requireUserConfirm: true,
50
+ mode: 'preflight',
51
+ ...config.confirmation
52
+ }
53
+ };
54
+ if (!this.config.onConfirmSensitive) {
55
+ this.config.onConfirmSensitive = async ctx => {
56
+ const locale = currentLocale(this.config.locale);
57
+ const label = ctx.label ?? ctx.action;
58
+ return DialogBus.requestConfirm(ctx.action === 'preflight' ? t(locale, 'confirm.preflightTitle') : t(locale, 'confirm.inlineTitle'), ctx.action === 'preflight' ? t(locale, 'confirm.preflightBody', {
59
+ label
60
+ }) : t(locale, 'confirm.inlineBody', {
61
+ label
62
+ }));
63
+ };
64
+ }
65
+ }
66
+ configure(patch) {
67
+ this.config = {
68
+ ...this.config,
69
+ ...patch
70
+ };
71
+ }
72
+ getConfig() {
73
+ return this.config;
74
+ }
75
+ message(key, vars) {
76
+ return message(key, vars, this.config.locale);
77
+ }
78
+ text(key, vars) {
79
+ return runtimeText(key, vars, this.config.locale);
80
+ }
81
+ isNativeReady() {
82
+ return NativeBridge.isAvailable();
83
+ }
84
+
85
+ /** Start a user-facing task (shows subtitle + appears in panel). */
86
+ startTask(title) {
87
+ this.confirmedSensitive.clear();
88
+ this.ocrTargets.clear();
89
+ this.planningTree = null;
90
+ const task = TaskStore.startTask(title);
91
+ UsageBus.emit({
92
+ type: 'task_started',
93
+ taskId: task.id,
94
+ goal: title,
95
+ at: Date.now()
96
+ });
97
+ return task;
98
+ }
99
+ finishTask(status = 'success', summary) {
100
+ this.confirmedSensitive.clear();
101
+ CursorController.hide();
102
+ const snap = TaskStore.snapshot();
103
+ const active = snap.tasks.find(t => t.id === snap.activeTaskId);
104
+ TaskStore.finishTask(status, undefined, summary);
105
+ UsageBus.emit({
106
+ type: 'task_finished',
107
+ taskId: active?.id,
108
+ status,
109
+ steps: active?.nodes?.length,
110
+ at: Date.now()
111
+ });
112
+ }
113
+
114
+ /** Manually append an observer log node (for cloud agent narration). */
115
+ log(kind, title, detail) {
116
+ if (this.config.observer === false) return null;
117
+ return TaskStore.appendNode({
118
+ kind,
119
+ title,
120
+ detail,
121
+ status: 'done'
122
+ });
123
+ }
124
+
125
+ /** Open a cloud-backed agent session (official gateway; LLM vendor is server-side). */
126
+ createSession(opts) {
127
+ return new AgentSession(this, {
128
+ ...opts,
129
+ onAskUser: opts.onAskUser ?? (q => DialogBus.requestAsk(q))
130
+ });
131
+ }
132
+
133
+ /**
134
+ * One-shot: talk to official gateway → local dump/find/tap until done.
135
+ * Users never supply model API keys. Token comes from opts or KokoProvider config.gateway.
136
+ */
137
+ activeSession = null;
138
+ executionEpoch = 0;
139
+ claimingCheckpoint = false;
140
+
141
+ /** @internal Sessions created through createSession share runGoal's owner. */
142
+ acquireSession(session) {
143
+ if (this.activeSession && this.activeSession !== session || this.claimingCheckpoint) {
144
+ throw new Error(runtimeText('runtime.alreadyRunning', undefined, this.config?.locale));
145
+ }
146
+ const acquired = !this.activeSession;
147
+ this.activeSession = session;
148
+ return acquired;
149
+ }
150
+
151
+ /** @internal Release only an owner acquired by a direct session.run(). */
152
+ releaseSession(session) {
153
+ if (this.activeSession === session) this.activeSession = null;
154
+ }
155
+
156
+ /** @internal Invalidates gestures already waiting on confirmation/animation. */
157
+ cancelPendingActions() {
158
+ this.executionEpoch++;
159
+ CursorController.hide();
160
+ }
161
+ assertExecutionCurrent(epoch) {
162
+ if (epoch !== this.executionEpoch) throw new Error('KokoAgent: task cancelled');
163
+ }
164
+ async runGoal(goal, opts) {
165
+ if (this.activeSession || this.claimingCheckpoint) {
166
+ throw new Error(runtimeText('runtime.alreadyRunning', undefined, this.config?.locale));
167
+ }
168
+ const token = opts?.token ?? this.config.gateway?.token;
169
+ if (!token) {
170
+ throw new Error(this.text('runtime.missingToken'));
171
+ }
172
+ const baseUrl = opts?.baseUrl ?? this.config.gateway?.baseUrl;
173
+ const locale = gatewayLocale(currentLocale(opts?.locale ?? this.config.locale));
174
+ void AccountStore.refresh({
175
+ token,
176
+ baseUrl
177
+ });
178
+ const session = this.createSession({
179
+ locale,
180
+ resumedFromReload: (opts?.resumes ?? 0) > 0,
181
+ localRetries: opts?.localRetries,
182
+ userGateTimeoutMs: opts?.userGateTimeoutMs,
183
+ onAskUser: opts?.onAskUser,
184
+ onNarration: opts?.onNarration,
185
+ baseUrl,
186
+ token
187
+ });
188
+ this.activeSession = session;
189
+ // An action can take down the context running it (locale/theme/RTL change,
190
+ // feature-flag remount). Persist the goal so the next init can resume it;
191
+ // see RunCheckpoint. Never let storage trouble block a run.
192
+ try {
193
+ await RunCheckpoint.begin(goal, opts?.resumes ?? 0).catch(() => {});
194
+ return await session.run(goal);
195
+ } finally {
196
+ // Keep ownership until cleanup settles; stop() must not let a second run
197
+ // overlap an outstanding gateway response or pending native gesture.
198
+ await RunCheckpoint.clear().catch(() => {});
199
+ if (this.activeSession === session) this.activeSession = null;
200
+ void AccountStore.refresh({
201
+ token,
202
+ baseUrl
203
+ });
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Pick up a run that a JS-context restart interrupted, if any.
209
+ *
210
+ * Called once per init by KokoProvider. Resolves to the resumed goal, or null
211
+ * when there was nothing fresh to resume. The planner decides what is left to
212
+ * do from the screen the App came back on — if the goal already happened, it
213
+ * answers `done` without touching anything.
214
+ */
215
+ async resumeInterruptedRun() {
216
+ if (this.activeSession || this.claimingCheckpoint) return null;
217
+ this.claimingCheckpoint = true;
218
+ const epoch = this.executionEpoch;
219
+ let pending;
220
+ try {
221
+ pending = await RunCheckpoint.claimResumable().catch(() => null);
222
+ } finally {
223
+ this.claimingCheckpoint = false;
224
+ }
225
+ if (!pending || epoch !== this.executionEpoch) return null;
226
+ try {
227
+ await this.runGoal(pending.goal, {
228
+ resumes: pending.resumes + 1
229
+ });
230
+ } catch {
231
+ // A resume is best-effort; a failure here must not break host startup.
232
+ }
233
+ return pending.goal;
234
+ }
235
+
236
+ /**
237
+ * On-device exploration crawl — builds a local screen/transition graph
238
+ * without a host feature tree. Safe-ish (skips sensitive labels). Call
239
+ * after SDK init / on a debug build; then runGoal can reuse the graph.
240
+ */
241
+ async bootstrapExplore(opts) {
242
+ const {
243
+ bootstrapExplore
244
+ } = await import('./explore/bootstrapExplore');
245
+ return bootstrapExplore(this, opts);
246
+ }
247
+
248
+ /** Snapshot of the on-device exploration graph (nodes/edges). */
249
+ getExplorationGraph() {
250
+ return ExplorationGraph.snapshot();
251
+ }
252
+ clearExplorationGraph() {
253
+ ExplorationGraph.clear();
254
+ }
255
+
256
+ /** Refresh plan / quota / entitlements from gateway. */
257
+ async refreshAccount() {
258
+ const token = this.config.gateway?.token;
259
+ if (!token) return null;
260
+ return AccountStore.refresh({
261
+ token,
262
+ baseUrl: this.config.gateway?.baseUrl
263
+ });
264
+ }
265
+ getAccount() {
266
+ return AccountStore.get();
267
+ }
268
+
269
+ /** Stop the in-flight runGoal / session, if any. */
270
+ stop() {
271
+ if (this.activeSession) this.activeSession.stop();else this.cancelPendingActions();
272
+ }
273
+
274
+ /** Open chat sheet (history + NL input) from host UI. */
275
+ openChat(taskId) {
276
+ TaskStore.openSheet(taskId);
277
+ }
278
+ closeChat() {
279
+ TaskStore.closeSheet();
280
+ }
281
+ getTaskStore() {
282
+ return TaskStore;
283
+ }
284
+ async dump(options) {
285
+ ExecutionGuard.assert('dump');
286
+ // Sheet Modal lives in another window and blocks host; close before scan.
287
+ if (TaskStore.snapshot().ui.sheetOpen) {
288
+ TaskStore.closeSheet();
289
+ // Host apps (OneKey) freezeOnBlur — need a beat to remount Empty states.
290
+ await sleep(480);
291
+ }
292
+ const silent = options?.silent === true;
293
+ const node = silent ? {
294
+ id: ''
295
+ } : this.track('dump', this.message('runtime.scan'));
296
+ try {
297
+ const tree = await NativeBridge.dump({
298
+ maxDepth: options?.maxDepth ?? this.config.dumpMaxDepth,
299
+ skipInvisible: options?.skipInvisible ?? this.config.dumpSkipInvisible
300
+ });
301
+ this.lastTree = tree;
302
+ this.warnIfDepthCapped(tree, options?.maxDepth ?? this.config.dumpMaxDepth ?? 0);
303
+ if (!silent) this.done(node, this.message('runtime.scanned'));
304
+ return tree;
305
+ } catch (e) {
306
+ if (!silent) this.fail(node, e);
307
+ throw e;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Screenshot the host app. By default hides Koko overlay layers
313
+ * (progress / cursor / sheet) so the image matches what dump sees.
314
+ */
315
+ async screenshot(options) {
316
+ ExecutionGuard.assert('screenshot');
317
+ return NativeBridge.screenshot({
318
+ hideOverlays: options?.hideOverlays ?? true
319
+ });
320
+ }
321
+ getLastTree() {
322
+ return this.lastTree;
323
+ }
324
+
325
+ /** @internal Return a locally observed OCR label for validating a planned action. */
326
+ observedOcrLabel(nodeId) {
327
+ return nodeId ? this.ocrTargets.get(nodeId)?.text : undefined;
328
+ }
329
+
330
+ /** @internal Pin the screen whose node ids the planner is about to see. */
331
+ setPlanningTree(tree) {
332
+ this.planningTree = tree;
333
+ }
334
+ async find(selector, tree) {
335
+ const wantedLabel = selectorLabel(selector);
336
+ const label = wantedLabel ?? this.text('runtime.element');
337
+ const node = this.track('find', this.message('runtime.find', {
338
+ label
339
+ }));
340
+ try {
341
+ const root = tree ?? (await this.dump({
342
+ silent: true
343
+ }));
344
+ if (sensitiveScreenKind(root)) throw new ActionValidationError(this.message('runtime.privateStep'));
345
+ let hit = find(root, selector);
346
+ // OCR can confirm only a unique visible text label. It cannot prove an
347
+ // index, nearby context, element type, or actual clickability.
348
+ const ocrEligible = selector.match.length === 1 && ('text' in selector.match[0] || 'accessibilityLabel' in selector.match[0]) && (selector.index === undefined || selector.index === 0);
349
+ if (!hit && !!wantedLabel && ocrEligible && NativeBridge.isAvailable()) {
350
+ try {
351
+ const ocr = await NativeBridge.recognizeScreenText({
352
+ maxTokens: 32,
353
+ hideOverlays: true
354
+ });
355
+ const directHit = findOcrTextHit(ocr.texts || [], label);
356
+ const textHit = directHit || findOcrTextHit(ocr.texts || [], label, {
357
+ translatedWebRegions: visibleWebViewFrames(root)
358
+ });
359
+ if (textHit?.frame) {
360
+ const f = textHit.frame;
361
+ // The id carries no coordinates. A later tap must recognize this
362
+ // text again and use its current frame rather than this snapshot.
363
+ const id = `ocr:local-${++this.nextOcrTargetId}`;
364
+ this.ocrTargets.set(id, {
365
+ text: textHit.text,
366
+ webview: !directHit
367
+ });
368
+ if (this.ocrTargets.size > 32) this.ocrTargets.delete(this.ocrTargets.keys().next().value);
369
+ hit = {
370
+ id,
371
+ type: 'KokoOcrText',
372
+ frame: f,
373
+ // Only return the requested label, not arbitrary OCR screen text.
374
+ // Raw OCR remains on-device even if a webpage contains secrets.
375
+ text: label,
376
+ clickable: true,
377
+ enabled: true,
378
+ visible: true,
379
+ children: []
380
+ };
381
+ }
382
+ } catch {
383
+ // OCR is optional; a normal miss remains a normal miss.
384
+ }
385
+ }
386
+ if (!hit && !tree && this.activeGoal) {
387
+ hit = await this.revealVisibleTarget(selector, wantedLabel || undefined);
388
+ }
389
+ this.done(node, this.message(hit ? 'runtime.found' : 'runtime.notFound', {
390
+ label
391
+ }), hit ? hit.id : undefined);
392
+ return hit;
393
+ } catch (e) {
394
+ this.fail(node, e);
395
+ throw e;
396
+ }
397
+ }
398
+ async findAll(selector, tree) {
399
+ const root = tree ?? this.lastTree ?? (await this.dump({
400
+ silent: true
401
+ }));
402
+ return findAll(root, selector);
403
+ }
404
+ async tap(target) {
405
+ const epoch = this.executionEpoch;
406
+ const assertCurrent = () => this.assertExecutionCurrent(epoch);
407
+ ExecutionGuard.assert('tap');
408
+ if (sensitiveScreenKind(await NativeBridge.dump())) {
409
+ throw new ActionValidationError(this.message('runtime.privateStep'));
410
+ }
411
+ assertCurrent();
412
+ this.lastTapViaHost = null;
413
+ let label = target.label ?? selectorLabel(target.selector) ?? this.text('runtime.target');
414
+ let hostHit = target.nodeId || target.point ? undefined : HostActionsStore.findForTap({
415
+ label,
416
+ text: selectorLabel(target.selector),
417
+ testID: selectorTestID(target.selector)
418
+ });
419
+ // Planner often taps dump nodeId of a native tab label; resolve copy then
420
+ // match host run (geometric hit-test on UITabBar is unreliable).
421
+ let preresolved = null;
422
+ if (!hostHit?.run) {
423
+ try {
424
+ preresolved = await this.resolveNode(target);
425
+ const nodeLabel = (preresolved?.text || preresolved?.accessibilityLabel || '').trim();
426
+ if (nodeLabel) {
427
+ const byNode = HostActionsStore.findForTap({
428
+ label: nodeLabel,
429
+ text: nodeLabel,
430
+ testID: preresolved?.testID
431
+ });
432
+ if (byNode?.run) {
433
+ hostHit = byNode;
434
+ label = nodeLabel;
435
+ }
436
+ }
437
+ } catch {
438
+ // Geometric path will surface the same resolve error.
439
+ }
440
+ }
441
+ assertCurrent();
442
+ // Host callbacks use the same visibility and confirmation guards as taps.
443
+ if (hostHit?.run) {
444
+ assertCurrent();
445
+ // A host callback is not permission to activate a mounted but hidden row.
446
+ const visible = preresolved ?? (target.options?.revealIfNeeded === false ? find(await this.dump({
447
+ silent: true
448
+ }), target.selector || {
449
+ match: [{
450
+ text: hostHit.text || hostHit.label
451
+ }]
452
+ }, tapFindOptions(target)) : await this.revealVisibleTarget(target.selector || {
453
+ match: [{
454
+ text: hostHit.text || hostHit.label
455
+ }]
456
+ }, hostHit.text || hostHit.label, tapFindOptions(target).preferNonInput));
457
+ if (visible) preresolved = visible;
458
+ if (!visible || !canRunHostActionForNode(hostHit, visible, this.lastTree)) hostHit = undefined;
459
+ }
460
+ if (hostHit?.run) {
461
+ const node = this.track('tap', this.message('runtime.tap', {
462
+ label
463
+ }));
464
+ try {
465
+ const confirmKey = `tap:${label}`;
466
+ if (!this.confirmedSensitive.has(confirmKey)) {
467
+ const allowed = await runConfirmationGate({
468
+ action: 'tap',
469
+ label,
470
+ selector: target.selector
471
+ }, this.config.confirmation, this.config.onConfirmSensitive);
472
+ assertCurrent();
473
+ if (!allowed) {
474
+ TaskStore.updateNode(node.id, {
475
+ status: 'failed',
476
+ title: this.message('runtime.confirmBlocked', {
477
+ label
478
+ })
479
+ });
480
+ throw new ActionValidationError(this.message('runtime.confirmationRequired'));
481
+ }
482
+ if (isSensitiveLabel(label, this.config.confirmation)) {
483
+ this.confirmedSensitive.add(confirmKey);
484
+ }
485
+ }
486
+ const silent = target.options?.silent;
487
+ const beforeSnap = await this.snapshotLine(true);
488
+ const duration = target.options?.cursorDurationMs ?? this.config.cursorDurationMs ?? 320;
489
+ const spot = await this.hostActionPoint(target, preresolved);
490
+ if (!silent) {
491
+ if (spot) {
492
+ assertCurrent();
493
+ await CursorController.moveTo(spot.x, spot.y, duration);
494
+ assertCurrent();
495
+ CursorController.setPressing(true);
496
+ await sleep(40);
497
+ } else {
498
+ CursorController.hide();
499
+ }
500
+ }
501
+ try {
502
+ if (!spot) throw new ActionValidationError(this.message('runtime.hostTargetMissing'));
503
+ await this.assertTapTargetCurrent(target, spot, preresolved);
504
+ assertCurrent();
505
+ if (!(await runHostAction(hostHit.run))) {
506
+ throw new ActionOutcomeUnknownError(`host action for ${label} did not settle`);
507
+ }
508
+ } finally {
509
+ if (!silent) {
510
+ await sleep(120);
511
+ CursorController.setPressing(false);
512
+ }
513
+ }
514
+ // One-shot CTAs: drop so the next screen is not poisoned.
515
+ // Tabs / persistent chrome keep `oneshot: false`.
516
+ if (hostHit.oneshot !== false) {
517
+ HostActionsStore.unregisterAction(hostHit.id);
518
+ }
519
+ // Navigation / root reset needs a beat before dump.
520
+ await sleep(hostHit.kind === 'tab' ? 700 : 900);
521
+ assertCurrent();
522
+ // Observe the result, but never turn an uncertain callback into a
523
+ // second coordinate tap: async work may already have committed.
524
+ if (beforeSnap && (await this.snapshotLine()) === beforeSnap) {
525
+ this.lastTapViaHost = null;
526
+ // A resolved callback may already have submitted async work. An
527
+ // unchanged screen does not prove it is safe to perform it again.
528
+ throw new ActionOutcomeUnknownError(`host action for ${label} is unverified; not replayed`);
529
+ } else {
530
+ this.lastTapViaHost = {
531
+ kind: hostHit.kind,
532
+ label
533
+ };
534
+ // Settings / modal hosts stack above progress — remount chrome on top.
535
+ TaskStore.liftChrome();
536
+ this.done(node, this.message('runtime.tapped', {
537
+ label
538
+ }));
539
+ return;
540
+ }
541
+ } catch (e) {
542
+ this.fail(node, e);
543
+ throw e;
544
+ }
545
+ }
546
+ assertCurrent();
547
+ let controlNode = preresolved ?? (await this.resolveNode(target));
548
+ let point;
549
+ try {
550
+ point = await this.resolvePoint(target);
551
+ } catch (e) {
552
+ // No target evidence means no decorative tap at a guessed position.
553
+ throw e;
554
+ }
555
+ // Refresh control metadata from the same visible tree used for the point.
556
+ ({
557
+ point,
558
+ node: controlNode
559
+ } = await this.ensureSafeTapPoint(target, point, controlNode));
560
+ assertCurrent();
561
+ const isToggle = Boolean(controlNode?.toggle);
562
+ const adjustableKind = controlNode ? classifyAdjustable(controlNode) : null;
563
+ const node = this.track('tap', isToggle ? this.message('runtime.toggle', {
564
+ label
565
+ }) : adjustableKind ? this.message('runtime.adjust', {
566
+ label
567
+ }) : this.message('runtime.tap', {
568
+ label
569
+ }));
570
+ try {
571
+ const confirmKey = `tap:${label}`;
572
+ if (!this.confirmedSensitive.has(confirmKey)) {
573
+ const allowed = await runConfirmationGate({
574
+ action: 'tap',
575
+ label,
576
+ selector: target.selector
577
+ }, this.config.confirmation, this.config.onConfirmSensitive);
578
+ assertCurrent();
579
+ if (!allowed) {
580
+ TaskStore.updateNode(node.id, {
581
+ status: 'failed',
582
+ title: this.message('runtime.confirmBlocked', {
583
+ label
584
+ })
585
+ });
586
+ throw new ActionValidationError(this.message('runtime.confirmationRequired'));
587
+ }
588
+ if (isSensitiveLabel(label, this.config.confirmation)) {
589
+ this.confirmedSensitive.add(confirmKey);
590
+ }
591
+ }
592
+ const silent = target.options?.silent;
593
+ const duration = target.options?.cursorDurationMs ?? this.config.cursorDurationMs ?? 320;
594
+
595
+ // Switches / toggles: prefer a real tap — native UISwitch handling is reliable.
596
+ // (A JS→swipe path used to miss UISwitch in dispatchSwipe.)
597
+ if (controlNode?.toggle && controlNode.frame) {
598
+ const targetPoint = centerOf(controlNode);
599
+ if (!silent) {
600
+ assertCurrent();
601
+ await CursorController.moveTo(targetPoint.x, targetPoint.y, duration);
602
+ assertCurrent();
603
+ CursorController.setPressing(true);
604
+ await sleep(40);
605
+ }
606
+ try {
607
+ await withChromeClearance([targetPoint], async () => {
608
+ await this.assertTapTargetCurrent(target, point, controlNode);
609
+ assertCurrent();
610
+ return NativeBridge.tap(targetPoint);
611
+ });
612
+ } finally {
613
+ if (!silent && epoch === this.executionEpoch) {
614
+ CursorController.showAt(targetPoint.x, targetPoint.y, 0);
615
+ await sleep(120);
616
+ CursorController.setPressing(false);
617
+ }
618
+ }
619
+ this.done(node, this.message('runtime.toggled', {
620
+ label
621
+ }));
622
+ return;
623
+ }
624
+
625
+ // Slider / picker: route to swipe. Stepper / segment: plain tap (native handles ± / index).
626
+ if (controlNode?.frame && adjustableKind && (adjustableKind === 'slider' || adjustableKind === 'picker' || adjustableKind === 'other')) {
627
+ const gesture = adjustableGesture(controlNode, adjustableKind, point);
628
+ if (gesture) {
629
+ if (!silent) {
630
+ assertCurrent();
631
+ await CursorController.moveTo(gesture.from.x, gesture.from.y, duration);
632
+ assertCurrent();
633
+ CursorController.setPressing(true);
634
+ await sleep(40);
635
+ }
636
+ try {
637
+ await withChromeClearance([gesture.from, gesture.to], async () => {
638
+ await this.assertTapTargetCurrent(target, point, controlNode);
639
+ assertCurrent();
640
+ return NativeBridge.swipe(gesture.from, gesture.to, gesture.durationMs);
641
+ });
642
+ } finally {
643
+ if (!silent && epoch === this.executionEpoch) {
644
+ CursorController.showAt(gesture.to.x, gesture.to.y, 0);
645
+ await sleep(120);
646
+ CursorController.setPressing(false);
647
+ }
648
+ }
649
+ this.done(node, this.message('runtime.adjusted', {
650
+ label
651
+ }));
652
+ return;
653
+ }
654
+ }
655
+
656
+ // System Alert / ActionSheet buttons: invoke handler by title (hit-testing is unreliable).
657
+ if (controlNode && isAlertActionNode(controlNode)) {
658
+ const title = (controlNode.text || controlNode.accessibilityLabel || label || '').trim();
659
+ if (!silent) {
660
+ assertCurrent();
661
+ await CursorController.moveTo(point.x, point.y, duration);
662
+ assertCurrent();
663
+ CursorController.setPressing(true);
664
+ await sleep(40);
665
+ }
666
+ try {
667
+ await this.assertTapTargetCurrent(target, point, controlNode);
668
+ assertCurrent();
669
+ const invoked = title ? await NativeBridge.invokeAlertAction(title) : false;
670
+ if (!invoked) {
671
+ await withChromeClearance([point], async () => {
672
+ await this.assertTapTargetCurrent(target, point, controlNode);
673
+ assertCurrent();
674
+ return NativeBridge.tap(point);
675
+ });
676
+ }
677
+ } finally {
678
+ if (!silent) {
679
+ await sleep(120);
680
+ CursorController.setPressing(false);
681
+ }
682
+ }
683
+ this.done(node, this.message('runtime.confirmed', {
684
+ label: title || label
685
+ }));
686
+ return;
687
+ }
688
+ if (!silent) {
689
+ assertCurrent();
690
+ await CursorController.moveTo(point.x, point.y, duration);
691
+ assertCurrent();
692
+ CursorController.setPressing(true);
693
+ await sleep(40);
694
+ }
695
+ try {
696
+ await this.assertTapTargetCurrent(target, point, controlNode);
697
+ assertCurrent();
698
+ if (!silent && epoch === this.executionEpoch) {
699
+ CursorController.showAt(point.x, point.y, 0);
700
+ }
701
+ // If an alert is up, prefer title invoke even for generic sheet taps.
702
+ let didAlert = false;
703
+ if (controlNode?.sheet && controlNode.clickable) {
704
+ const title = (controlNode.text || controlNode.accessibilityLabel || label || '').trim();
705
+ if (title) {
706
+ assertCurrent();
707
+ didAlert = await NativeBridge.invokeAlertAction(title);
708
+ }
709
+ }
710
+ if (!didAlert) {
711
+ await withChromeClearance([point], async () => {
712
+ await this.assertTapTargetCurrent(target, point, controlNode);
713
+ assertCurrent();
714
+ return NativeBridge.tap(point);
715
+ });
716
+ }
717
+ } finally {
718
+ if (!silent) {
719
+ await sleep(160);
720
+ CursorController.setPressing(false);
721
+ }
722
+ }
723
+ this.done(node, this.message('runtime.tapped', {
724
+ label
725
+ }));
726
+ } catch (e) {
727
+ this.fail(node, e);
728
+ throw e;
729
+ }
730
+ }
731
+
732
+ /** Animation and confirmations may outlive the layout that was planned. */
733
+ async assertTapTargetCurrent(target, point, expected) {
734
+ const currentPoint = await this.resolvePoint({
735
+ ...target,
736
+ options: {
737
+ ...target.options,
738
+ revealIfNeeded: false
739
+ }
740
+ });
741
+ if (Math.hypot(currentPoint.x - point.x, currentPoint.y - point.y) > 16) {
742
+ throw new ActionValidationError(this.message('runtime.positionChanged'));
743
+ }
744
+ if (expected && !expected.id.startsWith('ocr:')) {
745
+ const current = this.lastTree ? findNodeById(this.lastTree, expected.id) : null;
746
+ if (!current || current.enabled === false || current.visible === false || current.type !== expected.type || current.text !== expected.text || current.accessibilityLabel !== expected.accessibilityLabel || current.testID !== expected.testID) {
747
+ throw new ActionValidationError(this.message('runtime.contentChanged'));
748
+ }
749
+ }
750
+ }
751
+
752
+ /** Refresh node metadata after scroll-based target resolution. */
753
+ async ensureSafeTapPoint(target, point, controlNode) {
754
+ const tree = this.lastTree;
755
+ const current = tree ? target.selector ? find(tree, target.selector, tapFindOptions(target)) : target.nodeId ? findNodeById(tree, target.nodeId) : controlNode : controlNode;
756
+ return {
757
+ point,
758
+ node: current?.visible === false ? null : current
759
+ };
760
+ }
761
+
762
+ /** Reveal by visible swipes, only inside a natively confirmed scrollable list. */
763
+ async revealVisibleTarget(selector, label, preferNonInput = false) {
764
+ const epoch = this.executionEpoch;
765
+ const seen = new Set();
766
+ for (const direction of [1, -1]) {
767
+ for (let page = 0; page < 8; page++) {
768
+ const tree = await this.dump({
769
+ silent: true
770
+ });
771
+ if (sensitiveScreenKind(tree)) throw new ActionValidationError(this.message('runtime.privateStep'));
772
+ const hit = find(tree, selector, {
773
+ preferNonInput
774
+ }) || (label && allowsSoftLabelFallback(selector) ? findBySoftLabel(tree, label, {
775
+ preferNonInput
776
+ }) : null);
777
+ if (hit) return hit;
778
+ const viewport = scrollViewports(tree).filter(({
779
+ frame
780
+ }) => frame.height >= 140 && frame.width >= tree.frame.width * 0.45).sort((a, b) => b.frame.width * b.frame.height - a.frame.width * a.frame.height)[0];
781
+ if (!viewport) return null;
782
+ // Use the list itself, not the first few screen affordances: sticky
783
+ // headers can stay unchanged while later rows are still moving.
784
+ const fingerprint = `${direction}:${JSON.stringify(flattenTree(viewport.node).map(n => [n.id, n.text || n.accessibilityLabel || '', Math.round(n.frame.y)]))}`;
785
+ if (seen.has(fingerprint)) break;
786
+ seen.add(fingerprint);
787
+ this.log('info', this.message('runtime.reveal'));
788
+ const f = viewport.frame;
789
+ const x = f.x + f.width / 2;
790
+ const upper = f.y + f.height * 0.25;
791
+ const lower = f.y + f.height * 0.75;
792
+ this.assertExecutionCurrent(epoch);
793
+ await this.swipe({
794
+ x,
795
+ y: direction > 0 ? lower : upper
796
+ }, {
797
+ x,
798
+ y: direction > 0 ? upper : lower
799
+ }, {
800
+ durationMs: 420
801
+ });
802
+ await sleep(250);
803
+ }
804
+ }
805
+ return null;
806
+ }
807
+ async swipe(from, to, options) {
808
+ const epoch = this.executionEpoch;
809
+ const assertCurrent = () => this.assertExecutionCurrent(epoch);
810
+ ExecutionGuard.assert('swipe');
811
+ const tree = await this.dump({
812
+ silent: true
813
+ });
814
+ if (sensitiveScreenKind(tree)) throw new ActionValidationError(this.message('runtime.privateStep'));
815
+ const viewport = scrollViewports(tree).filter(({
816
+ frame: f
817
+ }) => from.x >= f.x && from.x <= f.x + f.width && from.y >= f.y && from.y <= f.y + f.height).sort((a, b) => a.frame.width * a.frame.height - b.frame.width * b.frame.height)[0];
818
+ if (viewport) ({
819
+ from,
820
+ to
821
+ } = boundedScrollGesture(viewport.frame, from, to));
822
+ const silent = options?.silent;
823
+ const node = silent ? {
824
+ id: ''
825
+ } : this.track('swipe', this.message('runtime.swipe'));
826
+ const durationMs = options?.durationMs ?? 280;
827
+ try {
828
+ if (!silent) {
829
+ assertCurrent();
830
+ await CursorController.moveTo(from.x, from.y, this.config.cursorDurationMs ?? 320);
831
+ assertCurrent();
832
+ CursorController.setPressing(true);
833
+ }
834
+ try {
835
+ await withChromeClearance([from, to], () => {
836
+ assertCurrent();
837
+ return NativeBridge.swipe(from, to, durationMs);
838
+ });
839
+ } finally {
840
+ if (!silent && epoch === this.executionEpoch) {
841
+ CursorController.showAt(to.x, to.y);
842
+ CursorController.setPressing(false);
843
+ }
844
+ }
845
+ this.done(node, this.message('runtime.swiped'));
846
+ } catch (e) {
847
+ this.fail(node, e);
848
+ throw e;
849
+ }
850
+ }
851
+
852
+ /**
853
+ * Two-finger pinch at center. scale>1 zoom in, scale<1 zoom out.
854
+ */
855
+ async pinch(center, scale, options) {
856
+ const epoch = this.executionEpoch;
857
+ const assertCurrent = () => this.assertExecutionCurrent(epoch);
858
+ ExecutionGuard.assert('pinch');
859
+ const silent = options?.silent;
860
+ const zoomIn = scale >= 1;
861
+ const node = silent ? {
862
+ id: ''
863
+ } : this.track('swipe', zoomIn ? this.message('runtime.zoomIn') : this.message('runtime.zoomOut'));
864
+ const durationMs = options?.durationMs ?? 280;
865
+ try {
866
+ if (!silent) {
867
+ assertCurrent();
868
+ await CursorController.moveTo(center.x, center.y, this.config.cursorDurationMs ?? 320);
869
+ assertCurrent();
870
+ CursorController.setPressing(true);
871
+ }
872
+ try {
873
+ await withChromeClearance([center], () => {
874
+ assertCurrent();
875
+ return NativeBridge.pinch(center, scale, durationMs);
876
+ });
877
+ } finally {
878
+ if (!silent && epoch === this.executionEpoch) {
879
+ CursorController.showAt(center.x, center.y);
880
+ CursorController.setPressing(false);
881
+ }
882
+ }
883
+ this.done(node, zoomIn ? this.message('runtime.zoomedIn') : this.message('runtime.zoomedOut'));
884
+ } catch (e) {
885
+ this.fail(node, e);
886
+ throw e;
887
+ }
888
+ }
889
+ async type(text, target = {}) {
890
+ const epoch = this.executionEpoch;
891
+ const assertCurrent = () => this.assertExecutionCurrent(epoch);
892
+ ExecutionGuard.assert('type');
893
+ if (sensitiveScreenKind(await NativeBridge.dump())) throw new ActionValidationError(this.message('runtime.privateStep'));
894
+ assertCurrent();
895
+ const preview = text.length > 18 ? `${text.slice(0, 18)}…` : text;
896
+ const node = this.track('type', this.message('runtime.input', {
897
+ text: preview
898
+ }));
899
+ try {
900
+ // Ensure a field is focused: tap selector / node, or first text field on screen.
901
+ // Native tap must becomeFirstResponder (keyboard); synthetic UIControl events alone do not.
902
+ let focusPoint = null;
903
+ if (target.selector || target.nodeId) {
904
+ focusPoint = await this.resolvePoint({
905
+ selector: target.selector,
906
+ nodeId: target.nodeId,
907
+ inputTarget: true
908
+ });
909
+ assertCurrent();
910
+ await this.tap({
911
+ selector: target.selector,
912
+ nodeId: target.nodeId,
913
+ options: {
914
+ silent: target.options?.silent
915
+ },
916
+ label: target.label ?? this.text('runtime.field'),
917
+ inputTarget: true
918
+ });
919
+ } else {
920
+ const root = this.lastTree ?? (await this.dump({
921
+ silent: true
922
+ }));
923
+ const field = findFirstTextField(root);
924
+ if (field) {
925
+ focusPoint = await this.resolvePoint({
926
+ nodeId: field.id
927
+ });
928
+ assertCurrent();
929
+ await this.tap({
930
+ nodeId: field.id,
931
+ options: {
932
+ silent: target.options?.silent
933
+ },
934
+ label: target.label ?? field.accessibilityLabel ?? field.text ?? this.text('runtime.field')
935
+ });
936
+ }
937
+ }
938
+ await sleep(160);
939
+ if (focusPoint) {
940
+ try {
941
+ assertCurrent();
942
+ await NativeBridge.focusAt(focusPoint);
943
+ } catch {
944
+ try {
945
+ assertCurrent();
946
+ await NativeBridge.focusNode(target.nodeId ?? '');
947
+ } catch {
948
+ // typeText will try becomeFirstResponder again
949
+ }
950
+ }
951
+ } else {
952
+ try {
953
+ assertCurrent();
954
+ await NativeBridge.focusNode(target.nodeId ?? '');
955
+ } catch {
956
+ // optional
957
+ }
958
+ }
959
+ await sleep(80);
960
+ assertCurrent();
961
+ await NativeBridge.typeText(text, target.options?.clear ?? false);
962
+ this.done(node, this.message('runtime.typed', {
963
+ text: preview
964
+ }));
965
+ } catch (e) {
966
+ this.fail(node, e);
967
+ throw e;
968
+ }
969
+ }
970
+ async requestConfirm(ctx) {
971
+ const label = ctx.label ?? ctx.action;
972
+ const node = this.track('confirm', this.message('runtime.confirm', {
973
+ label
974
+ }));
975
+ const ok = await runConfirmationGate(ctx, this.config.confirmation, this.config.onConfirmSensitive);
976
+ TaskStore.updateNode(node.id, {
977
+ status: ok ? 'done' : 'failed',
978
+ title: this.message(ok ? 'runtime.userConfirmed' : 'runtime.userDeclined', {
979
+ label
980
+ })
981
+ });
982
+ return ok;
983
+ }
984
+ hideCursor() {
985
+ CursorController.hide();
986
+ }
987
+
988
+ /** Run one agent protocol tool call. */
989
+ async runAction(action) {
990
+ return executeAgentAction(this, action);
991
+ }
992
+ track(kind, title) {
993
+ if (this.config.observer === false) {
994
+ return {
995
+ id: ''
996
+ };
997
+ }
998
+ return TaskStore.appendNode({
999
+ kind,
1000
+ title,
1001
+ status: 'running'
1002
+ });
1003
+ }
1004
+ done(node, title, detail) {
1005
+ if (!node.id || this.config.observer === false) return;
1006
+ TaskStore.updateNode(node.id, {
1007
+ status: 'done',
1008
+ title,
1009
+ detail
1010
+ });
1011
+ }
1012
+ fail(node, e) {
1013
+ if (!node.id || this.config.observer === false) return;
1014
+ const copy = e instanceof ActionValidationError ? e.localizedMessage : this.message('runtime.operationFailed');
1015
+ TaskStore.updateNode(node.id, {
1016
+ status: 'failed',
1017
+ title: copy
1018
+ });
1019
+ }
1020
+ async resolvePoint(target) {
1021
+ // A labelled cloud coordinate is a hint, not evidence that a row is visible.
1022
+ // Prefer a fresh selector/label and scroll lookup before dispatching a touch.
1023
+ if (target.point && !target.selector && !target.nodeId) {
1024
+ if (!this.activeGoal) return this.pointWithinWindow(target.point);
1025
+ const label = target.label?.match(/[「“"]([^」”"]+)[」”"]/)?.[1] || target.label?.replace(/^(点击|轻点|打开)\s*/, '').replace(/按钮$/, '');
1026
+ if (!label) throw new ActionValidationError(this.message('runtime.missingTarget'));
1027
+ return this.resolvePoint({
1028
+ selector: {
1029
+ match: [{
1030
+ text: label
1031
+ }]
1032
+ },
1033
+ label,
1034
+ options: target.options
1035
+ });
1036
+ }
1037
+ const root = await this.dump({
1038
+ silent: true
1039
+ });
1040
+ if (sensitiveScreenKind(root)) throw new ActionValidationError(this.message('runtime.privateStep'));
1041
+
1042
+ // An explicit selector is target evidence; a node path is only a hint.
1043
+ // In particular do not replace a selector with a stale recycled row id.
1044
+ if (target.selector) {
1045
+ let node = find(root, target.selector, tapFindOptions(target));
1046
+ const soft = selectorLabel(target.selector);
1047
+ const allowSoft = allowsSoftLabelFallback(target.selector);
1048
+ if (!node && soft && allowSoft) node = findBySoftLabel(root, soft, tapFindOptions(target));
1049
+ if (!node && soft && allowSoft && NativeBridge.isAvailable()) {
1050
+ const point = await this.currentOcrPoint(soft);
1051
+ if (point) return point;
1052
+ }
1053
+ if (!node && target.options?.revealIfNeeded !== false) {
1054
+ node = await this.revealVisibleTarget(target.selector, soft || undefined, tapFindOptions(target).preferNonInput);
1055
+ }
1056
+ if (!node || node.visible === false || node.enabled === false) {
1057
+ throw new ActionValidationError(this.message('runtime.missingTarget'));
1058
+ }
1059
+ return this.pointWithinWindow(centerOfLabel(node, soft));
1060
+ }
1061
+ if (target.nodeId) {
1062
+ if (target.nodeId.startsWith('ocr:')) {
1063
+ const observed = this.ocrTargets.get(target.nodeId);
1064
+ if (!observed) throw new ActionValidationError(this.message('runtime.ocrUnobserved'));
1065
+ const point = await this.currentOcrPoint(observed.text, observed.webview ? root : undefined);
1066
+ if (point) return point;
1067
+ throw new ActionValidationError(this.message('runtime.ocrMissing'));
1068
+ }
1069
+ // host:… is a catalog id, not a dump node — remap to visible text.
1070
+ if (target.nodeId.startsWith('host:')) {
1071
+ const host = HostActionsStore.getById(target.nodeId);
1072
+ const soft = host?.text || host?.label;
1073
+ if (soft) {
1074
+ const hit = target.options?.revealIfNeeded === false ? findBySoftLabel(root, soft) : await this.revealVisibleTarget({
1075
+ match: [{
1076
+ text: soft
1077
+ }]
1078
+ }, soft);
1079
+ if (hit && hit.visible !== false && hit.enabled !== false) return this.pointWithinWindow(centerOfLabel(hit, soft));
1080
+ }
1081
+ throw new ActionValidationError(this.message('runtime.hostNotVisible', {
1082
+ id: target.nodeId
1083
+ }));
1084
+ }
1085
+ const node = this.validatedNativeNode(root, target.nodeId);
1086
+ // label is narration, in any language. It must not override a real
1087
+ // current node or become an invented selector such as “Click Back”.
1088
+ return this.pointWithinWindow(centerOfLabel(node));
1089
+ }
1090
+ throw new ActionValidationError(this.message('runtime.invalidTarget'));
1091
+ }
1092
+ validatedNativeNode(root, nodeId) {
1093
+ const node = findNodeById(root, nodeId);
1094
+ if (!node || node.visible === false || node.enabled === false) {
1095
+ throw new ActionValidationError(this.message('runtime.nodeUnavailable'));
1096
+ }
1097
+ if (this.activeGoal) {
1098
+ const observed = this.planningTree ? findNodeById(this.planningTree, nodeId) : null;
1099
+ const identity = item => JSON.stringify([item.type, item.text || '', item.accessibilityLabel || '', item.testID || '']);
1100
+ if (!observed || identity(observed) !== identity(node)) {
1101
+ throw new ActionValidationError(this.message('runtime.nodeChanged'));
1102
+ }
1103
+ }
1104
+ return node;
1105
+ }
1106
+ async currentOcrPoint(text, webviewRoot) {
1107
+ if (!NativeBridge.isAvailable()) return null;
1108
+ try {
1109
+ const ocr = await NativeBridge.recognizeScreenText({
1110
+ maxTokens: 32,
1111
+ hideOverlays: true
1112
+ });
1113
+ const hit = findOcrTextHit(ocr.texts || [], text);
1114
+ const frame = hit?.frame;
1115
+ if (!frame || ![frame.x, frame.y, frame.width, frame.height].every(Number.isFinite)) return null;
1116
+ if (webviewRoot && (!hit || !ocrHitInFrames(hit, visibleWebViewFrames(webviewRoot)))) return null;
1117
+ return await this.pointWithinWindow({
1118
+ x: frame.x + frame.width / 2,
1119
+ y: frame.y + frame.height / 2
1120
+ });
1121
+ } catch {
1122
+ // No current positioned evidence means no touch, even if an older OCR
1123
+ // read found the same text at a plausible location.
1124
+ return null;
1125
+ }
1126
+ }
1127
+
1128
+ /**
1129
+ * A coordinate tap has no node to sanity-check it against, so an invented
1130
+ * point would dispatch into nowhere and only surface later as tap_noop.
1131
+ * Fail loudly instead.
1132
+ */
1133
+ /**
1134
+ * A tree that bottoms out exactly at the cap was almost certainly cut short,
1135
+ * and the part that gets cut is the page body — the agent is then left with
1136
+ * the shallow chrome and reports the control as missing. Surface it rather
1137
+ * than letting it read as an empty screen.
1138
+ */
1139
+ warnIfDepthCapped(tree, cap) {
1140
+ if (!cap) return;
1141
+ let deepest = 0;
1142
+ const walk = (n, d) => {
1143
+ if (d > deepest) deepest = d;
1144
+ for (const c of n.children ?? []) walk(c, d + 1);
1145
+ };
1146
+ walk(tree, 0);
1147
+ if (deepest >= cap) {
1148
+ AgentDebug.dumpTruncated(this.config, cap);
1149
+ }
1150
+ }
1151
+
1152
+ /**
1153
+ * Cheap screen fingerprint used to tell real navigation from a dead action.
1154
+ * The "before" side can reuse the tree the session just dumped for this step:
1155
+ * an extra full walk per tap is work the JS thread does not have to spare
1156
+ * while a task is running.
1157
+ */
1158
+ async snapshotLine(reuseLastTree = false) {
1159
+ try {
1160
+ const tree = reuseLastTree ? this.lastTree ?? (await this.dump({
1161
+ silent: true
1162
+ })) : await this.dump({
1163
+ silent: true
1164
+ });
1165
+ return tree ? screenSnapshotLine(tree) : '';
1166
+ } catch {
1167
+ return '';
1168
+ }
1169
+ }
1170
+ async pointWithinWindow(point) {
1171
+ if (!Number.isFinite(point.x) || !Number.isFinite(point.y) || point.x < 0 || point.y < 0) {
1172
+ throw new ActionValidationError(this.message('runtime.invalidPoint', {
1173
+ x: point.x,
1174
+ y: point.y
1175
+ }));
1176
+ }
1177
+ const root = this.lastTree ?? (await this.dump({
1178
+ silent: true
1179
+ }));
1180
+ const w = root?.frame?.width ?? 0;
1181
+ const h = root?.frame?.height ?? 0;
1182
+ if (w > 0 && h > 0 && (point.x > w || point.y > h)) {
1183
+ throw new ActionValidationError(this.message('runtime.outsideWindow'));
1184
+ }
1185
+ return point;
1186
+ }
1187
+
1188
+ /** Resolve the view node for a tap target (for toggle/adjustable routing). */
1189
+ /**
1190
+ * Where to point while a host action runs.
1191
+ *
1192
+ * Best effort by design: the whole reason this path exists is that the dump
1193
+ * sometimes cannot see the control, so a miss here is normal and must not
1194
+ * turn a working host action into a failed step.
1195
+ */
1196
+ async hostActionPoint(target, preresolved) {
1197
+ if (preresolved?.frame) return centerOfLabel(preresolved, target.label ?? selectorLabel(target.selector));
1198
+ try {
1199
+ return await this.resolvePoint(target);
1200
+ } catch {
1201
+ return null;
1202
+ }
1203
+ }
1204
+ async resolveNode(target) {
1205
+ if (target.point && !target.selector && !target.nodeId) return null;
1206
+ const root = await this.dump({
1207
+ silent: true
1208
+ });
1209
+ if (sensitiveScreenKind(root)) throw new ActionValidationError(this.message('runtime.privateStep'));
1210
+ let node = null;
1211
+ if (target.selector) {
1212
+ node = find(root, target.selector, tapFindOptions(target));
1213
+ if (!node) {
1214
+ const soft = selectorLabel(target.selector);
1215
+ if (soft && allowsSoftLabelFallback(target.selector)) node = findBySoftLabel(root, soft, tapFindOptions(target));
1216
+ }
1217
+ } else if (target.nodeId) {
1218
+ if (target.nodeId.startsWith('ocr:')) return null;
1219
+ if (target.nodeId.startsWith('host:')) {
1220
+ const host = HostActionsStore.getById(target.nodeId);
1221
+ const soft = host?.text || host?.label;
1222
+ if (soft) node = findBySoftLabel(root, soft);
1223
+ } else {
1224
+ node = this.validatedNativeNode(root, target.nodeId);
1225
+ }
1226
+ }
1227
+ if (!node || node.visible === false || node.enabled === false) return null;
1228
+ if (node.toggle || node.adjustable) return node;
1229
+ // Label may resolve to a wrapper; prefer a toggle / adjustable descendant.
1230
+ const nested = findControlDescendant(node);
1231
+ return nested ?? node;
1232
+ }
1233
+ }
1234
+ function tapFindOptions(target) {
1235
+ const inputIntent = /(?:search|input|text)\s*(?:box|field|input)|输入框|搜索框/i.test(target.label || '');
1236
+ return {
1237
+ preferNonInput: !target.inputTarget && !inputIntent
1238
+ };
1239
+ }
1240
+
1241
+ /** A fallback must never discard context, identity, location, or an index. */
1242
+ function allowsSoftLabelFallback(selector) {
1243
+ return selector.index === undefined && selector.match.every(rule => 'text' in rule || 'accessibilityLabel' in rule || 'clickable' in rule && rule.clickable === true);
1244
+ }
1245
+ function findControlDescendant(node) {
1246
+ if (node.toggle || node.adjustable) return node;
1247
+ for (const c of node.children) {
1248
+ const hit = findControlDescendant(c);
1249
+ if (hit) return hit;
1250
+ }
1251
+ return null;
1252
+ }
1253
+ function isAlertActionNode(node) {
1254
+ if (node.type === 'UIAlertAction' || node.id.startsWith('alert/action/')) return true;
1255
+ if (!node.sheet || !node.clickable) return false;
1256
+ const t = (node.text || node.accessibilityLabel || '').trim();
1257
+ return /^(取消|清空|删除|好|确定|确认|允许|不允许|OK|Cancel|Delete|Yes|No|Discard)$/i.test(t);
1258
+ }
1259
+ function selectorLabel(selector) {
1260
+ if (!selector) return undefined;
1261
+ for (const rule of selector.match) {
1262
+ if ('text' in rule) return rule.text;
1263
+ if ('nearText' in rule) return rule.nearText;
1264
+ if ('accessibilityLabel' in rule) return rule.accessibilityLabel;
1265
+ }
1266
+ return undefined;
1267
+ }
1268
+ function selectorTestID(selector) {
1269
+ if (!selector) return undefined;
1270
+ for (const rule of selector.match) {
1271
+ if ('testID' in rule) return rule.testID;
1272
+ }
1273
+ return undefined;
1274
+ }
1275
+ function classifyAdjustable(node) {
1276
+ const t = node.type.toLowerCase();
1277
+ if (/slider|seekbar|rating/i.test(t)) return 'slider';
1278
+ if (/stepper/i.test(t)) return 'stepper';
1279
+ if (/segment/i.test(t)) return 'segment';
1280
+ if (/picker|datepicker|spinner|numberpicker/i.test(t)) return 'picker';
1281
+ if (node.adjustable) {
1282
+ // Trait-only adjustable: prefer horizontal if wide, else vertical.
1283
+ if (node.frame.width >= node.frame.height * 1.4) return 'slider';
1284
+ return 'picker';
1285
+ }
1286
+ return null;
1287
+ }
1288
+
1289
+ /**
1290
+ * Map tap intent on an adjustable into a swipe that nudges value.
1291
+ * Uses tap X/Y relative to the control when available.
1292
+ */
1293
+ function adjustableGesture(node, kind, tap) {
1294
+ const f = node.frame;
1295
+ const midX = f.x + f.width / 2;
1296
+ const midY = f.y + f.height / 2;
1297
+ const insetX = Math.max(8, f.width * 0.12);
1298
+ const insetY = Math.max(8, f.height * 0.18);
1299
+ if (kind === 'slider') {
1300
+ // Drag from current thumb (if value known) toward the tap X.
1301
+ // Near-center taps used to nudge +28% of track → often slammed to max (e.g. 1.6×).
1302
+ const min = typeof node.min === 'number' ? node.min : 0;
1303
+ const max = typeof node.max === 'number' ? node.max : 1;
1304
+ const span = Math.max(1e-6, max - min);
1305
+ const cur = typeof node.value === 'number' && Number.isFinite(node.value) ? node.value : min + span * 0.5;
1306
+ const thumbRatio = Math.max(0, Math.min(1, (cur - min) / span));
1307
+ const trackLeft = f.x + insetX;
1308
+ const trackRight = f.x + f.width - insetX;
1309
+ const trackW = Math.max(1, trackRight - trackLeft);
1310
+ const fromX = trackLeft + thumbRatio * trackW;
1311
+ let toX = tap.x;
1312
+ if (Math.abs(toX - midX) < f.width * 0.1) {
1313
+ // Ambiguous center tap: one small step toward + (~12% of range).
1314
+ toX = fromX + trackW * 0.12;
1315
+ }
1316
+ toX = Math.max(trackLeft, Math.min(trackRight, toX));
1317
+ return {
1318
+ from: {
1319
+ x: fromX,
1320
+ y: midY
1321
+ },
1322
+ to: {
1323
+ x: toX,
1324
+ y: midY
1325
+ },
1326
+ durationMs: 200
1327
+ };
1328
+ }
1329
+ if (kind === 'stepper') {
1330
+ // Right half → +, left half → − (short horizontal nudge).
1331
+ const goPlus = tap.x >= midX;
1332
+ const from = {
1333
+ x: midX,
1334
+ y: midY
1335
+ };
1336
+ const to = {
1337
+ x: goPlus ? f.x + f.width - insetX : f.x + insetX,
1338
+ y: midY
1339
+ };
1340
+ return {
1341
+ from,
1342
+ to,
1343
+ durationMs: 160
1344
+ };
1345
+ }
1346
+ if (kind === 'picker') {
1347
+ // Vertical wheel: tap above mid → scroll up (earlier values), below → down.
1348
+ const goUp = tap.y < midY;
1349
+ const from = {
1350
+ x: midX,
1351
+ y: midY
1352
+ };
1353
+ const to = {
1354
+ x: midX,
1355
+ y: goUp ? f.y + insetY : f.y + f.height - insetY
1356
+ };
1357
+ return {
1358
+ from,
1359
+ to,
1360
+ durationMs: 260
1361
+ };
1362
+ }
1363
+ return null;
1364
+ }
1365
+ function findFirstTextField(root) {
1366
+ let best = null;
1367
+ const walk = n => {
1368
+ const t = n.type.toLowerCase();
1369
+ if (n.visible && (/textfield|textinput|edittext|uitextfield/i.test(t) || n.secure === true)) {
1370
+ best = n;
1371
+ }
1372
+ for (const c of n.children) walk(c);
1373
+ };
1374
+ walk(root);
1375
+ return best;
1376
+ }
1377
+
1378
+ /**
1379
+ * Before an agent gesture: dismiss chat sheet, and if the tap/swipe lands in
1380
+ * the bottom-right progress/tab dock, hide chrome → wait for RN unmount →
1381
+ * gesture → show chrome again.
1382
+ */
1383
+ async function withChromeClearance(points, action) {
1384
+ if (TaskStore.snapshot().ui.sheetOpen) {
1385
+ TaskStore.closeSheet();
1386
+ await sleep(480);
1387
+ }
1388
+ try {
1389
+ // iOS dispatch temporarily disables overlay hit-testing natively. Keep
1390
+ // the progress host mounted, including when touching beneath the pill.
1391
+ if (Platform.OS === 'ios' || !pointsOverlapProgressChrome(points)) {
1392
+ await action();
1393
+ return;
1394
+ }
1395
+ TaskStore.suppressChrome();
1396
+ // React must commit unmount before native hit-testing; 50ms was too short.
1397
+ await sleep(160);
1398
+ await action();
1399
+ } finally {
1400
+ TaskStore.restoreChrome();
1401
+ // Host Settings/sheet Modals stack above our progress Modal — remount
1402
+ // so stop / pill stay tappable.
1403
+ TaskStore.liftChrome();
1404
+ }
1405
+ }
1406
+ function sleep(ms) {
1407
+ return new Promise(resolve => setTimeout(resolve, ms));
1408
+ }
1409
+ let shared = null;
1410
+ export function getKokoAgent() {
1411
+ if (!shared) shared = new KokoAgent();
1412
+ return shared;
1413
+ }
1414
+ export function initKokoAgent(config) {
1415
+ shared = new KokoAgent(config);
1416
+ return shared;
1417
+ }
1418
+ //# sourceMappingURL=KokoAgent.js.map