@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,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Idle / dead-loop detection (mirrors SDK client + KokoAgent explore/escape).
|
|
3
|
+
* Stop on no-progress loops only — not because a goal needs many steps.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type HistoryLike = {
|
|
7
|
+
tool: string;
|
|
8
|
+
args?: Record<string, unknown>;
|
|
9
|
+
result: string;
|
|
10
|
+
ok?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function actionFingerprint(item: HistoryLike): string {
|
|
14
|
+
const tool = item.tool;
|
|
15
|
+
const args = item.args ?? {};
|
|
16
|
+
if (tool === "tap") {
|
|
17
|
+
const sel = args.selector as { match?: unknown } | undefined;
|
|
18
|
+
const matchKey = sel?.match != null ? JSON.stringify(sel.match).slice(0, 100) : "";
|
|
19
|
+
const nodeId = String(args.nodeId || "").trim();
|
|
20
|
+
const label = String(args.label || "").trim();
|
|
21
|
+
return `tap:${(matchKey || nodeId || label || "target").slice(0, 100)}`;
|
|
22
|
+
}
|
|
23
|
+
if (tool === "type") {
|
|
24
|
+
return `type:${String(args.text ?? "").slice(0, 40)}`;
|
|
25
|
+
}
|
|
26
|
+
if (tool === "find") {
|
|
27
|
+
return `find:${JSON.stringify(args.match ?? {}).slice(0, 100)}`;
|
|
28
|
+
}
|
|
29
|
+
if (tool === "swipe") {
|
|
30
|
+
const from = args.from as { x?: number; y?: number } | undefined;
|
|
31
|
+
const to = args.to as { x?: number; y?: number } | undefined;
|
|
32
|
+
return `swipe:${Math.round((from?.x ?? 0) / 40)},${Math.round((from?.y ?? 0) / 40)}→${Math.round(
|
|
33
|
+
(to?.x ?? 0) / 40,
|
|
34
|
+
)},${Math.round((to?.y ?? 0) / 40)}`;
|
|
35
|
+
}
|
|
36
|
+
if (tool === "pinch") {
|
|
37
|
+
const c = args.center as { x?: number; y?: number } | undefined;
|
|
38
|
+
const scale = Number(args.scale ?? 1);
|
|
39
|
+
return `pinch:${Math.round((c?.x ?? 0) / 40)},${Math.round((c?.y ?? 0) / 40)}×${scale.toFixed(2)}`;
|
|
40
|
+
}
|
|
41
|
+
if (tool === "dump") {
|
|
42
|
+
if (/empty|未识别|screen:\s*\(empty\)/i.test(item.result)) return "dump:empty";
|
|
43
|
+
return `dump:${item.result.replace(/\s+/g, " ").slice(0, 48)}`;
|
|
44
|
+
}
|
|
45
|
+
if (tool === "ask_user") return `ask:${String(args.question ?? "").slice(0, 40)}`;
|
|
46
|
+
return `${tool}:${JSON.stringify(args).slice(0, 60)}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function screenOf(item: HistoryLike): string {
|
|
50
|
+
const m = item.result.match(/(?:^|\|\|\s*)screen:\s*([^\r\n]*)/i);
|
|
51
|
+
return m?.[1]?.trim() ?? "";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Older hosts may return body text without a screen marker; retain all of it. */
|
|
55
|
+
function observationOf(item: HistoryLike): string {
|
|
56
|
+
return (screenOf(item) || item.result).replace(/\s+/g, " ").trim();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function sameObservation(items: HistoryLike[]): boolean {
|
|
60
|
+
return items.length >= 2 && items.every((h) => observationOf(h) === observationOf(items[0]!));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isFail(item: HistoryLike): boolean {
|
|
64
|
+
if (typeof item.ok === "boolean") return !item.ok;
|
|
65
|
+
return /^(?:fail(?:ed)?|error|null|tap_failed|tap_noop|scroll_noop|no_focus|empty|未识别)(?:\b|[::\s(]|$)/i.test(item.result.trim());
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Actions whose whole point is to change something on screen. */
|
|
69
|
+
const MUTATING = new Set(["tap", "swipe", "pinch", "type"]);
|
|
70
|
+
|
|
71
|
+
/** The client ran it and the screen did not react. */
|
|
72
|
+
function hadNoEffect(item: HistoryLike): boolean {
|
|
73
|
+
return item.ok === false || /^(?:tap_noop|tap_failed|scroll_noop|no_focus)\b/i.test(item.result.trim());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Selector wording drifts between retries — grounded text, then the a11y
|
|
78
|
+
* label, then a nodeId, then a coordinate fallback — so fingerprint equality
|
|
79
|
+
* misses the most common stall: aiming at the same place through a different
|
|
80
|
+
* description each time.
|
|
81
|
+
*
|
|
82
|
+
* Comparing whole screens across steps does not catch it either, because a
|
|
83
|
+
* rotating ad or carousel changes the fingerprint while the page stays put.
|
|
84
|
+
* Trust the per-step verdict instead: the client captures before and after
|
|
85
|
+
* around each action, moments apart, and marks it `tap_noop` when nothing
|
|
86
|
+
* moved. A window whose only attempts to change something all reported no
|
|
87
|
+
* effect is stuck, however the calls were phrased and whatever else animates.
|
|
88
|
+
*/
|
|
89
|
+
function madeNoProgress(history: HistoryLike[]): boolean {
|
|
90
|
+
const mutating = history.slice(-4).filter((h) => MUTATING.has(h.tool));
|
|
91
|
+
const preDispatch = mutating.filter(h => /^pre_dispatch:/i.test(h.result));
|
|
92
|
+
const dispatched = mutating.filter(h => !/^pre_dispatch:/i.test(h.result));
|
|
93
|
+
if (preDispatch.length >= 3 && preDispatch.length === mutating.length) return true;
|
|
94
|
+
const dead = dispatched.filter(hadNoEffect);
|
|
95
|
+
return dead.length >= 2 && dead.length === dispatched.length;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Bound interleaved find/dump loops on one unchanged observed screen. */
|
|
99
|
+
function repeatedReadOnly(history: HistoryLike[]): boolean {
|
|
100
|
+
const tail = history.slice(-8);
|
|
101
|
+
if (tail.length < 8 || !tail.every(h => h.tool === 'find' || h.tool === 'dump')) return false;
|
|
102
|
+
const finds = tail.filter(h => h.tool === 'find');
|
|
103
|
+
const screens = tail.map(screenOf).filter(Boolean);
|
|
104
|
+
if (finds.length < 3 || screens.length < 3 || !screens.every(s => s === screens[0])) return false;
|
|
105
|
+
const fps = finds.map(actionFingerprint);
|
|
106
|
+
return fps.some(fp => fps.filter(value => value === fp).length >= 3) || finds.every(isFail);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function isLooping(history: HistoryLike[]): boolean {
|
|
110
|
+
const recent = history.slice(-5);
|
|
111
|
+
if (recent.length < 3) return false;
|
|
112
|
+
|
|
113
|
+
if (madeNoProgress(history)) return true;
|
|
114
|
+
if (repeatedReadOnly(history)) return true;
|
|
115
|
+
|
|
116
|
+
const fps = recent.map(actionFingerprint);
|
|
117
|
+
const last = fps[fps.length - 1]!;
|
|
118
|
+
const sameFpCount = fps.filter((f) => f === last).length;
|
|
119
|
+
const screenStagnant = recent.length >= 3 && sameObservation(recent);
|
|
120
|
+
const lastThree = recent.slice(-3);
|
|
121
|
+
const allFail = lastThree.every(isFail);
|
|
122
|
+
const identicalResults =
|
|
123
|
+
lastThree.length === 3 &&
|
|
124
|
+
lastThree.every(
|
|
125
|
+
(h) => h.result === lastThree[0]!.result,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// dump/find are observe — identical verify dumps must not abort mid-goal.
|
|
129
|
+
if (sameFpCount >= 3) {
|
|
130
|
+
const lastTool = recent[recent.length - 1]?.tool;
|
|
131
|
+
if (lastTool !== "dump" && lastTool !== "find") {
|
|
132
|
+
if (allFail || identicalResults || screenStagnant) return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (recent.length >= 4) {
|
|
137
|
+
const a = fps[fps.length - 1];
|
|
138
|
+
const b = fps[fps.length - 2];
|
|
139
|
+
if (a && b && a !== b && fps[fps.length - 3] === a && fps[fps.length - 4] === b) {
|
|
140
|
+
// Alternating actions are common in valid workflows (select/continue,
|
|
141
|
+
// increment/confirm, tap/verify). Only stop when each phase also returns
|
|
142
|
+
// to the same observation, rather than when actions alone form A-B-A-B.
|
|
143
|
+
const cycle = recent.slice(-4);
|
|
144
|
+
if (observationOf(cycle[0]!) === observationOf(cycle[2]!) &&
|
|
145
|
+
observationOf(cycle[1]!) === observationOf(cycle[3]!)) return true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Observe-only thrash: a couple dumps for verify is ok; 3+ identical scans = stuck.
|
|
150
|
+
const trailing = recent.slice(-3);
|
|
151
|
+
if (
|
|
152
|
+
trailing.length >= 3 &&
|
|
153
|
+
trailing.every((h) => h.tool === "dump") &&
|
|
154
|
+
sameObservation(trailing)
|
|
155
|
+
) {
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const fails = recent.filter(isFail);
|
|
160
|
+
if (fails.length >= 3) {
|
|
161
|
+
const failFps = fails.map(actionFingerprint);
|
|
162
|
+
const failScreens = fails.map(screenOf).filter(Boolean);
|
|
163
|
+
const sameScreen = failScreens.length !== fails.length || failScreens.every(s => s === failScreens[0]);
|
|
164
|
+
if (failFps.length >= 3 && sameScreen && failFps.every((f) => f === failFps[0])) return true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Same screen + same *mutating* tool = stuck. Pure dump/find is verification.
|
|
168
|
+
if (screenStagnant) {
|
|
169
|
+
const tools = recent.slice(-3).map((h) => h.tool);
|
|
170
|
+
const t0 = tools[0];
|
|
171
|
+
if (
|
|
172
|
+
tools.every((t) => t === t0) &&
|
|
173
|
+
t0 !== "type" &&
|
|
174
|
+
t0 !== "dump" &&
|
|
175
|
+
t0 !== "find"
|
|
176
|
+
) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function isNearLoop(history: HistoryLike[]): boolean {
|
|
185
|
+
const recent = history.slice(-3);
|
|
186
|
+
if (recent.length < 2) return false;
|
|
187
|
+
|
|
188
|
+
// A bounded loading/verification wait can repeat; warn only if unchanged.
|
|
189
|
+
const trailingDumps = recent.slice(-2);
|
|
190
|
+
if (trailingDumps.length >= 2 && trailingDumps.every((h) => h.tool === "dump") &&
|
|
191
|
+
sameObservation(trailingDumps)) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const fps = recent.map(actionFingerprint);
|
|
196
|
+
const last = fps[fps.length - 1]!;
|
|
197
|
+
if (fps.filter((f) => f === last).length < 2) return false;
|
|
198
|
+
if (sameObservation(recent)) return true;
|
|
199
|
+
return (
|
|
200
|
+
recent.slice(-2).every(isFail) ||
|
|
201
|
+
recent.slice(-2).every((h) => h.result === recent[recent.length - 1]!.result)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const LOOP_ESCAPE_HINT = `【恢复评估 — 近期观察或动作重复,先核验当前状态】
|
|
206
|
+
- 对照用户目标和最新证据:已验证全部结果才 done(true);重复或空转本身不代表成功
|
|
207
|
+
- 加载、转场或已提交操作仍待结果时,可以在客户端预算内用 dump 只读核验;持续不变则如实 done(false)说明未确认,不重提请求或重走已完成流程
|
|
208
|
+
- tap_noop / tap_failed 后先核对当前控件与状态;只有存在有证据且安全的替代动作才调整 selector、目标或路径,不能为了逃逸而猜点
|
|
209
|
+
- 与当前子目标相关的标题、正文、页码或状态持续变化时,同名或交替按钮仍可能是正常进展;不要按固定点击次数或动作序列认定循环
|
|
210
|
+
- 下一步控件确实可见、可操作且属于当前目标时再 tap/type;已满足的选中状态不重复切换
|
|
211
|
+
- 仅目标属于当前列表且有滚动区域边界时才 swipe 查找;手势起终点在区域内,不能用滑动猜测导航
|
|
212
|
+
- 数值控件按实际类型、当前值、范围和用户精度要求调整,不预设手势方向;无效果、到边界或缺少证据时说明受阻
|
|
213
|
+
- find/tap 使用最新能力里的文案或 id;缺少安全下一步时允许只读观察或如实结束,不强制切换路径`;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ViewNode } from '../types';
|
|
2
|
+
import type { GatewayAction } from './GatewayClient';
|
|
3
|
+
import { find } from '../selector/match';
|
|
4
|
+
|
|
5
|
+
const norm = (s: string) => s.trim().toLocaleLowerCase();
|
|
6
|
+
const isInput = (n: ViewNode) => /textfield|textinput|edittext|uitextview|textarea/i.test(n.type) && !/label$/i.test(n.type);
|
|
7
|
+
const label = (n: ViewNode) => n.text || n.accessibilityLabel || '';
|
|
8
|
+
const recent = /^(recent(?: searches| search| history)?|search history|最近(?:搜索|记录)?|搜索历史|历史搜索|历史记录)$/i;
|
|
9
|
+
|
|
10
|
+
/** Only replace a search query with a uniquely identified visible recent item. */
|
|
11
|
+
export function recentSearchAction(action: GatewayAction, root: ViewNode | null, goal: string): GatewayAction | null {
|
|
12
|
+
if (action.tool !== 'type' || !root || !action.args.text.trim()) return null;
|
|
13
|
+
const query = norm(action.args.text);
|
|
14
|
+
if (!norm(goal).includes(query) || !/\b(open|find|search|look up)\b|打开|搜索|查找/i.test(goal) ||
|
|
15
|
+
/\b(type|enter|input|write|paste)\b|输入|键入|填写|粘贴/i.test(goal)) return null;
|
|
16
|
+
const nodes: ViewNode[] = [];
|
|
17
|
+
const walk = (n: ViewNode) => {
|
|
18
|
+
if (n.visible === false || n.enabled === false) return;
|
|
19
|
+
nodes.push(n);
|
|
20
|
+
n.children.forEach(walk);
|
|
21
|
+
};
|
|
22
|
+
walk(root);
|
|
23
|
+
const inputNodes = nodes.filter(isInput);
|
|
24
|
+
const fields = inputNodes.filter(n => !inputNodes.some(other => other.id.startsWith(n.id + '/')));
|
|
25
|
+
if (fields.length !== 1 || fields[0]?.secure || !/search|搜索|查找/i.test(label(fields[0]!))) return null;
|
|
26
|
+
if (action.args.nodeId && action.args.nodeId !== fields[0]!.id && !fields[0]!.id.startsWith(action.args.nodeId + '/')) return null;
|
|
27
|
+
if (action.args.selector) {
|
|
28
|
+
const selected = find(root, action.args.selector);
|
|
29
|
+
if (!selected || (selected.id !== fields[0]!.id &&
|
|
30
|
+
!fields[0]!.id.startsWith(selected.id + '/') && !selected.id.startsWith(fields[0]!.id + '/'))) return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const headings = nodes.filter(n => recent.test(label(n).trim()));
|
|
34
|
+
const candidates = nodes.filter(n => n.clickable && norm(label(n)) === query && !isInput(n));
|
|
35
|
+
if (!headings.length || !candidates.length) return null;
|
|
36
|
+
// Require a local section containing a recent heading and the candidate, not
|
|
37
|
+
// just two unrelated nodes somewhere on the page. Ancestors that include the
|
|
38
|
+
// search input or cover most of the screen cannot establish that relation.
|
|
39
|
+
const related = candidates.filter(candidate => headings.some(heading => nodes.some(section =>
|
|
40
|
+
section.id !== root.id && section.id !== fields[0]!.id &&
|
|
41
|
+
heading.id.startsWith(section.id + '/') && candidate.id.startsWith(section.id + '/') &&
|
|
42
|
+
!fields[0]!.id.startsWith(section.id + '/') &&
|
|
43
|
+
section.frame.height < root.frame.height * 0.7)));
|
|
44
|
+
const leaves = related.filter(n => !related.some(other => other.id.startsWith(n.id + '/')));
|
|
45
|
+
if (leaves.length !== 1) return null;
|
|
46
|
+
return { tool: 'tap', args: { nodeId: leaves[0]!.id, label: label(leaves[0]!) } };
|
|
47
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { GatewayAction } from './GatewayClient';
|
|
2
|
+
|
|
3
|
+
/** Protect a host-wallet request from accidentally selecting an unrelated provider. */
|
|
4
|
+
export function wrongHostWalletChoice(goal: string, action: GatewayAction, choices: string[], aliases: string[], observedLabel?: string): boolean {
|
|
5
|
+
if (action.tool !== 'tap' || !choices.length || !aliases.length) return false;
|
|
6
|
+
const normalize = (s: string) => s.toLocaleLowerCase().replace(/[^\p{L}\p{N}]/gu, '');
|
|
7
|
+
const g = normalize(goal);
|
|
8
|
+
// An explicitly named provider is a different user request, not a host-wallet default.
|
|
9
|
+
if (choices.some(choice => g.includes(normalize(choice)))) return false;
|
|
10
|
+
const matches = action.args.selector?.match || [];
|
|
11
|
+
const labels = [observedLabel, action.args.label, ...matches.flatMap(rule =>
|
|
12
|
+
['text', 'accessibilityLabel'].map(key => (rule as Record<string, unknown>)[key]).filter((x): x is string => typeof x === 'string'))]
|
|
13
|
+
.filter((s): s is string => typeof s === 'string').map(normalize);
|
|
14
|
+
return choices.some(choice => labels.includes(normalize(choice)) && !aliases.some(alias => normalize(alias) === normalize(choice)));
|
|
15
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ViewNode } from '../types';
|
|
2
|
+
import type { GatewayAction, AgentHistoryItem } from './GatewayClient';
|
|
3
|
+
|
|
4
|
+
/** Select a visible app-results category only when the user's query is on this page. */
|
|
5
|
+
export function webResultCategory(action: GatewayAction, root: ViewNode | null, goal: string, history: AgentHistoryItem[]): GatewayAction | null {
|
|
6
|
+
if (action.tool !== 'dump' || !root || !/(connect|连接|連接)/i.test(goal) || !/(wallet|钱包|錢包)/i.test(goal)) return null;
|
|
7
|
+
const nodes: ViewNode[] = [];
|
|
8
|
+
const visit = (node: ViewNode) => {
|
|
9
|
+
if (node.visible === false || node.enabled === false) return;
|
|
10
|
+
nodes.push(node);
|
|
11
|
+
node.children.forEach(visit);
|
|
12
|
+
};
|
|
13
|
+
visit(root);
|
|
14
|
+
const norm = (s: string) => s.trim().toLocaleLowerCase();
|
|
15
|
+
const fields = nodes.filter(n => /textfield|textinput|edittext/i.test(n.type) && !/label$/i.test(n.type));
|
|
16
|
+
if (!fields.some(n => {
|
|
17
|
+
const value = norm(n.text || n.accessibilityLabel || '');
|
|
18
|
+
return value.length >= 3 && norm(goal).includes(value);
|
|
19
|
+
})) return null;
|
|
20
|
+
const names = new Set(nodes.map(n => norm(n.text || n.accessibilityLabel || '')));
|
|
21
|
+
if (![...names].some(name => /^(tokens|代币|代幣)$/.test(name))) return null;
|
|
22
|
+
const candidates = nodes.filter(n => n.clickable && /^(dapps|dapp|应用|應用)$/.test(norm(n.text || n.accessibilityLabel || '')) && !n.selected);
|
|
23
|
+
const leaves = candidates.filter(n => !candidates.some(other => other.id.startsWith(n.id + '/')));
|
|
24
|
+
if (leaves.length !== 1) return null;
|
|
25
|
+
const node = leaves[0]!;
|
|
26
|
+
if (history.some(h => h.tool === 'tap' && h.args?.nodeId === node.id)) return null;
|
|
27
|
+
return { tool: 'tap', args: { nodeId: node.id, label: node.text || node.accessibilityLabel } };
|
|
28
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { GatewayClient, type GatewayConfig } from '../client/GatewayClient';
|
|
2
|
+
import type { KokoAccountSnapshot, KokoEntitlements, KokoPlanId } from '../types';
|
|
3
|
+
import { DEFAULT_ENTITLEMENTS, emptyAccount } from './branding';
|
|
4
|
+
import { isTrustedEntitlementHost } from './trust';
|
|
5
|
+
import { resolveGatewayBaseUrl } from '../client/GatewayClient';
|
|
6
|
+
|
|
7
|
+
type Listener = (account: KokoAccountSnapshot | null) => void;
|
|
8
|
+
|
|
9
|
+
function stripUntrustedBranding(
|
|
10
|
+
account: KokoAccountSnapshot,
|
|
11
|
+
baseUrl: string,
|
|
12
|
+
): KokoAccountSnapshot {
|
|
13
|
+
if (isTrustedEntitlementHost(baseUrl)) return account;
|
|
14
|
+
return {
|
|
15
|
+
...account,
|
|
16
|
+
entitlements: {
|
|
17
|
+
...account.entitlements,
|
|
18
|
+
custom_branding: false,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class AccountStoreImpl {
|
|
24
|
+
private account: KokoAccountSnapshot | null = null;
|
|
25
|
+
private listeners = new Set<Listener>();
|
|
26
|
+
private inflight: Promise<KokoAccountSnapshot | null> | null = null;
|
|
27
|
+
|
|
28
|
+
get(): KokoAccountSnapshot | null {
|
|
29
|
+
return this.account;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
subscribe(listener: Listener): () => void {
|
|
33
|
+
this.listeners.add(listener);
|
|
34
|
+
listener(this.account);
|
|
35
|
+
return () => {
|
|
36
|
+
this.listeners.delete(listener);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private emit() {
|
|
41
|
+
for (const l of this.listeners) l(this.account);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async refresh(gateway: GatewayConfig): Promise<KokoAccountSnapshot | null> {
|
|
45
|
+
if (this.inflight) return this.inflight;
|
|
46
|
+
let baseUrl: string;
|
|
47
|
+
try {
|
|
48
|
+
baseUrl = resolveGatewayBaseUrl(gateway);
|
|
49
|
+
} catch {
|
|
50
|
+
if (!this.account) {
|
|
51
|
+
this.account = emptyAccount();
|
|
52
|
+
this.emit();
|
|
53
|
+
}
|
|
54
|
+
return this.account;
|
|
55
|
+
}
|
|
56
|
+
this.inflight = (async () => {
|
|
57
|
+
try {
|
|
58
|
+
const client = new GatewayClient(gateway);
|
|
59
|
+
const me = await client.me();
|
|
60
|
+
this.account = stripUntrustedBranding(me, baseUrl);
|
|
61
|
+
this.emit();
|
|
62
|
+
return this.account;
|
|
63
|
+
} catch {
|
|
64
|
+
if (!this.account) {
|
|
65
|
+
this.account = emptyAccount();
|
|
66
|
+
this.emit();
|
|
67
|
+
}
|
|
68
|
+
return this.account;
|
|
69
|
+
} finally {
|
|
70
|
+
this.inflight = null;
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
return this.inflight;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
entitlements(): KokoEntitlements {
|
|
77
|
+
return this.account?.entitlements ?? { ...DEFAULT_ENTITLEMENTS };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
plan(): KokoPlanId {
|
|
81
|
+
return this.account?.plan ?? 'free';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const AccountStore = new AccountStoreImpl();
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { resolveDebugLogging } from './devMode';
|
|
2
|
+
import type { KokoAgentConfig } from '../types';
|
|
3
|
+
import type { Affordance } from '../privacy/screenModel';
|
|
4
|
+
import { extractAffordances } from '../privacy/screenModel';
|
|
5
|
+
import { HostActionsStore } from '../host/HostActions';
|
|
6
|
+
import type { ViewNode } from '../types';
|
|
7
|
+
|
|
8
|
+
type Cfg = Pick<KokoAgentConfig, 'debug' | 'devMode'> | undefined;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Developer-facing logs: what the SDK observed in the host App
|
|
12
|
+
* (controls / fields / actions). Never logs security policy internals.
|
|
13
|
+
*/
|
|
14
|
+
export const AgentDebug = {
|
|
15
|
+
enabled(config?: Cfg): boolean {
|
|
16
|
+
return resolveDebugLogging(config);
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
/** High-level run lifecycle (goal only, no policy). */
|
|
20
|
+
runStart(config: Cfg, goal: string) {
|
|
21
|
+
if (!resolveDebugLogging(config)) return;
|
|
22
|
+
// eslint-disable-next-line no-console
|
|
23
|
+
console.log('[koko] 开始任务:', goal.slice(0, 120));
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
runEnd(config: Cfg, summary: string, ok: boolean) {
|
|
27
|
+
if (!resolveDebugLogging(config)) return;
|
|
28
|
+
// eslint-disable-next-line no-console
|
|
29
|
+
console.log(ok ? '[koko] 任务完成:' : '[koko] 任务结束:', summary.slice(0, 160));
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/** The dump stopped at its depth cap, so the page body never reached us. */
|
|
33
|
+
dumpTruncated(config: Cfg, cap: number) {
|
|
34
|
+
if (!resolveDebugLogging(config)) return;
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.warn(
|
|
37
|
+
`[koko] 视图树在 maxDepth=${cap} 处被截断,页面正文可能完全缺失(只剩外层导航)。` +
|
|
38
|
+
'请调大 dumpMaxDepth。',
|
|
39
|
+
);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/** Capabilities discovered on the current screen. */
|
|
43
|
+
screenCapabilities(config: Cfg, tree: ViewNode | null | undefined) {
|
|
44
|
+
if (!resolveDebugLogging(config)) return;
|
|
45
|
+
const items = tree ? extractAffordances(tree, 24) : [];
|
|
46
|
+
const host = HostActionsStore.getActions();
|
|
47
|
+
if (!items.length && !host.length) {
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
console.log('[koko] 当前界面: 未识别到可操作控件');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const lines = [
|
|
53
|
+
...items.map(formatAffordance),
|
|
54
|
+
...host.map(
|
|
55
|
+
(a) => `宿主声明「${a.label}」${a.testID ? `(testID=${a.testID})` : ''}`,
|
|
56
|
+
),
|
|
57
|
+
];
|
|
58
|
+
// eslint-disable-next-line no-console
|
|
59
|
+
console.log(`[koko] 当前界面可用能力 (${lines.length}):\n - ${lines.join('\n - ')}`);
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
/** What the agent is about to do in the App (user-visible action). */
|
|
63
|
+
appAction(
|
|
64
|
+
config: Cfg,
|
|
65
|
+
step: number,
|
|
66
|
+
tool: string,
|
|
67
|
+
detail?: string,
|
|
68
|
+
) {
|
|
69
|
+
if (!resolveDebugLogging(config)) return;
|
|
70
|
+
const label = actionLabel(tool, detail);
|
|
71
|
+
// eslint-disable-next-line no-console
|
|
72
|
+
console.log(`[koko] 步骤 ${step}: ${label}`);
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
/** Soft failure for developers — generic, no rule leakage. */
|
|
76
|
+
runIssue(config: Cfg, message: string) {
|
|
77
|
+
if (!resolveDebugLogging(config)) return;
|
|
78
|
+
const safe = sanitizeDevMessage(message);
|
|
79
|
+
// eslint-disable-next-line no-console
|
|
80
|
+
console.warn('[koko] 任务遇到问题:', safe);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
function formatAffordance(a: Affordance): string {
|
|
85
|
+
const kind =
|
|
86
|
+
a.kind === 'button'
|
|
87
|
+
? '按钮'
|
|
88
|
+
: a.kind === 'field'
|
|
89
|
+
? '输入框'
|
|
90
|
+
: a.kind === 'row'
|
|
91
|
+
? '列表项'
|
|
92
|
+
: a.kind === 'link'
|
|
93
|
+
? '链接'
|
|
94
|
+
: a.kind === 'sheet'
|
|
95
|
+
? '弹层按钮'
|
|
96
|
+
: a.kind === 'toggle'
|
|
97
|
+
? '开关'
|
|
98
|
+
: a.kind === 'adjustable'
|
|
99
|
+
? '调节控件'
|
|
100
|
+
: '控件';
|
|
101
|
+
const near = a.near ? `(附近: ${a.near.slice(0, 40)})` : '';
|
|
102
|
+
return `${kind}「${a.label || '(无文案)'}」${near}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function actionLabel(tool: string, detail?: string): string {
|
|
106
|
+
const d = detail?.trim();
|
|
107
|
+
switch (tool) {
|
|
108
|
+
case 'dump':
|
|
109
|
+
return '扫描当前界面';
|
|
110
|
+
case 'find':
|
|
111
|
+
return d ? `定位「${d}」` : '定位控件';
|
|
112
|
+
case 'tap':
|
|
113
|
+
return d ? `点击「${d}」` : '点击';
|
|
114
|
+
case 'swipe':
|
|
115
|
+
return d ? `滑动(${d})` : '滑动';
|
|
116
|
+
case 'pinch':
|
|
117
|
+
return d ? `双指缩放(${d})` : '双指缩放';
|
|
118
|
+
case 'type':
|
|
119
|
+
return d ? `输入「${d}」` : '输入文字';
|
|
120
|
+
case 'ask_user':
|
|
121
|
+
return '等待你在 App 内操作';
|
|
122
|
+
case 'done':
|
|
123
|
+
return d ? `结束:${d}` : '结束';
|
|
124
|
+
default:
|
|
125
|
+
return d ? `${tool}: ${d}` : tool;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Strip security/policy jargon from messages shown in debug console. */
|
|
130
|
+
export function sanitizeDevMessage(message: string): string {
|
|
131
|
+
const lower = message.toLowerCase();
|
|
132
|
+
if (
|
|
133
|
+
/execution_permit|execution permit|permit expired|gateway host|allowlist|devmode|custom_branding|entitlement/i.test(
|
|
134
|
+
message,
|
|
135
|
+
)
|
|
136
|
+
) {
|
|
137
|
+
if (/quota|429/.test(lower)) return '今日用量已用尽,请稍后再试或联系服务商扩容';
|
|
138
|
+
if (/unauthorized|401/.test(lower)) return '鉴权失败,请检查 gateway.token';
|
|
139
|
+
return '暂时无法继续操作,请稍后重试或检查网络与账号配置';
|
|
140
|
+
}
|
|
141
|
+
return message.slice(0, 200);
|
|
142
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soft client gate: local dump/tap/swipe/type require a short-lived
|
|
3
|
+
* execution_permit from the official (or local-lab) gateway session.
|
|
4
|
+
* Always enforced — debug logging does not bypass this.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type GuardedAction = 'dump' | 'find' | 'tap' | 'swipe' | 'pinch' | 'type' | 'screenshot';
|
|
8
|
+
|
|
9
|
+
function peekExp(permit: string): number | null {
|
|
10
|
+
try {
|
|
11
|
+
const [payloadB64] = permit.split('.');
|
|
12
|
+
if (!payloadB64) return null;
|
|
13
|
+
const pad =
|
|
14
|
+
payloadB64.length % 4 === 0
|
|
15
|
+
? ''
|
|
16
|
+
: '='.repeat(4 - (payloadB64.length % 4));
|
|
17
|
+
const json = globalThis.atob
|
|
18
|
+
? globalThis.atob(payloadB64.replace(/-/g, '+').replace(/_/g, '/') + pad)
|
|
19
|
+
: Buffer.from(
|
|
20
|
+
payloadB64.replace(/-/g, '+').replace(/_/g, '/') + pad,
|
|
21
|
+
'base64',
|
|
22
|
+
).toString('utf8');
|
|
23
|
+
const payload = JSON.parse(json) as { exp?: number };
|
|
24
|
+
return typeof payload.exp === 'number' ? payload.exp : null;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
class ExecutionGuardImpl {
|
|
31
|
+
private permit: string | null = null;
|
|
32
|
+
private sessionId: string | null = null;
|
|
33
|
+
|
|
34
|
+
setPermit(permit: string | null, sessionId?: string | null) {
|
|
35
|
+
this.permit = permit;
|
|
36
|
+
if (sessionId !== undefined) this.sessionId = sessionId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getPermit() {
|
|
40
|
+
return this.permit;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getSessionId() {
|
|
44
|
+
return this.sessionId;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
clear() {
|
|
48
|
+
this.permit = null;
|
|
49
|
+
this.sessionId = null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
assert(action: GuardedAction) {
|
|
53
|
+
if (!this.permit) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`KokoAgent: ${action} is only available while a goal is running. Use runGoal().`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const exp = peekExp(this.permit);
|
|
59
|
+
if (exp != null && exp < Math.floor(Date.now() / 1000)) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`KokoAgent: session timed out during ${action}. Please run the goal again.`,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const ExecutionGuard = new ExecutionGuardImpl();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { KokoUsageEvent } from '../types';
|
|
2
|
+
|
|
3
|
+
type Listener = (event: KokoUsageEvent) => void;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fan-out for usage / lifecycle events. Host `onUsageEvent` is wired here.
|
|
7
|
+
* Never used to gate execution.
|
|
8
|
+
*/
|
|
9
|
+
class UsageBusImpl {
|
|
10
|
+
private listeners = new Set<Listener>();
|
|
11
|
+
private recent: KokoUsageEvent[] = [];
|
|
12
|
+
private readonly maxRecent = 100;
|
|
13
|
+
|
|
14
|
+
subscribe(listener: Listener): () => void {
|
|
15
|
+
this.listeners.add(listener);
|
|
16
|
+
return () => {
|
|
17
|
+
this.listeners.delete(listener);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
emit(event: KokoUsageEvent) {
|
|
22
|
+
this.recent.push(event);
|
|
23
|
+
if (this.recent.length > this.maxRecent) {
|
|
24
|
+
this.recent.splice(0, this.recent.length - this.maxRecent);
|
|
25
|
+
}
|
|
26
|
+
for (const l of this.listeners) {
|
|
27
|
+
try {
|
|
28
|
+
l(event);
|
|
29
|
+
} catch {
|
|
30
|
+
// host callbacks must not break the agent
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getRecent(): KokoUsageEvent[] {
|
|
36
|
+
return [...this.recent];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
clear() {
|
|
40
|
+
this.recent = [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const UsageBus = new UsageBusImpl();
|