mobile-debug-mcp 0.34.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 +4 -4
- package/AGENTS.md +12 -3
- package/CONTRIBUTING.md +79 -0
- package/README.md +156 -129
- 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 +16 -6
- package/agent-plugin/mcp.json +1 -1
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/mobile-debug-mcp/SKILL.md +27 -2
- 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/protocol.js +33 -0
- package/dist/debugger/sessions.js +104 -62
- package/dist/debugger/worker.js +53 -42
- 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 -3090
- 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 +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.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 +4 -2
- package/dist/observe/readiness.js +29 -10
- 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.js +22 -13
- 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/{debugger-handlers.js → handlers/debugger-handlers.js} +22 -12
- 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/{debugger-schema.js → schemas/debugger-schema.js} +11 -6
- package/dist/server/{journey-schema.js → schemas/journey-schema.js} +7 -22
- package/dist/server/tool-definitions.js +58 -1135
- package/dist/server-core.js +2 -2
- 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 +45 -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 +44 -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/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/tools/TOOLS.md +31 -18
- package/docs/tools/{evidence.md → correlated-evidence.md} +9 -1
- package/docs/tools/debugger.md +76 -0
- 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 +9 -1
- 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 +2 -1
- package/src/debugger/diagnostics.ts +43 -0
- package/src/debugger/guard.ts +6 -1
- package/{worker → src/debugger/java}/DebuggerWorker.java +9 -3
- package/src/debugger/protocol.ts +37 -0
- package/src/debugger/sessions.ts +314 -155
- package/src/debugger/worker.ts +51 -38
- 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 -3492
- 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 +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.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 +5 -3
- package/src/observe/readiness.ts +39 -18
- 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.ts +24 -15
- 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/{debugger-schema.ts → schemas/debugger-schema.ts} +13 -7
- package/src/server/{journey-schema.ts → schemas/journey-schema.ts} +7 -22
- package/src/server/{system-trace-schema.ts → schemas/system-trace-schema.ts} +3 -3
- package/src/server/tool-definitions.ts +67 -1143
- package/src/server-core.ts +2 -2
- package/src/server.ts +1 -1
- 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 +57 -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/interact/interaction.android.test.ts +56 -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 +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 +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/latency-journey-app/README.md +2 -0
- package/test/fixtures/readiness-app/README.md +2 -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/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/screenshot-encoding.test.ts +30 -0
- package/test/unit/observe/snapshot-logs.test.ts +14 -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/tool_definitions_parity.test.ts +8 -0
- 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/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/dist/server/{system-trace-schema.js → schemas/system-trace-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
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export const verificationModes = ['none', 'light', 'full'] as const
|
|
4
|
+
export const responseModes = ['compact', 'debug'] as const
|
|
5
|
+
export const verificationModeSchema = z.enum(verificationModes)
|
|
6
|
+
export const responseModeSchema = z.enum(responseModes)
|
|
7
|
+
export type VerificationMode = z.infer<typeof verificationModeSchema>
|
|
8
|
+
export type ResponseMode = z.infer<typeof responseModeSchema>
|
|
9
|
+
|
|
10
|
+
export const verificationModeJson = { type: 'string', enum: [...verificationModes] }
|
|
11
|
+
export const responseModeJson = { type: 'string', enum: [...responseModes] }
|
|
12
|
+
|
|
13
|
+
export function interactionControls(args: Record<string, unknown>) {
|
|
14
|
+
const verificationMode = ((typeof args.verificationMode === 'string' ? args.verificationMode : undefined) as VerificationMode | undefined) ?? 'full'
|
|
15
|
+
const responseMode = ((typeof args.responseMode === 'string' ? args.responseMode : undefined) as ResponseMode | undefined) ?? 'debug'
|
|
16
|
+
if (!verificationModes.includes(verificationMode) || !responseModes.includes(responseMode)) throw new Error('INVALID_ARGUMENT')
|
|
17
|
+
for (const key of ['verificationMode', 'responseMode']) if (args[key] !== undefined && typeof args[key] !== 'string') throw new Error('INVALID_ARGUMENT')
|
|
18
|
+
for (const key of ['actionTimeoutMs', 'verificationTimeoutMs']) if (args[key] !== undefined && (typeof args[key] !== 'number' || !Number.isInteger(args[key]))) throw new Error('INVALID_ARGUMENT')
|
|
19
|
+
const actionTimeoutMs = (typeof args.actionTimeoutMs === 'number' && Number.isFinite(args.actionTimeoutMs) ? args.actionTimeoutMs : undefined)
|
|
20
|
+
const verificationTimeoutMs = (typeof args.verificationTimeoutMs === 'number' && Number.isFinite(args.verificationTimeoutMs) ? args.verificationTimeoutMs : undefined)
|
|
21
|
+
return { verificationMode, responseMode,
|
|
22
|
+
actionTimeoutMs: actionTimeoutMs === undefined ? undefined : Math.max(100, Math.min(30000, actionTimeoutMs)),
|
|
23
|
+
verificationTimeoutMs: verificationTimeoutMs === undefined ? 3000 : Math.max(100, Math.min(60000, verificationTimeoutMs)) }
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
export type UiSelector = {
|
|
4
|
+
text?: string
|
|
5
|
+
resource_id?: string
|
|
6
|
+
accessibility_id?: string
|
|
7
|
+
contains?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const selectorSchema = z.object({
|
|
11
|
+
text: z.string().min(1).optional(), resource_id: z.string().min(1).optional(),
|
|
12
|
+
accessibility_id: z.string().min(1).optional(), contains: z.boolean().optional()
|
|
13
|
+
}).strict().refine(value => !!(value.text || value.resource_id || value.accessibility_id), 'Selector requires a target')
|
|
14
|
+
|
|
15
|
+
export const selectorJson = { type: 'object', additionalProperties: false, properties: {
|
|
16
|
+
text: { type: 'string', minLength: 1 }, resource_id: { type: 'string', minLength: 1 }, accessibility_id: { type: 'string', minLength: 1 }, contains: { type: 'boolean' }
|
|
17
|
+
}, anyOf: ['text', 'resource_id', 'accessibility_id'].map(key => ({ required: [key] })) }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { selectorSchema as selector, selectorJson } from './selector.js'
|
|
3
|
+
|
|
4
|
+
export interface DeviceTarget { platform?: 'android' | 'ios'; deviceId?: string }
|
|
5
|
+
export type ScrollSelector = { text?: string; resourceId?: string; contentDesc?: string; className?: string }
|
|
6
|
+
const pollIntervalMs = z.number().int().min(50).max(1000).optional()
|
|
7
|
+
export const waitForSchema = z.object({
|
|
8
|
+
condition: z.enum(['exists', 'visible', 'clickable']).optional(),
|
|
9
|
+
timeoutMs: z.number().int().min(100).max(10000).optional(), pollIntervalMs,
|
|
10
|
+
match: z.object({ index: z.number().int().nonnegative().optional() }).strict().optional()
|
|
11
|
+
}).strict()
|
|
12
|
+
export const targetFields = { selector: selector.optional(), elementId: z.string().min(1).optional() }
|
|
13
|
+
export const exactlyOneTarget = (value: { selector?: unknown, elementId?: string }) => Number(!!value.selector) + Number(!!value.elementId) === 1
|
|
14
|
+
export const tapElementControlsSchema = z.object({
|
|
15
|
+
elementId: z.string().min(1).optional(), selector: selector.optional(), waitFor: waitForSchema.optional()
|
|
16
|
+
}).strict().refine(value => Number(!!value.elementId) + Number(!!value.selector) === 1 && (!value.elementId || !value.waitFor))
|
|
17
|
+
|
|
18
|
+
export const targetJson = { selector: selectorJson, elementId: { type: 'string', minLength: 1 } }
|
|
19
|
+
export const oneTargetJson = [{ required: ['selector'], not: { required: ['elementId'] } }, { required: ['elementId'], not: { required: ['selector'] } }]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
export interface UIElementState {
|
|
2
|
+
checked?: boolean | null;
|
|
3
|
+
selected?: boolean | string | { id: string; label?: string } | null;
|
|
4
|
+
focused?: boolean | null;
|
|
5
|
+
expanded?: boolean | null;
|
|
6
|
+
enabled?: boolean | null;
|
|
7
|
+
text_value?: string | null;
|
|
8
|
+
value?: number | string | null;
|
|
9
|
+
raw_value?: number | string | null;
|
|
10
|
+
value_range?: {
|
|
11
|
+
min: number;
|
|
12
|
+
max: number;
|
|
13
|
+
step?: number | null;
|
|
14
|
+
} | null;
|
|
15
|
+
step?: number | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SelectorConfidence {
|
|
19
|
+
score: number;
|
|
20
|
+
reason: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface UIResolutionSelector {
|
|
24
|
+
value: string | null;
|
|
25
|
+
confidence: SelectorConfidence | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface UIElementSemanticMetadata {
|
|
29
|
+
is_clickable: boolean;
|
|
30
|
+
is_container: boolean;
|
|
31
|
+
semantic_role?: 'slider' | 'stepper' | 'dropdown' | 'segmented_control' | 'custom_adjustable' | 'composite_control' | null;
|
|
32
|
+
supported_actions?: string[] | null;
|
|
33
|
+
adjustable?: boolean | null;
|
|
34
|
+
state_shape?: 'continuous' | 'discrete' | 'semantic' | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface LoadingState {
|
|
38
|
+
active: boolean;
|
|
39
|
+
signal: string;
|
|
40
|
+
source: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface SnapshotDelta {
|
|
44
|
+
previous_snapshot_revision: number | null;
|
|
45
|
+
added_elements: number;
|
|
46
|
+
removed_elements: number;
|
|
47
|
+
mutated_elements: number;
|
|
48
|
+
total_elements: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface StateDelta {
|
|
52
|
+
base_snapshot_revision: number | null;
|
|
53
|
+
snapshot_revision: number;
|
|
54
|
+
added: UIElement[];
|
|
55
|
+
removed: Array<{ stable_id?: string; resourceId?: string; contentDescription?: string; text?: string; index: number }>;
|
|
56
|
+
changed: UIElement[];
|
|
57
|
+
truncated: boolean;
|
|
58
|
+
omitted_changes?: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface UIElement {
|
|
62
|
+
text: string | null;
|
|
63
|
+
contentDescription: string | null;
|
|
64
|
+
type: string;
|
|
65
|
+
clickable: boolean;
|
|
66
|
+
enabled: boolean;
|
|
67
|
+
visible: boolean;
|
|
68
|
+
bounds: [number, number, number, number];
|
|
69
|
+
resourceId: string | null;
|
|
70
|
+
parentId?: number;
|
|
71
|
+
children?: number[];
|
|
72
|
+
center?: [number, number];
|
|
73
|
+
depth?: number;
|
|
74
|
+
state?: UIElementState | null;
|
|
75
|
+
stable_id?: string | null;
|
|
76
|
+
role?: string | null;
|
|
77
|
+
test_tag?: string | null;
|
|
78
|
+
selector?: UIResolutionSelector | null;
|
|
79
|
+
semantic?: UIElementSemanticMetadata | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface ReadinessSummary {
|
|
83
|
+
state: 'loading' | 'transitioning' | 'settled' | 'unknown' | 'unresponsive' | 'debugger_paused';
|
|
84
|
+
scope: 'device_ui';
|
|
85
|
+
basis: 'observed' | 'heuristic' | 'insufficient';
|
|
86
|
+
captured_at_ms: number | null;
|
|
87
|
+
sample_count: number;
|
|
88
|
+
stable_for_ms: number;
|
|
89
|
+
snapshot_session_id: string | null;
|
|
90
|
+
snapshot_revision: number | null;
|
|
91
|
+
evidence: Array<{ code: string; source: string; captured_at_ms: number | null; snapshot_revision: number | null }>;
|
|
92
|
+
limitations: string[];
|
|
93
|
+
capabilities: { loading: boolean; transitioning: boolean; settled: boolean; unresponsive: boolean; debugger_paused: boolean };
|
|
94
|
+
}
|
package/src/debugger/android.ts
CHANGED
|
@@ -34,7 +34,8 @@ export class AndroidDebugNative implements DebugNative {
|
|
|
34
34
|
// `adb jdwp` is a subscription, not a one-shot command. Bound the sample.
|
|
35
35
|
let jdwpOutput: string
|
|
36
36
|
try { jdwpOutput = (await exec(resolveAdbCmd(), ['-s', device, 'jdwp'], { timeout: debuggerRemaining(500), signal: debuggerSignal(), maxBuffer: 1024 * 1024 })).stdout }
|
|
37
|
-
catch (
|
|
37
|
+
catch (error: unknown) {
|
|
38
|
+
const e = error as { killed?: boolean; stderr?: string; stdout?: string }
|
|
38
39
|
if (debuggerSignal()?.aborted) throw new DebuggerError('DEBUGGER_CANCELLED')
|
|
39
40
|
debuggerRemaining(1)
|
|
40
41
|
if (!e.killed || e.stderr?.trim()) throw nativeError(e, 'DEVICE_UNAVAILABLE')
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Only catalog values cross the debugger error boundary. Never inspect exception text. */
|
|
2
|
+
export const stages = ['prerequisite', 'compilation', 'worker_start', 'ipc', 'target_resolution', 'forwarding', 'attach', 'command', 'transport', 'cleanup', 'unknown'] as const
|
|
3
|
+
export const reasons = ['unavailable', 'unsupported', 'spawn_failed', 'process_exited', 'invalid_message', 'message_limit', 'write_failed', 'connection_refused', 'transport_lost', 'timeout', 'cancelled', 'operation_failed', 'unknown'] as const
|
|
4
|
+
export type DiagnosticStage = typeof stages[number]
|
|
5
|
+
export type DiagnosticReason = typeof reasons[number]
|
|
6
|
+
export interface DebuggerDiagnostic { stage: DiagnosticStage; reason: DiagnosticReason; recovery: string }
|
|
7
|
+
const recovery: Record<DiagnosticStage, string> = {
|
|
8
|
+
prerequisite: 'Check JDK 17+ availability, including java, javac and jdk.jdi.',
|
|
9
|
+
compilation: 'Check the JDK compiler and worker source/cache availability.',
|
|
10
|
+
worker_start: 'Check Java worker launch availability. Inspect session state and cleanup before attaching again.',
|
|
11
|
+
ipc: 'Inspect session state and cleanup. Detach before attempting a fresh attach.',
|
|
12
|
+
target_resolution: 'Check the explicit device and running debuggable app/process.',
|
|
13
|
+
forwarding: 'Check the explicit device and debugger forwarding availability.',
|
|
14
|
+
attach: 'Check the running debuggable target and whether another debugger is attached. Inspect cleanup before a fresh attach.',
|
|
15
|
+
command: 'Inspect debugger session state and cleanup before another state-changing command.',
|
|
16
|
+
transport: 'Inspect session state and cleanup. Detach before attempting a fresh attach; execution state may be unknown.',
|
|
17
|
+
cleanup: 'Retry detach_debugger and inspect cleanup.remaining_resources. Do not kill the app or ADB server.',
|
|
18
|
+
unknown: 'Inspect debugger session state and cleanup; the failure cause is unknown.'
|
|
19
|
+
}
|
|
20
|
+
export function diagnostic(stage: DiagnosticStage, reason: DiagnosticReason): DebuggerDiagnostic {
|
|
21
|
+
const guidance = reason === 'timeout' || reason === 'cancelled'
|
|
22
|
+
? 'Execution may be uncertain. Inspect session state and cleanup before another state-changing command.' : recovery[stage]
|
|
23
|
+
return { stage, reason, recovery: guidance }
|
|
24
|
+
}
|
|
25
|
+
export function parseDiagnostic(value: unknown): DebuggerDiagnostic {
|
|
26
|
+
if (!value || typeof value !== 'object') throw new Error('INVALID_WORKER_DIAGNOSTIC')
|
|
27
|
+
const { stage, reason } = value as Record<string, unknown>
|
|
28
|
+
if (!stages.includes(stage as DiagnosticStage) || !reasons.includes(reason as DiagnosticReason)) throw new Error('INVALID_WORKER_DIAGNOSTIC')
|
|
29
|
+
return diagnostic(stage as DiagnosticStage, reason as DiagnosticReason)
|
|
30
|
+
}
|
|
31
|
+
export class DebuggerError extends Error {
|
|
32
|
+
constructor(public code: string, public diagnostic?: DebuggerDiagnostic) { super(code) }
|
|
33
|
+
}
|
|
34
|
+
const validationCodes = new Set(['INVALID_ARGUMENT', 'DEBUGGER_BUSY', 'DEBUGGER_NOT_FOUND', 'DEBUGGER_PAUSED', 'DEBUGGER_NOT_PAUSED', 'DEBUGGER_STALE_REFERENCE'])
|
|
35
|
+
export function classify(error: unknown, stage: DiagnosticStage, fallback: string, reason: DiagnosticReason = 'unknown'): DebuggerError {
|
|
36
|
+
const existing = error instanceof DebuggerError ? error : new DebuggerError(fallback)
|
|
37
|
+
if (existing.diagnostic || validationCodes.has(existing.code)) return existing
|
|
38
|
+
const knownReason = existing.code === 'DEBUGGER_TIMEOUT' ? 'timeout' : existing.code === 'DEBUGGER_CANCELLED' ? 'cancelled' : reason
|
|
39
|
+
return new DebuggerError(existing.code, diagnostic(stage, knownReason))
|
|
40
|
+
}
|
|
41
|
+
export async function atStage<T>(stage: DiagnosticStage, fallback: string, operation: () => Promise<T>): Promise<T> {
|
|
42
|
+
try { return await operation() } catch (error) { throw classify(error, stage, fallback) }
|
|
43
|
+
}
|
package/src/debugger/guard.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
2
2
|
import { DebuggerError } from './worker.js'
|
|
3
|
-
|
|
3
|
+
interface PauseEvidence {
|
|
4
|
+
debug_session_id: string
|
|
5
|
+
captured_at_ms: number
|
|
6
|
+
target: unknown
|
|
7
|
+
}
|
|
8
|
+
let pauseProvider: (device: string) => PauseEvidence | null = () => null
|
|
4
9
|
export function registerDebuggerPauseProvider(provider: typeof pauseProvider) { pauseProvider = provider }
|
|
5
10
|
const context = new AsyncLocalStorage<{ platform: string; device: string; dispatched: boolean }>()
|
|
6
11
|
export function withDebuggerGuard<T>(platform: string, device: string, operation: () => Promise<T>) {
|
|
@@ -139,9 +139,15 @@ public final class DebuggerWorker {
|
|
|
139
139
|
try(Reader reader=new InputStreamReader(System.in,StandardCharsets.UTF_8)){
|
|
140
140
|
StringBuilder line=new StringBuilder();int ch;
|
|
141
141
|
while((ch=reader.read())!=-1){if(ch!='\n'){line.append((char)ch);if(line.length()>MAX_LINE)throw new IOException("IPC_LIMIT");continue;}
|
|
142
|
-
Object id=null;
|
|
143
|
-
try{@SuppressWarnings("unchecked") Map<String,Object>a=(Map<String,Object>)new Json(line.toString()).value();id=a.get("id");synchronized(lock){Object result=command(a);send(obj("id",id,"result",result));}}
|
|
144
|
-
catch(Exception e){
|
|
142
|
+
Object id=null;String commandName="";
|
|
143
|
+
try{@SuppressWarnings("unchecked") Map<String,Object>a=(Map<String,Object>)new Json(line.toString()).value();id=a.get("id");commandName=str(a,"command");synchronized(lock){Object result=command(a);send(obj("id",id,"result",result));}}
|
|
144
|
+
catch(Exception e){
|
|
145
|
+
String msg=e.getMessage();
|
|
146
|
+
String code=msg!=null&&msg.matches("(?:DEBUGGER|INVALID|PROCESS|DEVICE)_[A-Z_]+")?msg:e instanceof VMDisconnectedException?"DEBUGGER_DISCONNECTED":"DEBUGGER_WORKER_FAILED";
|
|
147
|
+
String stage=commandName.equals("attach")?"attach":e instanceof VMDisconnectedException?"transport":"command";
|
|
148
|
+
String reason=e instanceof java.net.ConnectException?"connection_refused":e instanceof VMDisconnectedException?"transport_lost":e instanceof java.net.SocketTimeoutException || e instanceof TransportTimeoutException?"timeout":"operation_failed";
|
|
149
|
+
send(obj("id",id,"error",obj("code",code,"diagnostic",obj("stage",stage,"reason",reason))));
|
|
150
|
+
}
|
|
145
151
|
line.setLength(0);
|
|
146
152
|
}
|
|
147
153
|
}finally{synchronized(lock){finish("parent_closed");}watchdog.shutdownNow();}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { parseDiagnostic, type DebuggerDiagnostic } from './diagnostics.js'
|
|
2
|
+
/** Worker messages contain private debuggee data; never include them in errors. */
|
|
3
|
+
export interface WorkerEvent extends Record<string, unknown> {
|
|
4
|
+
event: string
|
|
5
|
+
reason?: string
|
|
6
|
+
diagnostic?: DebuggerDiagnostic
|
|
7
|
+
stop_id?: string
|
|
8
|
+
}
|
|
9
|
+
export type WorkerReply = Record<string, unknown>
|
|
10
|
+
export type WorkerMessage =
|
|
11
|
+
| { kind: 'event'; value: WorkerEvent }
|
|
12
|
+
| { kind: 'reply'; id: number; result: WorkerReply; error?: { code?: string; diagnostic?: DebuggerDiagnostic } }
|
|
13
|
+
|
|
14
|
+
const workerCodes = new Set(['INVALID_ARGUMENT', 'DEBUGGER_BUSY', 'DEBUGGER_NOT_FOUND', 'DEBUGGER_NOT_PAUSED', 'DEBUGGER_STALE_REFERENCE', 'DEBUGGER_DISCONNECTED', 'DEBUGGER_WORKER_FAILED'])
|
|
15
|
+
function record(value: unknown): value is Record<string, unknown> {
|
|
16
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
17
|
+
}
|
|
18
|
+
export function parseWorkerMessage(value: unknown): WorkerMessage {
|
|
19
|
+
if (!record(value)) throw new Error('INVALID_WORKER_MESSAGE')
|
|
20
|
+
if (value.event) {
|
|
21
|
+
if (typeof value.event !== 'string') throw new Error('INVALID_WORKER_EVENT')
|
|
22
|
+
for (const field of ['reason', 'stop_id']) {
|
|
23
|
+
if (value[field] !== undefined && typeof value[field] !== 'string') throw new Error('INVALID_WORKER_EVENT')
|
|
24
|
+
}
|
|
25
|
+
const event = { ...value } as WorkerEvent
|
|
26
|
+
if (value.diagnostic !== undefined) event.diagnostic = parseDiagnostic(value.diagnostic)
|
|
27
|
+
return { kind: 'event', value: event }
|
|
28
|
+
}
|
|
29
|
+
if (typeof value.id !== 'number' || !Number.isSafeInteger(value.id) || value.id < 1) throw new Error('INVALID_WORKER_REPLY')
|
|
30
|
+
if (value.error) {
|
|
31
|
+
if (!record(value.error) || (value.error.code !== undefined && typeof value.error.code !== 'string')) throw new Error('INVALID_WORKER_ERROR')
|
|
32
|
+
if (value.error.code !== undefined && !workerCodes.has(value.error.code as string)) throw new Error('INVALID_WORKER_ERROR')
|
|
33
|
+
return { kind: 'reply', id: value.id, result: {}, error: { ...(value.error.code === undefined ? {} : { code: value.error.code as string }), ...(value.error.diagnostic === undefined ? {} : { diagnostic: parseDiagnostic(value.error.diagnostic) }) } }
|
|
34
|
+
}
|
|
35
|
+
if (!record(value.result)) throw new Error('INVALID_WORKER_RESULT')
|
|
36
|
+
return { kind: 'reply', id: value.id, result: value.result }
|
|
37
|
+
}
|