@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.
- package/CHANGELOG.md +10 -0
- package/CODE_OF_CONDUCT.md +3 -0
- package/CONTRIBUTING.md +9 -0
- package/LICENSE +21 -0
- package/README.md +65 -0
- package/README.zh-CN.md +50 -0
- package/SECURITY.md +5 -0
- package/android/build.gradle +40 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/cn/intentcomputing/kokoagentsdk/KokoAgentSdkModule.java +1356 -0
- package/android/src/main/java/cn/intentcomputing/kokoagentsdk/KokoAgentSdkPackage.java +23 -0
- package/docs/INTEGRATION.md +168 -0
- package/docs/INTEGRATION.zh-CN.md +140 -0
- package/docs/PRIVACY.md +11 -0
- package/docs/PRIVACY.zh-CN.md +11 -0
- package/docs/PUBLISH.md +11 -0
- package/docs/PUBLISH.zh-CN.md +11 -0
- package/ios/KokoAgentSdk/KokoAgentSdk.h +5 -0
- package/ios/KokoAgentSdk/KokoAgentSdk.m +2464 -0
- package/ios/KokoAgentSdk/KokoOcrBounds.h +20 -0
- package/ios/KokoAgentSdk/KokoScrollBounds.h +21 -0
- package/koko-agent-sdk.podspec +23 -0
- package/lib/commonjs/KokoAgent.js +1427 -0
- package/lib/commonjs/KokoAgent.js.map +1 -0
- package/lib/commonjs/assist/OnDeviceAssist.js +94 -0
- package/lib/commonjs/assist/OnDeviceAssist.js.map +1 -0
- package/lib/commonjs/assist/intentClassify.js +100 -0
- package/lib/commonjs/assist/intentClassify.js.map +1 -0
- package/lib/commonjs/assist/nodeRank.js +120 -0
- package/lib/commonjs/assist/nodeRank.js.map +1 -0
- package/lib/commonjs/assist/ocrTarget.js +135 -0
- package/lib/commonjs/assist/ocrTarget.js.map +1 -0
- package/lib/commonjs/assist/webVisualChange.js +29 -0
- package/lib/commonjs/assist/webVisualChange.js.map +1 -0
- package/lib/commonjs/client/ActionOutcomeUnknownError.js +28 -0
- package/lib/commonjs/client/ActionOutcomeUnknownError.js.map +1 -0
- package/lib/commonjs/client/AgentSession.js +858 -0
- package/lib/commonjs/client/AgentSession.js.map +1 -0
- package/lib/commonjs/client/GatewayClient.js +302 -0
- package/lib/commonjs/client/GatewayClient.js.map +1 -0
- package/lib/commonjs/client/OperationReplayGuard.js +62 -0
- package/lib/commonjs/client/OperationReplayGuard.js.map +1 -0
- package/lib/commonjs/client/RunCheckpoint.js +139 -0
- package/lib/commonjs/client/RunCheckpoint.js.map +1 -0
- package/lib/commonjs/client/loopDetect.js +184 -0
- package/lib/commonjs/client/loopDetect.js.map +1 -0
- package/lib/commonjs/client/recentSearch.js +50 -0
- package/lib/commonjs/client/recentSearch.js.map +1 -0
- package/lib/commonjs/client/walletChoiceGuard.js +18 -0
- package/lib/commonjs/client/walletChoiceGuard.js.map +1 -0
- package/lib/commonjs/client/webResultCategory.js +38 -0
- package/lib/commonjs/client/webResultCategory.js.map +1 -0
- package/lib/commonjs/commercial/AccountStore.js +78 -0
- package/lib/commonjs/commercial/AccountStore.js.map +1 -0
- package/lib/commonjs/commercial/AgentDebug.js +104 -0
- package/lib/commonjs/commercial/AgentDebug.js.map +1 -0
- package/lib/commonjs/commercial/ExecutionGuard.js +53 -0
- package/lib/commonjs/commercial/ExecutionGuard.js.map +1 -0
- package/lib/commonjs/commercial/UsageBus.js +42 -0
- package/lib/commonjs/commercial/UsageBus.js.map +1 -0
- package/lib/commonjs/commercial/branding.js +69 -0
- package/lib/commonjs/commercial/branding.js.map +1 -0
- package/lib/commonjs/commercial/devMode.js +52 -0
- package/lib/commonjs/commercial/devMode.js.map +1 -0
- package/lib/commonjs/commercial/trust.js +69 -0
- package/lib/commonjs/commercial/trust.js.map +1 -0
- package/lib/commonjs/confirmation/gate.js +62 -0
- package/lib/commonjs/confirmation/gate.js.map +1 -0
- package/lib/commonjs/cursor/CursorOverlay.js +141 -0
- package/lib/commonjs/cursor/CursorOverlay.js.map +1 -0
- package/lib/commonjs/cursor/PointerHand.js +51 -0
- package/lib/commonjs/cursor/PointerHand.js.map +1 -0
- package/lib/commonjs/cursor/controller.js +91 -0
- package/lib/commonjs/cursor/controller.js.map +1 -0
- package/lib/commonjs/cursor/pointer.js +49 -0
- package/lib/commonjs/cursor/pointer.js.map +1 -0
- package/lib/commonjs/debug/KokoRemoteSmoke.js +611 -0
- package/lib/commonjs/debug/KokoRemoteSmoke.js.map +1 -0
- package/lib/commonjs/explore/ExplorationGraph.js +418 -0
- package/lib/commonjs/explore/ExplorationGraph.js.map +1 -0
- package/lib/commonjs/explore/bootstrapExplore.js +59 -0
- package/lib/commonjs/explore/bootstrapExplore.js.map +1 -0
- package/lib/commonjs/host/HostActions.js +266 -0
- package/lib/commonjs/host/HostActions.js.map +1 -0
- package/lib/commonjs/i18n/index.js +169 -0
- package/lib/commonjs/i18n/index.js.map +1 -0
- package/lib/commonjs/i18n/runtimeMessages.js +184 -0
- package/lib/commonjs/i18n/runtimeMessages.js.map +1 -0
- package/lib/commonjs/index.js +640 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/native/NativeBridge.js +132 -0
- package/lib/commonjs/native/NativeBridge.js.map +1 -0
- package/lib/commonjs/native/navigationLabel.js +16 -0
- package/lib/commonjs/native/navigationLabel.js.map +1 -0
- package/lib/commonjs/native/normalizeViewTree.js +28 -0
- package/lib/commonjs/native/normalizeViewTree.js.map +1 -0
- package/lib/commonjs/native/pruneOffscreen.js +76 -0
- package/lib/commonjs/native/pruneOffscreen.js.map +1 -0
- package/lib/commonjs/native/scrollViewport.js +69 -0
- package/lib/commonjs/native/scrollViewport.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/privacy/redact.js +108 -0
- package/lib/commonjs/privacy/redact.js.map +1 -0
- package/lib/commonjs/privacy/screenEvidence.js +59 -0
- package/lib/commonjs/privacy/screenEvidence.js.map +1 -0
- package/lib/commonjs/privacy/screenModel.js +404 -0
- package/lib/commonjs/privacy/screenModel.js.map +1 -0
- package/lib/commonjs/privacy/sensitiveScreen.js +58 -0
- package/lib/commonjs/privacy/sensitiveScreen.js.map +1 -0
- package/lib/commonjs/privacy/userGate.js +213 -0
- package/lib/commonjs/privacy/userGate.js.map +1 -0
- package/lib/commonjs/protocol/actions.js +112 -0
- package/lib/commonjs/protocol/actions.js.map +1 -0
- package/lib/commonjs/provider/HostAppearanceStore.js +111 -0
- package/lib/commonjs/provider/HostAppearanceStore.js.map +1 -0
- package/lib/commonjs/provider/KokoProvider.js +81 -0
- package/lib/commonjs/provider/KokoProvider.js.map +1 -0
- package/lib/commonjs/provider/KokoUiContext.js +102 -0
- package/lib/commonjs/provider/KokoUiContext.js.map +1 -0
- package/lib/commonjs/selector/match.js +378 -0
- package/lib/commonjs/selector/match.js.map +1 -0
- package/lib/commonjs/task/TaskStore.js +361 -0
- package/lib/commonjs/task/TaskStore.js.map +1 -0
- package/lib/commonjs/task/types.js +2 -0
- package/lib/commonjs/task/types.js.map +1 -0
- package/lib/commonjs/task/useTaskStore.js +14 -0
- package/lib/commonjs/task/useTaskStore.js.map +1 -0
- package/lib/commonjs/types.js +2 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/ui/KokoChatSheet.js +885 -0
- package/lib/commonjs/ui/KokoChatSheet.js.map +1 -0
- package/lib/commonjs/ui/KokoComposer.js +161 -0
- package/lib/commonjs/ui/KokoComposer.js.map +1 -0
- package/lib/commonjs/ui/KokoDialogHost.js +254 -0
- package/lib/commonjs/ui/KokoDialogHost.js.map +1 -0
- package/lib/commonjs/ui/KokoEntryButton.js +81 -0
- package/lib/commonjs/ui/KokoEntryButton.js.map +1 -0
- package/lib/commonjs/ui/KokoObserver.js +522 -0
- package/lib/commonjs/ui/KokoObserver.js.map +1 -0
- package/lib/commonjs/ui/KokoOverlayLayer.js +45 -0
- package/lib/commonjs/ui/KokoOverlayLayer.js.map +1 -0
- package/lib/commonjs/ui/KokoSubtitle.js +95 -0
- package/lib/commonjs/ui/KokoSubtitle.js.map +1 -0
- package/lib/commonjs/ui/KokoTaskPanel.js +322 -0
- package/lib/commonjs/ui/KokoTaskPanel.js.map +1 -0
- package/lib/commonjs/ui/hostOverlay.js +126 -0
- package/lib/commonjs/ui/hostOverlay.js.map +1 -0
- package/lib/commonjs/ui/icons.js +132 -0
- package/lib/commonjs/ui/icons.js.map +1 -0
- package/lib/commonjs/ui/progressChrome.js +66 -0
- package/lib/commonjs/ui/progressChrome.js.map +1 -0
- package/lib/commonjs/ui/safeArea.js +96 -0
- package/lib/commonjs/ui/safeArea.js.map +1 -0
- package/lib/commonjs/ui/useOverlayOrigin.js +40 -0
- package/lib/commonjs/ui/useOverlayOrigin.js.map +1 -0
- package/lib/module/KokoAgent.js +1418 -0
- package/lib/module/KokoAgent.js.map +1 -0
- package/lib/module/assist/OnDeviceAssist.js +89 -0
- package/lib/module/assist/OnDeviceAssist.js.map +1 -0
- package/lib/module/assist/intentClassify.js +95 -0
- package/lib/module/assist/intentClassify.js.map +1 -0
- package/lib/module/assist/nodeRank.js +115 -0
- package/lib/module/assist/nodeRank.js.map +1 -0
- package/lib/module/assist/ocrTarget.js +123 -0
- package/lib/module/assist/ocrTarget.js.map +1 -0
- package/lib/module/assist/webVisualChange.js +24 -0
- package/lib/module/assist/webVisualChange.js.map +1 -0
- package/lib/module/client/ActionOutcomeUnknownError.js +23 -0
- package/lib/module/client/ActionOutcomeUnknownError.js.map +1 -0
- package/lib/module/client/AgentSession.js +854 -0
- package/lib/module/client/AgentSession.js.map +1 -0
- package/lib/module/client/GatewayClient.js +293 -0
- package/lib/module/client/GatewayClient.js.map +1 -0
- package/lib/module/client/OperationReplayGuard.js +58 -0
- package/lib/module/client/OperationReplayGuard.js.map +1 -0
- package/lib/module/client/RunCheckpoint.js +135 -0
- package/lib/module/client/RunCheckpoint.js.map +1 -0
- package/lib/module/client/loopDetect.js +177 -0
- package/lib/module/client/loopDetect.js.map +1 -0
- package/lib/module/client/recentSearch.js +46 -0
- package/lib/module/client/recentSearch.js.map +1 -0
- package/lib/module/client/walletChoiceGuard.js +14 -0
- package/lib/module/client/walletChoiceGuard.js.map +1 -0
- package/lib/module/client/webResultCategory.js +34 -0
- package/lib/module/client/webResultCategory.js.map +1 -0
- package/lib/module/commercial/AccountStore.js +75 -0
- package/lib/module/commercial/AccountStore.js.map +1 -0
- package/lib/module/commercial/AgentDebug.js +99 -0
- package/lib/module/commercial/AgentDebug.js.map +1 -0
- package/lib/module/commercial/ExecutionGuard.js +49 -0
- package/lib/module/commercial/ExecutionGuard.js.map +1 -0
- package/lib/module/commercial/UsageBus.js +38 -0
- package/lib/module/commercial/UsageBus.js.map +1 -0
- package/lib/module/commercial/branding.js +63 -0
- package/lib/module/commercial/branding.js.map +1 -0
- package/lib/module/commercial/devMode.js +45 -0
- package/lib/module/commercial/devMode.js.map +1 -0
- package/lib/module/commercial/trust.js +62 -0
- package/lib/module/commercial/trust.js.map +1 -0
- package/lib/module/confirmation/gate.js +54 -0
- package/lib/module/confirmation/gate.js.map +1 -0
- package/lib/module/cursor/CursorOverlay.js +136 -0
- package/lib/module/cursor/CursorOverlay.js.map +1 -0
- package/lib/module/cursor/PointerHand.js +47 -0
- package/lib/module/cursor/PointerHand.js.map +1 -0
- package/lib/module/cursor/controller.js +87 -0
- package/lib/module/cursor/controller.js.map +1 -0
- package/lib/module/cursor/pointer.js +45 -0
- package/lib/module/cursor/pointer.js.map +1 -0
- package/lib/module/debug/KokoRemoteSmoke.js +608 -0
- package/lib/module/debug/KokoRemoteSmoke.js.map +1 -0
- package/lib/module/explore/ExplorationGraph.js +406 -0
- package/lib/module/explore/ExplorationGraph.js.map +1 -0
- package/lib/module/explore/bootstrapExplore.js +55 -0
- package/lib/module/explore/bootstrapExplore.js.map +1 -0
- package/lib/module/host/HostActions.js +255 -0
- package/lib/module/host/HostActions.js.map +1 -0
- package/lib/module/i18n/index.js +159 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/i18n/runtimeMessages.js +180 -0
- package/lib/module/i18n/runtimeMessages.js.map +1 -0
- package/lib/module/index.js +44 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/native/NativeBridge.js +128 -0
- package/lib/module/native/NativeBridge.js.map +1 -0
- package/lib/module/native/navigationLabel.js +12 -0
- package/lib/module/native/navigationLabel.js.map +1 -0
- package/lib/module/native/normalizeViewTree.js +25 -0
- package/lib/module/native/normalizeViewTree.js.map +1 -0
- package/lib/module/native/pruneOffscreen.js +72 -0
- package/lib/module/native/pruneOffscreen.js.map +1 -0
- package/lib/module/native/scrollViewport.js +63 -0
- package/lib/module/native/scrollViewport.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/privacy/redact.js +103 -0
- package/lib/module/privacy/redact.js.map +1 -0
- package/lib/module/privacy/screenEvidence.js +50 -0
- package/lib/module/privacy/screenEvidence.js.map +1 -0
- package/lib/module/privacy/screenModel.js +397 -0
- package/lib/module/privacy/screenModel.js.map +1 -0
- package/lib/module/privacy/sensitiveScreen.js +52 -0
- package/lib/module/privacy/sensitiveScreen.js.map +1 -0
- package/lib/module/privacy/userGate.js +202 -0
- package/lib/module/privacy/userGate.js.map +1 -0
- package/lib/module/protocol/actions.js +108 -0
- package/lib/module/protocol/actions.js.map +1 -0
- package/lib/module/provider/HostAppearanceStore.js +101 -0
- package/lib/module/provider/HostAppearanceStore.js.map +1 -0
- package/lib/module/provider/KokoProvider.js +74 -0
- package/lib/module/provider/KokoProvider.js.map +1 -0
- package/lib/module/provider/KokoUiContext.js +96 -0
- package/lib/module/provider/KokoUiContext.js.map +1 -0
- package/lib/module/selector/match.js +366 -0
- package/lib/module/selector/match.js.map +1 -0
- package/lib/module/task/TaskStore.js +356 -0
- package/lib/module/task/TaskStore.js.map +1 -0
- package/lib/module/task/types.js +2 -0
- package/lib/module/task/types.js.map +1 -0
- package/lib/module/task/useTaskStore.js +10 -0
- package/lib/module/task/useTaskStore.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/ui/KokoChatSheet.js +879 -0
- package/lib/module/ui/KokoChatSheet.js.map +1 -0
- package/lib/module/ui/KokoComposer.js +155 -0
- package/lib/module/ui/KokoComposer.js.map +1 -0
- package/lib/module/ui/KokoDialogHost.js +247 -0
- package/lib/module/ui/KokoDialogHost.js.map +1 -0
- package/lib/module/ui/KokoEntryButton.js +74 -0
- package/lib/module/ui/KokoEntryButton.js.map +1 -0
- package/lib/module/ui/KokoObserver.js +516 -0
- package/lib/module/ui/KokoObserver.js.map +1 -0
- package/lib/module/ui/KokoOverlayLayer.js +39 -0
- package/lib/module/ui/KokoOverlayLayer.js.map +1 -0
- package/lib/module/ui/KokoSubtitle.js +90 -0
- package/lib/module/ui/KokoSubtitle.js.map +1 -0
- package/lib/module/ui/KokoTaskPanel.js +316 -0
- package/lib/module/ui/KokoTaskPanel.js.map +1 -0
- package/lib/module/ui/hostOverlay.js +120 -0
- package/lib/module/ui/hostOverlay.js.map +1 -0
- package/lib/module/ui/icons.js +124 -0
- package/lib/module/ui/icons.js.map +1 -0
- package/lib/module/ui/progressChrome.js +58 -0
- package/lib/module/ui/progressChrome.js.map +1 -0
- package/lib/module/ui/safeArea.js +92 -0
- package/lib/module/ui/safeArea.js.map +1 -0
- package/lib/module/ui/useOverlayOrigin.js +36 -0
- package/lib/module/ui/useOverlayOrigin.js.map +1 -0
- package/lib/typescript/commonjs/KokoAgent.d.ts +167 -0
- package/lib/typescript/commonjs/KokoAgent.d.ts.map +1 -0
- package/lib/typescript/commonjs/assist/OnDeviceAssist.d.ts +31 -0
- package/lib/typescript/commonjs/assist/OnDeviceAssist.d.ts.map +1 -0
- package/lib/typescript/commonjs/assist/intentClassify.d.ts +18 -0
- package/lib/typescript/commonjs/assist/intentClassify.d.ts.map +1 -0
- package/lib/typescript/commonjs/assist/nodeRank.d.ts +32 -0
- package/lib/typescript/commonjs/assist/nodeRank.d.ts.map +1 -0
- package/lib/typescript/commonjs/assist/ocrTarget.d.ts +25 -0
- package/lib/typescript/commonjs/assist/ocrTarget.d.ts.map +1 -0
- package/lib/typescript/commonjs/assist/webVisualChange.d.ts +6 -0
- package/lib/typescript/commonjs/assist/webVisualChange.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/ActionOutcomeUnknownError.d.ts +13 -0
- package/lib/typescript/commonjs/client/ActionOutcomeUnknownError.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/AgentSession.d.ts +56 -0
- package/lib/typescript/commonjs/client/AgentSession.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/GatewayClient.d.ts +149 -0
- package/lib/typescript/commonjs/client/GatewayClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/OperationReplayGuard.d.ts +13 -0
- package/lib/typescript/commonjs/client/OperationReplayGuard.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/RunCheckpoint.d.ts +57 -0
- package/lib/typescript/commonjs/client/RunCheckpoint.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/loopDetect.d.ts +15 -0
- package/lib/typescript/commonjs/client/loopDetect.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/recentSearch.d.ts +5 -0
- package/lib/typescript/commonjs/client/recentSearch.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/walletChoiceGuard.d.ts +4 -0
- package/lib/typescript/commonjs/client/walletChoiceGuard.d.ts.map +1 -0
- package/lib/typescript/commonjs/client/webResultCategory.d.ts +5 -0
- package/lib/typescript/commonjs/client/webResultCategory.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/AccountStore.d.ts +17 -0
- package/lib/typescript/commonjs/commercial/AccountStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/AgentDebug.d.ts +25 -0
- package/lib/typescript/commonjs/commercial/AgentDebug.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/ExecutionGuard.d.ts +18 -0
- package/lib/typescript/commonjs/commercial/ExecutionGuard.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/UsageBus.d.ts +18 -0
- package/lib/typescript/commonjs/commercial/UsageBus.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/branding.d.ts +25 -0
- package/lib/typescript/commonjs/commercial/branding.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/devMode.d.ts +26 -0
- package/lib/typescript/commonjs/commercial/devMode.d.ts.map +1 -0
- package/lib/typescript/commonjs/commercial/trust.d.ts +21 -0
- package/lib/typescript/commonjs/commercial/trust.d.ts.map +1 -0
- package/lib/typescript/commonjs/confirmation/gate.d.ts +18 -0
- package/lib/typescript/commonjs/confirmation/gate.d.ts.map +1 -0
- package/lib/typescript/commonjs/cursor/CursorOverlay.d.ts +13 -0
- package/lib/typescript/commonjs/cursor/CursorOverlay.d.ts.map +1 -0
- package/lib/typescript/commonjs/cursor/PointerHand.d.ts +16 -0
- package/lib/typescript/commonjs/cursor/PointerHand.d.ts.map +1 -0
- package/lib/typescript/commonjs/cursor/controller.d.ts +30 -0
- package/lib/typescript/commonjs/cursor/controller.d.ts.map +1 -0
- package/lib/typescript/commonjs/cursor/pointer.d.ts +23 -0
- package/lib/typescript/commonjs/cursor/pointer.d.ts.map +1 -0
- package/lib/typescript/commonjs/debug/KokoRemoteSmoke.d.ts +96 -0
- package/lib/typescript/commonjs/debug/KokoRemoteSmoke.d.ts.map +1 -0
- package/lib/typescript/commonjs/explore/ExplorationGraph.d.ts +96 -0
- package/lib/typescript/commonjs/explore/ExplorationGraph.d.ts.map +1 -0
- package/lib/typescript/commonjs/explore/bootstrapExplore.d.ts +40 -0
- package/lib/typescript/commonjs/explore/bootstrapExplore.d.ts.map +1 -0
- package/lib/typescript/commonjs/host/HostActions.d.ts +101 -0
- package/lib/typescript/commonjs/host/HostActions.d.ts.map +1 -0
- package/lib/typescript/commonjs/i18n/index.d.ts +20 -0
- package/lib/typescript/commonjs/i18n/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/i18n/runtimeMessages.d.ts +178 -0
- package/lib/typescript/commonjs/i18n/runtimeMessages.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +66 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/native/NativeBridge.d.ts +70 -0
- package/lib/typescript/commonjs/native/NativeBridge.d.ts.map +1 -0
- package/lib/typescript/commonjs/native/navigationLabel.d.ts +4 -0
- package/lib/typescript/commonjs/native/navigationLabel.d.ts.map +1 -0
- package/lib/typescript/commonjs/native/normalizeViewTree.d.ts +4 -0
- package/lib/typescript/commonjs/native/normalizeViewTree.d.ts.map +1 -0
- package/lib/typescript/commonjs/native/pruneOffscreen.d.ts +3 -0
- package/lib/typescript/commonjs/native/pruneOffscreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/native/scrollViewport.d.ts +13 -0
- package/lib/typescript/commonjs/native/scrollViewport.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/privacy/redact.d.ts +9 -0
- package/lib/typescript/commonjs/privacy/redact.d.ts.map +1 -0
- package/lib/typescript/commonjs/privacy/screenEvidence.d.ts +14 -0
- package/lib/typescript/commonjs/privacy/screenEvidence.d.ts.map +1 -0
- package/lib/typescript/commonjs/privacy/screenModel.d.ts +26 -0
- package/lib/typescript/commonjs/privacy/screenModel.d.ts.map +1 -0
- package/lib/typescript/commonjs/privacy/sensitiveScreen.d.ts +8 -0
- package/lib/typescript/commonjs/privacy/sensitiveScreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/privacy/userGate.d.ts +58 -0
- package/lib/typescript/commonjs/privacy/userGate.d.ts.map +1 -0
- package/lib/typescript/commonjs/protocol/actions.d.ts +7 -0
- package/lib/typescript/commonjs/protocol/actions.d.ts.map +1 -0
- package/lib/typescript/commonjs/provider/HostAppearanceStore.d.ts +64 -0
- package/lib/typescript/commonjs/provider/HostAppearanceStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/provider/KokoProvider.d.ts +39 -0
- package/lib/typescript/commonjs/provider/KokoProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/provider/KokoUiContext.d.ts +22 -0
- package/lib/typescript/commonjs/provider/KokoUiContext.d.ts.map +1 -0
- package/lib/typescript/commonjs/selector/match.d.ts +27 -0
- package/lib/typescript/commonjs/selector/match.d.ts.map +1 -0
- package/lib/typescript/commonjs/task/TaskStore.d.ts +65 -0
- package/lib/typescript/commonjs/task/TaskStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/task/types.d.ts +66 -0
- package/lib/typescript/commonjs/task/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/task/useTaskStore.d.ts +3 -0
- package/lib/typescript/commonjs/task/useTaskStore.d.ts.map +1 -0
- package/lib/typescript/commonjs/types.d.ts +372 -0
- package/lib/typescript/commonjs/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoChatSheet.d.ts +8 -0
- package/lib/typescript/commonjs/ui/KokoChatSheet.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoComposer.d.ts +13 -0
- package/lib/typescript/commonjs/ui/KokoComposer.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoDialogHost.d.ts +32 -0
- package/lib/typescript/commonjs/ui/KokoDialogHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoEntryButton.d.ts +18 -0
- package/lib/typescript/commonjs/ui/KokoEntryButton.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoObserver.d.ts +13 -0
- package/lib/typescript/commonjs/ui/KokoObserver.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoOverlayLayer.d.ts +35 -0
- package/lib/typescript/commonjs/ui/KokoOverlayLayer.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoSubtitle.d.ts +7 -0
- package/lib/typescript/commonjs/ui/KokoSubtitle.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/KokoTaskPanel.d.ts +7 -0
- package/lib/typescript/commonjs/ui/KokoTaskPanel.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hostOverlay.d.ts +28 -0
- package/lib/typescript/commonjs/ui/hostOverlay.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/icons.d.ts +26 -0
- package/lib/typescript/commonjs/ui/icons.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/progressChrome.d.ts +21 -0
- package/lib/typescript/commonjs/ui/progressChrome.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/safeArea.d.ts +12 -0
- package/lib/typescript/commonjs/ui/safeArea.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/useOverlayOrigin.d.ts +22 -0
- package/lib/typescript/commonjs/ui/useOverlayOrigin.d.ts.map +1 -0
- package/lib/typescript/module/KokoAgent.d.ts +167 -0
- package/lib/typescript/module/KokoAgent.d.ts.map +1 -0
- package/lib/typescript/module/assist/OnDeviceAssist.d.ts +31 -0
- package/lib/typescript/module/assist/OnDeviceAssist.d.ts.map +1 -0
- package/lib/typescript/module/assist/intentClassify.d.ts +18 -0
- package/lib/typescript/module/assist/intentClassify.d.ts.map +1 -0
- package/lib/typescript/module/assist/nodeRank.d.ts +32 -0
- package/lib/typescript/module/assist/nodeRank.d.ts.map +1 -0
- package/lib/typescript/module/assist/ocrTarget.d.ts +25 -0
- package/lib/typescript/module/assist/ocrTarget.d.ts.map +1 -0
- package/lib/typescript/module/assist/webVisualChange.d.ts +6 -0
- package/lib/typescript/module/assist/webVisualChange.d.ts.map +1 -0
- package/lib/typescript/module/client/ActionOutcomeUnknownError.d.ts +13 -0
- package/lib/typescript/module/client/ActionOutcomeUnknownError.d.ts.map +1 -0
- package/lib/typescript/module/client/AgentSession.d.ts +56 -0
- package/lib/typescript/module/client/AgentSession.d.ts.map +1 -0
- package/lib/typescript/module/client/GatewayClient.d.ts +149 -0
- package/lib/typescript/module/client/GatewayClient.d.ts.map +1 -0
- package/lib/typescript/module/client/OperationReplayGuard.d.ts +13 -0
- package/lib/typescript/module/client/OperationReplayGuard.d.ts.map +1 -0
- package/lib/typescript/module/client/RunCheckpoint.d.ts +57 -0
- package/lib/typescript/module/client/RunCheckpoint.d.ts.map +1 -0
- package/lib/typescript/module/client/loopDetect.d.ts +15 -0
- package/lib/typescript/module/client/loopDetect.d.ts.map +1 -0
- package/lib/typescript/module/client/recentSearch.d.ts +5 -0
- package/lib/typescript/module/client/recentSearch.d.ts.map +1 -0
- package/lib/typescript/module/client/walletChoiceGuard.d.ts +4 -0
- package/lib/typescript/module/client/walletChoiceGuard.d.ts.map +1 -0
- package/lib/typescript/module/client/webResultCategory.d.ts +5 -0
- package/lib/typescript/module/client/webResultCategory.d.ts.map +1 -0
- package/lib/typescript/module/commercial/AccountStore.d.ts +17 -0
- package/lib/typescript/module/commercial/AccountStore.d.ts.map +1 -0
- package/lib/typescript/module/commercial/AgentDebug.d.ts +25 -0
- package/lib/typescript/module/commercial/AgentDebug.d.ts.map +1 -0
- package/lib/typescript/module/commercial/ExecutionGuard.d.ts +18 -0
- package/lib/typescript/module/commercial/ExecutionGuard.d.ts.map +1 -0
- package/lib/typescript/module/commercial/UsageBus.d.ts +18 -0
- package/lib/typescript/module/commercial/UsageBus.d.ts.map +1 -0
- package/lib/typescript/module/commercial/branding.d.ts +25 -0
- package/lib/typescript/module/commercial/branding.d.ts.map +1 -0
- package/lib/typescript/module/commercial/devMode.d.ts +26 -0
- package/lib/typescript/module/commercial/devMode.d.ts.map +1 -0
- package/lib/typescript/module/commercial/trust.d.ts +21 -0
- package/lib/typescript/module/commercial/trust.d.ts.map +1 -0
- package/lib/typescript/module/confirmation/gate.d.ts +18 -0
- package/lib/typescript/module/confirmation/gate.d.ts.map +1 -0
- package/lib/typescript/module/cursor/CursorOverlay.d.ts +13 -0
- package/lib/typescript/module/cursor/CursorOverlay.d.ts.map +1 -0
- package/lib/typescript/module/cursor/PointerHand.d.ts +16 -0
- package/lib/typescript/module/cursor/PointerHand.d.ts.map +1 -0
- package/lib/typescript/module/cursor/controller.d.ts +30 -0
- package/lib/typescript/module/cursor/controller.d.ts.map +1 -0
- package/lib/typescript/module/cursor/pointer.d.ts +23 -0
- package/lib/typescript/module/cursor/pointer.d.ts.map +1 -0
- package/lib/typescript/module/debug/KokoRemoteSmoke.d.ts +96 -0
- package/lib/typescript/module/debug/KokoRemoteSmoke.d.ts.map +1 -0
- package/lib/typescript/module/explore/ExplorationGraph.d.ts +96 -0
- package/lib/typescript/module/explore/ExplorationGraph.d.ts.map +1 -0
- package/lib/typescript/module/explore/bootstrapExplore.d.ts +40 -0
- package/lib/typescript/module/explore/bootstrapExplore.d.ts.map +1 -0
- package/lib/typescript/module/host/HostActions.d.ts +101 -0
- package/lib/typescript/module/host/HostActions.d.ts.map +1 -0
- package/lib/typescript/module/i18n/index.d.ts +20 -0
- package/lib/typescript/module/i18n/index.d.ts.map +1 -0
- package/lib/typescript/module/i18n/runtimeMessages.d.ts +178 -0
- package/lib/typescript/module/i18n/runtimeMessages.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +66 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/native/NativeBridge.d.ts +70 -0
- package/lib/typescript/module/native/NativeBridge.d.ts.map +1 -0
- package/lib/typescript/module/native/navigationLabel.d.ts +4 -0
- package/lib/typescript/module/native/navigationLabel.d.ts.map +1 -0
- package/lib/typescript/module/native/normalizeViewTree.d.ts +4 -0
- package/lib/typescript/module/native/normalizeViewTree.d.ts.map +1 -0
- package/lib/typescript/module/native/pruneOffscreen.d.ts +3 -0
- package/lib/typescript/module/native/pruneOffscreen.d.ts.map +1 -0
- package/lib/typescript/module/native/scrollViewport.d.ts +13 -0
- package/lib/typescript/module/native/scrollViewport.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/privacy/redact.d.ts +9 -0
- package/lib/typescript/module/privacy/redact.d.ts.map +1 -0
- package/lib/typescript/module/privacy/screenEvidence.d.ts +14 -0
- package/lib/typescript/module/privacy/screenEvidence.d.ts.map +1 -0
- package/lib/typescript/module/privacy/screenModel.d.ts +26 -0
- package/lib/typescript/module/privacy/screenModel.d.ts.map +1 -0
- package/lib/typescript/module/privacy/sensitiveScreen.d.ts +8 -0
- package/lib/typescript/module/privacy/sensitiveScreen.d.ts.map +1 -0
- package/lib/typescript/module/privacy/userGate.d.ts +58 -0
- package/lib/typescript/module/privacy/userGate.d.ts.map +1 -0
- package/lib/typescript/module/protocol/actions.d.ts +7 -0
- package/lib/typescript/module/protocol/actions.d.ts.map +1 -0
- package/lib/typescript/module/provider/HostAppearanceStore.d.ts +64 -0
- package/lib/typescript/module/provider/HostAppearanceStore.d.ts.map +1 -0
- package/lib/typescript/module/provider/KokoProvider.d.ts +39 -0
- package/lib/typescript/module/provider/KokoProvider.d.ts.map +1 -0
- package/lib/typescript/module/provider/KokoUiContext.d.ts +22 -0
- package/lib/typescript/module/provider/KokoUiContext.d.ts.map +1 -0
- package/lib/typescript/module/selector/match.d.ts +27 -0
- package/lib/typescript/module/selector/match.d.ts.map +1 -0
- package/lib/typescript/module/task/TaskStore.d.ts +65 -0
- package/lib/typescript/module/task/TaskStore.d.ts.map +1 -0
- package/lib/typescript/module/task/types.d.ts +66 -0
- package/lib/typescript/module/task/types.d.ts.map +1 -0
- package/lib/typescript/module/task/useTaskStore.d.ts +3 -0
- package/lib/typescript/module/task/useTaskStore.d.ts.map +1 -0
- package/lib/typescript/module/types.d.ts +372 -0
- package/lib/typescript/module/types.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoChatSheet.d.ts +8 -0
- package/lib/typescript/module/ui/KokoChatSheet.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoComposer.d.ts +13 -0
- package/lib/typescript/module/ui/KokoComposer.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoDialogHost.d.ts +32 -0
- package/lib/typescript/module/ui/KokoDialogHost.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoEntryButton.d.ts +18 -0
- package/lib/typescript/module/ui/KokoEntryButton.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoObserver.d.ts +13 -0
- package/lib/typescript/module/ui/KokoObserver.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoOverlayLayer.d.ts +35 -0
- package/lib/typescript/module/ui/KokoOverlayLayer.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoSubtitle.d.ts +7 -0
- package/lib/typescript/module/ui/KokoSubtitle.d.ts.map +1 -0
- package/lib/typescript/module/ui/KokoTaskPanel.d.ts +7 -0
- package/lib/typescript/module/ui/KokoTaskPanel.d.ts.map +1 -0
- package/lib/typescript/module/ui/hostOverlay.d.ts +28 -0
- package/lib/typescript/module/ui/hostOverlay.d.ts.map +1 -0
- package/lib/typescript/module/ui/icons.d.ts +26 -0
- package/lib/typescript/module/ui/icons.d.ts.map +1 -0
- package/lib/typescript/module/ui/progressChrome.d.ts +21 -0
- package/lib/typescript/module/ui/progressChrome.d.ts.map +1 -0
- package/lib/typescript/module/ui/safeArea.d.ts +12 -0
- package/lib/typescript/module/ui/safeArea.d.ts.map +1 -0
- package/lib/typescript/module/ui/useOverlayOrigin.d.ts +22 -0
- package/lib/typescript/module/ui/useOverlayOrigin.d.ts.map +1 -0
- package/package.json +153 -0
- package/react-native.config.js +12 -0
- package/src/KokoAgent.ts +1415 -0
- package/src/assist/OnDeviceAssist.ts +133 -0
- package/src/assist/intentClassify.ts +122 -0
- package/src/assist/nodeRank.ts +167 -0
- package/src/assist/ocrTarget.ts +146 -0
- package/src/assist/webVisualChange.ts +24 -0
- package/src/client/ActionOutcomeUnknownError.ts +18 -0
- package/src/client/AgentSession.ts +952 -0
- package/src/client/GatewayClient.ts +439 -0
- package/src/client/OperationReplayGuard.ts +61 -0
- package/src/client/RunCheckpoint.ts +154 -0
- package/src/client/loopDetect.ts +213 -0
- package/src/client/recentSearch.ts +47 -0
- package/src/client/walletChoiceGuard.ts +15 -0
- package/src/client/webResultCategory.ts +28 -0
- package/src/commercial/AccountStore.ts +85 -0
- package/src/commercial/AgentDebug.ts +142 -0
- package/src/commercial/ExecutionGuard.ts +67 -0
- package/src/commercial/UsageBus.ts +44 -0
- package/src/commercial/branding.ts +97 -0
- package/src/commercial/devMode.ts +48 -0
- package/src/commercial/trust.ts +67 -0
- package/src/confirmation/gate.ts +82 -0
- package/src/cursor/CursorOverlay.tsx +138 -0
- package/src/cursor/PointerHand.tsx +49 -0
- package/src/cursor/controller.ts +98 -0
- package/src/cursor/pointer.ts +40 -0
- package/src/debug/KokoRemoteSmoke.tsx +561 -0
- package/src/explore/ExplorationGraph.ts +518 -0
- package/src/explore/bootstrapExplore.ts +89 -0
- package/src/host/HostActions.ts +349 -0
- package/src/i18n/index.ts +229 -0
- package/src/i18n/runtimeMessages.ts +180 -0
- package/src/index.ts +203 -0
- package/src/native/NativeBridge.ts +207 -0
- package/src/native/navigationLabel.ts +11 -0
- package/src/native/normalizeViewTree.ts +16 -0
- package/src/native/pruneOffscreen.ts +72 -0
- package/src/native/scrollViewport.ts +51 -0
- package/src/privacy/redact.ts +115 -0
- package/src/privacy/screenEvidence.ts +55 -0
- package/src/privacy/screenModel.ts +504 -0
- package/src/privacy/sensitiveScreen.ts +55 -0
- package/src/privacy/userGate.ts +233 -0
- package/src/protocol/actions.ts +66 -0
- package/src/provider/HostAppearanceStore.ts +148 -0
- package/src/provider/KokoProvider.tsx +118 -0
- package/src/provider/KokoUiContext.tsx +162 -0
- package/src/selector/match.ts +417 -0
- package/src/task/TaskStore.ts +387 -0
- package/src/task/types.ts +82 -0
- package/src/task/useTaskStore.ts +9 -0
- package/src/types.ts +318 -0
- package/src/ui/KokoChatSheet.tsx +930 -0
- package/src/ui/KokoComposer.tsx +174 -0
- package/src/ui/KokoDialogHost.tsx +249 -0
- package/src/ui/KokoEntryButton.tsx +74 -0
- package/src/ui/KokoObserver.tsx +587 -0
- package/src/ui/KokoOverlayLayer.tsx +53 -0
- package/src/ui/KokoSubtitle.tsx +80 -0
- package/src/ui/KokoTaskPanel.tsx +299 -0
- package/src/ui/hostOverlay.tsx +148 -0
- package/src/ui/icons.tsx +145 -0
- package/src/ui/progressChrome.ts +73 -0
- package/src/ui/safeArea.ts +95 -0
- package/src/ui/useOverlayOrigin.ts +29 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { ViewNode } from '../types';
|
|
2
|
+
import { NativeBridge } from '../native/NativeBridge';
|
|
3
|
+
import { sensitiveScreenKind } from '../privacy/sensitiveScreen';
|
|
4
|
+
import { classifyGoalIntent, type AssistIntent, type IntentResult } from './intentClassify';
|
|
5
|
+
import { verifiedGoalOcrLabels, verifiedWalletChoices } from './ocrTarget';
|
|
6
|
+
import {
|
|
7
|
+
assistHintsModelText,
|
|
8
|
+
rankNodesForGoal,
|
|
9
|
+
type RankedNode,
|
|
10
|
+
} from './nodeRank';
|
|
11
|
+
|
|
12
|
+
export type OnDeviceAssistResult = {
|
|
13
|
+
intent: AssistIntent;
|
|
14
|
+
confidence: number;
|
|
15
|
+
tokens: string[];
|
|
16
|
+
ocrTokens: string[];
|
|
17
|
+
/** Goal-derived labels verified against local OCR, never raw page text. */
|
|
18
|
+
goalOcrLabels?: string[];
|
|
19
|
+
/** Only allowlisted public wallet product names, verified locally. */
|
|
20
|
+
walletChoices?: string[];
|
|
21
|
+
ranked: RankedNode[];
|
|
22
|
+
/** Compact planner block (empty when nothing useful). */
|
|
23
|
+
modelText: string;
|
|
24
|
+
backend: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type BuildAssistOptions = {
|
|
28
|
+
/** Skip Vision OCR (tests / hosts without camera-style capture). Default false. */
|
|
29
|
+
skipOcr?: boolean;
|
|
30
|
+
/** Cap OCR tokens merged into ranking. */
|
|
31
|
+
maxOcrTokens?: number;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* On-device assist: JS intent + node rank, optional native OCR.
|
|
36
|
+
* Enriches the cloud planner `ui_screen_model` — does not replace the LLM.
|
|
37
|
+
*/
|
|
38
|
+
export async function buildOnDeviceAssist(
|
|
39
|
+
goal: string,
|
|
40
|
+
tree: ViewNode | null | undefined,
|
|
41
|
+
opts: BuildAssistOptions = {},
|
|
42
|
+
): Promise<OnDeviceAssistResult> {
|
|
43
|
+
const classified: IntentResult = classifyGoalIntent(goal);
|
|
44
|
+
if (sensitiveScreenKind(tree)) {
|
|
45
|
+
return { intent: classified.intent, confidence: classified.confidence,
|
|
46
|
+
tokens: [], ocrTokens: [], ranked: [], modelText: '', backend: 'local-private-screen' };
|
|
47
|
+
}
|
|
48
|
+
let ocrTokens: string[] = [];
|
|
49
|
+
let ocrTexts: Awaited<
|
|
50
|
+
ReturnType<typeof NativeBridge.recognizeScreenText>
|
|
51
|
+
>['texts'] = [];
|
|
52
|
+
let backend = 'js';
|
|
53
|
+
|
|
54
|
+
if (!opts.skipOcr && NativeBridge.isAvailable()) {
|
|
55
|
+
try {
|
|
56
|
+
const ocr = await NativeBridge.recognizeScreenText({
|
|
57
|
+
maxTokens: opts.maxOcrTokens ?? 24,
|
|
58
|
+
hideOverlays: true,
|
|
59
|
+
});
|
|
60
|
+
ocrTokens = (ocr.tokens || []).filter(Boolean).slice(0, opts.maxOcrTokens ?? 24);
|
|
61
|
+
ocrTexts = (ocr.texts || []).slice(0, 64);
|
|
62
|
+
if (ocr.backend) backend = `js+${ocr.backend}`;
|
|
63
|
+
} catch {
|
|
64
|
+
// Soft-fail: dump-only assist still helps the planner.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ranked = tree
|
|
69
|
+
? rankNodesForGoal(tree, {
|
|
70
|
+
intent: classified.intent,
|
|
71
|
+
tokens: classified.tokens,
|
|
72
|
+
ocrTokens,
|
|
73
|
+
limit: 8,
|
|
74
|
+
})
|
|
75
|
+
: [];
|
|
76
|
+
|
|
77
|
+
const modelText = assistHintsModelText(
|
|
78
|
+
classified.intent,
|
|
79
|
+
classified.confidence,
|
|
80
|
+
ranked,
|
|
81
|
+
ocrTokens,
|
|
82
|
+
backend,
|
|
83
|
+
ocrTexts,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
intent: classified.intent,
|
|
88
|
+
confidence: classified.confidence,
|
|
89
|
+
tokens: classified.tokens,
|
|
90
|
+
ocrTokens,
|
|
91
|
+
goalOcrLabels: verifiedGoalOcrLabels(goal, tree, ocrTexts),
|
|
92
|
+
walletChoices: verifiedWalletChoices(goal, tree, ocrTexts),
|
|
93
|
+
ranked,
|
|
94
|
+
modelText,
|
|
95
|
+
backend,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Sync path for unit tests / hosts that already have OCR tokens. */
|
|
100
|
+
export function buildOnDeviceAssistSync(
|
|
101
|
+
goal: string,
|
|
102
|
+
tree: ViewNode | null | undefined,
|
|
103
|
+
ocrTokens: string[] = [],
|
|
104
|
+
backend = 'js',
|
|
105
|
+
): OnDeviceAssistResult {
|
|
106
|
+
const classified = classifyGoalIntent(goal);
|
|
107
|
+
if (sensitiveScreenKind(tree)) return { intent: classified.intent,
|
|
108
|
+
confidence: classified.confidence, tokens: [], ocrTokens: [], ranked: [],
|
|
109
|
+
modelText: '', backend: 'local-private-screen' };
|
|
110
|
+
const ranked = tree
|
|
111
|
+
? rankNodesForGoal(tree, {
|
|
112
|
+
intent: classified.intent,
|
|
113
|
+
tokens: classified.tokens,
|
|
114
|
+
ocrTokens,
|
|
115
|
+
limit: 8,
|
|
116
|
+
})
|
|
117
|
+
: [];
|
|
118
|
+
return {
|
|
119
|
+
intent: classified.intent,
|
|
120
|
+
confidence: classified.confidence,
|
|
121
|
+
tokens: classified.tokens,
|
|
122
|
+
ocrTokens,
|
|
123
|
+
ranked,
|
|
124
|
+
modelText: assistHintsModelText(
|
|
125
|
+
classified.intent,
|
|
126
|
+
classified.confidence,
|
|
127
|
+
ranked,
|
|
128
|
+
ocrTokens,
|
|
129
|
+
backend,
|
|
130
|
+
),
|
|
131
|
+
backend,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-device goal intent classification (structural, host-agnostic).
|
|
3
|
+
* Complements Core ML / Vision OCR — no package IDs or product copy.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type AssistIntent =
|
|
7
|
+
| 'tap'
|
|
8
|
+
| 'type'
|
|
9
|
+
| 'scroll'
|
|
10
|
+
| 'back'
|
|
11
|
+
| 'search'
|
|
12
|
+
| 'settings'
|
|
13
|
+
| 'unknown';
|
|
14
|
+
|
|
15
|
+
export type IntentResult = {
|
|
16
|
+
intent: AssistIntent;
|
|
17
|
+
confidence: number;
|
|
18
|
+
/** Tokens useful for node ranking (from the goal itself). */
|
|
19
|
+
tokens: string[];
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const STOP = new Set(
|
|
23
|
+
[
|
|
24
|
+
'打开',
|
|
25
|
+
'进入',
|
|
26
|
+
'点击',
|
|
27
|
+
'点选',
|
|
28
|
+
'按下',
|
|
29
|
+
'点',
|
|
30
|
+
'一下',
|
|
31
|
+
'这个',
|
|
32
|
+
'那个',
|
|
33
|
+
'按钮',
|
|
34
|
+
'去',
|
|
35
|
+
'到',
|
|
36
|
+
'把',
|
|
37
|
+
'将',
|
|
38
|
+
'请',
|
|
39
|
+
'帮我',
|
|
40
|
+
'我想',
|
|
41
|
+
'the',
|
|
42
|
+
'a',
|
|
43
|
+
'an',
|
|
44
|
+
'to',
|
|
45
|
+
'open',
|
|
46
|
+
'tap',
|
|
47
|
+
'click',
|
|
48
|
+
'press',
|
|
49
|
+
'go',
|
|
50
|
+
].map((s) => s.toLowerCase()),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
/** Extract short goal tokens for ranking (CJK chunks + latin words). */
|
|
54
|
+
export function goalTokens(goal: string): string[] {
|
|
55
|
+
const raw = String(goal || '').trim();
|
|
56
|
+
if (!raw) return [];
|
|
57
|
+
const out: string[] = [];
|
|
58
|
+
const latin = raw.match(/[A-Za-z0-9_]{2,}/g) || [];
|
|
59
|
+
for (const w of latin) {
|
|
60
|
+
const n = w.toLowerCase();
|
|
61
|
+
if (!STOP.has(n)) out.push(n);
|
|
62
|
+
}
|
|
63
|
+
// CJK runs of 2–8 chars
|
|
64
|
+
const cjk = raw.match(/[\u4e00-\u9fff]{2,8}/g) || [];
|
|
65
|
+
for (const w of cjk) {
|
|
66
|
+
if (!STOP.has(w)) out.push(w);
|
|
67
|
+
}
|
|
68
|
+
return [...new Set(out)].slice(0, 12);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Cheap on-device intent — runs everywhere (JS). iOS Vision OCR enriches tokens separately.
|
|
73
|
+
*/
|
|
74
|
+
export function classifyGoalIntent(goal: string): IntentResult {
|
|
75
|
+
const g = String(goal || '').trim();
|
|
76
|
+
const tokens = goalTokens(g);
|
|
77
|
+
if (!g) return { intent: 'unknown', confidence: 0, tokens };
|
|
78
|
+
|
|
79
|
+
if (
|
|
80
|
+
/返回|后退|回去|关闭弹窗|关掉|dismiss|go\s*back|close\s*(this|dialog|sheet)?/i.test(
|
|
81
|
+
g,
|
|
82
|
+
)
|
|
83
|
+
) {
|
|
84
|
+
return { intent: 'back', confidence: 0.85, tokens };
|
|
85
|
+
}
|
|
86
|
+
if (
|
|
87
|
+
/搜索|查找|搜一下|search|find\s+(for|the)|query/i.test(g) &&
|
|
88
|
+
!/打开搜索|进入搜索设置/i.test(g)
|
|
89
|
+
) {
|
|
90
|
+
return { intent: 'search', confidence: 0.8, tokens };
|
|
91
|
+
}
|
|
92
|
+
if (
|
|
93
|
+
/输入|填写|键入|打字|type|enter\s+text|fill\s+in|写入/i.test(g) ||
|
|
94
|
+
/输入[「"'].+[」"']/.test(g)
|
|
95
|
+
) {
|
|
96
|
+
return { intent: 'type', confidence: 0.82, tokens };
|
|
97
|
+
}
|
|
98
|
+
if (
|
|
99
|
+
/设置|設定|偏好|语言|語言|主题|外观|locale|language|theme|settings|preferences/i.test(
|
|
100
|
+
g,
|
|
101
|
+
)
|
|
102
|
+
) {
|
|
103
|
+
return { intent: 'settings', confidence: 0.78, tokens };
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
/滚动|下滑|上滑|滑到底|翻页|scroll|swipe\s*(up|down)|下一屏/i.test(g)
|
|
107
|
+
) {
|
|
108
|
+
return { intent: 'scroll', confidence: 0.8, tokens };
|
|
109
|
+
}
|
|
110
|
+
if (
|
|
111
|
+
/点击|点选|按下|点一下|打开|进入|切换|选择|确认|提交|tap|click|press|open|select|confirm/i.test(
|
|
112
|
+
g,
|
|
113
|
+
)
|
|
114
|
+
) {
|
|
115
|
+
return { intent: 'tap', confidence: 0.75, tokens };
|
|
116
|
+
}
|
|
117
|
+
// Bare label goals → tap
|
|
118
|
+
if (tokens.length >= 1 && g.length <= 24) {
|
|
119
|
+
return { intent: 'tap', confidence: 0.55, tokens };
|
|
120
|
+
}
|
|
121
|
+
return { intent: 'unknown', confidence: 0.3, tokens };
|
|
122
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { ViewNode } from '../types';
|
|
2
|
+
import { flattenTree } from '../selector/match';
|
|
3
|
+
import type { AssistIntent } from './intentClassify';
|
|
4
|
+
|
|
5
|
+
export type RankedNode = {
|
|
6
|
+
id: string;
|
|
7
|
+
label: string;
|
|
8
|
+
score: number;
|
|
9
|
+
clickable: boolean;
|
|
10
|
+
kindHint: 'button' | 'field' | 'scroll' | 'other';
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type OcrTextHit = {
|
|
14
|
+
text: string;
|
|
15
|
+
confidence: number;
|
|
16
|
+
frame?: { x: number; y: number; width: number; height: number };
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function nodeLabel(n: ViewNode): string {
|
|
20
|
+
return (n.text || n.accessibilityLabel || n.testID || '').trim();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function kindHint(n: ViewNode, intent: AssistIntent): RankedNode['kindHint'] {
|
|
24
|
+
const t = `${n.type || ''} ${nodeLabel(n)}`.toLowerCase();
|
|
25
|
+
if (
|
|
26
|
+
/textinput|textfield|edittext|searchbar|uitextfield|rcttextfield/i.test(t) ||
|
|
27
|
+
intent === 'type' ||
|
|
28
|
+
intent === 'search'
|
|
29
|
+
) {
|
|
30
|
+
if (/textinput|textfield|edittext|search/i.test(t)) return 'field';
|
|
31
|
+
}
|
|
32
|
+
if (/scroll|list|flatlist|collection|table/i.test(t)) return 'scroll';
|
|
33
|
+
if (n.clickable || /button|touchable|pressable/i.test(t)) return 'button';
|
|
34
|
+
return 'other';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function tokenHit(label: string, tokens: string[]): number {
|
|
38
|
+
if (!label || !tokens.length) return 0;
|
|
39
|
+
const soft = label.toLowerCase().replace(/\s+/g, '');
|
|
40
|
+
let best = 0;
|
|
41
|
+
for (const tok of tokens) {
|
|
42
|
+
const t = tok.toLowerCase().replace(/\s+/g, '');
|
|
43
|
+
if (!t) continue;
|
|
44
|
+
if (soft === t) best = Math.max(best, 1);
|
|
45
|
+
else if (soft.includes(t) && t.length >= 2) {
|
|
46
|
+
best = Math.max(best, 0.55 + 0.35 * (t.length / Math.max(soft.length, 1)));
|
|
47
|
+
} else if (t.includes(soft) && soft.length >= 2) {
|
|
48
|
+
best = Math.max(best, 0.4 + 0.3 * (soft.length / t.length));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return Math.min(1, best);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Rank dump nodes for an on-device assist pass (goal tokens + OCR tokens + intent).
|
|
56
|
+
*/
|
|
57
|
+
export function rankNodesForGoal(
|
|
58
|
+
tree: ViewNode,
|
|
59
|
+
opts: {
|
|
60
|
+
intent: AssistIntent;
|
|
61
|
+
tokens: string[];
|
|
62
|
+
/** Extra tokens from Vision OCR (iOS). */
|
|
63
|
+
ocrTokens?: string[];
|
|
64
|
+
limit?: number;
|
|
65
|
+
},
|
|
66
|
+
): RankedNode[] {
|
|
67
|
+
const limit = opts.limit ?? 8;
|
|
68
|
+
const goalTok = [...new Set((opts.tokens || []).filter(Boolean))];
|
|
69
|
+
// OCR is supportive only — do not let whole-screen OCR drown the goal.
|
|
70
|
+
const ocrTok = [...new Set((opts.ocrTokens || []).filter(Boolean))].filter(
|
|
71
|
+
(t) => !goalTok.some((g) => g.toLowerCase() === t.toLowerCase()),
|
|
72
|
+
);
|
|
73
|
+
const flat = flattenTree(tree);
|
|
74
|
+
const scored: RankedNode[] = [];
|
|
75
|
+
|
|
76
|
+
for (const n of flat) {
|
|
77
|
+
if (!n.visible) continue;
|
|
78
|
+
const label = nodeLabel(n);
|
|
79
|
+
if (!label && !n.clickable) continue;
|
|
80
|
+
const goalHit = tokenHit(label || n.testID || '', goalTok);
|
|
81
|
+
const ocrHit = tokenHit(label || n.testID || '', ocrTok);
|
|
82
|
+
// Goal match dominates; OCR contributes at most ~0.35.
|
|
83
|
+
const hit = Math.max(goalHit, ocrHit * 0.35);
|
|
84
|
+
if (hit <= 0 && !(opts.intent === 'scroll' && /scroll|list/i.test(n.type))) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
let score = hit;
|
|
88
|
+
const kind = kindHint(n, opts.intent);
|
|
89
|
+
if (goalHit > 0) score += 0.08; // explicit goal evidence
|
|
90
|
+
if (n.clickable) score += 0.18;
|
|
91
|
+
else score -= 0.12; // non-clickable text nodes rarely the action target
|
|
92
|
+
if (n.enabled === false) score -= 0.25;
|
|
93
|
+
if (opts.intent === 'tap' || opts.intent === 'search' || opts.intent === 'settings') {
|
|
94
|
+
if (kind === 'button') score += 0.08;
|
|
95
|
+
}
|
|
96
|
+
if (opts.intent === 'type' || opts.intent === 'search') {
|
|
97
|
+
if (kind === 'field') score += 0.15;
|
|
98
|
+
}
|
|
99
|
+
if (opts.intent === 'scroll' && kind === 'scroll') score += 0.2;
|
|
100
|
+
// Prefer mid-screen affordances slightly (not status-bar chrome).
|
|
101
|
+
const cy = n.frame.y + n.frame.height / 2;
|
|
102
|
+
if (cy > 40 && cy < 900) score += 0.03;
|
|
103
|
+
scored.push({
|
|
104
|
+
id: n.id,
|
|
105
|
+
label: label || n.testID || n.type,
|
|
106
|
+
score: Math.min(1, score),
|
|
107
|
+
clickable: !!n.clickable,
|
|
108
|
+
kindHint: kind,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
scored.sort((a, b) => b.score - a.score);
|
|
113
|
+
// Dedupe by label keeping best score
|
|
114
|
+
const seen = new Set<string>();
|
|
115
|
+
const out: RankedNode[] = [];
|
|
116
|
+
for (const r of scored) {
|
|
117
|
+
const key = r.label.toLowerCase();
|
|
118
|
+
if (seen.has(key)) continue;
|
|
119
|
+
seen.add(key);
|
|
120
|
+
out.push(r);
|
|
121
|
+
if (out.length >= limit) break;
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Compact block for the cloud planner screen model. */
|
|
127
|
+
export function assistHintsModelText(
|
|
128
|
+
intent: AssistIntent,
|
|
129
|
+
confidence: number,
|
|
130
|
+
ranked: RankedNode[],
|
|
131
|
+
ocrTokens: string[],
|
|
132
|
+
backend: string,
|
|
133
|
+
ocrTexts: OcrTextHit[] = [],
|
|
134
|
+
): string {
|
|
135
|
+
if (!ranked.length && !ocrTokens.length && intent === 'unknown') return '';
|
|
136
|
+
const lines: string[] = [
|
|
137
|
+
`On-device assist (${backend}): intent=${intent} conf=${confidence.toFixed(2)}`,
|
|
138
|
+
];
|
|
139
|
+
if (ranked.length) {
|
|
140
|
+
lines.push('top_candidates:');
|
|
141
|
+
for (const r of ranked.slice(0, 6)) {
|
|
142
|
+
lines.push(
|
|
143
|
+
`- score=${r.score.toFixed(2)} id=${r.id} label="${r.label.replace(/"/g, '')}" clickable=${r.clickable} kind=${r.kindHint}`,
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (ocrTokens.length) {
|
|
148
|
+
lines.push(`ocr_tokens: ${ocrTokens.slice(0, 16).join(', ')}`);
|
|
149
|
+
}
|
|
150
|
+
const positioned = ocrTexts.filter(
|
|
151
|
+
(hit) => hit.text.trim() && hit.frame && hit.frame.width > 0 && hit.frame.height > 0,
|
|
152
|
+
);
|
|
153
|
+
if (positioned.length) {
|
|
154
|
+
lines.push(
|
|
155
|
+
'ocr_targets (visible text; point is window-absolute evidence for tap(point)):',
|
|
156
|
+
);
|
|
157
|
+
for (const hit of positioned.slice(0, 16)) {
|
|
158
|
+
const f = hit.frame!;
|
|
159
|
+
const x = Math.round(f.x + f.width / 2);
|
|
160
|
+
const y = Math.round(f.y + f.height / 2);
|
|
161
|
+
lines.push(
|
|
162
|
+
`- text="${hit.text.replace(/"/g, '')}" point=(${x},${y}) confidence=${hit.confidence.toFixed(2)}`,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return lines.join('\n');
|
|
167
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import type { Point, Frame, ViewNode } from '../types';
|
|
2
|
+
|
|
3
|
+
export type PositionedOcrText = {
|
|
4
|
+
text: string;
|
|
5
|
+
confidence: number;
|
|
6
|
+
frame?: Frame;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
function normalized(value: string): string {
|
|
10
|
+
return value
|
|
11
|
+
.toLocaleLowerCase()
|
|
12
|
+
.replace(/[^\p{L}\p{N}]+/gu, '');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Visible web regions let a short translated action stay scoped to the page. */
|
|
16
|
+
export function visibleWebViewFrames(root: ViewNode): Frame[] {
|
|
17
|
+
const frames: Frame[] = [];
|
|
18
|
+
const walk = (node: ViewNode) => {
|
|
19
|
+
if (node.visible === false) return;
|
|
20
|
+
if (/webview/i.test(node.type) && node.frame.width > 0 && node.frame.height > 0) {
|
|
21
|
+
const left = Math.max(root.frame.x, node.frame.x);
|
|
22
|
+
const top = Math.max(root.frame.y, node.frame.y);
|
|
23
|
+
const right = Math.min(root.frame.x + root.frame.width, node.frame.x + node.frame.width);
|
|
24
|
+
const bottom = Math.min(root.frame.y + root.frame.height, node.frame.y + node.frame.height);
|
|
25
|
+
if (right > left && bottom > top) frames.push({ x: left, y: top, width: right - left, height: bottom - top });
|
|
26
|
+
}
|
|
27
|
+
for (const child of node.children) walk(child);
|
|
28
|
+
};
|
|
29
|
+
walk(root);
|
|
30
|
+
return frames;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function ocrHitInFrames(hit: PositionedOcrText, frames: Frame[]): boolean {
|
|
34
|
+
if (!hit.frame) return false;
|
|
35
|
+
const x = hit.frame.x + hit.frame.width / 2, y = hit.frame.y + hit.frame.height / 2;
|
|
36
|
+
return frames.some(f => x >= f.x && x <= f.x + f.width && y >= f.y && y <= f.y + f.height);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Candidate labels are derived only from the user's goal, never screen text. */
|
|
40
|
+
export function goalOcrCandidates(goal: string): string[] {
|
|
41
|
+
if (/password|passcode|private\s*key|mnemonic|recovery\s*phrase|seed\s*phrase|密码|助记词|私钥|验证码/i.test(goal)) return [];
|
|
42
|
+
const stop = new Set(['please', 'for', 'me', 'my', 'the', 'a', 'an', 'to', 'and', 'then', 'of', 'in', 'on', 'from', 'with']);
|
|
43
|
+
const words = (goal.match(/[A-Za-z][A-Za-z0-9'-]*|[\u3400-\u9fff]{2,16}/g) || [])
|
|
44
|
+
.filter(word => !stop.has(word.toLowerCase())).slice(0, 20);
|
|
45
|
+
const out: string[] = [];
|
|
46
|
+
for (const size of [3, 2, 1]) {
|
|
47
|
+
for (let i = 0; i + size <= words.length; i++) {
|
|
48
|
+
const label = words.slice(i, i + size).join(' ');
|
|
49
|
+
if (label.length >= 3 && label.length <= 60 && !out.includes(label)) out.push(label);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Chinese goals often have no spaces between verbs and objects.
|
|
53
|
+
for (const word of words.filter(w => /[\u3400-\u9fff]/.test(w))) {
|
|
54
|
+
for (let length = Math.min(6, word.length); length >= 2; length--) {
|
|
55
|
+
for (let i = 0; i + length <= word.length; i++) {
|
|
56
|
+
const label = word.slice(i, i + length);
|
|
57
|
+
if (!out.includes(label)) out.push(label);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return out.slice(0, 100);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function verifiedGoalOcrLabels(goal: string, root: ViewNode | null | undefined, texts: PositionedOcrText[]): string[] {
|
|
65
|
+
if (!root) return [];
|
|
66
|
+
const regions = visibleWebViewFrames(root);
|
|
67
|
+
if (!regions.length) return [];
|
|
68
|
+
const onPage = texts.filter(hit => ocrHitInFrames(hit, regions));
|
|
69
|
+
return goalOcrCandidates(goal).filter(label =>
|
|
70
|
+
!!findOcrTextHit(onPage, label, { translatedWebRegions: regions }),
|
|
71
|
+
).slice(0, 6);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// These are public product names, never account names, addresses or page text.
|
|
75
|
+
export const PUBLIC_WALLET_CHOICES = [
|
|
76
|
+
'WalletConnect', 'MetaMask', 'Coinbase Wallet', 'Uniswap Mobile', 'Uniswap Wallet',
|
|
77
|
+
'Binance Wallet', 'Trust Wallet', 'Phantom', 'OKX Wallet', 'Rabby Wallet', 'OneKey', 'UKey', 'UKey Wallet', 'Solflare',
|
|
78
|
+
] as const;
|
|
79
|
+
|
|
80
|
+
export function walletConnectionAllowed(goal: string): boolean {
|
|
81
|
+
return /(connect|连接|連接)/i.test(goal) && /(wallet|钱包|錢包)/i.test(goal) &&
|
|
82
|
+
!/\b(?:do not|don't|never|without)\s+(?:connect|link|select|choose)\b|(?:不要|禁止|不|无需|無需)(?:连接|連接|选择|選擇)/i.test(goal) &&
|
|
83
|
+
!/password|passcode|private\s*key|mnemonic|recovery\s*phrase|seed\s*phrase|密码|助记词|私钥|验证码/i.test(goal);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function verifiedWalletChoices(goal: string, root: ViewNode | null | undefined, texts: PositionedOcrText[]): string[] {
|
|
87
|
+
if (!root || !walletConnectionAllowed(goal)) return [];
|
|
88
|
+
const regions = visibleWebViewFrames(root);
|
|
89
|
+
if (!regions.length) return [];
|
|
90
|
+
const page = texts.filter(hit => ocrHitInFrames(hit, regions));
|
|
91
|
+
// Require a visible chooser heading as well as multiple known product names.
|
|
92
|
+
if (!['connect wallet', '连接钱包', '連接錢包'].some(label => !!findOcrTextHit(page, label))) return [];
|
|
93
|
+
const choices = PUBLIC_WALLET_CHOICES.filter(label => !!findOcrTextHit(page, label));
|
|
94
|
+
return choices.length >= 2 ? choices.slice(0, 8) : [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resolve text that is visible in a WebView/Canvas but absent from the native
|
|
99
|
+
* accessibility tree. The frame comes from native OCR and is already in the
|
|
100
|
+
* same window-absolute logical coordinate space used by dispatchTap.
|
|
101
|
+
*/
|
|
102
|
+
export function findOcrTextPoint(
|
|
103
|
+
texts: PositionedOcrText[],
|
|
104
|
+
wanted: string,
|
|
105
|
+
): Point | null {
|
|
106
|
+
const hit = findOcrTextHit(texts, wanted);
|
|
107
|
+
const frame = hit?.frame;
|
|
108
|
+
return frame
|
|
109
|
+
? { x: frame.x + frame.width / 2, y: frame.y + frame.height / 2 }
|
|
110
|
+
: null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function findOcrTextHit(
|
|
114
|
+
texts: PositionedOcrText[],
|
|
115
|
+
wanted: string,
|
|
116
|
+
options: { translatedWebRegions?: Frame[] } = {},
|
|
117
|
+
): PositionedOcrText | null {
|
|
118
|
+
const target = normalized(wanted);
|
|
119
|
+
if (target.length < 2) return null;
|
|
120
|
+
|
|
121
|
+
const matches: PositionedOcrText[] = [];
|
|
122
|
+
for (const hit of texts) {
|
|
123
|
+
const frame = hit.frame;
|
|
124
|
+
if (!frame || ![frame.x, frame.y, frame.width, frame.height, hit.confidence].every(Number.isFinite) ||
|
|
125
|
+
frame.x < 0 || frame.y < 0 || frame.width <= 0 || frame.height <= 0 || hit.confidence < 0.6) continue;
|
|
126
|
+
const text = normalized(hit.text);
|
|
127
|
+
if (text === target) matches.push(hit);
|
|
128
|
+
}
|
|
129
|
+
// A fragment in prose or two equal labels gives no reliable target.
|
|
130
|
+
if (matches.length === 1) return matches[0]!;
|
|
131
|
+
if (matches.length > 1) return null;
|
|
132
|
+
|
|
133
|
+
// Common translated connect controls. A shortened action word is considered
|
|
134
|
+
// only inside a visible web view, with strong OCR and a single match.
|
|
135
|
+
const connectLabels = new Set(['connect', 'connectwallet', '连接', '连接钱包', '連接', '連接錢包']);
|
|
136
|
+
const regions = options.translatedWebRegions || [];
|
|
137
|
+
if (!connectLabels.has(target) || !regions.length) return null;
|
|
138
|
+
const translated = texts.filter(hit => {
|
|
139
|
+
const f = hit.frame;
|
|
140
|
+
return connectLabels.has(normalized(hit.text)) && f &&
|
|
141
|
+
[f.x, f.y, f.width, f.height, hit.confidence].every(Number.isFinite) &&
|
|
142
|
+
f.x >= 0 && f.y >= 0 && f.width > 0 && f.height > 0 && hit.confidence >= 0.8 &&
|
|
143
|
+
ocrHitInFrames(hit, regions);
|
|
144
|
+
});
|
|
145
|
+
return translated.length === 1 ? translated[0]! : null;
|
|
146
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ocrHitInFrames, visibleWebViewFrames, type PositionedOcrText } from './ocrTarget';
|
|
2
|
+
import type { ViewNode } from '../types';
|
|
3
|
+
|
|
4
|
+
/** Local-only text sets: callers may report only whether content changed. */
|
|
5
|
+
export function webVisualLabels(root: ViewNode | null, hits: PositionedOcrText[]): Set<string> | null {
|
|
6
|
+
if (!root) return null;
|
|
7
|
+
const frames = visibleWebViewFrames(root);
|
|
8
|
+
if (!frames.length) return null;
|
|
9
|
+
const labels = new Set<string>();
|
|
10
|
+
for (const hit of hits) {
|
|
11
|
+
if (hit.confidence < 0.7 || !ocrHitInFrames(hit, frames)) continue;
|
|
12
|
+
const text = hit.text.trim().toLocaleLowerCase().replace(/\s+/g, ' ');
|
|
13
|
+
// Ignore prices, counts and other rapidly changing numeric-only strings.
|
|
14
|
+
if (text.length >= 2 && /[\p{L}]/u.test(text)) labels.add(text);
|
|
15
|
+
}
|
|
16
|
+
return labels.size ? labels : null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function webVisualChanged(before: Set<string> | null, after: Set<string> | null): boolean {
|
|
20
|
+
if (!before || !after) return false;
|
|
21
|
+
let additions = 0;
|
|
22
|
+
for (const text of after) if (!before.has(text)) additions++;
|
|
23
|
+
return additions >= 2;
|
|
24
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { message, resolveText, type LocalizedText } from '../i18n';
|
|
2
|
+
|
|
3
|
+
/** A dispatched action may have committed; replay would risk a duplicate. */
|
|
4
|
+
export class ActionOutcomeUnknownError extends Error {
|
|
5
|
+
readonly localizedMessage = message('runtime.uncertainOutcome');
|
|
6
|
+
constructor(readonly detail: string) {
|
|
7
|
+
super(resolveText(message('runtime.uncertainOutcome')));
|
|
8
|
+
this.name = 'ActionOutcomeUnknownError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Validation rejected a target before an action was dispatched. Replan safely. */
|
|
13
|
+
export class ActionValidationError extends Error {
|
|
14
|
+
constructor(readonly localizedMessage: LocalizedText) {
|
|
15
|
+
super(resolveText(localizedMessage));
|
|
16
|
+
this.name = 'ActionValidationError';
|
|
17
|
+
}
|
|
18
|
+
}
|