mobile-debug-mcp 0.34.0 → 0.36.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/.cursor-plugin/marketplace.json +1 -1
- package/.github/copilot-instructions.md +14 -36
- package/.github/workflows/ci.yml +4 -4
- package/AGENTS.md +12 -3
- package/CONTRIBUTING.md +79 -0
- package/README.md +218 -129
- package/agent-plugin/.antigravity-plugin/README.md +48 -0
- package/agent-plugin/.antigravity-plugin/plugin.json +18 -0
- 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 +50 -11
- package/agent-plugin/cursor/.cursor-plugin/plugin.json +23 -0
- package/agent-plugin/cursor/LICENSE +201 -0
- package/agent-plugin/cursor/README.md +9 -0
- package/agent-plugin/cursor/skills/mobile-debug-mcp/SKILL.md +253 -0
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/mcp_config.json +13 -0
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +62 -17
- 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 +2 -1
- package/dist/debugger/diagnostics.js +54 -0
- package/dist/debugger/guard.js +4 -4
- package/dist/debugger/ios-worker.js +62 -0
- package/dist/debugger/ios.js +57 -0
- package/dist/debugger/protocol.js +33 -0
- package/dist/debugger/sessions.js +133 -74
- package/dist/debugger/worker.js +59 -46
- 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 +77 -3092
- 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 +44 -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 +114 -75
- 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-trace/artifact.js +63 -0
- package/dist/observe/ios-trace/capabilities.js +86 -0
- package/dist/observe/ios-trace/native.js +93 -0
- package/dist/observe/ios-trace/notification.js +35 -0
- package/dist/observe/ios-trace/process.js +98 -0
- package/dist/observe/ios-trace/sessions.js +244 -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 +5 -3
- package/dist/observe/readiness.js +33 -14
- 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-error.js +7 -0
- package/dist/observe/system-trace-router.js +81 -0
- package/dist/observe/system-trace.js +26 -21
- 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 +67 -0
- package/dist/server/handlers/debugger-response.js +9 -0
- package/dist/server/handlers/diagnostic.js +77 -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 +170 -0
- package/dist/server/schemas/condition-schema.js +2 -0
- package/dist/server/{debugger-schema.js → schemas/debugger-schema.js} +20 -12
- package/dist/server/{journey-schema.js → schemas/journey-schema.js} +7 -22
- package/dist/server/schemas/system-trace-schema.js +22 -0
- package/dist/server/tool-definitions.js +58 -1135
- package/dist/server-core.js +2 -2
- package/dist/server.js +4 -4
- package/dist/system/android-status.js +101 -0
- package/dist/system/android.js +37 -27
- package/dist/system/index.js +13 -439
- 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/ios/utils.js +48 -46
- package/dist/utils/java.js +65 -49
- package/dist/utils/resolve-device.js +4 -2
- package/dist/utils/ui/index.js +26 -26
- package/docs/CHANGELOG.md +67 -1
- package/docs/README.md +38 -0
- package/docs/agent-plugin-installation-verification.md +39 -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 +120 -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/intent.md +3 -2
- package/docs/specs/023-android-system-traces/plan.md +5 -7
- package/docs/specs/023-android-system-traces/spec.md +3 -1
- package/docs/specs/024-android-heap-dump-capture/intent.md +3 -1
- package/docs/specs/025-android-runtime-debugger/intent.md +4 -3
- package/docs/specs/025-android-runtime-debugger/plan.md +3 -1
- package/docs/specs/025-android-runtime-debugger/spec.md +4 -3
- 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/specs/031-ios-system-traces/intent.md +38 -0
- package/docs/specs/031-ios-system-traces/investigation.md +92 -0
- package/docs/specs/031-ios-system-traces/late-run-failure-evidence.json +32 -0
- package/docs/specs/031-ios-system-traces/plan.md +138 -0
- package/docs/specs/031-ios-system-traces/pr102-monitor-evidence.json +22 -0
- package/docs/specs/031-ios-system-traces/simulator-evidence.json +47 -0
- package/docs/specs/031-ios-system-traces/spec.md +135 -0
- package/docs/specs/032-ios-runtime-debugger/evidence.json +176 -0
- package/docs/specs/032-ios-runtime-debugger/intent.md +38 -0
- package/docs/specs/032-ios-runtime-debugger/plan.md +95 -0
- package/docs/specs/032-ios-runtime-debugger/report.md +205 -0
- package/docs/specs/032-ios-runtime-debugger/spec.md +153 -0
- package/docs/tools/TOOLS.md +31 -18
- package/docs/tools/{evidence.md → correlated-evidence.md} +9 -1
- package/docs/tools/debugger.md +120 -4
- package/docs/tools/interact.md +42 -20
- package/docs/tools/manage.md +25 -44
- package/docs/tools/observe.md +55 -23
- package/docs/tools/system-traces.md +89 -14
- package/docs/tools/system.md +12 -5
- package/package.json +12 -8
- package/scripts/agent-plugin.mjs +55 -5
- 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 +3 -2
- package/src/debugger/diagnostics.ts +43 -0
- package/src/debugger/guard.ts +10 -5
- package/src/debugger/ios-worker.ts +49 -0
- package/src/debugger/ios.ts +45 -0
- package/{worker → src/debugger/java}/DebuggerWorker.java +9 -3
- package/src/debugger/lldb/breakpoints.py +51 -0
- package/src/debugger/lldb/inspection.py +109 -0
- package/src/debugger/lldb/worker.py +203 -0
- package/src/debugger/protocol.ts +37 -0
- package/src/debugger/sessions.ts +326 -155
- package/src/debugger/worker.ts +57 -41
- 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 +89 -3494
- 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 +67 -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 +122 -70
- 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-trace/artifact.ts +55 -0
- package/src/observe/ios-trace/capabilities.ts +74 -0
- package/src/observe/ios-trace/native.ts +72 -0
- package/src/observe/ios-trace/notification.ts +30 -0
- package/src/observe/ios-trace/process.ts +82 -0
- package/src/observe/ios-trace/sessions.ts +204 -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 +6 -4
- package/src/observe/readiness.ts +42 -21
- 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-error.ts +3 -0
- package/src/observe/system-trace-router.ts +61 -0
- package/src/observe/system-trace.ts +28 -19
- 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 +58 -0
- package/src/server/handlers/debugger-response.ts +7 -0
- package/src/server/handlers/diagnostic.ts +86 -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 +170 -0
- package/src/server/schemas/condition-schema.ts +2 -0
- package/src/server/schemas/debugger-schema.ts +46 -0
- package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +7 -22
- package/src/server/schemas/system-trace-schema.ts +23 -0
- package/src/server/tool-definitions.ts +67 -1143
- package/src/server-core.ts +2 -2
- package/src/server.ts +4 -4
- package/src/system/android-status.ts +124 -0
- package/src/system/android.ts +33 -21
- package/src/system/index.ts +21 -525
- 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/ios/utils.ts +60 -61
- package/src/utils/java.ts +62 -43
- package/src/utils/resolve-device.ts +9 -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 +19 -3
- package/test/device/automated/debugger/runtime.ios.test.ts +221 -0
- package/test/device/automated/interact/interaction.android.test.ts +56 -0
- package/test/device/automated/observe/ios-system-trace.smoke.ts +119 -0
- package/test/device/automated/observe/system-trace.smoke.ts +1 -1
- package/test/device/manual/interact/modul8_selector_tap.manual.ts +1 -1
- package/test/fixtures/contracts/tool-definitions.json +3696 -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 +21 -0
- package/test/fixtures/debugger-app/MainActivity.kt +32 -0
- package/test/fixtures/debugger-app/README.md +52 -0
- package/test/fixtures/debugger-app/build.ts +25 -15
- package/test/fixtures/ios-debugger-app/Main.swift +95 -0
- package/test/fixtures/ios-debugger-app/README.md +27 -0
- package/test/fixtures/ios-debugger-app/build.ts +21 -0
- package/test/fixtures/latency-journey-app/README.md +2 -0
- package/test/fixtures/readiness-app/README.md +2 -0
- package/test/helpers/ios-trace-shutdown.ts +29 -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 +4 -0
- package/test/unit/debugger/handle-guards.test.ts +88 -0
- package/test/unit/debugger/ios-preparation.test.ts +57 -0
- package/test/unit/debugger/ios.test.ts +104 -0
- package/test/unit/debugger/lldb-worker.py +166 -0
- package/test/unit/debugger/lldb-worker.test.ts +10 -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 +1 -1
- 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/ios-trace-native.test.ts +90 -0
- package/test/unit/observe/ios-trace-sessions.test.ts +131 -0
- package/test/unit/observe/readiness.test.ts +1 -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-router.test.ts +49 -0
- package/test/unit/quality/agent-plugin-export.test.ts +38 -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 +12 -3
- package/test/unit/server/tool_definitions_parity.test.ts +8 -0
- package/dist/server/debugger-handlers.js +0 -38
- package/dist/server/system-trace-schema.js +0 -17
- package/dist/server/tool-handlers.js +0 -1000
- 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/debugger-handlers.ts +0 -29
- package/src/server/debugger-schema.ts +0 -37
- package/src/server/system-trace-schema.ts +0 -17
- package/src/server/tool-handlers.ts +0 -1008
- /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/ios/utils.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { checkDebuggerGuard } from '../../debugger/guard.js';
|
|
1
2
|
import { remainingBudget } from '../operation-budget.js';
|
|
2
3
|
import { execFile, spawn, execSync, spawnSync } from "child_process";
|
|
3
4
|
import { promises as fsPromises } from 'fs';
|
|
@@ -19,16 +20,14 @@ export function getConfiguredIdbPath() {
|
|
|
19
20
|
if (!p)
|
|
20
21
|
continue;
|
|
21
22
|
try {
|
|
22
|
-
if (fs.existsSync(p))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}
|
|
23
|
+
if (!fs.existsSync(p))
|
|
24
|
+
continue;
|
|
25
|
+
const raw = fs.readFileSync(p, 'utf8');
|
|
26
|
+
const json = JSON.parse(raw);
|
|
27
|
+
if (json?.idbPath)
|
|
28
|
+
return json.idbPath;
|
|
29
|
+
if (json?.IDB_PATH)
|
|
30
|
+
return json.IDB_PATH;
|
|
32
31
|
}
|
|
33
32
|
catch { }
|
|
34
33
|
}
|
|
@@ -96,6 +95,7 @@ export function execCommand(args, deviceId = "booted") {
|
|
|
96
95
|
return new Promise((resolve, reject) => {
|
|
97
96
|
// Use spawn for better stream control and consistency with Android implementation
|
|
98
97
|
const budgetMs = remainingBudget();
|
|
98
|
+
checkDebuggerGuard();
|
|
99
99
|
const child = spawn(getXcrunCmd(), args);
|
|
100
100
|
let stdout = '';
|
|
101
101
|
let stderr = '';
|
|
@@ -137,6 +137,7 @@ export function execCommandWithDiagnostics(args, deviceId = "booted") {
|
|
|
137
137
|
const DEFAULT_XCRUN_LOG_TIMEOUT = parseInt(process.env.MCP_XCRUN_LOG_TIMEOUT || '', 10) || 30000;
|
|
138
138
|
const DEFAULT_XCRUN_CMD_TIMEOUT = parseInt(process.env.MCP_XCRUN_TIMEOUT || '', 10) || 60000;
|
|
139
139
|
const timeoutMs = budgetMs || (args.includes('log') ? DEFAULT_XCRUN_LOG_TIMEOUT : DEFAULT_XCRUN_CMD_TIMEOUT);
|
|
140
|
+
checkDebuggerGuard();
|
|
140
141
|
const res = spawnSync(getXcrunCmd(), args, { encoding: 'utf8', timeout: timeoutMs });
|
|
141
142
|
const runResult = {
|
|
142
143
|
exitCode: typeof res.status === 'number' ? res.status : null,
|
|
@@ -214,18 +215,18 @@ export async function getIOSDeviceMetadata(deviceId = "booted") {
|
|
|
214
215
|
const devicesMap = data.devices || {};
|
|
215
216
|
for (const runtime in devicesMap) {
|
|
216
217
|
const devices = devicesMap[runtime];
|
|
217
|
-
if (Array.isArray(devices))
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
218
|
+
if (!Array.isArray(devices))
|
|
219
|
+
continue;
|
|
220
|
+
for (const device of devices) {
|
|
221
|
+
if (deviceId === "booted" || device.udid === deviceId) {
|
|
222
|
+
resolve({
|
|
223
|
+
platform: "ios",
|
|
224
|
+
id: device.udid,
|
|
225
|
+
osVersion: parseRuntimeName(runtime),
|
|
226
|
+
model: device.name,
|
|
227
|
+
simulator: true,
|
|
228
|
+
});
|
|
229
|
+
return;
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
}
|
|
@@ -257,36 +258,37 @@ export async function listIOSDevices(appId) {
|
|
|
257
258
|
const bmap = bdata.devices || {};
|
|
258
259
|
for (const rt in bmap) {
|
|
259
260
|
const devs = bmap[rt];
|
|
260
|
-
if (Array.isArray(devs))
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
if (!Array.isArray(devs))
|
|
262
|
+
continue;
|
|
263
|
+
for (const d of devs)
|
|
264
|
+
bootedSet.add(d.udid);
|
|
263
265
|
}
|
|
264
266
|
}
|
|
265
267
|
catch { }
|
|
266
268
|
}
|
|
267
269
|
for (const runtime in devicesMap) {
|
|
268
270
|
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
|
-
|
|
271
|
+
if (!Array.isArray(devices))
|
|
272
|
+
continue;
|
|
273
|
+
for (const device of devices) {
|
|
274
|
+
const info = {
|
|
275
|
+
platform: 'ios',
|
|
276
|
+
id: device.udid,
|
|
277
|
+
osVersion: parseRuntimeName(runtime),
|
|
278
|
+
model: device.name,
|
|
279
|
+
simulator: true,
|
|
280
|
+
booted: bootedSet.has(device.udid)
|
|
281
|
+
};
|
|
282
|
+
if (appId) {
|
|
283
|
+
// check if installed
|
|
284
|
+
const p = execCommand(['simctl', 'get_app_container', device.udid, appId, 'data'], device.udid)
|
|
285
|
+
.then(() => { info.appInstalled = true; })
|
|
286
|
+
.catch(() => { info.appInstalled = false; })
|
|
287
|
+
.then(() => { out.push(info); });
|
|
288
|
+
checks.push(p);
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
out.push(info);
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
294
|
}
|
package/dist/utils/java.js
CHANGED
|
@@ -39,27 +39,9 @@ export async function detectJavaHome(options = {}) {
|
|
|
39
39
|
}
|
|
40
40
|
debug('[java.detect] ANDROID_STUDIO_JDK present but java -version did not match expected versions');
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'/Applications/Android Studio.app/Contents/jbr/Contents/Home',
|
|
46
|
-
'/Applications/Android Studio Preview.app/Contents/jbr',
|
|
47
|
-
'/Applications/Android Studio Preview.app/Contents/jbr/Contents/Home',
|
|
48
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr',
|
|
49
|
-
'/Applications/Android Studio Preview 2022.3.app/Contents/jbr/Contents/Home',
|
|
50
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr',
|
|
51
|
-
'/Applications/Android Studio Preview 2023.1.app/Contents/jbr/Contents/Home'
|
|
52
|
-
];
|
|
53
|
-
for (const p of jbrCandidates) {
|
|
54
|
-
const javaBin = path.join(p, 'bin', 'java');
|
|
55
|
-
if (existsSync(javaBin)) {
|
|
56
|
-
const v = javaVersionOf(javaBin);
|
|
57
|
-
if (isJavaVersionAcceptable(v)) {
|
|
58
|
-
debug('[java.detect] Found Android Studio JBR at:', p);
|
|
59
|
-
return p;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
42
|
+
const jbr = findStudioJava(debug);
|
|
43
|
+
if (jbr)
|
|
44
|
+
return jbr;
|
|
63
45
|
// 3) If JAVA_HOME set, validate it (accept 17 or 21)
|
|
64
46
|
if (process.env.JAVA_HOME) {
|
|
65
47
|
try {
|
|
@@ -96,40 +78,74 @@ export async function detectJavaHome(options = {}) {
|
|
|
96
78
|
catch (e) {
|
|
97
79
|
debug('[java.detect] /usr/libexec/java_home -v 21 failed: ' + String(e));
|
|
98
80
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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;
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
'
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
];
|
|
121
|
-
for (const p of linuxCandidates) {
|
|
122
|
-
try {
|
|
123
|
-
if (existsSync(p))
|
|
124
|
-
return p;
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
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;
|
|
128
123
|
}
|
|
129
124
|
}
|
|
130
125
|
}
|
|
131
126
|
catch (e) {
|
|
132
|
-
debug('[java.detect]
|
|
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
|
+
}
|
|
133
149
|
}
|
|
134
150
|
return undefined;
|
|
135
151
|
}
|
|
@@ -66,6 +66,9 @@ async function resolveDevice(opts) {
|
|
|
66
66
|
throw new Error(`Device '${deviceId}' not found for platform ${platform}`);
|
|
67
67
|
return found;
|
|
68
68
|
}
|
|
69
|
+
return selectDevice(devices, platform, appId, prefer);
|
|
70
|
+
}
|
|
71
|
+
function selectDevice(devices, platform, appId, prefer) {
|
|
69
72
|
let candidates = devices.slice();
|
|
70
73
|
if (prefer === "physical")
|
|
71
74
|
candidates = candidates.filter(d => !d.simulator);
|
|
@@ -99,8 +102,7 @@ async function resolveDevice(opts) {
|
|
|
99
102
|
return candidates[0];
|
|
100
103
|
}
|
|
101
104
|
const list = candidates.map(d => ({ id: d.id, platform: d.platform, osVersion: d.osVersion, model: d.model, simulator: d.simulator, appInstalled: d.appInstalled }));
|
|
102
|
-
const err = new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`);
|
|
103
|
-
err.devices = list;
|
|
105
|
+
const err = Object.assign(new Error(`Multiple matching devices found: ${JSON.stringify(list, null, 2)}`), { devices: list });
|
|
104
106
|
throw err;
|
|
105
107
|
}
|
|
106
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,74 @@
|
|
|
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
|
+
## [0.36.0]
|
|
12
|
+
|
|
13
|
+
- Updated the agent plugin to `0.0.6`, pinned to MCP `0.36.0`.
|
|
14
|
+
|
|
15
|
+
- Add an optional iOS simulator LLDB backend to the existing debugger tools,
|
|
16
|
+
including exact source-file breakpoints, bounded static inspection, stepping,
|
|
17
|
+
platform-scoped pause guards and owned cleanup. A separate Swift concurrency
|
|
18
|
+
fixture checks inspection around await, cancellation and recovery; verification
|
|
19
|
+
coverage is recorded in specification 032. Physical iOS devices remain unsupported.
|
|
20
|
+
|
|
21
|
+
- Preserve iOS trace capture through isolated monitoring command failures; require
|
|
22
|
+
three consecutive non-definitive failures before discarding, while identity and
|
|
23
|
+
storage failures remain immediate and capture expiry still reconciles.
|
|
24
|
+
|
|
25
|
+
- Add optional iOS simulator Time Profiler capture through Instruments, with explicit
|
|
26
|
+
device/app targeting, recording-start notification, local `.trace` validation,
|
|
27
|
+
journey evidence linkage and owned cleanup. Physical devices and other templates
|
|
28
|
+
remain unsupported in the initial matrix. Android tracing retains its preset.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
- Added plugin `0.0.5` Antigravity compatibility and a standalone distribution
|
|
32
|
+
export. Generated a Cursor-native package for its supported path variables,
|
|
33
|
+
and checked/refined installation instructions for all four clients.
|
|
34
|
+
|
|
35
|
+
## [0.35.0]
|
|
36
|
+
|
|
37
|
+
- Updated the agent plugin to `0.0.4`, pinned to MCP `0.35.0`.
|
|
38
|
+
|
|
39
|
+
- Added an opt-in isolated Android coroutine debugger assessment fixture for
|
|
40
|
+
suspension, dispatcher changes, nested work, stepping and cancellation, with
|
|
41
|
+
explicit local dependencies. This does not add coroutine reconstruction.
|
|
42
|
+
- Added an opt-in isolated Kotlin debugger validation journey for named locals
|
|
43
|
+
before/after assignment, compiler scope tables, stale references and app recovery.
|
|
44
|
+
This adds evidence and regression coverage without changing debugger behaviour.
|
|
45
|
+
- Added opt-in debugger `responseMode: "compact"` to omit repeated target metadata
|
|
46
|
+
from routine commands while retaining diagnostics, execution state and cleanup.
|
|
47
|
+
Existing full responses remain the default; discovery and state stay complete.
|
|
48
|
+
- Android debugger failures now include bounded, sanitized stage/reason diagnostics
|
|
49
|
+
and static recovery guidance while preserving error codes. Capability probes
|
|
50
|
+
report ordered prerequisite diagnostics; terminal summaries retain failure evidence.
|
|
51
|
+
Raw stderr, exception messages and app locals are excluded from diagnostics.
|
|
52
|
+
|
|
53
|
+
- **Runtime requirement:** Node.js 22 or newer is now required. Updated Sharp,
|
|
54
|
+
Zod and transitive dependencies to clear the dependency audit findings; CI
|
|
55
|
+
configuration now uses Node 22. Public tool definitions remain unchanged.
|
|
56
|
+
- Split observation, snapshot, iOS build, Android utility and system diagnostic
|
|
57
|
+
responsibilities into typed services. Removed all 136 legacy quality exceptions;
|
|
58
|
+
production source meets the default size, complexity, nesting and explicit-any
|
|
59
|
+
limits. Added screenshot encoding and snapshot log normalization regressions.
|
|
60
|
+
|
|
61
|
+
- 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.
|
|
62
|
+
|
|
63
|
+
- 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.
|
|
64
|
+
|
|
65
|
+
- 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.
|
|
66
|
+
|
|
67
|
+
- 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.
|
|
68
|
+
|
|
69
|
+
- 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.
|
|
70
|
+
- 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.
|
|
71
|
+
- Fixed the debugger device check to fingerprint Java sources in `src/debugger/java/` after the worker relocation.
|
|
6
72
|
|
|
7
73
|
## [0.34.0]
|
|
8
74
|
- 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.
|
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,39 @@
|
|
|
1
|
+
# Agent plugin installation verification
|
|
2
|
+
|
|
3
|
+
Checked 2026-11-02 for plugin 0.0.5 and published MCP 0.35.0. This record separates
|
|
4
|
+
command/schema checks from installation and live device evidence.
|
|
5
|
+
|
|
6
|
+
| Client | Evidence | Limit |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| Codex CLI 0.166.0-alpha.5.1 | Marketplace-add and plugin-add syntax confirmed with installed CLI help and official docs; catalog paths checked by repository verification | No new Codex installation or agent journey performed |
|
|
9
|
+
| Claude Code 2.1.285 | Native strict validation passes for the marketplace, compatibility manifest and complete plugin folder; shell command syntax confirmed | No new Claude Code installation or agent journey performed |
|
|
10
|
+
| Cursor | Native package and catalog generated from the canonical skill; uses documented CURSOR_PLUGIN_ROOT; local-copy instructions preserve hidden files | Host loading in Cursor is unrun |
|
|
11
|
+
| Antigravity CLI 1.4.12 | Standalone export passes strict validation with zero warnings; local install discovers one skill and one MCP server | An agent print-mode attempt was denied by plan-mode MCP policy; a narrowly permitted read-only attempt timed out, so no agent tool-call success is claimed |
|
|
12
|
+
|
|
13
|
+
The Antigravity export contains native `plugin.json`, `mcp_config.json`, README,
|
|
14
|
+
license, logo and the shared skill. It excludes foreign client manifests and
|
|
15
|
+
Finder metadata. Export destinations must be new directories. Regression coverage
|
|
16
|
+
checks inventory, canonical skill/license bytes and refusal to overwrite existing
|
|
17
|
+
files. Cursor's generated skill/license are checked against their canonical
|
|
18
|
+
sources by `npm run check:agent-plugin`.
|
|
19
|
+
|
|
20
|
+
A separate SDK test launched the exact exported npx command from an expanded
|
|
21
|
+
PLUGIN_DATA working directory. It connected to published MCP 0.35.0, discovered
|
|
22
|
+
52 tools, selected emulator-5554 (Android 16/API 36), launched Settings and asserted
|
|
23
|
+
a fresh UI tree contained a visible Settings-owned resource. **PASS**; this is an
|
|
24
|
+
exported-config/device check, not an Antigravity agent interaction. Log:
|
|
25
|
+
`/tmp/antigravity-published-mcp-check.log`. The emulator remains running.
|
|
26
|
+
|
|
27
|
+
`npm run verify` **PASS**, all 91 unit files, including the exporter regression,
|
|
28
|
+
lint/quality/architecture, build and plugin consistency. Native Antigravity strict
|
|
29
|
+
validation and Claude strict validation also **PASS**. Markdown links and diff
|
|
30
|
+
whitespace were checked. No production server code or dependencies changed.
|
|
31
|
+
GitHub/local distribution does not require the optional Marketplace intake form;
|
|
32
|
+
no application was submitted.
|
|
33
|
+
|
|
34
|
+
## Primary documentation
|
|
35
|
+
|
|
36
|
+
- [OpenAI plugin packaging](https://developers.openai.com/plugins/build/plugins)
|
|
37
|
+
- [Claude Code installation](https://code.claude.com/docs/en/discover-plugins)
|
|
38
|
+
- [Cursor plugins and local testing](https://cursor.com/docs/plugins)
|
|
39
|
+
- [Antigravity plugin building and validation](https://antigravity.google/docs/build-plugins)
|
|
@@ -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).
|