taphound 0.2.0-dev.1 → 0.2.0-dev.12
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/README.md +49 -149
- package/README.zh-CN.md +47 -147
- package/assets/skills/taphound-case-suite/SKILL.md +363 -0
- package/assets/skills/taphound-case-suite/schemas/base-flow-record.schema.json +22 -0
- package/assets/skills/taphound-case-suite/schemas/case-catalog.schema.json +26 -0
- package/assets/skills/taphound-case-suite/schemas/case-ledger.schema.json +158 -0
- package/assets/skills/taphound-case-suite/schemas/suite-input.schema.json +41 -0
- package/assets/skills/taphound-case-suite/schemas/transition.schema.json +61 -0
- package/assets/skills/taphound-case-suite/scripts/ledger.mjs +1207 -0
- package/assets/skills/taphound-case-suite/templates/base-flow-record.example.json +20 -0
- package/assets/skills/taphound-case-suite/templates/suite-input.example.json +27 -0
- package/assets/skills/taphound-case-suite/templates/transition.example.json +8 -0
- package/assets/skills/taphound-flash/SKILL.md +115 -0
- package/assets/skills/taphound-flash/scripts/flash.mjs +585 -0
- package/assets/skills/taphound-flash/templates/flash-plan.example.json +15 -0
- package/assets/skills/taphound-journey-brief-author/CONTEXT-GUIDE.md +471 -0
- package/assets/skills/taphound-journey-brief-author/SKILL.md +494 -0
- package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.md +96 -0
- package/assets/skills/taphound-journey-brief-author/prompts/brief-author-role.zh-CN.md +80 -0
- package/assets/skills/taphound-journey-brief-author/prompts/context-analyze-project.md +309 -0
- package/assets/skills/taphound-journey-brief-author/schemas/context-refresh-result.json +123 -0
- package/assets/skills/taphound-journey-brief-author/schemas/project-context-module.json +192 -0
- package/assets/skills/taphound-journey-brief-author/schemas/project-context.json +152 -0
- package/assets/skills/taphound-journey-brief-author/templates/project-context-module.example.json +58 -0
- package/assets/skills/taphound-journey-brief-author/templates/project-context.example.json +51 -0
- package/assets/skills/taphound-journey-brief-author/templates/taphound-journey-brief.template.md +63 -0
- package/assets/skills/taphound-journey-generator/SKILL.md +507 -0
- package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/prompts/check-completion.md +3 -0
- package/assets/skills/taphound-journey-generator/prompts/consume-journey-brief.md +52 -0
- package/assets/skills/taphound-journey-generator/prompts/generate-step.md +211 -0
- package/assets/skills/taphound-journey-generator/prompts/select-flow.md +91 -0
- package/assets/skills/taphound-journey-generator/references/bridge.md +35 -0
- package/assets/skills/taphound-journey-generator/references/mid-session.md +44 -0
- package/assets/skills/taphound-journey-generator/schemas/external-flow.json +37 -0
- package/assets/skills/taphound-journey-generator/schemas/flow.json +28 -0
- package/assets/skills/taphound-journey-generator/schemas/journey-source.json +25 -0
- package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/observe-output.json +13 -4
- package/assets/skills/{taphound-ai-journey → taphound-journey-generator}/schemas/proposed-step-envelope.json +127 -5
- package/assets/skills/taphound-journey-generator/scripts/envelope.mjs +578 -0
- package/assets/skills/taphound-journey-generator/templates/external-flow.example.json +22 -0
- package/assets/skills/taphound-journey-generator/templates/flow.example.json +22 -0
- package/assets/skills/taphound-journey-generator/templates/journey-source.example.json +17 -0
- package/assets/skills/taphound-journey-generator/templates/taphound-journey-brief.example.md +70 -0
- package/assets/skills/taphound-verify-change/SKILL.md +91 -0
- package/assets/skills/taphound-verify-change/references/accept.md +38 -0
- package/assets/skills/taphound-verify-change/references/preserve.md +357 -0
- package/assets/skills/taphound-verify-change/schemas/workflow-manifest.schema.json +295 -0
- package/assets/skills/taphound-verify-change/scripts/handoff.mjs +482 -0
- package/assets/skills/taphound-verify-change/scripts/ui-refactor.mjs +505 -0
- package/dist/adapters/adb/adb-adapter.d.ts +16 -2
- package/dist/adapters/adb/adb-adapter.js +199 -0
- package/dist/adapters/adb/system-uiautomator-snapshot-provider.d.ts +13 -0
- package/dist/adapters/adb/system-uiautomator-snapshot-provider.js +122 -0
- package/dist/adapters/adb/ui-automator-parser.d.ts +3 -0
- package/dist/adapters/adb/ui-automator-parser.js +160 -0
- package/dist/adapters/adb/window-topology-parser.d.ts +2 -0
- package/dist/adapters/adb/window-topology-parser.js +101 -0
- package/dist/adapters/android-cli/android-cli-adapter.d.ts +16 -8
- package/dist/adapters/android-cli/android-cli-adapter.js +137 -15
- package/dist/adapters/android-cli/android-cli-snapshot-provider.d.ts +9 -0
- package/dist/adapters/android-cli/android-cli-snapshot-provider.js +99 -0
- package/dist/adapters/android-cli/layout-parser.js +12 -8
- package/dist/adapters/appium/appium-doctor.d.ts +7 -0
- package/dist/adapters/appium/appium-doctor.js +128 -0
- package/dist/adapters/appium/appium-ui-snapshot-provider.d.ts +42 -0
- package/dist/adapters/appium/appium-ui-snapshot-provider.js +309 -0
- package/dist/adapters/camera/camera-probe-adapter.d.ts +18 -0
- package/dist/adapters/camera/camera-probe-adapter.js +286 -0
- package/dist/adapters/filesystem/artifact-store.js +40 -1
- package/dist/adapters/filesystem/context-document-writer.d.ts +15 -0
- package/dist/adapters/filesystem/context-document-writer.js +112 -0
- package/dist/adapters/filesystem/diagnostics-journal.d.ts +17 -0
- package/dist/adapters/filesystem/diagnostics-journal.js +130 -0
- package/dist/adapters/filesystem/external-flow-registry.d.ts +17 -0
- package/dist/adapters/filesystem/external-flow-registry.js +325 -0
- package/dist/adapters/filesystem/generation-session-store.d.ts +17 -11
- package/dist/adapters/filesystem/generation-session-store.js +281 -855
- package/dist/adapters/filesystem/generation-store/session-lock.d.ts +29 -0
- package/dist/adapters/filesystem/generation-store/session-lock.js +202 -0
- package/dist/adapters/filesystem/generation-store/session-transitions.d.ts +24 -0
- package/dist/adapters/filesystem/generation-store/session-transitions.js +340 -0
- package/dist/adapters/filesystem/generation-store/store-files.d.ts +50 -0
- package/dist/adapters/filesystem/generation-store/store-files.js +363 -0
- package/dist/adapters/filesystem/journey-composition-store.d.ts +23 -0
- package/dist/adapters/filesystem/journey-composition-store.js +151 -0
- package/dist/adapters/filesystem/knowledge-registry.d.ts +12 -0
- package/dist/adapters/filesystem/knowledge-registry.js +223 -0
- package/dist/adapters/filesystem/project-bound-file.js +3 -5
- package/dist/adapters/filesystem/project-file-inspector.d.ts +2 -0
- package/dist/adapters/filesystem/project-file-inspector.js +57 -28
- package/dist/adapters/filesystem/project-identity-inspector.d.ts +7 -0
- package/dist/adapters/filesystem/project-identity-inspector.js +215 -0
- package/dist/adapters/filesystem/project-inventory-inspector.d.ts +8 -0
- package/dist/adapters/filesystem/project-inventory-inspector.js +93 -0
- package/dist/adapters/filesystem/project-module-discoverer.d.ts +6 -0
- package/dist/adapters/filesystem/project-module-discoverer.js +158 -0
- package/dist/adapters/filesystem/skill-installer.d.ts +7 -2
- package/dist/adapters/filesystem/skill-installer.js +40 -11
- package/dist/adapters/filesystem/workspace-layout.d.ts +7 -0
- package/dist/adapters/filesystem/workspace-layout.js +57 -0
- package/dist/adapters/git/node-git-diff.d.ts +17 -0
- package/dist/adapters/git/node-git-diff.js +114 -0
- package/dist/adapters/process/node-detached-process-launcher.d.ts +6 -0
- package/dist/adapters/process/node-detached-process-launcher.js +96 -0
- package/dist/adapters/process/node-process-runner.js +11 -2
- package/dist/adapters/prompt/inquirer-align-prompt.d.ts +27 -0
- package/dist/adapters/prompt/inquirer-align-prompt.js +65 -0
- package/dist/adapters/prompt/inquirer-generation-prompt.js +3 -0
- package/dist/adapters/prompt/inquirer-recorder-prompt.d.ts +9 -1
- package/dist/adapters/prompt/inquirer-recorder-prompt.js +63 -0
- package/dist/adapters/runtime/adb-runtime-backend.d.ts +67 -0
- package/dist/adapters/runtime/adb-runtime-backend.js +206 -0
- package/dist/adapters/runtime/fake-runtime-backend.d.ts +87 -0
- package/dist/adapters/runtime/fake-runtime-backend.js +240 -0
- package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.d.ts +45 -0
- package/dist/adapters/runtime/mobile-mcp/mcp-tool-client.js +153 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.d.ts +23 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-errors.js +39 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.d.ts +20 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-responses.js +180 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.d.ts +78 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-runtime-backend.js +379 -0
- package/dist/adapters/runtime/mobile-mcp/mobile-mcp-tools.d.ts +46 -0
- package/dist/adapters/runtime/session-adb-view.d.ts +53 -0
- package/dist/adapters/runtime/session-adb-view.js +193 -0
- package/dist/adapters/runtime/session-backed-ports.d.ts +21 -0
- package/dist/adapters/runtime/session-backed-ports.js +43 -0
- package/dist/adapters/runtime/shared-session-runtime-backend.d.ts +12 -0
- package/dist/adapters/runtime/shared-session-runtime-backend.js +64 -0
- package/dist/adapters/ui/auto-ui-snapshot-provider.d.ts +8 -0
- package/dist/adapters/ui/auto-ui-snapshot-provider.js +48 -0
- package/dist/adapters/ui/device-layout-temp.d.ts +6 -0
- package/dist/adapters/ui/device-layout-temp.js +18 -0
- package/dist/adapters/ui/device-ui-environment.d.ts +13 -0
- package/dist/adapters/ui/device-ui-environment.js +81 -0
- package/dist/adapters/ui/layout-normalization.d.ts +9 -0
- package/dist/adapters/ui/layout-normalization.js +44 -0
- package/dist/adapters/ui/ui-snapshot-error.d.ts +11 -0
- package/dist/adapters/ui/ui-snapshot-error.js +12 -0
- package/dist/adapters/ui/ui-snapshot-support.d.ts +15 -0
- package/dist/adapters/ui/ui-snapshot-support.js +12 -0
- package/dist/application/align/align-service.d.ts +42 -0
- package/dist/application/align/align-service.js +106 -0
- package/dist/application/assertion/expectation-evaluator.d.ts +18 -5
- package/dist/application/assertion/expectation-evaluator.js +156 -18
- package/dist/application/assertion/guarded-expectation.d.ts +45 -0
- package/dist/application/assertion/guarded-expectation.js +74 -0
- package/dist/application/checkpoint/baseline-capturer.d.ts +26 -0
- package/dist/application/checkpoint/baseline-capturer.js +163 -0
- package/dist/application/checkpoint/baseline-error.d.ts +5 -0
- package/dist/application/checkpoint/baseline-error.js +8 -0
- package/dist/application/checkpoint/baseline-service.d.ts +31 -0
- package/dist/application/checkpoint/baseline-service.js +147 -0
- package/dist/application/checkpoint/checkpoint-evaluator.d.ts +35 -0
- package/dist/application/checkpoint/checkpoint-evaluator.js +415 -0
- package/dist/application/checkpoint/regression-comparator.d.ts +18 -0
- package/dist/application/checkpoint/regression-comparator.js +192 -0
- package/dist/application/collector/logcat-collector.d.ts +22 -1
- package/dist/application/collector/logcat-collector.js +103 -15
- package/dist/application/collector/logcat-event.d.ts +8 -0
- package/dist/application/collector/logcat-event.js +79 -0
- package/dist/application/collector/logcat-stop.d.ts +2 -0
- package/dist/application/collector/logcat-stop.js +11 -0
- package/dist/application/context/context-generator.d.ts +45 -0
- package/dist/application/context/context-generator.js +228 -0
- package/dist/application/context/context-loader.d.ts +40 -0
- package/dist/application/context/context-loader.js +223 -0
- package/dist/application/context/context-refresher.d.ts +59 -0
- package/dist/application/context/context-refresher.js +349 -0
- package/dist/application/context/context-rehasher.d.ts +36 -0
- package/dist/application/context/context-rehasher.js +110 -0
- package/dist/application/context/context-validator.d.ts +23 -1
- package/dist/application/context/context-validator.js +116 -9
- package/dist/application/context/evidence-hash.d.ts +1 -0
- package/dist/application/context/evidence-hash.js +125 -0
- package/dist/application/context/evidence-match.d.ts +9 -0
- package/dist/application/context/evidence-match.js +8 -0
- package/dist/application/context/shard-identity.d.ts +2 -0
- package/dist/application/context/shard-identity.js +7 -0
- package/dist/application/contract/contract-loader.d.ts +25 -0
- package/dist/application/contract/contract-loader.js +68 -0
- package/dist/application/contract/contract-review.d.ts +25 -0
- package/dist/application/contract/contract-review.js +51 -0
- package/dist/application/contract/contract-verifier.d.ts +53 -0
- package/dist/application/contract/contract-verifier.js +645 -0
- package/dist/application/devices/resolve-device-assignments.d.ts +21 -0
- package/dist/application/devices/resolve-device-assignments.js +60 -0
- package/dist/application/diagnosis/failure-classifier.d.ts +23 -0
- package/dist/application/diagnosis/failure-classifier.js +179 -0
- package/dist/application/diagnostics/diagnostics-exporter.d.ts +29 -0
- package/dist/application/diagnostics/diagnostics-exporter.js +283 -0
- package/dist/application/diagnostics/ui-capture-telemetry.d.ts +16 -0
- package/dist/application/diagnostics/ui-capture-telemetry.js +81 -0
- package/dist/application/doctor/doctor-service.d.ts +36 -3
- package/dist/application/doctor/doctor-service.js +255 -25
- package/dist/application/generation/generation-app-preparer.d.ts +20 -0
- package/dist/application/generation/generation-app-preparer.js +28 -0
- package/dist/application/generation/generation-config-service.d.ts +21 -0
- package/dist/application/generation/generation-config-service.js +53 -0
- package/dist/application/generation/generation-confirmation-service.d.ts +14 -3
- package/dist/application/generation/generation-confirmation-service.js +109 -24
- package/dist/application/generation/generation-context-snapshot.d.ts +6 -0
- package/dist/application/generation/generation-context-snapshot.js +29 -0
- package/dist/application/generation/generation-finalizer.d.ts +15 -9
- package/dist/application/generation/generation-finalizer.js +167 -70
- package/dist/application/generation/generation-publisher.js +12 -8
- package/dist/application/generation/generation-recovery-service.d.ts +35 -0
- package/dist/application/generation/generation-recovery-service.js +144 -0
- package/dist/application/generation/generation-reopen-service.d.ts +15 -0
- package/dist/application/generation/generation-reopen-service.js +37 -0
- package/dist/application/generation/generation-replace-service.d.ts +32 -0
- package/dist/application/generation/generation-replace-service.js +116 -0
- package/dist/application/generation/generation-starter.d.ts +44 -4
- package/dist/application/generation/generation-starter.js +175 -8
- package/dist/application/generation/generation-step-executor.d.ts +67 -5
- package/dist/application/generation/generation-step-executor.js +471 -108
- package/dist/application/generation/proposed-step-validator.js +96 -30
- package/dist/application/generation/replay-policy-loader.d.ts +16 -0
- package/dist/application/generation/replay-policy-loader.js +29 -0
- package/dist/application/generation/risk-evaluator.d.ts +4 -1
- package/dist/application/generation/risk-evaluator.js +118 -3
- package/dist/application/generation/runtime-observer.d.ts +39 -7
- package/dist/application/generation/runtime-observer.js +193 -24
- package/dist/application/impact/impact-resolver.d.ts +32 -0
- package/dist/application/impact/impact-resolver.js +160 -0
- package/dist/application/init/init-service.js +26 -13
- package/dist/application/interaction/action-executor.d.ts +3 -2
- package/dist/application/interaction/action-executor.js +11 -1
- package/dist/application/interaction/action-target.d.ts +17 -0
- package/dist/application/interaction/action-target.js +40 -0
- package/dist/application/interaction/external-step-runner.d.ts +153 -0
- package/dist/application/interaction/external-step-runner.js +332 -0
- package/dist/application/interaction/fallback-resolver.d.ts +6 -3
- package/dist/application/interaction/fallback-resolver.js +7 -5
- package/dist/application/interaction/scroll-to-executor.d.ts +17 -3
- package/dist/application/interaction/scroll-to-executor.js +118 -36
- package/dist/application/journey/external-flow-resolver.d.ts +25 -0
- package/dist/application/journey/external-flow-resolver.js +22 -0
- package/dist/application/journey/journey-check-service.d.ts +54 -0
- package/dist/application/journey/journey-check-service.js +207 -0
- package/dist/application/journey/journey-promoter.d.ts +26 -0
- package/dist/application/journey/journey-promoter.js +123 -0
- package/dist/application/journey/journey-resolver.d.ts +42 -0
- package/dist/application/journey/journey-resolver.js +239 -0
- package/dist/application/journey/journey-retirer.d.ts +25 -0
- package/dist/application/journey/journey-retirer.js +87 -0
- package/dist/application/knowledge/anchor-resolver.d.ts +36 -0
- package/dist/application/knowledge/anchor-resolver.js +110 -0
- package/dist/application/knowledge/knowledge-loader.d.ts +16 -0
- package/dist/application/knowledge/knowledge-loader.js +36 -0
- package/dist/application/locator/layout-failure-summary.d.ts +2 -0
- package/dist/application/locator/layout-failure-summary.js +67 -0
- package/dist/application/locator/layout-traversal.d.ts +11 -0
- package/dist/application/locator/layout-traversal.js +18 -0
- package/dist/application/locator/locator-resolver.d.ts +13 -1
- package/dist/application/locator/locator-resolver.js +182 -18
- package/dist/application/observe/observe-service.d.ts +20 -0
- package/dist/application/observe/observe-service.js +91 -0
- package/dist/application/project/project-describer.d.ts +14 -6
- package/dist/application/project/project-describer.js +38 -5
- package/dist/application/recognition/screen-detector.d.ts +28 -0
- package/dist/application/recognition/screen-detector.js +111 -0
- package/dist/application/recorder/locator-selector.js +151 -17
- package/dist/application/recorder/recorder-service.d.ts +16 -4
- package/dist/application/recorder/recorder-service.js +420 -128
- package/dist/application/report/report-writer.d.ts +5 -0
- package/dist/application/report/report-writer.js +17 -1
- package/dist/application/runtime/cold-launch.d.ts +28 -0
- package/dist/application/runtime/cold-launch.js +59 -0
- package/dist/application/runtime/step-runner.d.ts +49 -4
- package/dist/application/runtime/step-runner.js +721 -130
- package/dist/application/runtime/verify-runtime.d.ts +57 -7
- package/dist/application/runtime/verify-runtime.js +577 -175
- package/dist/application/ui/cached-ui-snapshot-provider.d.ts +45 -0
- package/dist/application/ui/cached-ui-snapshot-provider.js +111 -0
- package/dist/application/ui/observed-ui-snapshot-provider.d.ts +15 -0
- package/dist/application/ui/observed-ui-snapshot-provider.js +66 -0
- package/dist/application/ui/ui-snapshot-lifecycle.d.ts +2 -0
- package/dist/application/ui/ui-snapshot-lifecycle.js +8 -0
- package/dist/application/ui/ui-stability-probe.d.ts +9 -0
- package/dist/application/ui/ui-stability-probe.js +24 -0
- package/dist/application/wait/idle-advice.d.ts +6 -0
- package/dist/application/wait/idle-advice.js +27 -0
- package/dist/application/wait/idle-profiles.d.ts +15 -0
- package/dist/application/wait/idle-profiles.js +75 -0
- package/dist/application/wait/idle-waiter.d.ts +28 -4
- package/dist/application/wait/idle-waiter.js +201 -15
- package/dist/cli/commands/align.d.ts +3 -0
- package/dist/cli/commands/align.js +124 -0
- package/dist/cli/commands/baseline.d.ts +3 -0
- package/dist/cli/commands/baseline.js +130 -0
- package/dist/cli/commands/context.js +300 -27
- package/dist/cli/commands/contract.d.ts +3 -0
- package/dist/cli/commands/contract.js +120 -0
- package/dist/cli/commands/diagnose.d.ts +3 -0
- package/dist/cli/commands/diagnose.js +84 -0
- package/dist/cli/commands/doctor.js +16 -9
- package/dist/cli/commands/failure.d.ts +3 -0
- package/dist/cli/commands/failure.js +63 -0
- package/dist/cli/commands/generation/lifecycle-commands.d.ts +5 -0
- package/dist/cli/commands/generation/lifecycle-commands.js +211 -0
- package/dist/cli/commands/generation/session-commands.d.ts +11 -0
- package/dist/cli/commands/generation/session-commands.js +472 -0
- package/dist/cli/commands/generation/shared.d.ts +1414 -0
- package/dist/cli/commands/generation/shared.js +291 -0
- package/dist/cli/commands/generation/step-commands.d.ts +8 -0
- package/dist/cli/commands/generation/step-commands.js +315 -0
- package/dist/cli/commands/generation.js +10 -507
- package/dist/cli/commands/impact.d.ts +3 -0
- package/dist/cli/commands/impact.js +87 -0
- package/dist/cli/commands/init.js +13 -6
- package/dist/cli/commands/journey.d.ts +3 -0
- package/dist/cli/commands/journey.js +382 -0
- package/dist/cli/commands/knowledge.d.ts +3 -0
- package/dist/cli/commands/knowledge.js +93 -0
- package/dist/cli/commands/observe.d.ts +3 -0
- package/dist/cli/commands/observe.js +127 -0
- package/dist/cli/commands/project.js +2 -1
- package/dist/cli/commands/record.js +18 -5
- package/dist/cli/commands/verify.js +326 -64
- package/dist/cli/dependencies.d.ts +136 -1
- package/dist/cli/dependencies.js +504 -52
- package/dist/cli/diagnostics-recorder.d.ts +31 -0
- package/dist/cli/diagnostics-recorder.js +82 -0
- package/dist/cli/diff-verification.d.ts +41 -0
- package/dist/cli/diff-verification.js +192 -0
- package/dist/cli/main.d.ts +1 -1
- package/dist/cli/main.js +107 -2
- package/dist/cli/output.d.ts +5 -3
- package/dist/cli/output.js +12 -0
- package/dist/cli/program.js +21 -1
- package/dist/cli/project-root.d.ts +1 -0
- package/dist/cli/project-root.js +6 -0
- package/dist/cli/runtime-selection.d.ts +22 -0
- package/dist/cli/runtime-selection.js +92 -0
- package/dist/cli/version.d.ts +1 -0
- package/dist/cli/version.js +14 -0
- package/dist/cli/workspace-guard.d.ts +2 -0
- package/dist/cli/workspace-guard.js +3 -0
- package/dist/domain/binding-reference.d.ts +4 -0
- package/dist/domain/binding-reference.js +23 -0
- package/dist/domain/checkpoint.d.ts +404 -0
- package/dist/domain/checkpoint.js +297 -0
- package/dist/domain/config.d.ts +107 -1
- package/dist/domain/config.js +52 -6
- package/dist/domain/contract.d.ts +413 -0
- package/dist/domain/contract.js +196 -0
- package/dist/domain/diagnostics.d.ts +1396 -0
- package/dist/domain/diagnostics.js +193 -0
- package/dist/domain/external-flow.d.ts +493 -0
- package/dist/domain/external-flow.js +15 -0
- package/dist/domain/failure-classification.d.ts +176 -0
- package/dist/domain/failure-classification.js +169 -0
- package/dist/domain/failure.d.ts +2 -1
- package/dist/domain/failure.js +123 -0
- package/dist/domain/generation.d.ts +1671 -132
- package/dist/domain/generation.js +202 -13
- package/dist/domain/geometry.d.ts +13 -0
- package/dist/domain/geometry.js +16 -0
- package/dist/domain/impact.d.ts +71 -0
- package/dist/domain/impact.js +76 -0
- package/dist/domain/init.d.ts +12 -4
- package/dist/domain/init.js +24 -18
- package/dist/domain/journey-composition.d.ts +2285 -0
- package/dist/domain/journey-composition.js +85 -0
- package/dist/domain/journey-lifecycle.d.ts +10 -0
- package/dist/domain/journey-lifecycle.js +9 -0
- package/dist/domain/journey.d.ts +2419 -212
- package/dist/domain/journey.js +384 -14
- package/dist/domain/knowledge.d.ts +165 -0
- package/dist/domain/knowledge.js +188 -0
- package/dist/domain/layout.d.ts +34 -5
- package/dist/domain/layout.js +64 -6
- package/dist/domain/locator-evidence.d.ts +3 -0
- package/dist/domain/locator-evidence.js +36 -0
- package/dist/domain/logcat-event.d.ts +54 -0
- package/dist/domain/logcat-event.js +40 -0
- package/dist/domain/observation.d.ts +33 -0
- package/dist/domain/observation.js +18 -0
- package/dist/domain/project-context.d.ts +219 -1
- package/dist/domain/project-context.js +209 -6
- package/dist/domain/proposed-step.d.ts +340 -60
- package/dist/domain/proposed-step.js +23 -3
- package/dist/domain/report.d.ts +1455 -28
- package/dist/domain/report.js +211 -14
- package/dist/domain/runtime-snapshot.d.ts +58 -1
- package/dist/domain/runtime-snapshot.js +14 -3
- package/dist/domain/runtime.d.ts +50 -0
- package/dist/domain/runtime.js +36 -0
- package/dist/domain/system-app-profiles.d.ts +6 -0
- package/dist/domain/system-app-profiles.js +43 -0
- package/dist/domain/ui-backend.d.ts +28 -0
- package/dist/domain/ui-backend.js +33 -0
- package/dist/domain/ui-cache.d.ts +11 -0
- package/dist/domain/ui-cache.js +10 -0
- package/dist/domain/verify-receipt.d.ts +17 -0
- package/dist/domain/verify-receipt.js +17 -0
- package/dist/domain/window-hierarchy.d.ts +84 -0
- package/dist/domain/window-hierarchy.js +172 -0
- package/dist/domain/workflow-manifest.d.ts +77 -0
- package/dist/domain/workflow-manifest.js +136 -0
- package/dist/domain/workspace.d.ts +30 -0
- package/dist/domain/workspace.js +74 -0
- package/dist/ports/adb.d.ts +34 -1
- package/dist/ports/align-prompt.d.ts +11 -0
- package/dist/ports/align-prompt.js +6 -0
- package/dist/ports/anchor-resolver.d.ts +30 -0
- package/dist/ports/anchor-resolver.js +1 -0
- package/dist/ports/annotated-screen-resolver.d.ts +4 -0
- package/dist/ports/annotated-screen-resolver.js +1 -0
- package/dist/ports/camera-probe.d.ts +23 -0
- package/dist/ports/camera-probe.js +8 -0
- package/dist/ports/context-document-writer.d.ts +24 -0
- package/dist/ports/context-document-writer.js +1 -0
- package/dist/ports/detached-process-launcher.d.ts +12 -0
- package/dist/ports/detached-process-launcher.js +1 -0
- package/dist/ports/diagnostics.d.ts +15 -0
- package/dist/ports/diagnostics.js +1 -0
- package/dist/ports/external-flow-registry.d.ts +37 -0
- package/dist/ports/external-flow-registry.js +1 -0
- package/dist/ports/generation-prompt.d.ts +2 -1
- package/dist/ports/generation-session-store.d.ts +12 -2
- package/dist/ports/git-diff.d.ts +9 -0
- package/dist/ports/git-diff.js +1 -0
- package/dist/ports/journey-composition-store.d.ts +17 -0
- package/dist/ports/journey-composition-store.js +1 -0
- package/dist/ports/knowledge-registry.d.ts +20 -0
- package/dist/ports/knowledge-registry.js +1 -0
- package/dist/ports/process-runner.d.ts +7 -0
- package/dist/ports/project-file-inspector.d.ts +1 -0
- package/dist/ports/project-identity-inspector.d.ts +24 -0
- package/dist/ports/project-identity-inspector.js +1 -0
- package/dist/ports/project-inventory-inspector.d.ts +21 -0
- package/dist/ports/project-inventory-inspector.js +1 -0
- package/dist/ports/project-module-discoverer.d.ts +26 -0
- package/dist/ports/project-module-discoverer.js +1 -0
- package/dist/ports/recorder-prompt.d.ts +10 -1
- package/dist/ports/runtime-backend.d.ts +89 -0
- package/dist/ports/runtime-backend.js +13 -0
- package/dist/ports/runtime-capability.d.ts +12 -0
- package/dist/ports/runtime-capability.js +20 -0
- package/dist/ports/runtime-session-ports.d.ts +25 -0
- package/dist/ports/runtime-session-ports.js +1 -0
- package/dist/ports/screenshot.d.ts +11 -0
- package/dist/ports/screenshot.js +1 -0
- package/dist/ports/skill-installer.d.ts +2 -2
- package/dist/ports/ui-snapshot.d.ts +35 -0
- package/dist/ports/ui-snapshot.js +1 -0
- package/dist/ports/ui-stability.d.ts +19 -0
- package/dist/ports/ui-stability.js +1 -0
- package/dist/ports/workspace-layout.d.ts +4 -0
- package/dist/ports/workspace-layout.js +1 -0
- package/dist/shared/errors.d.ts +2 -0
- package/dist/shared/errors.js +22 -0
- package/dist/shared/paths.d.ts +2 -0
- package/dist/shared/paths.js +24 -0
- package/dist/shared/strings.d.ts +2 -0
- package/dist/shared/strings.js +16 -0
- package/package.json +7 -2
- package/assets/skills/taphound-ai-journey/GUIDE.md +0 -862
- package/assets/skills/taphound-ai-journey/SKILL.md +0 -377
- package/assets/skills/taphound-ai-journey/prompts/analyze-project.md +0 -526
- package/assets/skills/taphound-ai-journey/prompts/generate-step.md +0 -109
- package/assets/skills/taphound-ai-journey/schemas/project-context.json +0 -81
- package/assets/skills/taphound-ai-journey/templates/project-context.example.json +0 -49
- package/dist/ports/android-cli.d.ts +0 -21
- /package/dist/{ports/android-cli.js → adapters/runtime/mobile-mcp/mobile-mcp-tools.js} +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AdbPort, AppIdentity, DeviceIdentity, DeviceInfo, DumpLogcatOptions, LaunchActivityOptions, LogcatOptions, ResolvedActivity, StartActivityByIntentOptions } from "../../ports/adb.js";
|
|
2
|
+
import type { CommandResult, RunningCommand } from "../../ports/process-runner.js";
|
|
3
|
+
import type { RuntimeSession } from "../../ports/runtime-backend.js";
|
|
4
|
+
import type { RuntimeSessionPortViews } from "../../ports/runtime-session-ports.js";
|
|
5
|
+
import type { ScreenshotOptions, ScreenshotPort } from "../../ports/screenshot.js";
|
|
6
|
+
import type { Point } from "../../domain/geometry.js";
|
|
7
|
+
import type { ForegroundComponent } from "../../domain/activity.js";
|
|
8
|
+
import type { AppProcess } from "../../domain/app-process.js";
|
|
9
|
+
import type { WindowTopology } from "../../domain/window-hierarchy.js";
|
|
10
|
+
/**
|
|
11
|
+
* One borrowed `RuntimeSession` exposed as the legacy `AdbPort`. The view
|
|
12
|
+
* holds a single already-opened session: the serial in every call must match
|
|
13
|
+
* the session's bound serial, and device discovery belongs to
|
|
14
|
+
* `RuntimeBackend.listDevices`. Level 1 session-first orchestrators feed their
|
|
15
|
+
* `AdbPort`-shaped helpers through this view until Level 2 retypes them.
|
|
16
|
+
*/
|
|
17
|
+
export declare class RuntimeSessionAdbView implements AdbPort {
|
|
18
|
+
private readonly session;
|
|
19
|
+
constructor(session: RuntimeSession);
|
|
20
|
+
devices(): Promise<readonly DeviceInfo[]>;
|
|
21
|
+
foregroundComponent(identity: AppIdentity): Promise<ForegroundComponent>;
|
|
22
|
+
currentActivity(identity: AppIdentity): Promise<string>;
|
|
23
|
+
deviceIdentity(identity: AppIdentity): Promise<DeviceIdentity>;
|
|
24
|
+
isInstalled(identity: AppIdentity): Promise<boolean>;
|
|
25
|
+
launchActivity(options: LaunchActivityOptions): Promise<CommandResult>;
|
|
26
|
+
startActivityByIntent(options: StartActivityByIntentOptions): Promise<CommandResult>;
|
|
27
|
+
resolveLauncherActivity(): Promise<ResolvedActivity | undefined>;
|
|
28
|
+
forceStop(identity: AppIdentity): Promise<CommandResult>;
|
|
29
|
+
appProcesses(identity: AppIdentity): Promise<readonly AppProcess[]>;
|
|
30
|
+
windowTopology(identity: AppIdentity): Promise<WindowTopology>;
|
|
31
|
+
tap(point: Point, deviceSerial: string, signal?: AbortSignal): Promise<CommandResult>;
|
|
32
|
+
longClick(point: Point, durationMs: number, deviceSerial: string, signal?: AbortSignal): Promise<CommandResult>;
|
|
33
|
+
swipe(from: Point, to: Point, durationMs: number, deviceSerial: string, signal?: AbortSignal): Promise<CommandResult>;
|
|
34
|
+
back(deviceSerial: string, signal?: AbortSignal): Promise<CommandResult>;
|
|
35
|
+
inputText(text: string, deviceSerial: string, signal?: AbortSignal): Promise<CommandResult>;
|
|
36
|
+
startLogcat(options: LogcatOptions): RunningCommand;
|
|
37
|
+
dumpLogcat(options: DumpLogcatOptions): Promise<CommandResult>;
|
|
38
|
+
private assertBoundSerial;
|
|
39
|
+
}
|
|
40
|
+
/** One borrowed session exposed as the serial-keyed `ScreenshotPort`. */
|
|
41
|
+
export declare class SessionBoundScreenshotAdapter implements ScreenshotPort {
|
|
42
|
+
private readonly session;
|
|
43
|
+
constructor(session: RuntimeSession);
|
|
44
|
+
capture(options: ScreenshotOptions): Promise<CommandResult>;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Legacy port views for one borrowed session: the `AdbPort` view above, a
|
|
48
|
+
* session-bound screenshot port, the session's annotated-screen resolver
|
|
49
|
+
* (fail-closed when the backend lacks the capability), and the required UI
|
|
50
|
+
* stability probe. Session-first orchestrators pass these views to helpers
|
|
51
|
+
* that still speak the legacy port types.
|
|
52
|
+
*/
|
|
53
|
+
export declare function runtimeSessionPortViews(session: RuntimeSession): RuntimeSessionPortViews;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { runtimeCapabilityMissing } from "../../ports/runtime-capability.js";
|
|
2
|
+
import { FailClosedAnnotatedScreenResolver } from "./session-backed-ports.js";
|
|
3
|
+
function appQuery(identity) {
|
|
4
|
+
return {
|
|
5
|
+
packageName: identity.packageName,
|
|
6
|
+
...(identity.signal === undefined ? {} : { signal: identity.signal }),
|
|
7
|
+
...(identity.timeoutMs === undefined
|
|
8
|
+
? {}
|
|
9
|
+
: { timeoutMs: identity.timeoutMs })
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function launchOptions(options) {
|
|
13
|
+
return {
|
|
14
|
+
packageName: options.packageName,
|
|
15
|
+
activity: options.activity,
|
|
16
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
17
|
+
...(options.timeoutMs === undefined
|
|
18
|
+
? {}
|
|
19
|
+
: { timeoutMs: options.timeoutMs })
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One borrowed `RuntimeSession` exposed as the legacy `AdbPort`. The view
|
|
24
|
+
* holds a single already-opened session: the serial in every call must match
|
|
25
|
+
* the session's bound serial, and device discovery belongs to
|
|
26
|
+
* `RuntimeBackend.listDevices`. Level 1 session-first orchestrators feed their
|
|
27
|
+
* `AdbPort`-shaped helpers through this view until Level 2 retypes them.
|
|
28
|
+
*/
|
|
29
|
+
export class RuntimeSessionAdbView {
|
|
30
|
+
session;
|
|
31
|
+
constructor(session) {
|
|
32
|
+
this.session = session;
|
|
33
|
+
}
|
|
34
|
+
devices() {
|
|
35
|
+
return Promise.reject(new Error("Device discovery is not available through a runtime session view; "
|
|
36
|
+
+ "use the runtime backend instead"));
|
|
37
|
+
}
|
|
38
|
+
async foregroundComponent(identity) {
|
|
39
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
40
|
+
if (this.session.foregroundComponent === undefined) {
|
|
41
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "foregroundComponent");
|
|
42
|
+
}
|
|
43
|
+
return this.session.foregroundComponent(appQuery(identity));
|
|
44
|
+
}
|
|
45
|
+
async currentActivity(identity) {
|
|
46
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
47
|
+
if (this.session.currentActivity === undefined) {
|
|
48
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "currentActivity");
|
|
49
|
+
}
|
|
50
|
+
return this.session.currentActivity(appQuery(identity));
|
|
51
|
+
}
|
|
52
|
+
async deviceIdentity(identity) {
|
|
53
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
54
|
+
if (this.session.deviceIdentity === undefined) {
|
|
55
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "deviceIdentity");
|
|
56
|
+
}
|
|
57
|
+
return this.session.deviceIdentity(appQuery(identity));
|
|
58
|
+
}
|
|
59
|
+
async isInstalled(identity) {
|
|
60
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
61
|
+
return this.session.isInstalled(appQuery(identity));
|
|
62
|
+
}
|
|
63
|
+
async launchActivity(options) {
|
|
64
|
+
this.assertBoundSerial(options.deviceSerial);
|
|
65
|
+
return this.session.launchApp(launchOptions(options));
|
|
66
|
+
}
|
|
67
|
+
async startActivityByIntent(options) {
|
|
68
|
+
this.assertBoundSerial(options.deviceSerial);
|
|
69
|
+
if (this.session.startActivityByIntent === undefined) {
|
|
70
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "startActivityByIntent");
|
|
71
|
+
}
|
|
72
|
+
return this.session.startActivityByIntent({
|
|
73
|
+
action: options.action,
|
|
74
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
75
|
+
...(options.timeoutMs === undefined
|
|
76
|
+
? {}
|
|
77
|
+
: { timeoutMs: options.timeoutMs })
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
resolveLauncherActivity() {
|
|
81
|
+
return Promise.reject(new Error("resolveLauncherActivity is not available through the runtime backend SPI"));
|
|
82
|
+
}
|
|
83
|
+
async forceStop(identity) {
|
|
84
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
85
|
+
return this.session.forceStop(appQuery(identity));
|
|
86
|
+
}
|
|
87
|
+
async appProcesses(identity) {
|
|
88
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
89
|
+
if (this.session.appProcesses === undefined) {
|
|
90
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "appProcesses");
|
|
91
|
+
}
|
|
92
|
+
return this.session.appProcesses(appQuery(identity));
|
|
93
|
+
}
|
|
94
|
+
async windowTopology(identity) {
|
|
95
|
+
this.assertBoundSerial(identity.deviceSerial);
|
|
96
|
+
if (this.session.windowTopology === undefined) {
|
|
97
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "windowTopology");
|
|
98
|
+
}
|
|
99
|
+
return this.session.windowTopology(appQuery(identity));
|
|
100
|
+
}
|
|
101
|
+
async tap(point, deviceSerial, signal) {
|
|
102
|
+
this.assertBoundSerial(deviceSerial);
|
|
103
|
+
return this.session.tap(point, signal);
|
|
104
|
+
}
|
|
105
|
+
async longClick(point, durationMs, deviceSerial, signal) {
|
|
106
|
+
this.assertBoundSerial(deviceSerial);
|
|
107
|
+
return this.session.longClick(point, durationMs, signal);
|
|
108
|
+
}
|
|
109
|
+
async swipe(from, to, durationMs, deviceSerial, signal) {
|
|
110
|
+
this.assertBoundSerial(deviceSerial);
|
|
111
|
+
return this.session.swipe(from, to, durationMs, signal);
|
|
112
|
+
}
|
|
113
|
+
async back(deviceSerial, signal) {
|
|
114
|
+
this.assertBoundSerial(deviceSerial);
|
|
115
|
+
return this.session.back(signal);
|
|
116
|
+
}
|
|
117
|
+
async inputText(text, deviceSerial, signal) {
|
|
118
|
+
this.assertBoundSerial(deviceSerial);
|
|
119
|
+
return this.session.inputText(text, signal);
|
|
120
|
+
}
|
|
121
|
+
startLogcat(options) {
|
|
122
|
+
this.assertBoundSerial(options.deviceSerial);
|
|
123
|
+
if (this.session.startLogcat === undefined) {
|
|
124
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "startLogcat");
|
|
125
|
+
}
|
|
126
|
+
const running = this.session.startLogcat({
|
|
127
|
+
onStdoutLine: options.onStdoutLine,
|
|
128
|
+
...(options.onStderrLine === undefined
|
|
129
|
+
? {}
|
|
130
|
+
: { onStderrLine: options.onStderrLine }),
|
|
131
|
+
...(options.signal === undefined ? {} : { signal: options.signal })
|
|
132
|
+
});
|
|
133
|
+
return {
|
|
134
|
+
started: running.started,
|
|
135
|
+
completion: running.completion,
|
|
136
|
+
stop: () => running.stop()
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
async dumpLogcat(options) {
|
|
140
|
+
this.assertBoundSerial(options.deviceSerial);
|
|
141
|
+
if (this.session.dumpLogcat === undefined) {
|
|
142
|
+
throw runtimeCapabilityMissing(this.session.descriptor.id, "dumpLogcat");
|
|
143
|
+
}
|
|
144
|
+
return this.session.dumpLogcat({
|
|
145
|
+
maxLines: options.maxLines,
|
|
146
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
147
|
+
...(options.timeoutMs === undefined
|
|
148
|
+
? {}
|
|
149
|
+
: { timeoutMs: options.timeoutMs })
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
assertBoundSerial(deviceSerial) {
|
|
153
|
+
if (deviceSerial !== this.session.deviceSerial) {
|
|
154
|
+
throw new Error(`Runtime session bound to "${this.session.deviceSerial}" cannot `
|
|
155
|
+
+ `serve device "${deviceSerial}"`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** One borrowed session exposed as the serial-keyed `ScreenshotPort`. */
|
|
160
|
+
export class SessionBoundScreenshotAdapter {
|
|
161
|
+
session;
|
|
162
|
+
constructor(session) {
|
|
163
|
+
this.session = session;
|
|
164
|
+
}
|
|
165
|
+
capture(options) {
|
|
166
|
+
if (options.deviceSerial !== this.session.deviceSerial) {
|
|
167
|
+
return Promise.reject(new Error(`Runtime session bound to "${this.session.deviceSerial}" cannot `
|
|
168
|
+
+ `serve device "${options.deviceSerial}"`));
|
|
169
|
+
}
|
|
170
|
+
return this.session.captureScreenshot({
|
|
171
|
+
outputPath: options.outputPath,
|
|
172
|
+
...(options.annotate === undefined ? {} : { annotate: options.annotate }),
|
|
173
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
174
|
+
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs })
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Legacy port views for one borrowed session: the `AdbPort` view above, a
|
|
180
|
+
* session-bound screenshot port, the session's annotated-screen resolver
|
|
181
|
+
* (fail-closed when the backend lacks the capability), and the required UI
|
|
182
|
+
* stability probe. Session-first orchestrators pass these views to helpers
|
|
183
|
+
* that still speak the legacy port types.
|
|
184
|
+
*/
|
|
185
|
+
export function runtimeSessionPortViews(session) {
|
|
186
|
+
return {
|
|
187
|
+
adb: new RuntimeSessionAdbView(session),
|
|
188
|
+
screenshots: new SessionBoundScreenshotAdapter(session),
|
|
189
|
+
annotatedScreens: session.annotatedScreens
|
|
190
|
+
?? new FailClosedAnnotatedScreenResolver(session.descriptor.id),
|
|
191
|
+
uiStability: session.uiStability
|
|
192
|
+
};
|
|
193
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Point } from "../../domain/geometry.js";
|
|
2
|
+
import type { AnnotatedScreenResolverPort } from "../../ports/annotated-screen-resolver.js";
|
|
3
|
+
import type { CommandResult } from "../../ports/process-runner.js";
|
|
4
|
+
import type { RuntimeSessionOpener } from "../../ports/runtime-backend.js";
|
|
5
|
+
import type { ScreenshotOptions, ScreenshotPort } from "../../ports/screenshot.js";
|
|
6
|
+
import type { OpenUiSnapshotProviderOptions, UiSnapshotProvider, UiSnapshotProviderFactory } from "../../ports/ui-snapshot.js";
|
|
7
|
+
export declare class SessionBackedScreenshotAdapter implements ScreenshotPort {
|
|
8
|
+
private readonly sessions;
|
|
9
|
+
constructor(sessions: RuntimeSessionOpener);
|
|
10
|
+
capture(options: ScreenshotOptions): Promise<CommandResult>;
|
|
11
|
+
}
|
|
12
|
+
export declare class SessionBackedUiSnapshotProviderFactory implements UiSnapshotProviderFactory {
|
|
13
|
+
private readonly sessions;
|
|
14
|
+
constructor(sessions: RuntimeSessionOpener);
|
|
15
|
+
open(options: OpenUiSnapshotProviderOptions): Promise<UiSnapshotProvider>;
|
|
16
|
+
}
|
|
17
|
+
export declare class FailClosedAnnotatedScreenResolver implements AnnotatedScreenResolverPort {
|
|
18
|
+
private readonly backendId;
|
|
19
|
+
constructor(backendId: string);
|
|
20
|
+
resolve(): Promise<Point>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { runtimeCapabilityMissing } from "../../ports/runtime-capability.js";
|
|
2
|
+
export class SessionBackedScreenshotAdapter {
|
|
3
|
+
sessions;
|
|
4
|
+
constructor(sessions) {
|
|
5
|
+
this.sessions = sessions;
|
|
6
|
+
}
|
|
7
|
+
capture(options) {
|
|
8
|
+
return this.sessions.openSession({
|
|
9
|
+
deviceSerial: options.deviceSerial,
|
|
10
|
+
...(options.signal === undefined ? {} : { signal: options.signal })
|
|
11
|
+
}).then((session) => (session.captureScreenshot({
|
|
12
|
+
outputPath: options.outputPath,
|
|
13
|
+
...(options.annotate === undefined ? {} : { annotate: options.annotate }),
|
|
14
|
+
...(options.signal === undefined ? {} : { signal: options.signal }),
|
|
15
|
+
...(options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs })
|
|
16
|
+
})));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export class SessionBackedUiSnapshotProviderFactory {
|
|
20
|
+
sessions;
|
|
21
|
+
constructor(sessions) {
|
|
22
|
+
this.sessions = sessions;
|
|
23
|
+
}
|
|
24
|
+
open(options) {
|
|
25
|
+
return this.sessions.openSession({
|
|
26
|
+
deviceSerial: options.deviceSerial,
|
|
27
|
+
...(options.signal === undefined ? {} : { signal: options.signal })
|
|
28
|
+
}).then((session) => (session.openUiSnapshots({
|
|
29
|
+
timeoutMs: options.timeoutMs,
|
|
30
|
+
...(options.backend === undefined ? {} : { backend: options.backend }),
|
|
31
|
+
...(options.signal === undefined ? {} : { signal: options.signal })
|
|
32
|
+
})));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class FailClosedAnnotatedScreenResolver {
|
|
36
|
+
backendId;
|
|
37
|
+
constructor(backendId) {
|
|
38
|
+
this.backendId = backendId;
|
|
39
|
+
}
|
|
40
|
+
resolve() {
|
|
41
|
+
return Promise.reject(runtimeCapabilityMissing(this.backendId, "annotated screens"));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DeviceInfo } from "../../domain/runtime.js";
|
|
2
|
+
import type { OpenRuntimeSessionOptions, RuntimeBackend, RuntimeSession } from "../../ports/runtime-backend.js";
|
|
3
|
+
export declare class SharedSessionRuntimeBackend implements RuntimeBackend {
|
|
4
|
+
private readonly backend;
|
|
5
|
+
private readonly sessions;
|
|
6
|
+
constructor(backend: RuntimeBackend);
|
|
7
|
+
get descriptor(): RuntimeBackend["descriptor"];
|
|
8
|
+
get capabilities(): RuntimeBackend["capabilities"];
|
|
9
|
+
listDevices(signal?: AbortSignal): Promise<readonly DeviceInfo[]>;
|
|
10
|
+
openSession(options: OpenRuntimeSessionOptions): Promise<RuntimeSession>;
|
|
11
|
+
close(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
function borrowedProvider(provider) {
|
|
2
|
+
return new Proxy(provider, {
|
|
3
|
+
get(target, property, receiver) {
|
|
4
|
+
if (property === "close") {
|
|
5
|
+
return () => Promise.resolve();
|
|
6
|
+
}
|
|
7
|
+
const value = Reflect.get(target, property, receiver);
|
|
8
|
+
return typeof value === "function"
|
|
9
|
+
? value.bind(target)
|
|
10
|
+
: value;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
function borrowedSession(session) {
|
|
15
|
+
return new Proxy(session, {
|
|
16
|
+
get(target, property, receiver) {
|
|
17
|
+
if (property === "close") {
|
|
18
|
+
return () => Promise.resolve();
|
|
19
|
+
}
|
|
20
|
+
if (property === "openUiSnapshots") {
|
|
21
|
+
return async (options) => borrowedProvider(await target.openUiSnapshots(options));
|
|
22
|
+
}
|
|
23
|
+
const value = Reflect.get(target, property, receiver);
|
|
24
|
+
return typeof value === "function"
|
|
25
|
+
? value.bind(target)
|
|
26
|
+
: value;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export class SharedSessionRuntimeBackend {
|
|
31
|
+
backend;
|
|
32
|
+
sessions = new Map();
|
|
33
|
+
constructor(backend) {
|
|
34
|
+
this.backend = backend;
|
|
35
|
+
}
|
|
36
|
+
get descriptor() {
|
|
37
|
+
return this.backend.descriptor;
|
|
38
|
+
}
|
|
39
|
+
get capabilities() {
|
|
40
|
+
return this.backend.capabilities;
|
|
41
|
+
}
|
|
42
|
+
listDevices(signal) {
|
|
43
|
+
return this.backend.listDevices(signal);
|
|
44
|
+
}
|
|
45
|
+
openSession(options) {
|
|
46
|
+
const existing = this.sessions.get(options.deviceSerial);
|
|
47
|
+
if (existing !== undefined) {
|
|
48
|
+
return existing.then(borrowedSession);
|
|
49
|
+
}
|
|
50
|
+
const opened = this.backend.openSession(options);
|
|
51
|
+
opened.catch(() => {
|
|
52
|
+
if (this.sessions.get(options.deviceSerial) === opened) {
|
|
53
|
+
this.sessions.delete(options.deviceSerial);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.sessions.set(options.deviceSerial, opened);
|
|
57
|
+
return opened.then(borrowedSession);
|
|
58
|
+
}
|
|
59
|
+
async close() {
|
|
60
|
+
const sessions = [...this.sessions.values()];
|
|
61
|
+
this.sessions.clear();
|
|
62
|
+
await Promise.all(sessions.map((session) => (session.then((opened) => opened.close(), () => undefined))));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { OpenUiSnapshotProviderOptions, UiSnapshotProvider, UiSnapshotProviderFactory } from "../../ports/ui-snapshot.js";
|
|
2
|
+
export declare class AutoUiSnapshotProviderFactory implements UiSnapshotProviderFactory {
|
|
3
|
+
private readonly system;
|
|
4
|
+
private readonly androidCli;
|
|
5
|
+
private readonly appium?;
|
|
6
|
+
constructor(system: UiSnapshotProviderFactory, androidCli: UiSnapshotProviderFactory, appium?: UiSnapshotProviderFactory | undefined);
|
|
7
|
+
open(options: OpenUiSnapshotProviderOptions): Promise<UiSnapshotProvider>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { UiSnapshotError } from "./ui-snapshot-error.js";
|
|
2
|
+
export class AutoUiSnapshotProviderFactory {
|
|
3
|
+
system;
|
|
4
|
+
androidCli;
|
|
5
|
+
appium;
|
|
6
|
+
constructor(system, androidCli, appium) {
|
|
7
|
+
this.system = system;
|
|
8
|
+
this.androidCli = androidCli;
|
|
9
|
+
this.appium = appium;
|
|
10
|
+
}
|
|
11
|
+
async open(options) {
|
|
12
|
+
if (options.backend === "system-uiautomator") {
|
|
13
|
+
return this.system.open(options);
|
|
14
|
+
}
|
|
15
|
+
if (options.backend === "android-cli") {
|
|
16
|
+
return this.androidCli.open(options);
|
|
17
|
+
}
|
|
18
|
+
if (options.backend === "appium-uiautomator2") {
|
|
19
|
+
if (this.appium !== undefined)
|
|
20
|
+
return this.appium.open(options);
|
|
21
|
+
throw new UiSnapshotError("UI_BACKEND_UNAVAILABLE", "appium-uiautomator2", "Appium UiAutomator2 provider is not installed");
|
|
22
|
+
}
|
|
23
|
+
const appium = this.appium;
|
|
24
|
+
const probe = appium;
|
|
25
|
+
if (probe?.probe !== undefined && await probe.probe(options.timeoutMs)) {
|
|
26
|
+
try {
|
|
27
|
+
return await appium.open(options);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (!isAutoFallbackable(error))
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return await this.system.open(options);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (!isAutoFallbackable(error))
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
return this.androidCli.open(options);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isAutoFallbackable(error) {
|
|
45
|
+
return error instanceof UiSnapshotError
|
|
46
|
+
&& (error.code === "UI_BACKEND_UNAVAILABLE"
|
|
47
|
+
|| error.code === "UI_SNAPSHOT_INVALID");
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ProcessRunner } from "../../ports/process-runner.js";
|
|
2
|
+
export declare const DEVICE_LAYOUT_TEMP_PREFIX = "/data/local/tmp/taphound-uiautomator-";
|
|
3
|
+
export declare const DEVICE_LAYOUT_TEMP_GLOB = "/data/local/tmp/taphound-uiautomator-*.xml";
|
|
4
|
+
export declare const DEVICE_LAYOUT_TEMP_SWEEP_TIMEOUT_MS = 5000;
|
|
5
|
+
export declare function createDeviceLayoutPath(): string;
|
|
6
|
+
export declare function sweepDeviceLayoutTemp(runner: ProcessRunner, deviceSerial: string, signal?: AbortSignal): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
export const DEVICE_LAYOUT_TEMP_PREFIX = "/data/local/tmp/taphound-uiautomator-";
|
|
3
|
+
export const DEVICE_LAYOUT_TEMP_GLOB = `${DEVICE_LAYOUT_TEMP_PREFIX}*.xml`;
|
|
4
|
+
export const DEVICE_LAYOUT_TEMP_SWEEP_TIMEOUT_MS = 5000;
|
|
5
|
+
export function createDeviceLayoutPath() {
|
|
6
|
+
return `${DEVICE_LAYOUT_TEMP_PREFIX}${randomUUID()}.xml`;
|
|
7
|
+
}
|
|
8
|
+
export async function sweepDeviceLayoutTemp(runner, deviceSerial, signal) {
|
|
9
|
+
if (signal?.aborted === true) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
await runner.run({
|
|
13
|
+
executable: "adb",
|
|
14
|
+
args: ["-s", deviceSerial, "shell", "rm", "-f", DEVICE_LAYOUT_TEMP_GLOB],
|
|
15
|
+
timeoutMs: DEVICE_LAYOUT_TEMP_SWEEP_TIMEOUT_MS,
|
|
16
|
+
...(signal === undefined ? {} : { signal })
|
|
17
|
+
}).catch(() => undefined);
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type DisplayViewport } from "../../domain/geometry.js";
|
|
2
|
+
import type { UiBackendDescriptor } from "../../domain/ui-backend.js";
|
|
3
|
+
import type { ProcessRunner } from "../../ports/process-runner.js";
|
|
4
|
+
export interface DeviceUiEnvironment {
|
|
5
|
+
sdkLevel: number;
|
|
6
|
+
viewport: DisplayViewport;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseDisplayRotation(dumpsysInput: string): DisplayViewport["rotation"] | undefined;
|
|
9
|
+
export declare function readDeviceUiEnvironment(runner: ProcessRunner, backendId: UiBackendDescriptor["id"], options: {
|
|
10
|
+
deviceSerial: string;
|
|
11
|
+
timeoutMs: number;
|
|
12
|
+
signal?: AbortSignal | undefined;
|
|
13
|
+
}): Promise<DeviceUiEnvironment>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
import { DisplayViewportSchema } from "../../domain/geometry.js";
|
|
3
|
+
import { UiSnapshotError } from "./ui-snapshot-error.js";
|
|
4
|
+
function usable(result) {
|
|
5
|
+
return result.exitCode === 0
|
|
6
|
+
&& !result.timedOut
|
|
7
|
+
&& !result.cancelled
|
|
8
|
+
&& result.spawnError === undefined;
|
|
9
|
+
}
|
|
10
|
+
function message(result, fallback) {
|
|
11
|
+
return result.stderr.trim() || result.spawnError || fallback;
|
|
12
|
+
}
|
|
13
|
+
export function parseDisplayRotation(dumpsysInput) {
|
|
14
|
+
const orientation = /SurfaceOrientation:\s*([0-3])/i.exec(dumpsysInput)?.[1]
|
|
15
|
+
?? /Viewport[^\n]*\borientation=([0-3])\b/i.exec(dumpsysInput)?.[1];
|
|
16
|
+
if (orientation !== undefined) {
|
|
17
|
+
return [0, 90, 180, 270][Number(orientation)];
|
|
18
|
+
}
|
|
19
|
+
const rotationIndex = /\bRotation([0-3])\b/i.exec(dumpsysInput)?.[1];
|
|
20
|
+
if (rotationIndex !== undefined) {
|
|
21
|
+
return [0, 90, 180, 270][Number(rotationIndex)];
|
|
22
|
+
}
|
|
23
|
+
const degrees = /\bROT_(0|90|180|270)\b/i.exec(dumpsysInput)?.[1];
|
|
24
|
+
if (degrees === undefined)
|
|
25
|
+
return undefined;
|
|
26
|
+
const parsed = Number(degrees);
|
|
27
|
+
return parsed === 0 || parsed === 90 || parsed === 180 || parsed === 270
|
|
28
|
+
? parsed
|
|
29
|
+
: undefined;
|
|
30
|
+
}
|
|
31
|
+
export async function readDeviceUiEnvironment(runner, backendId, options) {
|
|
32
|
+
const startedAt = performance.now();
|
|
33
|
+
const run = async (args) => {
|
|
34
|
+
const remainingMs = Math.max(1, options.timeoutMs - (performance.now() - startedAt));
|
|
35
|
+
const result = await runner.run({
|
|
36
|
+
executable: "adb",
|
|
37
|
+
args: ["-s", options.deviceSerial, ...args],
|
|
38
|
+
timeoutMs: remainingMs,
|
|
39
|
+
...(options.signal === undefined ? {} : { signal: options.signal })
|
|
40
|
+
});
|
|
41
|
+
if (!usable(result)) {
|
|
42
|
+
throw new UiSnapshotError(result.timedOut || result.cancelled
|
|
43
|
+
? "UI_SNAPSHOT_FAILED"
|
|
44
|
+
: "UI_BACKEND_UNAVAILABLE", backendId, message(result, `Unable to inspect device UI environment`));
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
const sdkResult = await run([
|
|
49
|
+
"shell",
|
|
50
|
+
"getprop",
|
|
51
|
+
"ro.build.version.sdk"
|
|
52
|
+
]);
|
|
53
|
+
const sdkLevel = Number(sdkResult.stdout.trim());
|
|
54
|
+
if (!Number.isSafeInteger(sdkLevel)) {
|
|
55
|
+
throw new UiSnapshotError("UI_BACKEND_UNAVAILABLE", backendId, "Device returned an invalid Android SDK level");
|
|
56
|
+
}
|
|
57
|
+
if (sdkLevel < 26) {
|
|
58
|
+
throw new UiSnapshotError("UI_BACKEND_UNAVAILABLE", backendId, `UI snapshots require Android API 26 or newer; device is API ${String(sdkLevel)}`);
|
|
59
|
+
}
|
|
60
|
+
const sizeResult = await run(["shell", "wm", "size"]);
|
|
61
|
+
const size = /(?:Physical size:\s*)?(\d+)x(\d+)/i.exec(sizeResult.stdout);
|
|
62
|
+
const width = Number(size?.[1]);
|
|
63
|
+
const height = Number(size?.[2]);
|
|
64
|
+
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height)) {
|
|
65
|
+
throw new UiSnapshotError("UI_BACKEND_UNAVAILABLE", backendId, "Device returned an invalid physical display size");
|
|
66
|
+
}
|
|
67
|
+
const rotationResult = await run(["shell", "dumpsys", "input"]);
|
|
68
|
+
const rotation = parseDisplayRotation(rotationResult.stdout);
|
|
69
|
+
if (rotation === undefined) {
|
|
70
|
+
throw new UiSnapshotError("UI_BACKEND_UNAVAILABLE", backendId, "Device returned an invalid display rotation");
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
sdkLevel,
|
|
74
|
+
viewport: DisplayViewportSchema.parse({
|
|
75
|
+
width,
|
|
76
|
+
height,
|
|
77
|
+
rotation,
|
|
78
|
+
coordinateSpace: "physicalDisplayPixels"
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Bounds } from "../../domain/layout.js";
|
|
2
|
+
export declare function normalizeResourceId(value: string | undefined): string | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Hot-path variant for already-numeric edges (one call per parsed node).
|
|
5
|
+
* Enforces the same contract as `RawBoundsSchema` plus `BoundsSchema`
|
|
6
|
+
* without allocating Zod issues for valid input.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeBoundsEdges(left: number, top: number, right: number, bottom: number): Bounds | undefined;
|
|
9
|
+
export declare function normalizeBounds(value: unknown): Bounds | undefined;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { BoundsSchema } from "../../domain/layout.js";
|
|
3
|
+
const RawBoundsSchema = z.strictObject({
|
|
4
|
+
left: z.number().int().nonnegative(),
|
|
5
|
+
top: z.number().int().nonnegative(),
|
|
6
|
+
right: z.number().int().nonnegative(),
|
|
7
|
+
bottom: z.number().int().nonnegative()
|
|
8
|
+
});
|
|
9
|
+
export function normalizeResourceId(value) {
|
|
10
|
+
if (value === undefined || value.length === 0)
|
|
11
|
+
return undefined;
|
|
12
|
+
const separator = value.lastIndexOf(":id/");
|
|
13
|
+
return separator >= 0 ? value.slice(separator + 4) : value;
|
|
14
|
+
}
|
|
15
|
+
function isEdge(value) {
|
|
16
|
+
return Number.isSafeInteger(value) && value >= 0;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Hot-path variant for already-numeric edges (one call per parsed node).
|
|
20
|
+
* Enforces the same contract as `RawBoundsSchema` plus `BoundsSchema`
|
|
21
|
+
* without allocating Zod issues for valid input.
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeBoundsEdges(left, top, right, bottom) {
|
|
24
|
+
if (!isEdge(left) || !isEdge(top) || !isEdge(right) || !isEdge(bottom)) {
|
|
25
|
+
return normalizeBounds({ left, top, right, bottom });
|
|
26
|
+
}
|
|
27
|
+
if (right < left || bottom < top) {
|
|
28
|
+
throw new Error("Bounds edges are reversed");
|
|
29
|
+
}
|
|
30
|
+
if (right === left || bottom === top) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return { left, top, right, bottom };
|
|
34
|
+
}
|
|
35
|
+
export function normalizeBounds(value) {
|
|
36
|
+
const raw = RawBoundsSchema.parse(value);
|
|
37
|
+
if (raw.right < raw.left || raw.bottom < raw.top) {
|
|
38
|
+
throw new Error("Bounds edges are reversed");
|
|
39
|
+
}
|
|
40
|
+
if (raw.right === raw.left || raw.bottom === raw.top) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return BoundsSchema.parse(raw);
|
|
44
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { UiBackendDescriptor } from "../../domain/ui-backend.js";
|
|
2
|
+
export type UiSnapshotErrorCode = "UI_BACKEND_UNAVAILABLE" | "UI_SNAPSHOT_FAILED" | "UI_SNAPSHOT_INVALID";
|
|
3
|
+
export declare class UiSnapshotError extends Error {
|
|
4
|
+
readonly code: UiSnapshotErrorCode;
|
|
5
|
+
readonly backendId: UiBackendDescriptor["id"];
|
|
6
|
+
readonly name = "UiSnapshotError";
|
|
7
|
+
readonly terminal: boolean;
|
|
8
|
+
constructor(code: UiSnapshotErrorCode, backendId: UiBackendDescriptor["id"], message: string, options?: ErrorOptions & {
|
|
9
|
+
terminal?: boolean | undefined;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class UiSnapshotError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
backendId;
|
|
4
|
+
name = "UiSnapshotError";
|
|
5
|
+
terminal;
|
|
6
|
+
constructor(code, backendId, message, options) {
|
|
7
|
+
super(message, options);
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.backendId = backendId;
|
|
10
|
+
this.terminal = options?.terminal ?? false;
|
|
11
|
+
}
|
|
12
|
+
}
|