mobster-cli 0.4.3__py3-none-any.whl
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.
- mobile_agent/__init__.py +4 -0
- mobile_agent/__main__.py +598 -0
- mobile_agent/accounts/__init__.py +1 -0
- mobile_agent/accounts/context.py +80 -0
- mobile_agent/accounts/mcp.py +55 -0
- mobile_agent/accounts/pacing.py +318 -0
- mobile_agent/accounts/register.py +78 -0
- mobile_agent/accounts/routes.py +212 -0
- mobile_agent/accounts/routing.py +69 -0
- mobile_agent/accounts/screen.py +273 -0
- mobile_agent/accounts/stats.py +54 -0
- mobile_agent/accounts/store.py +394 -0
- mobile_agent/agent_hooks.py +123 -0
- mobile_agent/ai_plans/__init__.py +7 -0
- mobile_agent/ai_plans/agents.py +96 -0
- mobile_agent/ai_plans/claude_code.py +208 -0
- mobile_agent/ai_plans/cli.py +400 -0
- mobile_agent/ai_plans/codex.py +258 -0
- mobile_agent/ai_plans/compat_chat.py +307 -0
- mobile_agent/ai_plans/device_login.py +164 -0
- mobile_agent/ai_plans/draft_client.py +68 -0
- mobile_agent/ai_plans/gemini.py +137 -0
- mobile_agent/ai_plans/instructions.py +65 -0
- mobile_agent/ai_plans/mcp_http.py +160 -0
- mobile_agent/ai_plans/phone_tools.py +892 -0
- mobile_agent/ai_plans/providers.py +235 -0
- mobile_agent/ai_plans/routes.py +160 -0
- mobile_agent/ai_plans/runner.py +400 -0
- mobile_agent/ai_plans/vault.py +114 -0
- mobile_agent/alerts.py +337 -0
- mobile_agent/android/__init__.py +18 -0
- mobile_agent/android/adb.py +268 -0
- mobile_agent/android/conditions.py +128 -0
- mobile_agent/android/doctor.py +54 -0
- mobile_agent/android/driver.py +137 -0
- mobile_agent/android/emulator.py +216 -0
- mobile_agent/android/logs.py +85 -0
- mobile_agent/android/manager.py +225 -0
- mobile_agent/android/records.py +31 -0
- mobile_agent/android/tree.py +96 -0
- mobile_agent/answer_shapes.py +230 -0
- mobile_agent/api_devices.py +333 -0
- mobile_agent/api_errors.py +17 -0
- mobile_agent/api_get.py +249 -0
- mobile_agent/api_http.py +467 -0
- mobile_agent/api_post.py +453 -0
- mobile_agent/api_routes.py +173 -0
- mobile_agent/app_api/__init__.py +4 -0
- mobile_agent/app_api/cli.py +151 -0
- mobile_agent/app_api/endpoints.py +193 -0
- mobile_agent/app_api/mcp.py +54 -0
- mobile_agent/app_api/openapi.py +146 -0
- mobile_agent/app_api/reading.py +172 -0
- mobile_agent/app_api/register.py +10 -0
- mobile_agent/app_api/screen.py +216 -0
- mobile_agent/app_api/service.py +382 -0
- mobile_agent/app_api/sessions.py +404 -0
- mobile_agent/app_api/tokens.py +167 -0
- mobile_agent/app_choice.py +131 -0
- mobile_agent/app_icons.py +183 -0
- mobile_agent/app_killer.py +69 -0
- mobile_agent/artifacts.py +606 -0
- mobile_agent/attach/__init__.py +13 -0
- mobile_agent/attach/cli.py +46 -0
- mobile_agent/attach/flutter.py +28 -0
- mobile_agent/attach/score.py +119 -0
- mobile_agent/attach/web.py +13 -0
- mobile_agent/attachments/__init__.py +1 -0
- mobile_agent/attachments/agent.py +418 -0
- mobile_agent/attachments/extract.py +217 -0
- mobile_agent/attachments/mcp.py +104 -0
- mobile_agent/attachments/register.py +73 -0
- mobile_agent/attachments/routes.py +326 -0
- mobile_agent/attachments/service.py +170 -0
- mobile_agent/attachments/sniff.py +152 -0
- mobile_agent/attachments/store.py +441 -0
- mobile_agent/audit_verify.py +436 -0
- mobile_agent/bench/README.md +410 -0
- mobile_agent/bench/__init__.py +0 -0
- mobile_agent/bench/__main__.py +394 -0
- mobile_agent/bench/ab.py +168 -0
- mobile_agent/bench/actuation.py +368 -0
- mobile_agent/bench/agents/__init__.py +9 -0
- mobile_agent/bench/agents/base.py +105 -0
- mobile_agent/bench/agents/plan_clients.py +245 -0
- mobile_agent/bench/agents/smart.py +533 -0
- mobile_agent/bench/checks.py +358 -0
- mobile_agent/bench/decide_gate.py +214 -0
- mobile_agent/bench/diagnose.py +181 -0
- mobile_agent/bench/evals/__init__.py +14 -0
- mobile_agent/bench/evals/build.py +565 -0
- mobile_agent/bench/evals/checkpoint.py +214 -0
- mobile_agent/bench/evals/irt.py +219 -0
- mobile_agent/bench/evals/l0.py +647 -0
- mobile_agent/bench/evals/l1.py +866 -0
- mobile_agent/bench/evals/models.py +124 -0
- mobile_agent/bench/evals/pairwise.py +189 -0
- mobile_agent/bench/evals/proxy.py +90 -0
- mobile_agent/bench/evals/sets.py +149 -0
- mobile_agent/bench/evals/traces.py +446 -0
- mobile_agent/bench/fixtures.py +176 -0
- mobile_agent/bench/guard_replay.py +129 -0
- mobile_agent/bench/h2-manifest.json +20 -0
- mobile_agent/bench/h3-manifest.json +20 -0
- mobile_agent/bench/heldout-manifest.json +32 -0
- mobile_agent/bench/heldout.py +375 -0
- mobile_agent/bench/iosworld.py +901 -0
- mobile_agent/bench/iosworld_stats.py +510 -0
- mobile_agent/bench/llm_units.py +116 -0
- mobile_agent/bench/manifest.json +93 -0
- mobile_agent/bench/metrics.py +66 -0
- mobile_agent/bench/phone.py +44 -0
- mobile_agent/bench/replay.py +172 -0
- mobile_agent/bench/report.py +207 -0
- mobile_agent/bench/runner.py +456 -0
- mobile_agent/bench/safety.py +310 -0
- mobile_agent/bench/stream_timing.py +213 -0
- mobile_agent/bench/suite.py +444 -0
- mobile_agent/bench/sweep.py +176 -0
- mobile_agent/bench/tape.py +798 -0
- mobile_agent/bench/tape_replay.py +88 -0
- mobile_agent/bench/trace_evals.py +128 -0
- mobile_agent/bench/trace_view.py +81 -0
- mobile_agent/bench/truth/iphone15pro.json +138 -0
- mobile_agent/bench/truth.py +340 -0
- mobile_agent/bench/tuning.py +543 -0
- mobile_agent/bench/tuning_analysis.py +656 -0
- mobile_agent/bench/vague-heldout-manifest.json +12 -0
- mobile_agent/bench/vague_rubric.py +135 -0
- mobile_agent/bench/vague_run.py +243 -0
- mobile_agent/brand.py +454 -0
- mobile_agent/brand_fonts.py +756 -0
- mobile_agent/build_identity.py +21 -0
- mobile_agent/cable_bt.py +623 -0
- mobile_agent/cable_bt_runtime.py +128 -0
- mobile_agent/catalog.py +69 -0
- mobile_agent/chart_svg.py +415 -0
- mobile_agent/chat_here.py +189 -0
- mobile_agent/cli_constants.py +5 -0
- mobile_agent/cli_parser.py +611 -0
- mobile_agent/cli_run.py +115 -0
- mobile_agent/compiled_read/__init__.py +21 -0
- mobile_agent/compiled_read/delta.py +89 -0
- mobile_agent/compiled_read/extractors.py +202 -0
- mobile_agent/compiled_read/routes.py +56 -0
- mobile_agent/completion.py +267 -0
- mobile_agent/compose.py +48 -0
- mobile_agent/config.py +114 -0
- mobile_agent/connectors/__init__.py +1 -0
- mobile_agent/connectors/api_session.py +76 -0
- mobile_agent/connectors/callback_page.py +146 -0
- mobile_agent/connectors/client.py +582 -0
- mobile_agent/connectors/github_app.py +55 -0
- mobile_agent/connectors/graph_api.py +396 -0
- mobile_agent/connectors/imports.py +170 -0
- mobile_agent/connectors/issue.py +66 -0
- mobile_agent/connectors/keystore.py +85 -0
- mobile_agent/connectors/marks.py +222 -0
- mobile_agent/connectors/oauth.py +476 -0
- mobile_agent/connectors/picker.py +228 -0
- mobile_agent/connectors/presets.py +591 -0
- mobile_agent/connectors/register.py +48 -0
- mobile_agent/connectors/routes.py +153 -0
- mobile_agent/connectors/service.py +966 -0
- mobile_agent/connectors/shared.py +136 -0
- mobile_agent/connectors/skill.py +446 -0
- mobile_agent/connectors/slack_api.py +269 -0
- mobile_agent/connectors/steps.py +92 -0
- mobile_agent/connectors/store.py +144 -0
- mobile_agent/connectors/vault.py +72 -0
- mobile_agent/console.py +178 -0
- mobile_agent/content_queue/__init__.py +1 -0
- mobile_agent/content_queue/client.py +263 -0
- mobile_agent/content_queue/importing.py +153 -0
- mobile_agent/content_queue/media_check.py +224 -0
- mobile_agent/content_queue/prompt.py +64 -0
- mobile_agent/content_queue/register.py +91 -0
- mobile_agent/content_queue/routes.py +370 -0
- mobile_agent/content_queue/runner.py +475 -0
- mobile_agent/content_queue/store.py +521 -0
- mobile_agent/contract.py +996 -0
- mobile_agent/contract_asks.py +248 -0
- mobile_agent/contract_prompt.py +45 -0
- mobile_agent/contract_screen.py +981 -0
- mobile_agent/contract_view.py +84 -0
- mobile_agent/corpus/__init__.py +26 -0
- mobile_agent/corpus/cli.py +63 -0
- mobile_agent/corpus/consent.py +55 -0
- mobile_agent/corpus/listener.py +76 -0
- mobile_agent/corpus/register.py +9 -0
- mobile_agent/corpus/skeleton.py +72 -0
- mobile_agent/corpus/store.py +143 -0
- mobile_agent/costs.py +161 -0
- mobile_agent/decider_scope.py +40 -0
- mobile_agent/decision_provider.py +189 -0
- mobile_agent/deeplinks.py +352 -0
- mobile_agent/device_info.py +116 -0
- mobile_agent/device_manager.py +978 -0
- mobile_agent/device_status.py +195 -0
- mobile_agent/device_targets.py +217 -0
- mobile_agent/devices.py +676 -0
- mobile_agent/devkit/__init__.py +64 -0
- mobile_agent/devkit/account_cli.py +90 -0
- mobile_agent/devkit/asc.py +562 -0
- mobile_agent/devkit/asc_cli.py +214 -0
- mobile_agent/devkit/ci.py +737 -0
- mobile_agent/devkit/ci_cli.py +196 -0
- mobile_agent/devkit/ci_hosts.py +194 -0
- mobile_agent/devkit/es256.py +197 -0
- mobile_agent/devkit/expo.py +440 -0
- mobile_agent/devkit/expo_cli.py +405 -0
- mobile_agent/devkit/expo_dev.py +203 -0
- mobile_agent/devkit/expo_routes.py +90 -0
- mobile_agent/devkit/fixtures_cli.py +133 -0
- mobile_agent/devkit/fixtures_routes.py +82 -0
- mobile_agent/devkit/links.py +375 -0
- mobile_agent/devkit/links_cli.py +123 -0
- mobile_agent/devkit/links_routes.py +83 -0
- mobile_agent/devkit/nightly.py +152 -0
- mobile_agent/devkit/shots.py +203 -0
- mobile_agent/devkit/testflight.py +155 -0
- mobile_agent/devkit/testflight_cli.py +127 -0
- mobile_agent/devkit/testflight_routes.py +111 -0
- mobile_agent/devkit/xcode.py +236 -0
- mobile_agent/devkit/xcode_cli.py +101 -0
- mobile_agent/devtools.py +419 -0
- mobile_agent/doctor.py +509 -0
- mobile_agent/doctor_fix.py +467 -0
- mobile_agent/downloads.py +55 -0
- mobile_agent/drivers.py +793 -0
- mobile_agent/dry_run.py +102 -0
- mobile_agent/effect_ledger.py +83 -0
- mobile_agent/engine_health.py +378 -0
- mobile_agent/engine_hooks.py +96 -0
- mobile_agent/engines.py +408 -0
- mobile_agent/env_file.py +63 -0
- mobile_agent/env_secrets.py +149 -0
- mobile_agent/errors.py +15 -0
- mobile_agent/evals/__init__.py +3 -0
- mobile_agent/evals/app_survey.py +149 -0
- mobile_agent/evals/development/__init__.py +1 -0
- mobile_agent/evals/development/score.py +276 -0
- mobile_agent/evals/latency_report.py +312 -0
- mobile_agent/evals/offline_report.py +374 -0
- mobile_agent/evals/oracles.py +298 -0
- mobile_agent/evals/redteam/__init__.py +15 -0
- mobile_agent/evals/redteam/__main__.py +72 -0
- mobile_agent/evals/redteam/cases.py +730 -0
- mobile_agent/evals/redteam/harness.py +604 -0
- mobile_agent/evals/redteam/live.py +139 -0
- mobile_agent/evals/redteam/plain.py +85 -0
- mobile_agent/evals/vision/__init__.py +0 -0
- mobile_agent/evals/vision/images/dog_001.jpg +0 -0
- mobile_agent/evals/vision/images/dog_002.jpg +0 -0
- mobile_agent/evals/vision/images/dog_003.jpg +0 -0
- mobile_agent/evals/vision/images/dog_004.jpg +0 -0
- mobile_agent/evals/vision/images/dog_005.jpg +0 -0
- mobile_agent/evals/vision/images/dog_006.jpg +0 -0
- mobile_agent/evals/vision/images/dog_007.jpg +0 -0
- mobile_agent/evals/vision/images/dog_010.jpg +0 -0
- mobile_agent/evals/vision/images/dog_011.jpg +0 -0
- mobile_agent/evals/vision/images/dog_013.jpg +0 -0
- mobile_agent/evals/vision/images/dog_014.jpg +0 -0
- mobile_agent/evals/vision/images/dog_015.jpg +0 -0
- mobile_agent/evals/vision/images/dog_016.jpg +0 -0
- mobile_agent/evals/vision/images/dog_017.jpg +0 -0
- mobile_agent/evals/vision/images/dog_019.jpg +0 -0
- mobile_agent/evals/vision/images/dog_020.jpg +0 -0
- mobile_agent/evals/vision/images/dog_021.jpg +0 -0
- mobile_agent/evals/vision/images/dog_022.jpg +0 -0
- mobile_agent/evals/vision/images/dog_023.jpg +0 -0
- mobile_agent/evals/vision/images/dog_024.jpg +0 -0
- mobile_agent/evals/vision/images/dog_026.jpg +0 -0
- mobile_agent/evals/vision/images/dog_027.jpg +0 -0
- mobile_agent/evals/vision/images/dog_034.jpg +0 -0
- mobile_agent/evals/vision/images/dog_035.jpg +0 -0
- mobile_agent/evals/vision/images/dog_038.jpg +0 -0
- mobile_agent/evals/vision/images/dog_042.jpg +0 -0
- mobile_agent/evals/vision/images/dog_047.jpg +0 -0
- mobile_agent/evals/vision/images/dog_052.jpg +0 -0
- mobile_agent/evals/vision/images/dog_058.jpg +0 -0
- mobile_agent/evals/vision/images/dog_062.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_000.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_010.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_011.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_015.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_016.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_017.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_019.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_021.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_025.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_026.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_027.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_030.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_032.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_033.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_034.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_035.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_036.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_037.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_039.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_040.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_041.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_042.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_043.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_044.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_046.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_047.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_048.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_049.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_051.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_053.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_054.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_055.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_058.jpg +0 -0
- mobile_agent/evals/vision/images/eyes_059.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_002.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_003.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_004.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_007.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_009.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_010.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_011.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_012.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_013.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_014.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_016.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_017.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_023.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_027.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_029.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_032.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_033.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_036.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_041.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_043.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_047.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_049.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_051.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_053.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_056.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_057.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_058.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_059.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_060.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_061.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_062.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_063.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_064.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_065.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_066.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_067.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_068.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_069.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_070.jpg +0 -0
- mobile_agent/evals/vision/images/receipt_071.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_000.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_001.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_002.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_004.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_005.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_008.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_009.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_010.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_012.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_013.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_015.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_016.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_017.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_018.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_021.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_022.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_023.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_024.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_030.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_031.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_032.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_033.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_034.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_036.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_038.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_039.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_040.jpg +0 -0
- mobile_agent/evals/vision/images/sunglasses_041.jpg +0 -0
- mobile_agent/evals/vision/manifest.json +2355 -0
- mobile_agent/eventbus.py +110 -0
- mobile_agent/explain.py +34 -0
- mobile_agent/failure_line.py +197 -0
- mobile_agent/fanout.py +663 -0
- mobile_agent/feedback/__init__.py +2 -0
- mobile_agent/feedback/bundle.py +204 -0
- mobile_agent/feedback/outbox.py +196 -0
- mobile_agent/feedback/register.py +9 -0
- mobile_agent/feedback/routes.py +177 -0
- mobile_agent/fleet.py +841 -0
- mobile_agent/fleet_health.py +729 -0
- mobile_agent/fleet_phone.py +186 -0
- mobile_agent/frontier/__init__.py +79 -0
- mobile_agent/frontier/act.py +380 -0
- mobile_agent/frontier/actions.py +70 -0
- mobile_agent/frontier/agent.py +256 -0
- mobile_agent/frontier/approvals.py +366 -0
- mobile_agent/frontier/hooks.py +199 -0
- mobile_agent/frontier/interrupts.py +125 -0
- mobile_agent/frontier/observe.py +331 -0
- mobile_agent/frontier/phases.py +381 -0
- mobile_agent/frontier/pipeline.py +61 -0
- mobile_agent/frontier/prompt.py +384 -0
- mobile_agent/frontier/protocol.py +91 -0
- mobile_agent/frontier/safety.py +467 -0
- mobile_agent/frontier/saved.py +375 -0
- mobile_agent/frontier/screen.py +419 -0
- mobile_agent/frontier/skills.py +147 -0
- mobile_agent/frontier/stages/__init__.py +1 -0
- mobile_agent/frontier/stages/after.py +192 -0
- mobile_agent/frontier/stages/approve.py +138 -0
- mobile_agent/frontier/stages/controls.py +115 -0
- mobile_agent/frontier/stages/ends.py +102 -0
- mobile_agent/frontier/stages/gate.py +92 -0
- mobile_agent/frontier/stages/guards.py +132 -0
- mobile_agent/frontier/stages/points.py +155 -0
- mobile_agent/frontier/stages/send.py +177 -0
- mobile_agent/frontier/turn.py +151 -0
- mobile_agent/full_disk_access.py +83 -0
- mobile_agent/gemini.py +69 -0
- mobile_agent/genuine.py +120 -0
- mobile_agent/graph/__init__.py +4 -0
- mobile_agent/graph/catalog.py +789 -0
- mobile_agent/graph/chain.py +306 -0
- mobile_agent/graph/dispatch.py +98 -0
- mobile_agent/graph/draft.py +373 -0
- mobile_agent/graph/edit.py +76 -0
- mobile_agent/graph/estimate.py +189 -0
- mobile_agent/graph/expr.py +562 -0
- mobile_agent/graph/functions.py +271 -0
- mobile_agent/graph/infer.py +144 -0
- mobile_agent/graph/nodes.py +936 -0
- mobile_agent/graph/phone_steps.py +178 -0
- mobile_agent/graph/rerun.py +327 -0
- mobile_agent/graph/run.py +899 -0
- mobile_agent/graph/schema.py +842 -0
- mobile_agent/graph/state.py +161 -0
- mobile_agent/graph/values.py +198 -0
- mobile_agent/harness/__init__.py +2 -0
- mobile_agent/harness/checkpoints.py +468 -0
- mobile_agent/harness/control.py +101 -0
- mobile_agent/harness/prewarm.py +213 -0
- mobile_agent/harness/register.py +43 -0
- mobile_agent/harness/routes.py +114 -0
- mobile_agent/harness/settings.py +66 -0
- mobile_agent/harness/tools/__init__.py +67 -0
- mobile_agent/harness/tools/ask_user.py +102 -0
- mobile_agent/harness/tools/watch.py +120 -0
- mobile_agent/harness_api.py +815 -0
- mobile_agent/hedge.py +203 -0
- mobile_agent/help_topics.py +305 -0
- mobile_agent/hints.py +248 -0
- mobile_agent/history.py +69 -0
- mobile_agent/home.py +214 -0
- mobile_agent/http_pool.py +175 -0
- mobile_agent/image_policy.py +139 -0
- mobile_agent/inbox.py +148 -0
- mobile_agent/installed_apps.py +344 -0
- mobile_agent/integrations/__init__.py +1 -0
- mobile_agent/integrations/cli.py +472 -0
- mobile_agent/integrations/client_files.py +65 -0
- mobile_agent/integrations/clients.py +998 -0
- mobile_agent/integrations/doctor.py +185 -0
- mobile_agent/integrations/jsonc.py +383 -0
- mobile_agent/integrations/routes.py +135 -0
- mobile_agent/integrations/rules.py +112 -0
- mobile_agent/integrations/server_options.py +46 -0
- mobile_agent/integrations/skill.py +152 -0
- mobile_agent/integrations/skill_files.py +10 -0
- mobile_agent/integrations/textedit.py +309 -0
- mobile_agent/intents/__init__.py +17 -0
- mobile_agent/intents/atlas.py +216 -0
- mobile_agent/intents/callback.py +44 -0
- mobile_agent/intents/cli.py +55 -0
- mobile_agent/intents/harvest.py +91 -0
- mobile_agent/intents/plan.py +93 -0
- mobile_agent/ios/__init__.py +1 -0
- mobile_agent/ios/guide.py +16 -0
- mobile_agent/ios/kb.py +212 -0
- mobile_agent/ios/kb_data.py +1588 -0
- mobile_agent/ios/mcp.py +44 -0
- mobile_agent/ios/register.py +8 -0
- mobile_agent/ios/system.py +369 -0
- mobile_agent/journal.py +531 -0
- mobile_agent/keychain_acl.py +374 -0
- mobile_agent/keys.py +395 -0
- mobile_agent/latency_overlap.py +36 -0
- mobile_agent/latency_trace.py +170 -0
- mobile_agent/learned/__init__.py +15 -0
- mobile_agent/learned/app_path.py +160 -0
- mobile_agent/learned/code_read.py +38 -0
- mobile_agent/learned/parts.py +546 -0
- mobile_agent/learned/programs.py +691 -0
- mobile_agent/learned/register.py +171 -0
- mobile_agent/learned/routes.py +61 -0
- mobile_agent/learned/taught.py +329 -0
- mobile_agent/learned/teach.py +538 -0
- mobile_agent/learned/workflows.py +647 -0
- mobile_agent/learned/zero.py +41 -0
- mobile_agent/links.py +37 -0
- mobile_agent/listen.py +607 -0
- mobile_agent/lock_spike.py +278 -0
- mobile_agent/lockscreen.py +526 -0
- mobile_agent/login.py +354 -0
- mobile_agent/longform/__init__.py +15 -0
- mobile_agent/longform/ads.py +191 -0
- mobile_agent/longform/blocks.py +117 -0
- mobile_agent/longform/budget.py +265 -0
- mobile_agent/longform/context.py +285 -0
- mobile_agent/longform/costs.py +93 -0
- mobile_agent/longform/digest.py +145 -0
- mobile_agent/longform/extract.py +508 -0
- mobile_agent/longform/feed.py +505 -0
- mobile_agent/longform/followup.py +168 -0
- mobile_agent/longform/frames.py +82 -0
- mobile_agent/longform/identity.py +87 -0
- mobile_agent/longform/inbox.py +221 -0
- mobile_agent/longform/items.py +425 -0
- mobile_agent/longform/models.py +115 -0
- mobile_agent/longform/notebook.py +329 -0
- mobile_agent/longform/plan.py +614 -0
- mobile_agent/longform/recall.py +195 -0
- mobile_agent/longform/receipts.py +81 -0
- mobile_agent/longform/register.py +124 -0
- mobile_agent/longform/report.py +343 -0
- mobile_agent/longform/routes.py +102 -0
- mobile_agent/longform/session.py +644 -0
- mobile_agent/longform/store.py +146 -0
- mobile_agent/longform/synthesis.py +347 -0
- mobile_agent/mac_tools.py +223 -0
- mobile_agent/manual_control.py +143 -0
- mobile_agent/maps.py +149 -0
- mobile_agent/marks.py +92 -0
- mobile_agent/mcp_server/__init__.py +3 -0
- mobile_agent/mcp_server/__main__.py +29 -0
- mobile_agent/mcp_server/action_journal.py +24 -0
- mobile_agent/mcp_server/action_tools.py +638 -0
- mobile_agent/mcp_server/approvals.py +219 -0
- mobile_agent/mcp_server/catalog.py +92 -0
- mobile_agent/mcp_server/cli.py +194 -0
- mobile_agent/mcp_server/codes.py +147 -0
- mobile_agent/mcp_server/device_tools.py +306 -0
- mobile_agent/mcp_server/direct.py +272 -0
- mobile_agent/mcp_server/expo_tools.py +105 -0
- mobile_agent/mcp_server/phone_tools.py +510 -0
- mobile_agent/mcp_server/protocol.py +364 -0
- mobile_agent/mcp_server/registry.py +55 -0
- mobile_agent/mcp_server/run_tools.py +531 -0
- mobile_agent/mcp_server/schemas.py +425 -0
- mobile_agent/mcp_server/screen_tools.py +168 -0
- mobile_agent/mcp_server/session.py +469 -0
- mobile_agent/mcp_server/support.py +145 -0
- mobile_agent/mcp_server/tools.py +493 -0
- mobile_agent/memory/__init__.py +9 -0
- mobile_agent/memory/cli.py +207 -0
- mobile_agent/memory/extract.py +191 -0
- mobile_agent/memory/listener.py +100 -0
- mobile_agent/memory/model.py +144 -0
- mobile_agent/memory/project.py +96 -0
- mobile_agent/memory/provider.py +127 -0
- mobile_agent/memory/register.py +21 -0
- mobile_agent/memory/retrieval.py +172 -0
- mobile_agent/memory/routes.py +216 -0
- mobile_agent/memory/runs.py +124 -0
- mobile_agent/memory/store.py +806 -0
- mobile_agent/memory/writer.py +278 -0
- mobile_agent/mirroring.py +585 -0
- mobile_agent/mirroring_runtime.py +221 -0
- mobile_agent/model_clients.py +604 -0
- mobile_agent/narrate.py +813 -0
- mobile_agent/native_helpers.py +84 -0
- mobile_agent/netxray/__init__.py +1 -0
- mobile_agent/netxray/analyze.py +322 -0
- mobile_agent/netxray/attribution.py +62 -0
- mobile_agent/netxray/capture.py +88 -0
- mobile_agent/netxray/cli.py +142 -0
- mobile_agent/netxray/job.py +219 -0
- mobile_agent/netxray/mobster-pcap.c +560 -0
- mobile_agent/netxray/packets.py +410 -0
- mobile_agent/netxray/pcapng.py +223 -0
- mobile_agent/netxray/register.py +93 -0
- mobile_agent/netxray/report.py +214 -0
- mobile_agent/netxray/store.py +48 -0
- mobile_agent/netxray/summary.py +157 -0
- mobile_agent/netxray/target.py +67 -0
- mobile_agent/netxray/tool.py +66 -0
- mobile_agent/netxray/trackers.py +194 -0
- mobile_agent/notify_triggers/__init__.py +1 -0
- mobile_agent/notify_triggers/rules.py +39 -0
- mobile_agent/notify_triggers/sources.py +315 -0
- mobile_agent/notify_triggers/watch.py +135 -0
- mobile_agent/offers.py +86 -0
- mobile_agent/orchestrate.py +215 -0
- mobile_agent/outlets/__init__.py +1 -0
- mobile_agent/outlets/connect.py +249 -0
- mobile_agent/outlets/folder.py +180 -0
- mobile_agent/outlets/hooks.py +453 -0
- mobile_agent/outlets/inbound.py +472 -0
- mobile_agent/outlets/inbound_reply.py +57 -0
- mobile_agent/outlets/inbound_routes.py +81 -0
- mobile_agent/outlets/kinds.py +308 -0
- mobile_agent/outlets/mail.py +110 -0
- mobile_agent/outlets/net.py +86 -0
- mobile_agent/outlets/notion.py +244 -0
- mobile_agent/outlets/register.py +56 -0
- mobile_agent/outlets/routes.py +135 -0
- mobile_agent/outlets/service.py +580 -0
- mobile_agent/outlets/sheets.py +169 -0
- mobile_agent/outlets/slack.py +177 -0
- mobile_agent/outlets/store.py +194 -0
- mobile_agent/outlets/vault.py +80 -0
- mobile_agent/outlets/webhook.py +316 -0
- mobile_agent/output_contract.py +141 -0
- mobile_agent/owner_presence.py +211 -0
- mobile_agent/ownership.py +219 -0
- mobile_agent/packs/__init__.py +1 -0
- mobile_agent/packs/calendar.py +243 -0
- mobile_agent/packs/context.py +68 -0
- mobile_agent/packs/core.py +757 -0
- mobile_agent/packs/front_door.py +316 -0
- mobile_agent/packs/heal.py +214 -0
- mobile_agent/packs/health.py +122 -0
- mobile_agent/packs/insights.py +76 -0
- mobile_agent/packs/instagram.py +640 -0
- mobile_agent/packs/linkedin.py +106 -0
- mobile_agent/packs/maps.py +196 -0
- mobile_agent/packs/mcp.py +149 -0
- mobile_agent/packs/messages.py +270 -0
- mobile_agent/packs/notes.py +226 -0
- mobile_agent/packs/photos.py +166 -0
- mobile_agent/packs/pins.py +47 -0
- mobile_agent/packs/reddit.py +110 -0
- mobile_agent/packs/register.py +276 -0
- mobile_agent/packs/rows.py +108 -0
- mobile_agent/packs/safari.py +143 -0
- mobile_agent/packs/settings.py +253 -0
- mobile_agent/packs/social.py +300 -0
- mobile_agent/packs/threads.py +97 -0
- mobile_agent/packs/tiktok.py +455 -0
- mobile_agent/packs/tools.py +290 -0
- mobile_agent/packs/x.py +127 -0
- mobile_agent/packs/youtube.py +199 -0
- mobile_agent/parity.py +270 -0
- mobile_agent/paths.py +99 -0
- mobile_agent/perception.py +470 -0
- mobile_agent/permissions/__init__.py +32 -0
- mobile_agent/permissions/consequence.py +535 -0
- mobile_agent/permissions/exceptions.py +99 -0
- mobile_agent/permissions/gate.py +316 -0
- mobile_agent/permissions/outside.py +316 -0
- mobile_agent/permissions/policy.py +288 -0
- mobile_agent/permissions/project_policy.py +411 -0
- mobile_agent/permissions/register.py +148 -0
- mobile_agent/permissions/rules.py +291 -0
- mobile_agent/phone_io/__init__.py +146 -0
- mobile_agent/phone_io/cli.py +427 -0
- mobile_agent/phone_io/clipboard.py +78 -0
- mobile_agent/phone_io/controls.py +78 -0
- mobile_agent/phone_io/files.py +289 -0
- mobile_agent/phone_io/handoff.py +123 -0
- mobile_agent/phone_io/icloud.py +118 -0
- mobile_agent/phone_io/install.py +188 -0
- mobile_agent/phone_io/network_capture.py +188 -0
- mobile_agent/phone_io/network_cli.py +138 -0
- mobile_agent/phone_io/network_profiles.py +138 -0
- mobile_agent/phone_io/photos.py +512 -0
- mobile_agent/phone_io/recording.py +115 -0
- mobile_agent/phone_io/secrets.py +146 -0
- mobile_agent/phone_io/transfer.py +895 -0
- mobile_agent/phone_io/tunnel.py +129 -0
- mobile_agent/phone_ready.py +91 -0
- mobile_agent/pinning.py +158 -0
- mobile_agent/plan_gate.py +807 -0
- mobile_agent/plugins/__init__.py +3 -0
- mobile_agent/plugins/install.py +163 -0
- mobile_agent/plugins/manifest.py +242 -0
- mobile_agent/plugins/register.py +15 -0
- mobile_agent/plugins/routes.py +82 -0
- mobile_agent/plugins/service.py +322 -0
- mobile_agent/plugins/skills.py +76 -0
- mobile_agent/plugins/store.py +79 -0
- mobile_agent/pool.py +285 -0
- mobile_agent/power_watch.py +275 -0
- mobile_agent/premium_model.py +22 -0
- mobile_agent/project_env.py +291 -0
- mobile_agent/project_env_cli.py +74 -0
- mobile_agent/project_env_routes.py +55 -0
- mobile_agent/projects/__init__.py +27 -0
- mobile_agent/projects/ci.py +332 -0
- mobile_agent/projects/clone.py +339 -0
- mobile_agent/projects/drafts.py +158 -0
- mobile_agent/projects/folder.py +436 -0
- mobile_agent/projects/github.py +131 -0
- mobile_agent/projects/register.py +31 -0
- mobile_agent/projects/revisions.py +253 -0
- mobile_agent/projects/routes.py +234 -0
- mobile_agent/projects/runs.py +297 -0
- mobile_agent/projects/service.py +695 -0
- mobile_agent/projects/setup.py +84 -0
- mobile_agent/projects/store.py +379 -0
- mobile_agent/projects/sync.py +380 -0
- mobile_agent/projects/workflow_files.py +270 -0
- mobile_agent/replay_core/__init__.py +26 -0
- mobile_agent/replay_core/checks.py +594 -0
- mobile_agent/replay_core/engine.py +596 -0
- mobile_agent/replay_core/heal.py +364 -0
- mobile_agent/replay_core/path.py +240 -0
- mobile_agent/replay_core/recorder.py +206 -0
- mobile_agent/replay_core/store.py +171 -0
- mobile_agent/result_blocks.py +941 -0
- mobile_agent/run.py +642 -0
- mobile_agent/run_delivery.py +123 -0
- mobile_agent/run_executor.py +200 -0
- mobile_agent/run_export.py +284 -0
- mobile_agent/run_gif.py +891 -0
- mobile_agent/runner_hints.py +86 -0
- mobile_agent/runner_renewal.py +205 -0
- mobile_agent/runtime_create.py +549 -0
- mobile_agent/runtime_driver.py +458 -0
- mobile_agent/runtime_limits.py +319 -0
- mobile_agent/runtime_queue.py +394 -0
- mobile_agent/runtime_runs.py +383 -0
- mobile_agent/runtime_status.py +181 -0
- mobile_agent/runtime_teach.py +295 -0
- mobile_agent/runtime_work.py +599 -0
- mobile_agent/screen_text.py +101 -0
- mobile_agent/secret_filter.py +113 -0
- mobile_agent/serve.py +160 -0
- mobile_agent/server.py +363 -0
- mobile_agent/service_support.py +42 -0
- mobile_agent/settle/__init__.py +1 -0
- mobile_agent/settle/predict.py +102 -0
- mobile_agent/settle/replay.py +92 -0
- mobile_agent/settle/store.py +93 -0
- mobile_agent/settle/stream.py +43 -0
- mobile_agent/setup_cli.py +225 -0
- mobile_agent/setup_errors.py +87 -0
- mobile_agent/setup_service.py +527 -0
- mobile_agent/share.py +104 -0
- mobile_agent/signing.py +184 -0
- mobile_agent/sim/__init__.py +6 -0
- mobile_agent/sim/__main__.py +26 -0
- mobile_agent/sim/api.py +952 -0
- mobile_agent/sim/apps.py +172 -0
- mobile_agent/sim/biometrics.py +84 -0
- mobile_agent/sim/cli.py +271 -0
- mobile_agent/sim/doctor.py +293 -0
- mobile_agent/sim/governor.py +90 -0
- mobile_agent/sim/holders.py +88 -0
- mobile_agent/sim/models.py +62 -0
- mobile_agent/sim/registry.py +161 -0
- mobile_agent/sim/simctl.py +269 -0
- mobile_agent/sim/wda.py +618 -0
- mobile_agent/sim/xcode.py +74 -0
- mobile_agent/skills/__init__.py +12 -0
- mobile_agent/skills/codes.py +597 -0
- mobile_agent/skills/notifications.py +281 -0
- mobile_agent/skills/open_url.py +127 -0
- mobile_agent/smart_events.py +588 -0
- mobile_agent/smart_result.py +490 -0
- mobile_agent/smart_run.py +413 -0
- mobile_agent/state.py +662 -0
- mobile_agent/states.py +217 -0
- mobile_agent/steering.py +70 -0
- mobile_agent/style.py +178 -0
- mobile_agent/supervised.py +234 -0
- mobile_agent/swift/helper_bt_hid.swift +534 -0
- mobile_agent/swift/helper_doc_text.swift +184 -0
- mobile_agent/swift/helper_draft_reply.swift +170 -0
- mobile_agent/swift/helper_map.swift +110 -0
- mobile_agent/swift/helper_mirroring.swift +1099 -0
- mobile_agent/swift/helper_mjpeg_mp4.swift +103 -0
- mobile_agent/swift/helper_pdf.swift +100 -0
- mobile_agent/swift/helper_phone_audio.swift +993 -0
- mobile_agent/swift/helper_phone_screen.swift +416 -0
- mobile_agent/swift/helper_screen_text.swift +24 -0
- mobile_agent/swift/helper_transfer.swift +246 -0
- mobile_agent/swift/ocr.swift +22 -0
- mobile_agent/task_policy.py +337 -0
- mobile_agent/team_signing/__init__.py +34 -0
- mobile_agent/team_signing/apple_ca.py +37 -0
- mobile_agent/team_signing/bundle.py +136 -0
- mobile_agent/team_signing/cli.py +208 -0
- mobile_agent/team_signing/identity.py +248 -0
- mobile_agent/team_signing/ledger.py +105 -0
- mobile_agent/team_signing/prebuilt.py +61 -0
- mobile_agent/team_signing/resign.py +256 -0
- mobile_agent/team_signing/service.py +382 -0
- mobile_agent/team_signing/tooling.py +243 -0
- mobile_agent/team_signing/writes.py +268 -0
- mobile_agent/terminal_image.py +81 -0
- mobile_agent/testkit/__init__.py +1 -0
- mobile_agent/testkit/a11y_baseline.py +132 -0
- mobile_agent/testkit/api.py +403 -0
- mobile_agent/testkit/capsule.py +400 -0
- mobile_agent/testkit/capsule_cli.py +57 -0
- mobile_agent/testkit/cli.py +948 -0
- mobile_agent/testkit/cli_arguments.py +193 -0
- mobile_agent/testkit/comparison.py +288 -0
- mobile_agent/testkit/comparison_cli.py +41 -0
- mobile_agent/testkit/discover.py +257 -0
- mobile_agent/testkit/editor.py +243 -0
- mobile_agent/testkit/execute.py +515 -0
- mobile_agent/testkit/github_checks.py +248 -0
- mobile_agent/testkit/gitref.py +66 -0
- mobile_agent/testkit/heal_review.py +176 -0
- mobile_agent/testkit/health.py +480 -0
- mobile_agent/testkit/history.py +255 -0
- mobile_agent/testkit/hosted_results.py +321 -0
- mobile_agent/testkit/input_files.py +173 -0
- mobile_agent/testkit/jobs.py +285 -0
- mobile_agent/testkit/junit_verdict.py +33 -0
- mobile_agent/testkit/maestro.py +802 -0
- mobile_agent/testkit/mcp.py +562 -0
- mobile_agent/testkit/mcp_comparison.py +88 -0
- mobile_agent/testkit/minimize.py +471 -0
- mobile_agent/testkit/minimizer_cli.py +48 -0
- mobile_agent/testkit/notify.py +212 -0
- mobile_agent/testkit/phone_video.py +191 -0
- mobile_agent/testkit/pr.py +491 -0
- mobile_agent/testkit/pr_report.py +562 -0
- mobile_agent/testkit/prbuild.py +148 -0
- mobile_agent/testkit/proof_report.py +55 -0
- mobile_agent/testkit/provenance.py +119 -0
- mobile_agent/testkit/prrun.py +244 -0
- mobile_agent/testkit/recent.py +166 -0
- mobile_agent/testkit/recipes.py +146 -0
- mobile_agent/testkit/record.py +204 -0
- mobile_agent/testkit/register.py +288 -0
- mobile_agent/testkit/reports.py +998 -0
- mobile_agent/testkit/repro.py +432 -0
- mobile_agent/testkit/scenario.py +440 -0
- mobile_agent/testkit/scenario_cli.py +37 -0
- mobile_agent/testkit/snapshots_cli.py +60 -0
- mobile_agent/testkit/suite.py +670 -0
- mobile_agent/testkit/targets.py +497 -0
- mobile_agent/testkit/xctest.py +378 -0
- mobile_agent/threads/__init__.py +1 -0
- mobile_agent/threads/chat_once.py +264 -0
- mobile_agent/threads/cli.py +740 -0
- mobile_agent/threads/client.py +326 -0
- mobile_agent/threads/context.py +246 -0
- mobile_agent/threads/mcp.py +739 -0
- mobile_agent/threads/recent.py +34 -0
- mobile_agent/threads/register.py +54 -0
- mobile_agent/threads/routes.py +188 -0
- mobile_agent/threads/service.py +975 -0
- mobile_agent/threads/store.py +361 -0
- mobile_agent/threads/summary.py +117 -0
- mobile_agent/threads/term.py +101 -0
- mobile_agent/threads/workflow_cli.py +104 -0
- mobile_agent/tls.py +36 -0
- mobile_agent/traces.py +271 -0
- mobile_agent/tracks.py +235 -0
- mobile_agent/transport.py +271 -0
- mobile_agent/triggers/__init__.py +1 -0
- mobile_agent/triggers/actions.py +204 -0
- mobile_agent/triggers/model.py +146 -0
- mobile_agent/triggers/register.py +29 -0
- mobile_agent/triggers/routes.py +101 -0
- mobile_agent/triggers/service.py +387 -0
- mobile_agent/triggers/store.py +142 -0
- mobile_agent/tui/__init__.py +89 -0
- mobile_agent/tui/app.py +582 -0
- mobile_agent/tui/chrome.py +321 -0
- mobile_agent/tui/commands.py +375 -0
- mobile_agent/tui/demo_phone.py +369 -0
- mobile_agent/tui/images.py +29 -0
- mobile_agent/tui/keys.py +64 -0
- mobile_agent/tui/prompt.py +195 -0
- mobile_agent/tui/render.py +395 -0
- mobile_agent/tui/screens.py +180 -0
- mobile_agent/tui/session.py +308 -0
- mobile_agent/tui/tasks.py +287 -0
- mobile_agent/tui/theme.py +118 -0
- mobile_agent/tui/widgets.py +272 -0
- mobile_agent/update_check.py +213 -0
- mobile_agent/usage.py +184 -0
- mobile_agent/verify/__init__.py +0 -0
- mobile_agent/verify/__main__.py +41 -0
- mobile_agent/verify/a11y.py +189 -0
- mobile_agent/verify/actions.py +290 -0
- mobile_agent/verify/assertions.py +570 -0
- mobile_agent/verify/audit.py +312 -0
- mobile_agent/verify/business.py +221 -0
- mobile_agent/verify/business_run.py +131 -0
- mobile_agent/verify/business_state.py +168 -0
- mobile_agent/verify/check_schema.py +398 -0
- mobile_agent/verify/checks.py +614 -0
- mobile_agent/verify/cli.py +423 -0
- mobile_agent/verify/conditions.py +483 -0
- mobile_agent/verify/crashes.py +321 -0
- mobile_agent/verify/device_audit.py +246 -0
- mobile_agent/verify/dialogs.py +287 -0
- mobile_agent/verify/evidence.py +705 -0
- mobile_agent/verify/fixtures.py +305 -0
- mobile_agent/verify/flow.py +213 -0
- mobile_agent/verify/l10n.py +141 -0
- mobile_agent/verify/netcerts.py +67 -0
- mobile_agent/verify/netproxy.py +356 -0
- mobile_agent/verify/netrun.py +81 -0
- mobile_agent/verify/netshim.m +28 -0
- mobile_agent/verify/netshim.py +48 -0
- mobile_agent/verify/netstubs.py +132 -0
- mobile_agent/verify/overlay.py +174 -0
- mobile_agent/verify/perf.py +239 -0
- mobile_agent/verify/proof.py +192 -0
- mobile_agent/verify/replay_admission.py +48 -0
- mobile_agent/verify/report.py +952 -0
- mobile_agent/verify/run_cleanup.py +67 -0
- mobile_agent/verify/run_links.py +48 -0
- mobile_agent/verify/run_perf.py +44 -0
- mobile_agent/verify/run_secrets.py +39 -0
- mobile_agent/verify/runner.py +976 -0
- mobile_agent/verify/runs.py +57 -0
- mobile_agent/verify/screen_coverage.py +181 -0
- mobile_agent/verify/smart.py +106 -0
- mobile_agent/verify/snapshot_run.py +114 -0
- mobile_agent/verify/snapshots.py +306 -0
- mobile_agent/verify/sound.py +335 -0
- mobile_agent/verify/source_observation.py +130 -0
- mobile_agent/verify/system_surfaces/__init__.py +7 -0
- mobile_agent/verify/system_surfaces/play.py +106 -0
- mobile_agent/verify/system_surfaces/spec.py +139 -0
- mobile_agent/verify/system_surfaces/stage.py +138 -0
- mobile_agent/verify/system_surfaces/surfaces.py +121 -0
- mobile_agent/verify/tree.py +223 -0
- mobile_agent/verify/verdict.py +377 -0
- mobile_agent/verify/wire.py +392 -0
- mobile_agent/verify/wirestore.py +176 -0
- mobile_agent/waiting/__init__.py +1 -0
- mobile_agent/waiting/contacts.py +73 -0
- mobile_agent/waiting/drafts.py +136 -0
- mobile_agent/waiting/job.py +145 -0
- mobile_agent/waiting/messages.py +174 -0
- mobile_agent/waiting/rank.py +115 -0
- mobile_agent/waiting/register.py +26 -0
- mobile_agent/watch.py +502 -0
- mobile_agent/wda/__init__.py +2 -0
- mobile_agent/wda/frame_clock.py +646 -0
- mobile_agent/wda/frame_source.py +325 -0
- mobile_agent/wda/frame_store.py +115 -0
- mobile_agent/wda/gate.py +163 -0
- mobile_agent/wda/gestures.py +291 -0
- mobile_agent/wda/guards.py +94 -0
- mobile_agent/wda/identity.py +55 -0
- mobile_agent/wda/observe.py +884 -0
- mobile_agent/wda/patches.py +856 -0
- mobile_agent/wda/point_gestures.py +150 -0
- mobile_agent/wda/source.py +32 -0
- mobile_agent/wda/system_dialogs.py +571 -0
- mobile_agent/wda/text.py +694 -0
- mobile_agent/wda/timeouts.py +77 -0
- mobile_agent/wda/video.py +505 -0
- mobile_agent/wda/watchdog.py +243 -0
- mobile_agent/wireless/__init__.py +15 -0
- mobile_agent/wireless/api.py +354 -0
- mobile_agent/wireless/cli.py +287 -0
- mobile_agent/wireless/devicectl.py +229 -0
- mobile_agent/wireless/exposure.py +33 -0
- mobile_agent/wireless/mobster-wifi-pair.c +122 -0
- mobile_agent/wireless/monitor.py +332 -0
- mobile_agent/wireless/network.py +334 -0
- mobile_agent/wireless/onboarding.py +293 -0
- mobile_agent/wireless/pair.py +124 -0
- mobile_agent/wireless/probe.py +322 -0
- mobile_agent/wireless/register.py +8 -0
- mobile_agent/wireless/relay.py +179 -0
- mobile_agent/wireless/result.py +87 -0
- mobile_agent/wireless/store.py +85 -0
- mobile_agent/wireless/switch.py +77 -0
- mobile_agent/wireless/transport.py +118 -0
- mobile_agent/wireless/words.py +81 -0
- mobile_agent/wireless/xctestrun.py +83 -0
- mobile_agent/workflow_tools.py +59 -0
- mobile_agent/workflows/__init__.py +2 -0
- mobile_agent/workflows/brief.py +201 -0
- mobile_agent/workflows/cron.py +110 -0
- mobile_agent/workflows/health.py +257 -0
- mobile_agent/workflows/history.py +126 -0
- mobile_agent/workflows/records.py +442 -0
- mobile_agent/workflows/runs.py +1000 -0
- mobile_agent/workflows/scheduler.py +134 -0
- mobile_agent/workflows/service.py +973 -0
- mobile_agent/workflows/starters.py +285 -0
- mobile_agent/workflows/triggers.py +248 -0
- mobile_agent/xray/__init__.py +1 -0
- mobile_agent/xray/app_cli.py +116 -0
- mobile_agent/xray/cli.py +21 -0
- mobile_agent/xray/crawl.py +754 -0
- mobile_agent/xray/diff.py +171 -0
- mobile_agent/xray/diff_cli.py +43 -0
- mobile_agent/xray/job.py +184 -0
- mobile_agent/xray/paywall.py +188 -0
- mobile_agent/xray/policy.py +305 -0
- mobile_agent/xray/register.py +43 -0
- mobile_agent/xray/report.py +283 -0
- mobile_agent/xray/screens.py +117 -0
- mobster_cli-0.4.3.dist-info/METADATA +93 -0
- mobster_cli-0.4.3.dist-info/RECORD +1009 -0
- mobster_cli-0.4.3.dist-info/WHEEL +5 -0
- mobster_cli-0.4.3.dist-info/entry_points.txt +3 -0
- mobster_cli-0.4.3.dist-info/licenses/LICENSE +21 -0
- mobster_cli-0.4.3.dist-info/top_level.txt +1 -0
mobile_agent/devtools.py
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"""The developer commands in ORDER: their fixed help, and each command's module loaded only when it runs."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import contextlib
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import signal
|
|
8
|
+
import sys
|
|
9
|
+
import threading
|
|
10
|
+
|
|
11
|
+
from .help_topics import HELP
|
|
12
|
+
|
|
13
|
+
# The commands in the order `mobster --help` lists them.
|
|
14
|
+
ORDER = ("verify", "sim", "mcp", "phone", "alerts", "audit", "chat", "workflow", "memory", "test", "wifi", "api", "ci",
|
|
15
|
+
"account", "expo", "asc", "testflight", "xcode", "fixtures", "links", "xray", "env", "signing")
|
|
16
|
+
# `mobster intents` is hidden unless the flag is on: the help snapshots and the docs reference never list it.
|
|
17
|
+
if os.environ.get("MOBSTER_EXPERIMENTAL_INTENTS", "").strip().casefold() in ("1", "true", "yes", "on"):
|
|
18
|
+
ORDER += ("intents",)
|
|
19
|
+
HELP["intents"] = "read a simulator's apps for the links they declare (experimental)"
|
|
20
|
+
MISSING_EXIT = 3
|
|
21
|
+
PACKAGES = {"verify": "mobile_agent.verify", "sim": "mobile_agent.sim", "mcp": "mobile_agent.mcp_server",
|
|
22
|
+
"phone": "mobile_agent.phone_io", "alerts": "mobile_agent.alerts", "audit": "mobile_agent.audit_verify"}
|
|
23
|
+
PACKAGES.update({"chat": "mobile_agent.threads", "workflow": "mobile_agent.threads", "memory": "mobile_agent.memory",
|
|
24
|
+
"test": "mobile_agent.testkit", "wifi": "mobile_agent.wireless", "api": "mobile_agent.app_api"})
|
|
25
|
+
PACKAGES["xray"] = "mobile_agent.xray"
|
|
26
|
+
PACKAGES["intents"] = "mobile_agent.intents"
|
|
27
|
+
PACKAGES["env"] = "mobile_agent.project_env_cli"
|
|
28
|
+
PACKAGES["signing"] = "mobile_agent.team_signing"
|
|
29
|
+
PACKAGES.update({name: "mobile_agent.devkit" for name in ("ci", "account", "expo", "asc", "testflight", "xcode",
|
|
30
|
+
"fixtures", "links")})
|
|
31
|
+
# The module that holds a command's add_arguments and run, where it isn't the package's ``cli``.
|
|
32
|
+
CLI_MODULES = {"workflow": "workflow_cli", "ci": "ci_cli", "account": "account_cli", "expo": "expo_cli",
|
|
33
|
+
"asc": "asc_cli", "testflight": "testflight_cli", "xcode": "xcode_cli", "fixtures": "fixtures_cli",
|
|
34
|
+
"links": "links_cli"}
|
|
35
|
+
|
|
36
|
+
# name: (description, epilog). The one-line help each command shows in `mobster --help` is help_topics.HELP.
|
|
37
|
+
TEXT = {
|
|
38
|
+
"verify": (
|
|
39
|
+
"Check an iOS app on a headless simulator that Mobster manages. Mobster installs and\n"
|
|
40
|
+
"launches the app, runs the steps (Smart, on your OpenAI or Anthropic key) or none\n"
|
|
41
|
+
"(a launch-only check), and checks your declared assertions. No model grades the\n"
|
|
42
|
+
"outcome. Each run writes a report, with frames when available.\n\n"
|
|
43
|
+
"A check is a saved YAML file. verify is the one-off form of `mobster test`: it runs one\n"
|
|
44
|
+
"check, from flags or --check FILE, and --save NAME keeps it for `mobster test`.",
|
|
45
|
+
"exit codes: 0 passed, 1 failed, 2 needs review, 3 couldn't run (usage errors too),\n"
|
|
46
|
+
" 130 ctrl+c\n\n"
|
|
47
|
+
"examples:\n"
|
|
48
|
+
" mobster verify --bundle com.apple.Preferences --text General\n"
|
|
49
|
+
" mobster verify --app build/YourApp.app --open-url yourapp://lesson --text \"Fill in the blank\"\n"
|
|
50
|
+
" mobster verify \"Open General, then About\" --bundle com.apple.Preferences --text \"iOS Version\"\n"
|
|
51
|
+
" mobster verify --check .mobster/checks/lesson-complete.yaml --json"),
|
|
52
|
+
"sim": (
|
|
53
|
+
"Manage the headless simulators that `mobster verify` and `mobster mcp` run on: list\n"
|
|
54
|
+
"them, prepare one (create, boot, build and start WebDriverAgent), shut them down,\n"
|
|
55
|
+
"erase or delete them. It deletes only simulators Mobster created.",
|
|
56
|
+
None),
|
|
57
|
+
"mcp": (
|
|
58
|
+
"Serve Mobster as an MCP server on stdio, so your coding agent can launch and check\n"
|
|
59
|
+
"an iOS app on a simulator: it starts a check with verify_start, drives the app with\n"
|
|
60
|
+
"screen, tap, type_text and swipe, and gets the verdict from verify_finish.",
|
|
61
|
+
"examples:\n"
|
|
62
|
+
" mobster mcp install --all add Mobster to Claude Code, Codex, Cursor and the others found here\n"
|
|
63
|
+
" mobster mcp clients which agent clients are here, and which run Mobster\n"
|
|
64
|
+
" mobster mcp doctor start the server as a client would and call status"),
|
|
65
|
+
"phone": (
|
|
66
|
+
"Phone utilities that aren't tasks: put text on the phone's clipboard (or print what it\n"
|
|
67
|
+
"holds), and install a signed .app or .ipa on a USB iPhone or a Mobster simulator.",
|
|
68
|
+
"examples:\n"
|
|
69
|
+
" mobster phone clipboard set \"https://example.com/invite/42\"\n"
|
|
70
|
+
" mobster phone clipboard get\n"
|
|
71
|
+
" mobster phone file put menu.pdf --app com.apple.Pages\n"
|
|
72
|
+
" mobster phone install build/YourApp.ipa --device \"Work iPhone\""),
|
|
73
|
+
"alerts": (
|
|
74
|
+
"Mobster posts to MOBSTER_ALERT_WEBHOOK_URL (https: Slack, Discord, ntfy or any JSON\n"
|
|
75
|
+
"webhook) when a scheduled task fails, stops or waits a minute for your approval.\n"
|
|
76
|
+
"The post never holds the task's answer or anything it typed.",
|
|
77
|
+
"example:\n"
|
|
78
|
+
" mobster alerts test"),
|
|
79
|
+
"audit": (
|
|
80
|
+
"Check a Team plan audit export offline: the hash chain, the signed head of the API's\n"
|
|
81
|
+
"export, and with --keys every Mac's signature. Nothing leaves this Mac.",
|
|
82
|
+
"examples:\n"
|
|
83
|
+
" mobster audit verify audit.jsonl\n"
|
|
84
|
+
" mobster audit verify audit.jsonl --keys keys.json\n"
|
|
85
|
+
" mobster audit verify export.json"),
|
|
86
|
+
}
|
|
87
|
+
TEXT.update({
|
|
88
|
+
"chat": ("Start or continue a conversation with Mobster's agent on your iPhone. Follow-ups use\n"
|
|
89
|
+
"what earlier tasks found; type while it works to steer it. Uses Mobster for Mac or\n"
|
|
90
|
+
"`mobster serve` when one is open, so approvals show there too. With neither open, a\n"
|
|
91
|
+
"message runs here in the terminal, and `mobster chat` alone opens the terminal UI.",
|
|
92
|
+
"examples:\n mobster chat\n mobster chat \"What's on my calendar tomorrow?\"\n"
|
|
93
|
+
" mobster chat --thread 3f9c2a1b7d0e \"Now text Sam the first one\"\n"
|
|
94
|
+
" mobster chat --workflow \"Reels digest\" --set topic=basketball"),
|
|
95
|
+
"workflow": ("Print a saved workflow's steps from Mobster for Mac or `mobster serve`, in the order\n"
|
|
96
|
+
"they run: each one's type, title and the steps it waits for. `mobster chat --workflow`\n"
|
|
97
|
+
"runs one.",
|
|
98
|
+
"examples:\n mobster workflow show \"Answer DMs\"\n mobster workflow show "
|
|
99
|
+
"3f9c2a1b7d0e --draft --json"),
|
|
100
|
+
"memory": ("List, add and delete the things Mobster remembers, in your words. Mobster's agent\n"
|
|
101
|
+
"reads the ones that fit each task. Everything stays on this Mac.",
|
|
102
|
+
"examples:\n mobster memory list\n mobster memory add \"My gym is the one on 5th Street\"\n"
|
|
103
|
+
" mobster memory pin 3f9c2a1b7d0e"),
|
|
104
|
+
"test": ("Run every check in .mobster/checks (or the paths given) on one or more devices, in\n"
|
|
105
|
+
"parallel, with retries, flake detection, and JUnit and HTML reports with the frames.\n"
|
|
106
|
+
"A check is a saved YAML file; `mobster verify` runs one without saving it.",
|
|
107
|
+
"exit codes: 0 passed, 1 failed, 2 needs review, 3 couldn't run, 130 ctrl+c\n\n"
|
|
108
|
+
"examples:\n mobster test\n"
|
|
109
|
+
" mobster test --sim \"iPhone 17 Pro\" --sim \"iPhone SE (3rd generation)\" --parallel 2\n"
|
|
110
|
+
" mobster test --junit build/junit.xml --html build/mobster-report\n"
|
|
111
|
+
" mobster test record --run 3f9c2a1b7d0e --name paywall"),
|
|
112
|
+
"wifi": ("Turn on Wi-Fi use for an iPhone you set up with a cable once, see how each phone is\n"
|
|
113
|
+
"connected, and check the encrypted link between this Mac and the phone.",
|
|
114
|
+
"examples:\n mobster wifi status\n mobster wifi on --device \"Sam's iPhone\"\n"
|
|
115
|
+
" mobster wifi probe --device \"Sam's iPhone\""),
|
|
116
|
+
"api": ("Serve every app Mobster has an app pack for as an API on this Mac: GET /v1/<app>/<thing>\n"
|
|
117
|
+
"reads that app on your iPhone into rows (JSON or CSV), and GET /v1/openapi.json\n"
|
|
118
|
+
"describes every endpoint. Each one is also an MCP tool in `mobster mcp`. Every\n"
|
|
119
|
+
"endpoint only reads, and each client calls it with its own token.",
|
|
120
|
+
"examples:\n mobster api tokens create n8n\n mobster api serve --phone \"Test iPhone\"\n"
|
|
121
|
+
" mobster api tokens revoke n8n"),
|
|
122
|
+
"ci": ("Run your app's checks on every pull request or merge request, on a hosted macOS runner\n"
|
|
123
|
+
"(simulators, signed in with a CI token) or a Mac of yours (its simulators and the iPhones\n"
|
|
124
|
+
"plugged into it), in GitHub Actions, GitLab CI, Xcode Cloud, Codemagic, Bitrise or CircleCI.\n"
|
|
125
|
+
"One comment on the PR keeps the verdict, the repro steps, frames, GIFs and videos.",
|
|
126
|
+
"examples:\n mobster ci init\n mobster ci doctor\n mobster ci run --device \"Test iPhone\"\n"
|
|
127
|
+
" mobster ci comment --dry-run"),
|
|
128
|
+
"account": ("Manage your Mobster account from the terminal. For now that is CI tokens: the secret a hosted CI\n"
|
|
129
|
+
"runner signs in with to run simulator checks, with no Mac of yours.",
|
|
130
|
+
"examples:\n mobster account ci-token create \"app repo\"\n mobster account ci-token list\n"
|
|
131
|
+
" mobster account ci-token revoke <ID>"),
|
|
132
|
+
"expo": ("Open your Expo app on a simulator or your iPhone from the JavaScript Metro serves, in\n"
|
|
133
|
+
"your dev client or Expo Go, and check a screen. Build it for checks and CI: Release\n"
|
|
134
|
+
"for the simulator, with the JavaScript inside, or your dev client on your iPhone.",
|
|
135
|
+
"examples:\n mobster expo preview --device \"Test iPhone\" --expect \"Welcome back\"\n"
|
|
136
|
+
" mobster expo reload\n mobster expo build\n mobster expo build --device \"Test iPhone\""),
|
|
137
|
+
"asc": ("Use your own App Store Connect API key, kept in your Keychain, to list builds and read\n"
|
|
138
|
+
"your testers' TestFlight feedback and crashes, and make App Store screenshots from your\n"
|
|
139
|
+
"checks in every size and language. Read-only: Mobster submits nothing to Apple.",
|
|
140
|
+
"examples:\n mobster asc key add --key-id 2X9R4HXF34 --issuer-id <issuer id> --p8 AuthKey_2X9R4HXF34.p8\n"
|
|
141
|
+
" mobster asc builds --app com.example.yourapp\n mobster asc feedback --app "
|
|
142
|
+
"com.example.yourapp --crashes\n"
|
|
143
|
+
" mobster asc screenshots --size 6.9 --size 13"),
|
|
144
|
+
"testflight": ("List your app's TestFlight builds, pick one and install it on your iPhone through the\n"
|
|
145
|
+
"TestFlight app, with an App Store Connect API key kept per project in your Keychain. The\n"
|
|
146
|
+
"build and version go on the next `mobster test` report. Read-only: Mobster submits nothing\n"
|
|
147
|
+
"to Apple.",
|
|
148
|
+
"examples:\n mobster testflight key add --key-id 2X9R4HXF34 --issuer-id <issuer id> "
|
|
149
|
+
"--p8 AuthKey_2X9R4HXF34.p8\n"
|
|
150
|
+
" mobster testflight list --app com.example.yourapp\n"
|
|
151
|
+
" mobster testflight install --app com.example.yourapp --build 87 --device \"Test iPhone\""),
|
|
152
|
+
"signing": ("Put Mobster's helper on an iPhone without Xcode, for a paid Apple Developer team. With your own\n"
|
|
153
|
+
"App Store Connect key, `card` reads your team and prints the three requests Mobster would send to\n"
|
|
154
|
+
"Apple (register your iPhone, create a development certificate, create a development profile),\n"
|
|
155
|
+
"and `apply` sends them after you approve their digest, signs the helper on this Mac and installs\n"
|
|
156
|
+
"it with pymobiledevice3. Off unless MOBSTER_EXPERIMENTAL_NO_XCODE=1.",
|
|
157
|
+
"examples:\n mobster signing card\n mobster signing apply --approve <digest>\n"
|
|
158
|
+
" mobster signing export helper.tgz\n mobster signing import helper.tgz --team ABCDE12345"),
|
|
159
|
+
"xray": ("X-ray an app on your iPhone. `app` maps an app with App X-ray: Mobster taps through every\n"
|
|
160
|
+
"control that opens a screen and writes a map of the screens, how they connect and the paywalls\n"
|
|
161
|
+
"it found, with no model and no tap on anything that could act. `network` records the phone's\n"
|
|
162
|
+
"traffic with Network X-ray and says which domains and companies each app talked to, reading\n"
|
|
163
|
+
"hostnames, sizes and times only. `diff` compares two maps to see what an update changed.\n"
|
|
164
|
+
"Everything stays on this Mac.",
|
|
165
|
+
"examples:\n mobster xray app com.apple.Preferences\n mobster xray app Weather "
|
|
166
|
+
"--screens 60 --minutes 10\n"
|
|
167
|
+
" mobster xray network --device \"Test iPhone\" --seconds 30\n"
|
|
168
|
+
" mobster xray diff before/map.json after/map.json"),
|
|
169
|
+
"intents": ("Experimental (MOBSTER_EXPERIMENTAL_INTENTS=1). `harvest` reads a simulator's apps for the URL\n"
|
|
170
|
+
"schemes and associated domains they declare, and keeps them as discovered links the agent can\n"
|
|
171
|
+
"open before it taps.",
|
|
172
|
+
"examples:\n mobster intents harvest\n mobster intents harvest --sim <UDID> --force"),
|
|
173
|
+
"env": ("Keep a project's test credentials and other secrets in your Keychain, named in\n"
|
|
174
|
+
".mobster/env.example (names only, committed). A check writes ${NAME} in its launch\n"
|
|
175
|
+
"settings and steps; the run fills it in and masks it everywhere. A name with no value\n"
|
|
176
|
+
"stops the run before it starts. Values are never printed or written to the project.",
|
|
177
|
+
"examples:\n mobster env set TEST_PASSWORD\n printf '%s' \"$PW\" | mobster env "
|
|
178
|
+
"set TEST_PASSWORD --stdin\n"
|
|
179
|
+
" mobster env list\n mobster env unset TEST_PASSWORD"),
|
|
180
|
+
"links": ("List the deep links your project has, from .mobster/links.yaml, the Expo config, the Xcode\n"
|
|
181
|
+
"project and links a check opened, and open each on a simulator to see which screen it\n"
|
|
182
|
+
"lands on. A step can then say \"open cart\" instead of the address.",
|
|
183
|
+
"examples:\n mobster links list\n mobster links check\n mobster links check "
|
|
184
|
+
"cart --sim \"iPhone 17 Pro\""),
|
|
185
|
+
"fixtures": ("List the app states your checks start from (.mobster/fixtures/: a reset, launch args, seed files,\n"
|
|
186
|
+
"the keychain, the pasteboard, sign-in steps) and put a simulator's app in one now.",
|
|
187
|
+
"examples:\n mobster fixtures list\n mobster fixtures apply logged-in-cart "
|
|
188
|
+
"--bundle com.example.shop"),
|
|
189
|
+
"xcode": ("Add a post-action to your Xcode scheme: after each simulator build, Mobster runs the\n"
|
|
190
|
+
"checks of the app you built, on that build, in the background, and the verdict comes\n"
|
|
191
|
+
"as a notification.",
|
|
192
|
+
"examples:\n mobster xcode hook --scheme YourApp\n mobster xcode hook --scheme YourApp --tag smoke\n"
|
|
193
|
+
" mobster xcode unhook --scheme YourApp"),
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def load(name):
|
|
198
|
+
"""The command's ``cli`` module, or None when this build doesn't have it. Static imports,
|
|
199
|
+
so PyInstaller bundles them."""
|
|
200
|
+
try:
|
|
201
|
+
if name == "verify":
|
|
202
|
+
from .verify import cli
|
|
203
|
+
elif name == "sim":
|
|
204
|
+
from .sim import cli
|
|
205
|
+
elif name == "mcp":
|
|
206
|
+
from .mcp_server import cli
|
|
207
|
+
elif name == "phone":
|
|
208
|
+
from .phone_io import cli
|
|
209
|
+
elif name == "alerts":
|
|
210
|
+
from . import alerts as cli
|
|
211
|
+
elif name == "audit":
|
|
212
|
+
from . import audit_verify as cli
|
|
213
|
+
elif name == "chat":
|
|
214
|
+
from .threads import cli
|
|
215
|
+
elif name == "workflow":
|
|
216
|
+
from .threads import workflow_cli as cli
|
|
217
|
+
elif name == "memory":
|
|
218
|
+
from .memory import cli
|
|
219
|
+
elif name == "test":
|
|
220
|
+
from .testkit import cli
|
|
221
|
+
elif name == "wifi":
|
|
222
|
+
from .wireless import cli
|
|
223
|
+
elif name == "api":
|
|
224
|
+
from .app_api import cli
|
|
225
|
+
elif name == "ci":
|
|
226
|
+
from .devkit import ci_cli as cli
|
|
227
|
+
elif name == "account":
|
|
228
|
+
from .devkit import account_cli as cli
|
|
229
|
+
elif name == "expo":
|
|
230
|
+
from .devkit import expo_cli as cli
|
|
231
|
+
elif name == "asc":
|
|
232
|
+
from .devkit import asc_cli as cli
|
|
233
|
+
elif name == "testflight":
|
|
234
|
+
from .devkit import testflight_cli as cli
|
|
235
|
+
elif name == "links":
|
|
236
|
+
from .devkit import links_cli as cli
|
|
237
|
+
elif name == "fixtures":
|
|
238
|
+
from .devkit import fixtures_cli as cli
|
|
239
|
+
elif name == "xcode":
|
|
240
|
+
from .devkit import xcode_cli as cli
|
|
241
|
+
elif name == "xray":
|
|
242
|
+
from .xray import cli
|
|
243
|
+
elif name == "env":
|
|
244
|
+
from . import project_env_cli as cli
|
|
245
|
+
elif name == "intents":
|
|
246
|
+
from .intents import cli
|
|
247
|
+
elif name == "signing":
|
|
248
|
+
from .team_signing import cli
|
|
249
|
+
else:
|
|
250
|
+
return None
|
|
251
|
+
except ImportError as error:
|
|
252
|
+
package = PACKAGES[name]
|
|
253
|
+
if getattr(error, "name", None) in (package, f"{package}.{CLI_MODULES.get(name, 'cli')}"):
|
|
254
|
+
return None
|
|
255
|
+
raise
|
|
256
|
+
return cli
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def load_integrations():
|
|
260
|
+
"""`mobster mcp install`, `clients` and `doctor`."""
|
|
261
|
+
try:
|
|
262
|
+
from .integrations import cli
|
|
263
|
+
except ImportError as error:
|
|
264
|
+
if getattr(error, "name", None) in ("mobile_agent.integrations", "mobile_agent.integrations.cli"):
|
|
265
|
+
return None
|
|
266
|
+
raise
|
|
267
|
+
return cli
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def add_commands(command, helpers, load_only=None):
|
|
271
|
+
"""Create the subparsers through ``command(name, help, description, epilog)``."""
|
|
272
|
+
parsers = {}
|
|
273
|
+
for name in ORDER:
|
|
274
|
+
description, epilog = TEXT[name]
|
|
275
|
+
parser = command(name, HELP[name], description, epilog)
|
|
276
|
+
if load_only is not None and name not in load_only:
|
|
277
|
+
parser.add_argument("rest", nargs=argparse.REMAINDER, help=argparse.SUPPRESS)
|
|
278
|
+
parser.set_defaults(unloaded_command=True)
|
|
279
|
+
parsers[name] = parser
|
|
280
|
+
continue
|
|
281
|
+
module = load(name)
|
|
282
|
+
if module is None:
|
|
283
|
+
parser.add_argument("rest", nargs=argparse.REMAINDER, help=argparse.SUPPRESS)
|
|
284
|
+
parser.set_defaults(stub_command=True)
|
|
285
|
+
else:
|
|
286
|
+
module.add_arguments(parser, helpers)
|
|
287
|
+
if name == "mcp" and load_integrations() is not None:
|
|
288
|
+
load_integrations().add_subcommands(parser, helpers) # install, clients, doctor
|
|
289
|
+
parsers[name] = parser
|
|
290
|
+
return parsers
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# The signals `verify` and `sim` stop on the way ctrl+c stops them; `mcp` handles its own (mcp_server/cli.py).
|
|
294
|
+
STOP_SIGNALS = ("SIGTERM", "SIGHUP")
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class Terminated(KeyboardInterrupt):
|
|
298
|
+
"""SIGTERM or SIGHUP, raised where ctrl+c would be."""
|
|
299
|
+
|
|
300
|
+
def __init__(self, signum):
|
|
301
|
+
super().__init__(signal.Signals(signum).name)
|
|
302
|
+
self.signum = signum
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@contextlib.contextmanager
|
|
306
|
+
def signals_as_interrupt():
|
|
307
|
+
"""SIGTERM and SIGHUP raise ``Terminated`` (a KeyboardInterrupt) in the main thread for the duration."""
|
|
308
|
+
caught = []
|
|
309
|
+
if threading.current_thread() is not threading.main_thread():
|
|
310
|
+
yield caught
|
|
311
|
+
return
|
|
312
|
+
|
|
313
|
+
def handler(signum, frame):
|
|
314
|
+
first = not caught
|
|
315
|
+
caught.append(signum)
|
|
316
|
+
if first:
|
|
317
|
+
raise Terminated(signum)
|
|
318
|
+
|
|
319
|
+
previous = {}
|
|
320
|
+
for name in STOP_SIGNALS:
|
|
321
|
+
number = getattr(signal, name, None)
|
|
322
|
+
if number is not None:
|
|
323
|
+
previous[number] = signal.signal(number, handler)
|
|
324
|
+
try:
|
|
325
|
+
yield caught
|
|
326
|
+
finally:
|
|
327
|
+
for number, old in previous.items():
|
|
328
|
+
signal.signal(number, old)
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
def run(args):
|
|
332
|
+
"""Run the developer command ``args.command``; returns its exit code."""
|
|
333
|
+
name = args.command
|
|
334
|
+
module = load(name)
|
|
335
|
+
if module is None:
|
|
336
|
+
print(f"`mobster {name}` is not in this build", file=sys.stderr, flush=True)
|
|
337
|
+
return MISSING_EXIT
|
|
338
|
+
if name in ("chat", "memory", "test", "wifi", "xray"):
|
|
339
|
+
# The SOTA tracks' commands register their pieces first (seam S1).
|
|
340
|
+
from . import tracks
|
|
341
|
+
tracks.load()
|
|
342
|
+
if name == "mcp" and getattr(args, "mcp_command", None):
|
|
343
|
+
return load_integrations().run(args)
|
|
344
|
+
if name not in ("verify", "sim"):
|
|
345
|
+
return module.run(args)
|
|
346
|
+
with signals_as_interrupt() as caught:
|
|
347
|
+
try:
|
|
348
|
+
code = module.run(args)
|
|
349
|
+
except KeyboardInterrupt:
|
|
350
|
+
code = 130
|
|
351
|
+
return 128 + caught[0] if caught else code
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def usage_exit(command, message=None, *, as_json=False):
|
|
355
|
+
"""The exit code for a usage error found outside a command's own parser (`mobster --demo verify`)."""
|
|
356
|
+
if command != "verify":
|
|
357
|
+
return 2
|
|
358
|
+
module = load("verify")
|
|
359
|
+
if module is not None and message and (as_json or not _isatty(sys.stdout)):
|
|
360
|
+
try:
|
|
361
|
+
print(json.dumps(module.usage_result(message), ensure_ascii=False), flush=True)
|
|
362
|
+
except BrokenPipeError:
|
|
363
|
+
pass
|
|
364
|
+
return 3
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def option_hint(parser, message):
|
|
368
|
+
"""" Did you mean --execute?" for argparse's "unrecognized arguments: --exec", else ""."""
|
|
369
|
+
import difflib
|
|
370
|
+
if not message.startswith("unrecognized arguments:"):
|
|
371
|
+
return ""
|
|
372
|
+
flags = [option for option in parser._option_string_actions if option.startswith("--")]
|
|
373
|
+
hints = []
|
|
374
|
+
for word in message.split(":", 1)[1].split():
|
|
375
|
+
if word.startswith("--") and word not in flags:
|
|
376
|
+
stem = word.split("=", 1)[0]
|
|
377
|
+
hints += [flag for flag in flags if flag.startswith(stem)][:1] or \
|
|
378
|
+
difflib.get_close_matches(stem, flags, n=1, cutoff=.6)
|
|
379
|
+
return f". Did you mean {' and '.join(dict.fromkeys(hints))}?" if hints else ""
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class ProgressLines:
|
|
383
|
+
"""verify's and sim's progress on stderr, one line each."""
|
|
384
|
+
|
|
385
|
+
def __init__(self, stream=None):
|
|
386
|
+
self.stream = stream or sys.stderr
|
|
387
|
+
self.live = _isatty(self.stream) and os.environ.get("TERM") != "dumb"
|
|
388
|
+
self.pending = False
|
|
389
|
+
self.lock = threading.Lock()
|
|
390
|
+
|
|
391
|
+
def __call__(self, line):
|
|
392
|
+
with self.lock:
|
|
393
|
+
try:
|
|
394
|
+
if self.live and str(line).startswith("Still "):
|
|
395
|
+
self.stream.write("\r\033[K" + str(line))
|
|
396
|
+
self.pending = True
|
|
397
|
+
else:
|
|
398
|
+
self.stream.write(("\r\033[K" if self.pending else "") + str(line) + "\n")
|
|
399
|
+
self.pending = False
|
|
400
|
+
self.stream.flush()
|
|
401
|
+
except (OSError, ValueError):
|
|
402
|
+
pass
|
|
403
|
+
|
|
404
|
+
def end(self):
|
|
405
|
+
with self.lock:
|
|
406
|
+
if self.pending:
|
|
407
|
+
try:
|
|
408
|
+
self.stream.write("\r\033[K")
|
|
409
|
+
self.stream.flush()
|
|
410
|
+
except (OSError, ValueError):
|
|
411
|
+
pass
|
|
412
|
+
self.pending = False
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def _isatty(stream):
|
|
416
|
+
try:
|
|
417
|
+
return stream.isatty()
|
|
418
|
+
except (AttributeError, ValueError):
|
|
419
|
+
return False
|