mobile-debug-mcp 0.33.0 → 0.35.0
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/.agents/skills/mcp-builder/SKILL.md +44 -64
- package/.agents/skills/mcp-builder/references/build-flags.md +44 -43
- package/.agents/skills/mcp-builder/references/diagnostics-schema.md +4 -1
- package/.agents/skills/mcp-builder/references/toolchain-details.md +49 -62
- package/.agents/skills/spec-review/references/spec-review-checklist.md +7 -0
- package/.agents/skills/test-authoring/SKILL.md +7 -6
- package/.agents/skills/test-authoring/references/repo-test-layout.md +3 -1
- package/.agents/skills/test-authoring/references/test-authoring-workflow.md +16 -7
- package/.agents/skills/test-authoring/references/test-quality-checklist.md +2 -1
- package/.github/copilot-instructions.md +14 -36
- package/.github/workflows/ci.yml +23 -2
- package/AGENTS.md +12 -3
- package/CONTRIBUTING.md +79 -0
- package/README.md +158 -124
- package/agent-plugin/.claude-plugin/plugin.json +2 -2
- package/agent-plugin/.codex-plugin/plugin.json +1 -1
- package/agent-plugin/.cursor-plugin/plugin.json +2 -2
- package/agent-plugin/.mcp.json +1 -1
- package/agent-plugin/README.md +20 -6
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +113 -4
- package/dist/contracts/execution-controls.js +24 -0
- package/dist/contracts/selector.js +8 -0
- package/dist/contracts/target.js +15 -0
- package/dist/contracts/ui.js +1 -0
- package/dist/debugger/android.js +79 -0
- package/dist/debugger/diagnostics.js +54 -0
- package/dist/debugger/guard.js +30 -0
- package/dist/debugger/protocol.js +33 -0
- package/dist/debugger/sessions.js +304 -0
- package/dist/debugger/worker.js +176 -0
- package/dist/interact/adjustment/adjustment-context.js +41 -0
- package/dist/interact/adjustment/adjustment-gestures.js +55 -0
- package/dist/interact/adjustment/adjustment-plan.js +18 -0
- package/dist/interact/adjustment/adjustment-resolution.js +127 -0
- package/dist/interact/adjustment/adjustment-result.js +19 -0
- package/dist/interact/adjustment/adjustment-semantic.js +64 -0
- package/dist/interact/adjustment/adjustment-verification.js +35 -0
- package/dist/interact/adjustment/adjustment.js +52 -0
- package/dist/interact/adjustment/control-geometry.js +87 -0
- package/dist/interact/adjustment/control-values.js +136 -0
- package/dist/interact/adjustment/slider-labels.js +84 -0
- package/dist/interact/assertions/screen-assertion.js +37 -0
- package/dist/interact/assertions/state-assertion-context.js +35 -0
- package/dist/interact/assertions/state-assertion.js +76 -0
- package/dist/interact/assertions/state-comparison.js +141 -0
- package/dist/interact/assertions/visibility-assertion.js +34 -0
- package/dist/interact/conditional-action.js +12 -7
- package/dist/interact/index.js +65 -3074
- package/dist/interact/input-service.js +1 -0
- package/dist/interact/interaction-trace.js +21 -0
- package/dist/interact/model.js +1 -0
- package/dist/interact/observation.js +1 -0
- package/dist/interact/targeting/candidate-ancestor.js +58 -0
- package/dist/interact/targeting/candidate-result.js +23 -0
- package/dist/interact/targeting/candidate-scoring.js +50 -0
- package/dist/interact/targeting/element-helpers.js +216 -0
- package/dist/interact/targeting/find-element.js +65 -0
- package/dist/interact/targeting/nearby-control.js +56 -0
- package/dist/interact/targeting/resolved-elements.js +21 -0
- package/dist/interact/targeting/tap-target.js +17 -0
- package/dist/interact/targeting/target-scope.js +104 -0
- package/dist/interact/waits/legacy-log-wait.js +38 -0
- package/dist/interact/waits/legacy-wait-observations.js +103 -0
- package/dist/interact/waits/legacy-wait-state.js +34 -0
- package/dist/interact/waits/legacy-wait.js +48 -0
- package/dist/interact/waits/screen-wait.js +49 -0
- package/dist/interact/waits/ui-change-helpers.js +157 -0
- package/dist/interact/waits/ui-change-state.js +18 -0
- package/dist/interact/waits/ui-change-wait.js +77 -0
- package/dist/interact/waits/ui-wait-condition.js +56 -0
- package/dist/interact/waits/ui-wait-state.js +38 -0
- package/dist/interact/waits/ui-wait.js +106 -0
- package/dist/manage/android.js +55 -51
- package/dist/manage/index.js +38 -75
- package/dist/manage/ios/build-types.js +1 -0
- package/dist/manage/ios/build.js +210 -0
- package/dist/manage/ios/project-discovery.js +29 -0
- package/dist/manage/ios/scheme.js +18 -0
- package/dist/manage/ios.js +42 -256
- package/dist/observe/android/context.js +1 -0
- package/dist/observe/android/current-screen.js +55 -0
- package/dist/observe/android/fingerprint.js +13 -0
- package/dist/observe/android/log-stream.js +132 -0
- package/dist/observe/android/logs.js +107 -0
- package/dist/observe/android/screenshot.js +70 -0
- package/dist/observe/android/ui-tree.js +107 -0
- package/dist/observe/android.js +16 -520
- package/dist/observe/evidence.js +122 -76
- package/dist/observe/index.js +16 -263
- package/dist/observe/ios/context.js +16 -0
- package/dist/observe/ios/fingerprint.js +12 -0
- package/dist/observe/ios/log-stream.js +105 -0
- package/dist/observe/ios/logs.js +168 -0
- package/dist/observe/ios/screenshot.js +22 -0
- package/dist/observe/ios/ui-elements.js +241 -0
- package/dist/observe/ios/ui-tree.js +137 -0
- package/dist/observe/ios.js +17 -715
- package/dist/observe/logs/model.js +1 -0
- package/dist/{network → observe/network}/index.js +2 -2
- package/dist/observe/readiness-service.js +13 -2
- package/dist/observe/readiness.js +44 -18
- package/dist/observe/screenshot-encoding.js +41 -0
- package/dist/observe/snapshot-collection.js +79 -0
- package/dist/observe/snapshot-logs.js +30 -0
- package/dist/observe/snapshot-metadata.js +43 -31
- package/dist/observe/snapshot-semantic.js +115 -0
- package/dist/observe/system-trace-android.js +135 -0
- package/dist/observe/system-trace.js +294 -0
- package/dist/runtime/action-results.js +270 -0
- package/dist/runtime/clock.js +4 -0
- package/dist/server/common.js +1 -256
- package/dist/server/definitions/assert.js +162 -0
- package/dist/server/definitions/diagnostic.js +118 -0
- package/dist/server/definitions/input.js +274 -0
- package/dist/server/definitions/manage.js +194 -0
- package/dist/server/definitions/observe.js +149 -0
- package/dist/server/definitions/target.js +138 -0
- package/dist/server/definitions/wait.js +105 -0
- package/dist/server/handlers/action-execution.js +163 -0
- package/dist/server/handlers/correlation.js +23 -0
- package/dist/server/handlers/debugger-handlers.js +48 -0
- package/dist/server/handlers/debugger-response.js +9 -0
- package/dist/server/handlers/diagnostic.js +69 -0
- package/dist/server/handlers/handler-types.js +1 -0
- package/dist/server/handlers/input.js +154 -0
- package/dist/server/handlers/interact.js +113 -0
- package/dist/server/handlers/journey-assertions.js +35 -0
- package/dist/server/handlers/journey.js +147 -0
- package/dist/server/handlers/manage.js +119 -0
- package/dist/server/handlers/observe.js +95 -0
- package/dist/server/handlers/payload.js +4 -0
- package/dist/server/handlers/tool-handlers.js +160 -0
- package/dist/server/schemas/condition-schema.js +2 -0
- package/dist/server/schemas/debugger-schema.js +47 -0
- package/dist/server/{journey-schema.js → schemas/journey-schema.js} +8 -22
- package/dist/server/schemas/system-trace-schema.js +17 -0
- package/dist/server/tool-definitions.js +62 -1134
- package/dist/server-core.js +4 -4
- package/dist/server.js +34 -0
- package/dist/system/android-status.js +101 -0
- package/dist/system/android.js +37 -27
- package/dist/system/index.js +13 -438
- package/dist/system/ios-status.js +132 -0
- package/dist/system/ios.js +11 -8
- package/dist/system/model.js +1 -0
- package/dist/system/probes.js +105 -0
- package/dist/system/status-summary.js +43 -0
- package/dist/system/unsupported-status.js +52 -0
- package/dist/utils/android/commands.js +89 -0
- package/dist/utils/android/gradle.js +139 -0
- package/dist/utils/android/logs.js +103 -0
- package/dist/utils/android/ui-tree.js +233 -0
- package/dist/utils/android/utils.js +6 -564
- package/dist/utils/cli/idb/idb-helper.js +4 -6
- package/dist/utils/cli/idb/install-idb.js +13 -9
- package/dist/utils/cli/ios/preflight-ios.js +42 -38
- package/dist/utils/exec.js +2 -0
- package/dist/utils/ios/utils.js +45 -46
- package/dist/utils/java.js +75 -57
- package/dist/utils/operation-budget.js +2 -0
- package/dist/utils/resolve-device.js +6 -2
- package/dist/utils/ui/index.js +26 -26
- package/docs/CHANGELOG.md +48 -0
- package/docs/README.md +38 -0
- package/docs/benchmarks/README.md +18 -0
- package/docs/benchmarks/interaction-latency/README.md +14 -0
- package/docs/benchmarks/interaction-latency/final.md +4 -1
- package/docs/benchmarks/interaction-latency/ios-validation.md +2 -0
- package/docs/benchmarks/ui-tree-performance/README.md +24 -16
- package/docs/benchmarks/ui-tree-performance/comparison.md +11 -10
- package/docs/code-structure.md +118 -0
- package/docs/specs/001-state-verification/spec.md +16 -14
- package/docs/specs/002-richer-element-identity/spec.md +12 -10
- package/docs/specs/003-wait-and-synchronization-reliability/spec.md +12 -10
- package/docs/specs/004-action-verification-routing/spec.md +3 -3
- package/docs/specs/005-unified-action-execution-and-verification-model/spec.md +2 -0
- package/docs/specs/006-runtime-action-instrumentation-and-binding-layer/spec.md +2 -0
- package/docs/specs/007-actionability-resolution-and-executable-target-selection/spec.md +3 -1
- package/docs/specs/008-adjustable-control-support-and-semantic-value-manipulation/spec.md +3 -4
- package/docs/specs/009-semantic-control-modeling-for-custom-and-composite-controls/spec.md +2 -0
- package/docs/specs/010-verification-stabilization-and-temporal-convergence/spec.md +2 -2
- package/docs/specs/011-recovery-and-replanning-for-failed-or-ambiguous-interaction-flows/spec.md +2 -2
- package/docs/specs/011.1-recovery-contract-types-and-runtime-wiring-spec/spec.md +2 -0
- package/docs/specs/012-action-trace-and-xecution-observability/spec.md +2 -3
- package/docs/specs/013-wait-and-synchronization-reliability/spec.md +19 -19
- package/docs/specs/014-actionability-resolution/spec.md +20 -18
- package/docs/specs/015-adjustable-control-support/spec.md +17 -15
- package/docs/specs/016-environment-tools/spec.md +20 -20
- package/docs/specs/018-interaction-latency-and-batched-journeys/spec.md +2 -0
- package/docs/specs/019-ui-tree-observation-performance/spec.md +3 -1
- package/docs/specs/020-conditional-actions/intent.md +5 -3
- package/docs/specs/020-conditional-actions/plan.md +8 -9
- package/docs/specs/020-conditional-actions/spec.md +4 -2
- package/docs/specs/021-app-readiness-signals/intent.md +4 -2
- package/docs/specs/021-app-readiness-signals/plan.md +7 -6
- package/docs/specs/021-app-readiness-signals/spec.md +3 -1
- package/docs/specs/022-correlated-evidence/intent.md +4 -4
- package/docs/specs/022-correlated-evidence/plan.md +10 -11
- package/docs/specs/022-correlated-evidence/spec.md +3 -1
- package/docs/specs/023-android-system-traces/device-evidence.json +38 -0
- package/docs/specs/023-android-system-traces/emulator-recheck.json +38 -0
- package/docs/specs/023-android-system-traces/intent.md +41 -0
- package/docs/specs/023-android-system-traces/plan.md +115 -0
- package/docs/specs/023-android-system-traces/spec.md +122 -0
- package/docs/specs/024-android-heap-dump-capture/intent.md +41 -0
- package/docs/specs/025-android-runtime-debugger/intent.md +41 -0
- package/docs/specs/025-android-runtime-debugger/plan.md +106 -0
- package/docs/specs/025-android-runtime-debugger/spec.md +183 -0
- package/docs/specs/026-code-structure-and-quality-gates/health-plan.md +88 -0
- package/docs/specs/026-code-structure-and-quality-gates/intent.md +47 -0
- package/docs/specs/026-code-structure-and-quality-gates/plan.md +191 -0
- package/docs/specs/026-code-structure-and-quality-gates/spec.md +138 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification-final.json +200 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification-thin-facade.json +154 -0
- package/docs/specs/026-code-structure-and-quality-gates/verification.json +136 -0
- package/docs/specs/027-debugger-failure-diagnostics/intent.md +43 -0
- package/docs/specs/027-debugger-failure-diagnostics/plan.md +86 -0
- package/docs/specs/027-debugger-failure-diagnostics/spec.md +133 -0
- package/docs/specs/028-compact-debugger-responses/intent.md +41 -0
- package/docs/specs/028-compact-debugger-responses/plan.md +112 -0
- package/docs/specs/028-compact-debugger-responses/spec.md +108 -0
- package/docs/specs/029-kotlin-locals-validation/report.md +119 -0
- package/docs/specs/030-android-coroutine-validation/evidence.json +475 -0
- package/docs/specs/030-android-coroutine-validation/intent.md +47 -0
- package/docs/specs/030-android-coroutine-validation/plan.md +147 -0
- package/docs/specs/030-android-coroutine-validation/report.md +240 -0
- package/docs/specs/030-android-coroutine-validation/spec.md +107 -0
- package/docs/tools/TOOLS.md +31 -16
- package/docs/tools/{evidence.md → correlated-evidence.md} +14 -3
- package/docs/tools/debugger.md +180 -0
- package/docs/tools/interact.md +42 -20
- package/docs/tools/manage.md +25 -44
- package/docs/tools/observe.md +64 -25
- package/docs/tools/system-traces.md +134 -0
- package/docs/tools/system.md +12 -5
- package/package.json +11 -8
- package/scripts/architecture-graph.mjs +69 -0
- package/scripts/check-architecture.mjs +47 -0
- package/scripts/code-quality-baseline.json +1 -0
- package/scripts/code-quality.mjs +161 -0
- package/src/contracts/execution-controls.ts +26 -0
- package/src/contracts/selector.ts +17 -0
- package/src/contracts/target.ts +19 -0
- package/src/contracts/ui.ts +94 -0
- package/src/debugger/android.ts +66 -0
- package/src/debugger/diagnostics.ts +43 -0
- package/src/debugger/guard.ts +31 -0
- package/src/debugger/java/DebuggerWorker.java +166 -0
- package/src/debugger/protocol.ts +37 -0
- package/src/debugger/sessions.ts +327 -0
- package/src/debugger/worker.ts +135 -0
- package/src/interact/adjustment/adjustment-context.ts +83 -0
- package/src/interact/adjustment/adjustment-gestures.ts +48 -0
- package/src/interact/adjustment/adjustment-plan.ts +23 -0
- package/src/interact/adjustment/adjustment-resolution.ts +104 -0
- package/src/interact/adjustment/adjustment-result.ts +34 -0
- package/src/interact/adjustment/adjustment-semantic.ts +53 -0
- package/src/interact/adjustment/adjustment-verification.ts +60 -0
- package/src/interact/adjustment/adjustment.ts +49 -0
- package/src/interact/adjustment/control-geometry.ts +120 -0
- package/src/interact/adjustment/control-values.ts +141 -0
- package/src/interact/adjustment/slider-labels.ts +84 -0
- package/src/interact/assertions/screen-assertion.ts +39 -0
- package/src/interact/assertions/state-assertion-context.ts +48 -0
- package/src/interact/assertions/state-assertion.ts +64 -0
- package/src/interact/assertions/state-comparison.ts +168 -0
- package/src/interact/assertions/visibility-assertion.ts +41 -0
- package/src/interact/conditional-action.ts +18 -12
- package/src/interact/index.ts +76 -3491
- package/src/interact/input-service.ts +11 -0
- package/src/interact/interaction-trace.ts +36 -0
- package/src/interact/model.ts +109 -0
- package/src/interact/observation.ts +7 -0
- package/src/interact/targeting/candidate-ancestor.ts +49 -0
- package/src/interact/targeting/candidate-result.ts +24 -0
- package/src/interact/targeting/candidate-scoring.ts +42 -0
- package/src/interact/targeting/element-helpers.ts +243 -0
- package/src/interact/targeting/find-element.ts +47 -0
- package/src/interact/targeting/nearby-control.ts +46 -0
- package/src/interact/targeting/resolved-elements.ts +20 -0
- package/src/interact/targeting/tap-target.ts +22 -0
- package/src/interact/targeting/target-scope.ts +121 -0
- package/src/interact/waits/legacy-log-wait.ts +30 -0
- package/src/interact/waits/legacy-wait-observations.ts +55 -0
- package/src/interact/waits/legacy-wait-state.ts +48 -0
- package/src/interact/waits/legacy-wait.ts +34 -0
- package/src/interact/waits/screen-wait.ts +37 -0
- package/src/interact/waits/ui-change-helpers.ts +184 -0
- package/src/interact/waits/ui-change-state.ts +26 -0
- package/src/interact/waits/ui-change-wait.ts +59 -0
- package/src/interact/waits/ui-wait-condition.ts +52 -0
- package/src/interact/waits/ui-wait-state.ts +55 -0
- package/src/interact/waits/ui-wait.ts +84 -0
- package/src/manage/android.ts +56 -50
- package/src/manage/index.ts +63 -93
- package/src/manage/ios/build-types.ts +14 -0
- package/src/manage/ios/build.ts +230 -0
- package/src/manage/ios/project-discovery.ts +26 -0
- package/src/manage/ios/scheme.ts +16 -0
- package/src/manage/ios.ts +65 -298
- package/src/observe/android/context.ts +1 -0
- package/src/observe/android/current-screen.ts +63 -0
- package/src/observe/android/fingerprint.ts +13 -0
- package/src/observe/android/log-stream.ts +127 -0
- package/src/observe/android/logs.ts +110 -0
- package/src/observe/android/screenshot.ts +79 -0
- package/src/observe/android/ui-tree.ts +113 -0
- package/src/observe/android.ts +17 -531
- package/src/observe/evidence.ts +130 -71
- package/src/observe/index.ts +24 -286
- package/src/observe/ios/context.ts +22 -0
- package/src/observe/ios/fingerprint.ts +12 -0
- package/src/observe/ios/log-stream.ts +103 -0
- package/src/observe/ios/logs.ts +179 -0
- package/src/observe/ios/screenshot.ts +26 -0
- package/src/observe/ios/ui-elements.ts +266 -0
- package/src/observe/ios/ui-tree.ts +143 -0
- package/src/observe/ios.ts +18 -749
- package/src/observe/logs/model.ts +11 -0
- package/src/{network → observe/network}/index.ts +2 -2
- package/src/observe/readiness-service.ts +10 -3
- package/src/observe/readiness.ts +49 -22
- package/src/observe/screenshot-encoding.ts +32 -0
- package/src/observe/snapshot-collection.ts +69 -0
- package/src/observe/snapshot-logs.ts +26 -0
- package/src/observe/snapshot-metadata.ts +51 -31
- package/src/observe/snapshot-semantic.ts +153 -0
- package/src/observe/system-trace-android.ts +133 -0
- package/src/observe/system-trace.ts +227 -0
- package/src/runtime/action-results.ts +376 -0
- package/src/runtime/clock.ts +9 -0
- package/src/server/common.ts +9 -359
- package/src/server/definitions/assert.ts +164 -0
- package/src/server/definitions/diagnostic.ts +120 -0
- package/src/server/definitions/input.ts +276 -0
- package/src/server/definitions/manage.ts +196 -0
- package/src/server/definitions/observe.ts +151 -0
- package/src/server/definitions/target.ts +140 -0
- package/src/server/definitions/wait.ts +107 -0
- package/src/server/handlers/action-execution.ts +164 -0
- package/src/server/handlers/correlation.ts +20 -0
- package/src/server/handlers/debugger-handlers.ts +39 -0
- package/src/server/handlers/debugger-response.ts +7 -0
- package/src/server/handlers/diagnostic.ts +79 -0
- package/src/server/handlers/handler-types.ts +7 -0
- package/src/server/handlers/input.ts +173 -0
- package/src/server/handlers/interact.ts +135 -0
- package/src/server/handlers/journey-assertions.ts +39 -0
- package/src/server/handlers/journey.ts +132 -0
- package/src/server/handlers/manage.ts +141 -0
- package/src/server/handlers/observe.ts +116 -0
- package/src/server/handlers/payload.ts +36 -0
- package/src/server/handlers/tool-handlers.ts +159 -0
- package/src/server/schemas/condition-schema.ts +2 -0
- package/src/server/schemas/debugger-schema.ts +43 -0
- package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +8 -22
- package/src/server/schemas/system-trace-schema.ts +17 -0
- package/src/server/tool-definitions.ts +69 -1140
- package/src/server-core.ts +4 -4
- package/src/server.ts +25 -1
- package/src/system/android-status.ts +124 -0
- package/src/system/android.ts +33 -21
- package/src/system/index.ts +21 -523
- package/src/system/ios-status.ts +147 -0
- package/src/system/ios.ts +14 -10
- package/src/system/model.ts +41 -0
- package/src/system/probes.ts +114 -0
- package/src/system/status-summary.ts +47 -0
- package/src/system/unsupported-status.ts +55 -0
- package/src/types.ts +16 -106
- package/src/utils/android/commands.ts +81 -0
- package/src/utils/android/gradle.ts +132 -0
- package/src/utils/android/logs.ts +103 -0
- package/src/utils/android/ui-tree.ts +239 -0
- package/src/utils/android/utils.ts +16 -556
- package/src/utils/cli/idb/check-idb.ts +4 -4
- package/src/utils/cli/idb/idb-helper.ts +6 -8
- package/src/utils/cli/idb/install-idb.ts +15 -9
- package/src/utils/cli/ios/preflight-ios.ts +39 -31
- package/src/utils/cli/ios/run-ios-ui-tree-tap.ts +4 -4
- package/src/utils/exec.ts +2 -0
- package/src/utils/ios/utils.ts +57 -61
- package/src/utils/java.ts +71 -51
- package/src/utils/operation-budget.ts +2 -0
- package/src/utils/resolve-device.ts +11 -6
- package/src/utils/ui/index.ts +28 -28
- package/test/device/automated/debugger/coroutine-lifecycle.ts +27 -0
- package/test/device/automated/debugger/coroutine-support.ts +140 -0
- package/test/device/automated/debugger/coroutine.android.test.ts +169 -0
- package/test/device/automated/debugger/kotlin.android.test.ts +127 -0
- package/test/device/automated/debugger/runtime.android.test.ts +219 -0
- package/test/device/automated/interact/interaction.android.test.ts +56 -0
- package/test/device/automated/observe/system-trace.smoke.ts +104 -0
- package/test/device/manual/interact/modul8_selector_tap.manual.ts +1 -1
- package/test/fixtures/contracts/tool-definitions.json +3536 -0
- package/test/fixtures/coroutine-app/MainActivity.kt +100 -0
- package/test/fixtures/coroutine-app/README.md +48 -0
- package/test/fixtures/coroutine-app/build.ts +35 -0
- package/test/fixtures/debugger-app/MainActivity.java +67 -0
- package/test/fixtures/debugger-app/MainActivity.kt +32 -0
- package/test/fixtures/debugger-app/NoLocals.java +7 -0
- package/test/fixtures/debugger-app/README.md +65 -0
- package/test/fixtures/debugger-app/build.ts +39 -0
- package/test/fixtures/latency-journey-app/README.md +2 -0
- package/test/fixtures/readiness-app/README.md +2 -0
- package/test/helpers/perfetto.ts +59 -0
- package/test/unit/debugger/coroutine-lifecycle.test.ts +43 -0
- package/test/unit/debugger/diagnostic-sessions.test.ts +67 -0
- package/test/unit/debugger/diagnostics.test.ts +80 -0
- package/test/unit/debugger/guards.test.ts +50 -0
- package/test/unit/debugger/native.test.ts +33 -0
- package/test/unit/debugger/preparation.test.ts +32 -0
- package/test/unit/debugger/protocol.test.ts +15 -0
- package/test/unit/debugger/sessions.test.ts +83 -0
- package/test/unit/interact/adjustment_service.test.ts +42 -0
- package/test/unit/interact/adjustment_verification.test.ts +35 -0
- package/test/unit/interact/clock_dependencies.test.ts +63 -0
- package/test/unit/interact/element_helpers.test.ts +19 -0
- package/test/unit/interact/legacy_wait_service.test.ts +17 -0
- package/test/unit/interact/state_comparison.test.ts +20 -0
- package/test/unit/interact/target_scope.test.ts +35 -0
- package/test/unit/network/get_network_activity.test.ts +1 -1
- package/test/unit/observe/readiness.test.ts +3 -1
- package/test/unit/observe/screenshot-encoding.test.ts +30 -0
- package/test/unit/observe/snapshot-logs.test.ts +14 -0
- package/test/unit/observe/system-trace-android.test.ts +52 -0
- package/test/unit/observe/system-trace.test.ts +166 -0
- package/test/unit/quality/architecture.test.ts +60 -0
- package/test/unit/quality/code-quality.test.ts +58 -0
- package/test/unit/quality/interaction_boundaries.test.ts +24 -0
- package/test/unit/server/conditional_actions.test.ts +1 -1
- package/test/unit/server/conditional_schema.test.ts +2 -2
- package/test/unit/server/debugger-response.test.ts +63 -0
- package/test/unit/server/system-trace.test.ts +64 -0
- package/test/unit/server/tool_definitions_parity.test.ts +8 -0
- package/dist/server/tool-handlers.js +0 -893
- package/docs/ROADMAP.md +0 -646
- package/docs/benchmarks/ui-tree-performance/bridge-probe.json +0 -29
- package/docs/benchmarks/ui-tree-performance/initial-baseline.json +0 -59560
- package/docs/specs/baseline-spec-v0.md +0 -312
- package/docs/specs/mcp-tooling-spec-v1.md +0 -446
- package/src/server/tool-handlers.ts +0 -923
- /package/dist/{server/condition-schema.js → contracts/condition.js} +0 -0
- /package/dist/server/{readiness-schema.js → schemas/readiness-schema.js} +0 -0
- /package/src/{server/condition-schema.ts → contracts/condition.ts} +0 -0
- /package/src/server/{readiness-schema.ts → schemas/readiness-schema.ts} +0 -0
|
@@ -22,11 +22,10 @@ async function findFirst(root, patterns, maxDepth = 4) {
|
|
|
22
22
|
console.error('DEBUG findFirst: entries', ents.map(e => e.name));
|
|
23
23
|
for (const e of ents) {
|
|
24
24
|
const full = path.join(dir, e.name);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
25
|
+
const matched = patterns.some(pattern => e.name.endsWith(pattern));
|
|
26
|
+
if (matched) {
|
|
27
|
+
console.error('DEBUG findFirst: matched', full);
|
|
28
|
+
return full;
|
|
30
29
|
}
|
|
31
30
|
if (e.isDirectory() && depth < maxDepth)
|
|
32
31
|
queue.push({ dir: full, depth: depth + 1 });
|
|
@@ -52,26 +51,7 @@ function startCompanionIfNeeded(companionPath, udid) {
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
async function main() {
|
|
55
|
-
const
|
|
56
|
-
let projectArg;
|
|
57
|
-
let udid;
|
|
58
|
-
let startCompanion = false;
|
|
59
|
-
let kmpBuild = null;
|
|
60
|
-
for (let i = 0; i < args.length; i++) {
|
|
61
|
-
const a = args[i];
|
|
62
|
-
if (a === '--project' && args[i + 1]) {
|
|
63
|
-
projectArg = args[i + 1];
|
|
64
|
-
i++;
|
|
65
|
-
}
|
|
66
|
-
else if (a === '--udid' && args[i + 1]) {
|
|
67
|
-
udid = args[i + 1];
|
|
68
|
-
i++;
|
|
69
|
-
}
|
|
70
|
-
else if (a === '--start-companion')
|
|
71
|
-
startCompanion = true;
|
|
72
|
-
else if (!projectArg)
|
|
73
|
-
projectArg = a;
|
|
74
|
-
}
|
|
54
|
+
const { projectArg, udid, startCompanion, kmpBuild } = argumentsForPreflight(process.argv.slice(2));
|
|
75
55
|
const cwd = process.cwd();
|
|
76
56
|
const projectRoot = projectArg ? path.resolve(projectArg) : cwd;
|
|
77
57
|
// If user passed a direct .xcodeproj or .xcworkspace path, accept it as the projectFile
|
|
@@ -108,15 +88,8 @@ async function main() {
|
|
|
108
88
|
// 4) idb_companion
|
|
109
89
|
const companionPath = commandWhich('idb_companion');
|
|
110
90
|
const companionAvailable = !!companionPath;
|
|
111
|
-
const suggestions =
|
|
112
|
-
|
|
113
|
-
suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
|
|
114
|
-
if (!kmpFramework)
|
|
115
|
-
suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
|
|
116
|
-
if (!idbAvailable)
|
|
117
|
-
suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
|
|
118
|
-
if (!companionAvailable)
|
|
119
|
-
suggestions.push('Install idb_companion and ensure it is in PATH');
|
|
91
|
+
const suggestions = preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable);
|
|
92
|
+
const companionInfo = { cmd: companionPath, installed: companionAvailable };
|
|
120
93
|
const result = {
|
|
121
94
|
ok: !!projectFile && !!idbAvailable,
|
|
122
95
|
project: {
|
|
@@ -133,10 +106,7 @@ async function main() {
|
|
|
133
106
|
cmd: idbPath,
|
|
134
107
|
installed: idbAvailable
|
|
135
108
|
},
|
|
136
|
-
idb_companion:
|
|
137
|
-
cmd: companionPath,
|
|
138
|
-
installed: companionAvailable
|
|
139
|
-
},
|
|
109
|
+
idb_companion: companionInfo,
|
|
140
110
|
suggestions
|
|
141
111
|
};
|
|
142
112
|
if (startCompanion && udid) {
|
|
@@ -153,3 +123,37 @@ main().catch(e => {
|
|
|
153
123
|
console.log(JSON.stringify({ ok: false, error: e instanceof Error ? e.message : String(e) }, null, 2));
|
|
154
124
|
process.exit(2);
|
|
155
125
|
});
|
|
126
|
+
function argumentsForPreflight(args) {
|
|
127
|
+
let projectArg;
|
|
128
|
+
let udid;
|
|
129
|
+
let startCompanion = false;
|
|
130
|
+
const kmpBuild = null;
|
|
131
|
+
for (let i = 0; i < args.length; i++) {
|
|
132
|
+
const a = args[i];
|
|
133
|
+
if (a === '--project' && args[i + 1]) {
|
|
134
|
+
projectArg = args[i + 1];
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
else if (a === '--udid' && args[i + 1]) {
|
|
138
|
+
udid = args[i + 1];
|
|
139
|
+
i++;
|
|
140
|
+
}
|
|
141
|
+
else if (a === '--start-companion')
|
|
142
|
+
startCompanion = true;
|
|
143
|
+
else if (!projectArg)
|
|
144
|
+
projectArg = a;
|
|
145
|
+
}
|
|
146
|
+
return { projectArg, udid, startCompanion, kmpBuild };
|
|
147
|
+
}
|
|
148
|
+
function preflightSuggestions(projectFile, kmpFramework, idbAvailable, companionAvailable) {
|
|
149
|
+
const suggestions = [];
|
|
150
|
+
if (!projectFile)
|
|
151
|
+
suggestions.push('Provide correct project path or ensure .xcodeproj/.xcworkspace exists in project dir');
|
|
152
|
+
if (!kmpFramework)
|
|
153
|
+
suggestions.push('Run KMP Gradle task to produce Shared.framework before xcodebuild (e.g., :shared:embedAndSignAppleFrameworkForXcode)');
|
|
154
|
+
if (!idbAvailable)
|
|
155
|
+
suggestions.push('Ensure idb is in PATH or set MCP_IDB_PATH / IDB_PATH');
|
|
156
|
+
if (!companionAvailable)
|
|
157
|
+
suggestions.push('Install idb_companion and ensure it is in PATH');
|
|
158
|
+
return suggestions;
|
|
159
|
+
}
|
package/dist/utils/exec.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { checkDebuggerGuard } from '../debugger/guard.js';
|
|
1
2
|
import { remainingBudget } from './operation-budget.js';
|
|
2
3
|
import { spawn } from 'child_process';
|
|
3
4
|
export async function execCmd(cmd, args, opts = {}) {
|
|
4
5
|
const { env, cwd, shell } = opts;
|
|
5
6
|
const timeout = remainingBudget(opts.timeout ?? 0);
|
|
6
7
|
return new Promise((resolve, reject) => {
|
|
8
|
+
checkDebuggerGuard();
|
|
7
9
|
const child = spawn(cmd, args, { env: { ...process.env, ...(env || {}) }, cwd, shell });
|
|
8
10
|
let stdout = '';
|
|
9
11
|
let stderr = '';
|
package/dist/utils/ios/utils.js
CHANGED
|
@@ -19,16 +19,14 @@ export function getConfiguredIdbPath() {
|
|
|
19
19
|
if (!p)
|
|
20
20
|
continue;
|
|
21
21
|
try {
|
|
22
|
-
if (fs.existsSync(p))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}
|
|
22
|
+
if (!fs.existsSync(p))
|
|
23
|
+
continue;
|
|
24
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
25
|
+
const json = JSON.parse(raw);
|
|
26
|
+
if (json?.idbPath)
|
|
27
|
+
return json.idbPath;
|
|
28
|
+
if (json?.IDB_PATH)
|
|
29
|
+
return json.IDB_PATH;
|
|
32
30
|
}
|
|
33
31
|
catch { }
|
|
34
32
|
}
|
|
@@ -214,18 +212,18 @@ export async function getIOSDeviceMetadata(deviceId = "booted") {
|
|
|
214
212
|
const devicesMap = data.devices || {};
|
|
215
213
|
for (const runtime in devicesMap) {
|
|
216
214
|
const devices = devicesMap[runtime];
|
|
217
|
-
if (Array.isArray(devices))
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
215
|
+
if (!Array.isArray(devices))
|
|
216
|
+
continue;
|
|
217
|
+
for (const device of devices) {
|
|
218
|
+
if (deviceId === "booted" || device.udid === deviceId) {
|
|
219
|
+
resolve({
|
|
220
|
+
platform: "ios",
|
|
221
|
+
id: device.udid,
|
|
222
|
+
osVersion: parseRuntimeName(runtime),
|
|
223
|
+
model: device.name,
|
|
224
|
+
simulator: true,
|
|
225
|
+
});
|
|
226
|
+
return;
|
|
229
227
|
}
|
|
230
228
|
}
|
|
231
229
|
}
|
|
@@ -257,36 +255,37 @@ export async function listIOSDevices(appId) {
|
|
|
257
255
|
const bmap = bdata.devices || {};
|
|
258
256
|
for (const rt in bmap) {
|
|
259
257
|
const devs = bmap[rt];
|
|
260
|
-
if (Array.isArray(devs))
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
if (!Array.isArray(devs))
|
|
259
|
+
continue;
|
|
260
|
+
for (const d of devs)
|
|
261
|
+
bootedSet.add(d.udid);
|
|
263
262
|
}
|
|
264
263
|
}
|
|
265
264
|
catch { }
|
|
266
265
|
}
|
|
267
266
|
for (const runtime in devicesMap) {
|
|
268
267
|
const devices = devicesMap[runtime];
|
|
269
|
-
if (Array.isArray(devices))
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
268
|
+
if (!Array.isArray(devices))
|
|
269
|
+
continue;
|
|
270
|
+
for (const device of devices) {
|
|
271
|
+
const info = {
|
|
272
|
+
platform: 'ios',
|
|
273
|
+
id: device.udid,
|
|
274
|
+
osVersion: parseRuntimeName(runtime),
|
|
275
|
+
model: device.name,
|
|
276
|
+
simulator: true,
|
|
277
|
+
booted: bootedSet.has(device.udid)
|
|
278
|
+
};
|
|
279
|
+
if (appId) {
|
|
280
|
+
// check if installed
|
|
281
|
+
const p = execCommand(['simctl', 'get_app_container', device.udid, appId, 'data'], device.udid)
|
|
282
|
+
.then(() => { info.appInstalled = true; })
|
|
283
|
+
.catch(() => { info.appInstalled = false; })
|
|
284
|
+
.then(() => { out.push(info); });
|
|
285
|
+
checks.push(p);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
out.push(info);
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
291
|
}
|
package/dist/utils/java.js
CHANGED
|
@@ -25,52 +25,36 @@ function javaVersionOf(javaBin) {
|
|
|
25
25
|
return undefined;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
export async function detectJavaHome() {
|
|
28
|
+
export async function detectJavaHome(options = {}) {
|
|
29
|
+
const debug = (...args) => { if (!options.quiet)
|
|
30
|
+
console.debug(...args); };
|
|
29
31
|
try {
|
|
30
32
|
// 1) Honor explicit ANDROID_STUDIO_JDK env (highest priority)
|
|
31
33
|
const envStudio = process.env.ANDROID_STUDIO_JDK || process.env.ANDROID_STUDIO_JBR;
|
|
32
34
|
if (envStudio && existsSync(path.join(envStudio, 'bin', 'java'))) {
|
|
33
35
|
const v = javaVersionOf(path.join(envStudio, 'bin', 'java'));
|
|
34
36
|
if (isJavaVersionAcceptable(v)) {
|
|
35
|
-
|
|
37
|
+
debug('[java.detect] Using ANDROID_STUDIO_JDK from env:', envStudio);
|
|
36
38
|
return envStudio;
|
|
37
39
|
}
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
// 2) Android Studio JBR candidates (prefer these over JAVA_HOME)
|
|
41
|
-
const jbrCandidates = [
|
|
42
|
-
'/Applications/Android Studio.app/Contents/jbr',
|
|
43
|
-
'/Applications/Android Studio.app/Contents/jbr/Contents/Home',
|
|
44
|
-
'/Applications/Android Studio Preview.app/Contents/jbr',
|
|
45
|
-
'/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
|
|
46
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
|
|
47
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
|
|
48
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
|
|
49
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
|
|
50
|
-
];
|
|
51
|
-
for (const p of jbrCandidates) {
|
|
52
|
-
const javaBin = path.join(p, 'bin', 'java');
|
|
53
|
-
if (existsSync(javaBin)) {
|
|
54
|
-
const v = javaVersionOf(javaBin);
|
|
55
|
-
if (isJavaVersionAcceptable(v)) {
|
|
56
|
-
console.debug('[java.detect] Found Android Studio JBR at:', p);
|
|
57
|
-
return p;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
40
|
+
debug('[java.detect] ANDROID_STUDIO_JDK present but java -version did not match expected versions');
|
|
60
41
|
}
|
|
42
|
+
const jbr = findStudioJava(debug);
|
|
43
|
+
if (jbr)
|
|
44
|
+
return jbr;
|
|
61
45
|
// 3) If JAVA_HOME set, validate it (accept 17 or 21)
|
|
62
46
|
if (process.env.JAVA_HOME) {
|
|
63
47
|
try {
|
|
64
48
|
const javaBin = path.join(process.env.JAVA_HOME, 'bin', 'java');
|
|
65
49
|
const v = javaVersionOf(javaBin);
|
|
66
50
|
if (isJavaVersionAcceptable(v)) {
|
|
67
|
-
|
|
51
|
+
debug('[java.detect] Using JAVA_HOME from env:', process.env.JAVA_HOME);
|
|
68
52
|
return process.env.JAVA_HOME;
|
|
69
53
|
}
|
|
70
|
-
|
|
54
|
+
debug('[java.detect] Existing JAVA_HOME does not appear to be acceptable Java (17/21), will search');
|
|
71
55
|
}
|
|
72
56
|
catch {
|
|
73
|
-
|
|
57
|
+
debug('[java.detect] Failed to validate existing JAVA_HOME, searching for JDK');
|
|
74
58
|
}
|
|
75
59
|
}
|
|
76
60
|
// 4) macOS explicit path for JDK 17
|
|
@@ -84,7 +68,7 @@ export async function detectJavaHome() {
|
|
|
84
68
|
return out17;
|
|
85
69
|
}
|
|
86
70
|
catch (e) {
|
|
87
|
-
|
|
71
|
+
debug('[java.detect] /usr/libexec/java_home -v 17 failed: ' + String(e));
|
|
88
72
|
}
|
|
89
73
|
try {
|
|
90
74
|
const out21 = execSync('/usr/libexec/java_home -v 21', { stdio: ['ignore', 'pipe', 'pipe'] }).toString().trim();
|
|
@@ -92,42 +76,76 @@ export async function detectJavaHome() {
|
|
|
92
76
|
return out21;
|
|
93
77
|
}
|
|
94
78
|
catch (e) {
|
|
95
|
-
|
|
79
|
+
debug('[java.detect] /usr/libexec/java_home -v 21 failed: ' + String(e));
|
|
96
80
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
81
|
+
const commonHome = findMacJavaHome(debug);
|
|
82
|
+
if (commonHome)
|
|
83
|
+
return commonHome;
|
|
84
|
+
return findLinuxJavaHome(debug);
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
debug('[java.detect] error detecting java home:', e instanceof Error ? e.message : String(e));
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
function findStudioJava(debug) {
|
|
92
|
+
// 2) Android Studio JBR candidates (prefer these over JAVA_HOME)
|
|
93
|
+
const jbrCandidates = [
|
|
94
|
+
'/Applications/Android Studio.app/Contents/jbr',
|
|
95
|
+
'/Applications/Android Studio.app/Contents/jbr/Contents/Home',
|
|
96
|
+
'/Applications/Android Studio Preview.app/Contents/jbr',
|
|
97
|
+
'/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
|
|
98
|
+
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
|
|
99
|
+
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
|
|
100
|
+
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
|
|
101
|
+
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
|
|
102
|
+
];
|
|
103
|
+
for (const p of jbrCandidates) {
|
|
104
|
+
const javaBin = path.join(p, 'bin', 'java');
|
|
105
|
+
if (existsSync(javaBin)) {
|
|
106
|
+
const v = javaVersionOf(javaBin);
|
|
107
|
+
if (isJavaVersionAcceptable(v)) {
|
|
108
|
+
debug('[java.detect] Found Android Studio JBR at:', p);
|
|
109
|
+
return p;
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
];
|
|
119
|
-
for (const p of linuxCandidates) {
|
|
120
|
-
try {
|
|
121
|
-
if (existsSync(p))
|
|
122
|
-
return p;
|
|
123
|
-
}
|
|
124
|
-
catch (e) {
|
|
125
|
-
console.debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
|
|
112
|
+
}
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
function findMacJavaHome(debug) {
|
|
116
|
+
// 6) macOS common JDK locations
|
|
117
|
+
try {
|
|
118
|
+
const homes = execSync('ls -1 /Library/Java/JavaVirtualMachines || true', { stdio: ['ignore', 'pipe', 'inherit'] }).toString().split(/\r?\n/).filter(Boolean);
|
|
119
|
+
for (const h of homes) {
|
|
120
|
+
if (h.toLowerCase().includes('17') || h.toLowerCase().includes('jdk-17') || h.toLowerCase().includes('21') || h.toLowerCase().includes('jdk-21')) {
|
|
121
|
+
const candidate = `/Library/Java/JavaVirtualMachines/${h}/Contents/Home`;
|
|
122
|
+
return candidate;
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
125
|
}
|
|
129
126
|
catch (e) {
|
|
130
|
-
|
|
127
|
+
debug('[java.detect] listing /Library/Java/JavaVirtualMachines failed: ' + String(e));
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
function findLinuxJavaHome(debug) {
|
|
132
|
+
// 7) Linux locations
|
|
133
|
+
const linuxCandidates = [
|
|
134
|
+
'/usr/lib/jvm/java-17-openjdk-amd64',
|
|
135
|
+
'/usr/lib/jvm/java-17-openjdk',
|
|
136
|
+
'/usr/lib/jvm/zulu17',
|
|
137
|
+
'/usr/lib/jvm/temurin-17-jdk',
|
|
138
|
+
'/usr/lib/jvm/temurin-21-jdk',
|
|
139
|
+
'/usr/lib/jvm/java-21-openjdk-amd64'
|
|
140
|
+
];
|
|
141
|
+
for (const p of linuxCandidates) {
|
|
142
|
+
try {
|
|
143
|
+
if (existsSync(p))
|
|
144
|
+
return p;
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
debug(`[java.detect] checking linux candidate ${p} failed: ${String(e)}`);
|
|
148
|
+
}
|
|
131
149
|
}
|
|
132
150
|
return undefined;
|
|
133
151
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkDebuggerGuard } from '../debugger/guard.js';
|
|
1
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
3
|
const budgets = new AsyncLocalStorage();
|
|
3
4
|
export function hasFiniteBudget() { return Number.isFinite(budgets.getStore()?.deadline); }
|
|
@@ -38,6 +39,7 @@ export async function runWithSeparateBudget(timeoutMs, operation) {
|
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
export function markDispatchStarted() {
|
|
42
|
+
checkDebuggerGuard(true);
|
|
41
43
|
remainingBudget();
|
|
42
44
|
let budget = budgets.getStore();
|
|
43
45
|
while (budget) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkDebuggerGuard } from '../debugger/guard.js';
|
|
1
2
|
import { bindEvidenceDevice } from '../observe/evidence.js';
|
|
2
3
|
import { retainConnectedDeviceSnapshots } from '../observe/snapshot-metadata.js';
|
|
3
4
|
import { measure } from './timing.js';
|
|
@@ -42,6 +43,7 @@ export function withResolvedDevice(device, operation) {
|
|
|
42
43
|
return deviceContext.run(device, operation);
|
|
43
44
|
}
|
|
44
45
|
export async function resolveTargetDevice(opts) {
|
|
46
|
+
checkDebuggerGuard();
|
|
45
47
|
const device = await resolveDevice(opts);
|
|
46
48
|
bindEvidenceDevice(device);
|
|
47
49
|
return device;
|
|
@@ -64,6 +66,9 @@ async function resolveDevice(opts) {
|
|
|
64
66
|
throw new Error(`Device '${deviceId}' not found for platform ${platform}`);
|
|
65
67
|
return found;
|
|
66
68
|
}
|
|
69
|
+
return selectDevice(devices, platform, appId, prefer);
|
|
70
|
+
}
|
|
71
|
+
function selectDevice(devices, platform, appId, prefer) {
|
|
67
72
|
let candidates = devices.slice();
|
|
68
73
|
if (prefer === "physical")
|
|
69
74
|
candidates = candidates.filter(d => !d.simulator);
|
|
@@ -97,8 +102,7 @@ async function resolveDevice(opts) {
|
|
|
97
102
|
return candidates[0];
|
|
98
103
|
}
|
|
99
104
|
const list = candidates.map(d => ({ id: d.id, platform: d.platform, osVersion: d.osVersion, model: d.model, simulator: d.simulator, appInstalled: d.appInstalled }));
|
|
100
|
-
const err = new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`);
|
|
101
|
-
err.devices = list;
|
|
105
|
+
const err = Object.assign(new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`), { devices: list });
|
|
102
106
|
throw err;
|
|
103
107
|
}
|
|
104
108
|
throw new Error(`No devices found for platform ${platform}`);
|
package/dist/utils/ui/index.js
CHANGED
|
@@ -73,36 +73,11 @@ export function computeScreenFingerprint(tree, current, platform, limit = 50) {
|
|
|
73
73
|
}
|
|
74
74
|
export async function scrollToElementShared(opts) {
|
|
75
75
|
const { selector, direction = 'down', maxScrolls = 10, scrollAmount = 0.7, deviceId, fetchTree, swipe, stabilizationDelayMs = 350 } = opts;
|
|
76
|
-
const matchElement = (el) => {
|
|
77
|
-
if (!el)
|
|
78
|
-
return false;
|
|
79
|
-
if (selector.text !== undefined && selector.text !== el.text)
|
|
80
|
-
return false;
|
|
81
|
-
if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
|
|
82
|
-
return false;
|
|
83
|
-
if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
|
|
84
|
-
return false;
|
|
85
|
-
if (selector.className !== undefined && selector.className !== el.type)
|
|
86
|
-
return false;
|
|
87
|
-
return true;
|
|
88
|
-
};
|
|
89
|
-
const isVisible = (el, resolution) => {
|
|
90
|
-
if (!el)
|
|
91
|
-
return false;
|
|
92
|
-
if (el.visible === false)
|
|
93
|
-
return false;
|
|
94
|
-
if (!el.bounds || !resolution || !resolution.width || !resolution.height)
|
|
95
|
-
return (el.visible === undefined ? true : !!el.visible);
|
|
96
|
-
const [left, top, right, bottom] = el.bounds;
|
|
97
|
-
const withinY = bottom > 0 && top < resolution.height;
|
|
98
|
-
const withinX = right > 0 && left < resolution.width;
|
|
99
|
-
return withinX && withinY;
|
|
100
|
-
};
|
|
101
76
|
const findVisibleMatch = (elements, resolution) => {
|
|
102
77
|
if (!Array.isArray(elements))
|
|
103
78
|
return null;
|
|
104
79
|
for (const e of elements) {
|
|
105
|
-
if (matchElement(e) && isVisible(e, resolution))
|
|
80
|
+
if (matchElement(selector, e) && isVisible(e, resolution))
|
|
106
81
|
return e;
|
|
107
82
|
}
|
|
108
83
|
return null;
|
|
@@ -169,3 +144,28 @@ export async function scrollToElementShared(opts) {
|
|
|
169
144
|
}
|
|
170
145
|
return { success: false, reason: 'Element not found after scrolling', scrollsPerformed: scrollsPerformed };
|
|
171
146
|
}
|
|
147
|
+
function matchElement(selector, el) {
|
|
148
|
+
if (!el)
|
|
149
|
+
return false;
|
|
150
|
+
if (selector.text !== undefined && selector.text !== el.text)
|
|
151
|
+
return false;
|
|
152
|
+
if (selector.resourceId !== undefined && selector.resourceId !== el.resourceId)
|
|
153
|
+
return false;
|
|
154
|
+
if (selector.contentDesc !== undefined && selector.contentDesc !== el.contentDescription)
|
|
155
|
+
return false;
|
|
156
|
+
if (selector.className !== undefined && selector.className !== el.type)
|
|
157
|
+
return false;
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
function isVisible(el, resolution) {
|
|
161
|
+
if (!el)
|
|
162
|
+
return false;
|
|
163
|
+
if (el.visible === false)
|
|
164
|
+
return false;
|
|
165
|
+
if (!el.bounds || !resolution || !resolution.width || !resolution.height)
|
|
166
|
+
return (el.visible === undefined ? true : !!el.visible);
|
|
167
|
+
const [left, top, right, bottom] = el.bounds;
|
|
168
|
+
const withinY = bottom > 0 && top < resolution.height;
|
|
169
|
+
const withinX = right > 0 && left < resolution.width;
|
|
170
|
+
return withinX && withinY;
|
|
171
|
+
}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
[Documentation](README.md)
|
|
4
|
+
|
|
5
|
+
Entries describe their release at the time it was recorded. Historical source
|
|
6
|
+
paths and commands may have moved; use the [contribution guide](../CONTRIBUTING.md)
|
|
7
|
+
and [tool reference](tools/TOOLS.md) for the current checkout.
|
|
8
|
+
|
|
3
9
|
All notable changes to the **Mobile Debug MCP** project will be documented in this file.
|
|
4
10
|
|
|
5
11
|
## Unreleased
|
|
12
|
+
|
|
13
|
+
## [0.35.0]
|
|
14
|
+
|
|
15
|
+
- Updated the agent plugin to `0.0.4`, pinned to MCP `0.35.0`.
|
|
16
|
+
|
|
17
|
+
- Added an opt-in isolated Android coroutine debugger assessment fixture for
|
|
18
|
+
suspension, dispatcher changes, nested work, stepping and cancellation, with
|
|
19
|
+
explicit local dependencies. This does not add coroutine reconstruction.
|
|
20
|
+
- Added an opt-in isolated Kotlin debugger validation journey for named locals
|
|
21
|
+
before/after assignment, compiler scope tables, stale references and app recovery.
|
|
22
|
+
This adds evidence and regression coverage without changing debugger behaviour.
|
|
23
|
+
- Added opt-in debugger `responseMode: "compact"` to omit repeated target metadata
|
|
24
|
+
from routine commands while retaining diagnostics, execution state and cleanup.
|
|
25
|
+
Existing full responses remain the default; discovery and state stay complete.
|
|
26
|
+
- Android debugger failures now include bounded, sanitized stage/reason diagnostics
|
|
27
|
+
and static recovery guidance while preserving error codes. Capability probes
|
|
28
|
+
report ordered prerequisite diagnostics; terminal summaries retain failure evidence.
|
|
29
|
+
Raw stderr, exception messages and app locals are excluded from diagnostics.
|
|
30
|
+
|
|
31
|
+
- **Runtime requirement:** Node.js 22 or newer is now required. Updated Sharp,
|
|
32
|
+
Zod and transitive dependencies to clear the dependency audit findings; CI
|
|
33
|
+
configuration now uses Node 22. Public tool definitions remain unchanged.
|
|
34
|
+
- Split observation, snapshot, iOS build, Android utility and system diagnostic
|
|
35
|
+
responsibilities into typed services. Removed all 136 legacy quality exceptions;
|
|
36
|
+
production source meets the default size, complexity, nesting and explicit-any
|
|
37
|
+
limits. Added screenshot encoding and snapshot log normalization regressions.
|
|
38
|
+
|
|
39
|
+
- Split server handlers by capability, share target/execution-control contracts, and inject clocks into interaction polling services while preserving tool contracts. Added deterministic timing tests and an Android labelled-slider convergence journey.
|
|
40
|
+
|
|
41
|
+
- Added ArchUnitTS architecture checks to lint and CI for shared contracts, server boundaries, pure interaction calculations and runtime dependency cycles. Negative controls cover NodeNext resolution, aliases, dynamic imports and re-exports.
|
|
42
|
+
|
|
43
|
+
- Group interaction services by adjustment, targeting, waits and assertions; separate server schemas and handlers, and place log-derived network observations under `observe/network`. Tool contracts and behaviour are unchanged.
|
|
44
|
+
|
|
45
|
+
- Reduced `ToolsInteract` to a typed composition facade within the enforced class budget. Extracted adjustment, candidate resolution, synchronization and assertion services without new legacy exceptions, and added an isolated Android interaction journey plus a permanent default-budget regression check.
|
|
46
|
+
|
|
47
|
+
- Added code-quality gates to lint and CI for source/class/function size, complexity, nesting, explicit `any`, and interaction/runtime import boundaries. Legacy exceptions have per-symbol ceilings that cannot grow unnoticed.
|
|
48
|
+
- Extracted typed UI/control helpers, bounded handle storage, action-result construction and capability-specific tool definitions; clarified and typed debugger session operations and worker protocol messages while retaining public tool contracts.
|
|
49
|
+
- Fixed the debugger device check to fingerprint Java sources in `src/debugger/java/` after the worker relocation.
|
|
50
|
+
|
|
51
|
+
## [0.34.0]
|
|
52
|
+
- Added optional Android JDI runtime debugging: explicit device/process attach, source breakpoints/events, bounded stacks and shallow locals, stepping/resume, stale-reference rejection, pause-aware UI guards/readiness, expiry and owned detach/cleanup. Requires a host JDK 17+ and a running debuggable app; evaluation, mutation, native/coroutine and iOS debugging remain unsupported.
|
|
53
|
+
- Added optional bounded Android Perfetto capture with capability/start/status/stop/cancel tools, explicit journey trace linkage, local artifacts, process-ownership checks and retryable cleanup. iOS tracing and automatic trace analysis remain unsupported.
|
|
6
54
|
- Made readiness unit-test polling time deterministic while retaining exact sample-count and timeout assertions, eliminating host timer-rounding flakes.
|
|
7
55
|
- Isolated snapshot unit tests from physical device discovery and native handlers so they run without connected devices. Readiness deadline expiry now retains the last valid observation instead of intermittently resetting loading to unknown.
|
|
8
56
|
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Documentation
|
|
2
|
+
|
|
3
|
+
Mobile Debug MCP provides tools for building, controlling, and inspecting Android
|
|
4
|
+
and iOS apps. Start with the [project README](../README.md) for requirements,
|
|
5
|
+
installation, and client configuration.
|
|
6
|
+
|
|
7
|
+
## Choose a starting point
|
|
8
|
+
|
|
9
|
+
- **New to the server?** See the [project overview and installation options](../README.md#start-here).
|
|
10
|
+
- **Looking up a tool?** Use the [tool reference](tools/TOOLS.md) for inputs,
|
|
11
|
+
responses, examples, and shared interaction principles.
|
|
12
|
+
- **Troubleshooting setup?** Check [environment diagnostics](tools/system.md) and
|
|
13
|
+
the [tool path settings](../README.md#environment-setup).
|
|
14
|
+
- **Investigating an app failure?** Start with [observations](tools/observe.md)
|
|
15
|
+
and [evidence correlation](tools/correlated-evidence.md). For deeper Android
|
|
16
|
+
investigation, use [system traces](tools/system-traces.md) or the
|
|
17
|
+
[runtime debugger](tools/debugger.md).
|
|
18
|
+
- **Installing a client plugin?** See [client installation](../README.md#agent-plugin)
|
|
19
|
+
and the [plugin guide](../agent-plugin/README.md) for packaging and versioning.
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
- [Contribution guide](../CONTRIBUTING.md): local setup, validation, and documentation conventions.
|
|
24
|
+
- [Code structure and quality checks](code-structure.md): module ownership, enforced limits, and existing debt.
|
|
25
|
+
- [Development process](specs/process.md): maintenance and feature workflows.
|
|
26
|
+
- [Agent entrypoint](../AGENTS.md) and [repository skills](../.agents/skills/README.md).
|
|
27
|
+
|
|
28
|
+
## Design and evidence
|
|
29
|
+
|
|
30
|
+
- [Design records](specs/): feature intent, specifications, and dated verification
|
|
31
|
+
records, grouped by feature.
|
|
32
|
+
- [Changelog](CHANGELOG.md): release history.
|
|
33
|
+
- [Benchmark index](benchmarks/README.md): reproducible performance checks and recorded limits.
|
|
34
|
+
|
|
35
|
+
The tool reference describes the current checkout. Specifications record design
|
|
36
|
+
intent and may contain earlier contracts; approval alone does not establish that
|
|
37
|
+
a feature shipped. Verification records describe the named build and environment,
|
|
38
|
+
not every supported platform or the currently published npm package.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
[Documentation](../README.md)
|
|
4
|
+
|
|
5
|
+
Use these guides to run a benchmark or inspect its recorded results. Each
|
|
6
|
+
benchmark has one directory containing its instructions, report, and supporting
|
|
7
|
+
data. Generated filenames are retained so the harness can update them directly.
|
|
8
|
+
|
|
9
|
+
These reports describe particular builds and devices. Passing a smoke check does
|
|
10
|
+
not establish a performance improvement, and Android timings do not establish
|
|
11
|
+
iOS latency.
|
|
12
|
+
|
|
13
|
+
| Benchmark | Protocol | Recorded results | Design |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| Interaction latency | [Run the benchmark](interaction-latency/README.md) | [Android measurements](interaction-latency/final.md), [iOS interaction validation](interaction-latency/ios-validation.md) | [018](../specs/018-interaction-latency-and-batched-journeys/spec.md) |
|
|
16
|
+
| UI-tree observation | [Run the paired benchmark](ui-tree-performance/README.md) | [Comparison and limitations](ui-tree-performance/comparison.md) | [019](../specs/019-ui-tree-observation-performance/spec.md) |
|
|
17
|
+
|
|
18
|
+
Fixture instructions: [latency journey app](../../test/fixtures/latency-journey-app/README.md).
|