extra-desktop 0.3.2__tar.gz → 0.3.4__tar.gz
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.
- {extra_desktop-0.3.2/extra_desktop.egg-info → extra_desktop-0.3.4}/PKG-INFO +23 -11
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/README.md +12 -8
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/pyproject.toml +27 -12
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/__init__.py +1 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/cli.py +157 -7
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/__init__.py +13 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/distiller.py +96 -18
- extra_desktop-0.3.4/src/extra/core/mode.py +153 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/base.py +2 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/shell.py +13 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/shell.py +7 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/focus.py +42 -8
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/input_engine.py +49 -30
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/shell.py +30 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/uia_plane.py +82 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/vision_parser.py +17 -6
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/stall_breaker.py +105 -2
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/subtask.py +416 -2
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/__init__.py +30 -0
- extra_desktop-0.3.4/src/extra/fastpath/comms.py +233 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/fs.py +42 -7
- extra_desktop-0.3.4/src/extra/fastpath/relay.py +26 -0
- extra_desktop-0.3.4/src/extra/fastpath/tunnel.py +24 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/mcp/server.py +3855 -111
- extra_desktop-0.3.4/src/extra/relay/__init__.py +42 -0
- extra_desktop-0.3.4/src/extra/relay/client.py +354 -0
- extra_desktop-0.3.4/src/extra/relay/tunnel.py +257 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra_desktop.egg-info}/PKG-INFO +23 -11
- extra_desktop-0.3.4/src/extra_desktop.egg-info/SOURCES.txt +193 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src}/extra_desktop.egg-info/requires.txt +14 -2
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_app_registry_dynamic.py +26 -0
- extra_desktop-0.3.4/tests/test_comms_and_modal.py +137 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_composer_director_soul.py +4 -2
- extra_desktop-0.3.4/tests/test_execution_modes.py +205 -0
- extra_desktop-0.3.4/tests/test_full_nifty_speedrun_benchmark.py +249 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_hierarchical_benchmarks.py +5 -4
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_issue4_bottlenecks.py +2 -6
- extra_desktop-0.3.4/tests/test_mcp_sse_transport.py +201 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pillar1_funnel.py +10 -3
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pillar2_installer.py +1 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_security_hardening.py +94 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_stall_breaker_cognitive.py +114 -0
- extra_desktop-0.3.4/tests/test_sub_30s_speedrun_benchmark.py +133 -0
- extra_desktop-0.3.4/tests/test_subtask_compiler_expansion.py +186 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_tiered_verification.py +1 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_tiered_verification_benchmarks.py +6 -4
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_ui_distiller.py +171 -1
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_verification_mcp.py +86 -0
- extra_desktop-0.3.2/extra_desktop.egg-info/SOURCES.txt +0 -250
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/LICENSE +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/NOTICE +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/setup.cfg +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/capture.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/composer/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/composer/blueprint.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/composer/folding.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/composer/lineage.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/composer/verifier.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/analyzer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/api_synthesizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/crystallizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/curator.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/evolution/harness_generator.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/focus.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/geometry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/input_engine.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/memory/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/memory/db.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/memory/embeddings.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/memory/ingest.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/memory/recall.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/auditor.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/config.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/dashboard.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/ledger.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/sanitizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/metrics/telemetry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/motion/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/motion/curves.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/motion/profiler.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/motion/stroke.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/motion/windmouse.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/atspi_plane.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/capture.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/focus.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/geometry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/input_engine.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/linux/permissions.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/ax_plane.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/capture.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/focus.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/geometry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/input_engine.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/macos/permissions.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/capture.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/child_session.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/geometry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/platform/windows/pip_window.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/cdp_sniffer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/detector.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/scraper.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/session_vault.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/scout/synthesizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/compressor.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/critic.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/decider.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/eyes.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/gateman.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/grammar.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/runtime.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/schemas.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/soul/state_critic.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/uia_plane.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/core/uninstall.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/bridge.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/browser.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/cli_harness.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/cli_hub.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/clipboard_html.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/shell.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/vectorizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/visualizer.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/web/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/fastpath/web_workspace.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src/extra}/mcp/__init__.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src}/extra_desktop.egg-info/dependency_links.txt +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src}/extra_desktop.egg-info/entry_points.txt +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4/src}/extra_desktop.egg-info/top_level.txt +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_acceleration_suite.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_bridge_sandbox.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_canvas_stall_breaker.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_child_session.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_cli_harness.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_core_engine.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_dynamic_batching.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_evolution.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_evolution_harness.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_geometry_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_human_mouse.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_input_engine_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_launch_maximize.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_lineage.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_atspi.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_capture.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_focus.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_geometry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_input.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_linux_shell.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_ax.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_core.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_focus_shell.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_indicators.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_input.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_perception.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_macos_safety.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_mcp_schemas_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_memory_kuzu.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_memory_subsystem_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_metrics.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_milestone_budgeting.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_paint_remediation.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_perception_vision_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pillar3_tcc_playbook.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pillar4_web_edge.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pillar5_package_ecosystem.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_pre_release_fixes.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_process_shell_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_scout.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_scout_evolution_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_soul_benchmarks.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_soul_evolution.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_soul_runtime.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_stall_breaker_exhaustive.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_state_critic.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_subtask_runner.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_telemetry.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_uninstall.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_universal_tasksuite.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_vision_parser.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_visual_grounding.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_web_to_api.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_web_workspace.py +0 -0
- {extra_desktop-0.3.2 → extra_desktop-0.3.4}/tests/test_windows_indicators.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: extra-desktop
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Flashless Linux, Windows & macOS Computer-Use Engine & Model Context Protocol (MCP) Server
|
|
5
5
|
Author-email: AIYantra Engineering Team <engineering@yantraos.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -11,14 +11,15 @@ Requires-Python: >=3.10
|
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
13
|
License-File: NOTICE
|
|
14
|
-
Requires-Dist: mcp
|
|
14
|
+
Requires-Dist: mcp<2,>=1.0.0
|
|
15
|
+
Requires-Dist: websockets>=13.0
|
|
15
16
|
Requires-Dist: playwright>=1.47.0
|
|
16
17
|
Requires-Dist: pillow>=10.4.0
|
|
17
18
|
Requires-Dist: beautifulsoup4>=4.12.3
|
|
18
19
|
Requires-Dist: imagehash>=4.3.1
|
|
19
20
|
Requires-Dist: numpy>=1.26.0
|
|
20
21
|
Requires-Dist: psutil>=6.0.0
|
|
21
|
-
Requires-Dist: kuzu>=0.11.0
|
|
22
|
+
Requires-Dist: kuzu>=0.11.0; python_version < "3.14"
|
|
22
23
|
Requires-Dist: fastembed>=0.8.0
|
|
23
24
|
Requires-Dist: onnxruntime>=1.19.0
|
|
24
25
|
Requires-Dist: pywin32>=306; sys_platform == "win32"
|
|
@@ -32,12 +33,19 @@ Requires-Dist: pyobjc-framework-ScreenCaptureKit>=10.0; sys_platform == "darwin"
|
|
|
32
33
|
Requires-Dist: evdev>=1.7.0; sys_platform == "linux"
|
|
33
34
|
Requires-Dist: mss>=9.0.1; sys_platform == "linux"
|
|
34
35
|
Requires-Dist: jeepney>=0.8.0; sys_platform == "linux"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-asyncio>=0.24.0; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff>=0.6.0; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy>=1.11.0; extra == "dev"
|
|
41
|
+
Provides-Extra: benchmark
|
|
42
|
+
Requires-Dist: pytest-benchmark>=4.0.0; extra == "benchmark"
|
|
35
43
|
Dynamic: license-file
|
|
36
44
|
|
|
37
45
|
<div align="center">
|
|
38
46
|
|
|
39
47
|
<a href="https://extra.yantraos.com">
|
|
40
|
-
<img src="
|
|
48
|
+
<img src="assets/logo.png" alt="Extra — Get extra from your AI" width="420" />
|
|
41
49
|
</a>
|
|
42
50
|
|
|
43
51
|
# Extra
|
|
@@ -54,7 +62,7 @@ Dynamic: license-file
|
|
|
54
62
|
[](https://yantraos.com)
|
|
55
63
|
[](https://github.com/AIYantra/extra)
|
|
56
64
|
|
|
57
|
-
[Website](https://extra.yantraos.com) • [Quickstart](#-quickstart-1-minute) • [Linux Guide](README_LINUX.md) • [macOS Guide](README_MACOS.md) • [Architecture](ARCHITECTURE.md) • [License](LICENSE)
|
|
65
|
+
[Website](https://extra.yantraos.com) • [Quickstart](#-quickstart-1-minute) • [Linux Guide](README_LINUX.md) • [macOS Guide](README_MACOS.md) • [Architecture](docs/ARCHITECTURE.md) • [License](LICENSE)
|
|
58
66
|
|
|
59
67
|
<br/>
|
|
60
68
|
<br/>
|
|
@@ -67,7 +75,9 @@ Dynamic: license-file
|
|
|
67
75
|
|
|
68
76
|
---
|
|
69
77
|
|
|
70
|
-
##
|
|
78
|
+
## What is Extra and Why Does It Exist?
|
|
79
|
+
|
|
80
|
+
Extra is an open-source Computer Use protocol and Model Context Protocol (MCP) server developed by yantraOS. It bridges LLMs (including ChatGPT, Claude, Cursor, and Gemini) directly to physical desktop operating systems across Linux, macOS, and Windows. Extra replaces fragile vision-only screenshot loops with native OS accessibility trees and sub-3ms GPU frame streaming, delivering pixel-perfect clicking, instant typing, and up to 225× lower token costs.
|
|
71
81
|
|
|
72
82
|
Today's AI assistants can write brilliant essays and code, but they are trapped inside a chat window. When you need them to click a button, open an app, organize your files, or input data into a spreadsheet, they can only give you text instructions.
|
|
73
83
|
|
|
@@ -81,7 +91,7 @@ It connects **Claude, Google Antigravity, Cursor, AGY**, or any autonomous agent
|
|
|
81
91
|
|
|
82
92
|
---
|
|
83
93
|
|
|
84
|
-
##
|
|
94
|
+
## What Can an AI Assistant Do With Extra?
|
|
85
95
|
|
|
86
96
|
Once Extra is running, you can talk to your AI like a real human assistant sitting at your desk:
|
|
87
97
|
|
|
@@ -190,7 +200,9 @@ Or using native Python:
|
|
|
190
200
|
|
|
191
201
|
---
|
|
192
202
|
|
|
193
|
-
##
|
|
203
|
+
## How Does Extra Work Under the Hood?
|
|
204
|
+
|
|
205
|
+
Extra operates via a sovereign Dual-Plane Architecture that decouples visual perception from hardware actuation. For perception, Extra combines sub-3ms GPU frame capture (DirectX DXGI, Metal, Spectacle) with OS accessibility hierarchy inspection (COM UI Automation, AT-SPI2, Quartz). For actuation, Extra dispatches lossless kernel and Win32 hardware events with zero coordinate drift, guaranteeing deterministic control across all resolutions and display scaling factors.
|
|
194
206
|
|
|
195
207
|
Extra is engineered from the ground up for speed, reliability, and token efficiency:
|
|
196
208
|
|
|
@@ -278,14 +290,14 @@ extra/
|
|
|
278
290
|
├── cli.py # CLI runner (extra doctor, test, indicators, run, inspect, snap)
|
|
279
291
|
├── install.ps1 # 1-line PowerShell installer (Windows)
|
|
280
292
|
├── install.sh # 1-line bash installer (macOS)
|
|
281
|
-
├── pyproject.toml # PyPI package manifest (extra-desktop v0.3.
|
|
282
|
-
├── package.json # npm package manifest (@yantraos/extra-desktop v0.3.
|
|
293
|
+
├── pyproject.toml # PyPI package manifest (extra-desktop v0.3.3)
|
|
294
|
+
├── package.json # npm package manifest (@yantraos/extra-desktop v0.3.3)
|
|
283
295
|
├── server.json # Official MCP registry manifest
|
|
284
296
|
├── glama.json # Glama MCP ecosystem manifest
|
|
285
297
|
├── smithery.yaml # Smithery 1-click deployment manifest
|
|
286
298
|
├── requirements.txt # Enterprise-audited dependency manifest
|
|
287
299
|
├── STARTER_PROMPT.md # Master AI system prompt & setup directive
|
|
288
|
-
├──
|
|
300
|
+
├── docs/ # Full System Architecture & Specifications
|
|
289
301
|
└── RELEASE_NOTES.md # Comprehensive version release notes
|
|
290
302
|
```
|
|
291
303
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
3
|
<a href="https://extra.yantraos.com">
|
|
4
|
-
<img src="
|
|
4
|
+
<img src="assets/logo.png" alt="Extra — Get extra from your AI" width="420" />
|
|
5
5
|
</a>
|
|
6
6
|
|
|
7
7
|
# Extra
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
[](https://yantraos.com)
|
|
19
19
|
[](https://github.com/AIYantra/extra)
|
|
20
20
|
|
|
21
|
-
[Website](https://extra.yantraos.com) • [Quickstart](#-quickstart-1-minute) • [Linux Guide](README_LINUX.md) • [macOS Guide](README_MACOS.md) • [Architecture](ARCHITECTURE.md) • [License](LICENSE)
|
|
21
|
+
[Website](https://extra.yantraos.com) • [Quickstart](#-quickstart-1-minute) • [Linux Guide](README_LINUX.md) • [macOS Guide](README_MACOS.md) • [Architecture](docs/ARCHITECTURE.md) • [License](LICENSE)
|
|
22
22
|
|
|
23
23
|
<br/>
|
|
24
24
|
<br/>
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
##
|
|
34
|
+
## What is Extra and Why Does It Exist?
|
|
35
|
+
|
|
36
|
+
Extra is an open-source Computer Use protocol and Model Context Protocol (MCP) server developed by yantraOS. It bridges LLMs (including ChatGPT, Claude, Cursor, and Gemini) directly to physical desktop operating systems across Linux, macOS, and Windows. Extra replaces fragile vision-only screenshot loops with native OS accessibility trees and sub-3ms GPU frame streaming, delivering pixel-perfect clicking, instant typing, and up to 225× lower token costs.
|
|
35
37
|
|
|
36
38
|
Today's AI assistants can write brilliant essays and code, but they are trapped inside a chat window. When you need them to click a button, open an app, organize your files, or input data into a spreadsheet, they can only give you text instructions.
|
|
37
39
|
|
|
@@ -45,7 +47,7 @@ It connects **Claude, Google Antigravity, Cursor, AGY**, or any autonomous agent
|
|
|
45
47
|
|
|
46
48
|
---
|
|
47
49
|
|
|
48
|
-
##
|
|
50
|
+
## What Can an AI Assistant Do With Extra?
|
|
49
51
|
|
|
50
52
|
Once Extra is running, you can talk to your AI like a real human assistant sitting at your desk:
|
|
51
53
|
|
|
@@ -154,7 +156,9 @@ Or using native Python:
|
|
|
154
156
|
|
|
155
157
|
---
|
|
156
158
|
|
|
157
|
-
##
|
|
159
|
+
## How Does Extra Work Under the Hood?
|
|
160
|
+
|
|
161
|
+
Extra operates via a sovereign Dual-Plane Architecture that decouples visual perception from hardware actuation. For perception, Extra combines sub-3ms GPU frame capture (DirectX DXGI, Metal, Spectacle) with OS accessibility hierarchy inspection (COM UI Automation, AT-SPI2, Quartz). For actuation, Extra dispatches lossless kernel and Win32 hardware events with zero coordinate drift, guaranteeing deterministic control across all resolutions and display scaling factors.
|
|
158
162
|
|
|
159
163
|
Extra is engineered from the ground up for speed, reliability, and token efficiency:
|
|
160
164
|
|
|
@@ -242,14 +246,14 @@ extra/
|
|
|
242
246
|
├── cli.py # CLI runner (extra doctor, test, indicators, run, inspect, snap)
|
|
243
247
|
├── install.ps1 # 1-line PowerShell installer (Windows)
|
|
244
248
|
├── install.sh # 1-line bash installer (macOS)
|
|
245
|
-
├── pyproject.toml # PyPI package manifest (extra-desktop v0.3.
|
|
246
|
-
├── package.json # npm package manifest (@yantraos/extra-desktop v0.3.
|
|
249
|
+
├── pyproject.toml # PyPI package manifest (extra-desktop v0.3.3)
|
|
250
|
+
├── package.json # npm package manifest (@yantraos/extra-desktop v0.3.3)
|
|
247
251
|
├── server.json # Official MCP registry manifest
|
|
248
252
|
├── glama.json # Glama MCP ecosystem manifest
|
|
249
253
|
├── smithery.yaml # Smithery 1-click deployment manifest
|
|
250
254
|
├── requirements.txt # Enterprise-audited dependency manifest
|
|
251
255
|
├── STARTER_PROMPT.md # Master AI system prompt & setup directive
|
|
252
|
-
├──
|
|
256
|
+
├── docs/ # Full System Architecture & Specifications
|
|
253
257
|
└── RELEASE_NOTES.md # Comprehensive version release notes
|
|
254
258
|
```
|
|
255
259
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "extra-desktop"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.4"
|
|
8
8
|
description = "Flashless Linux, Windows & macOS Computer-Use Engine & Model Context Protocol (MCP) Server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -13,14 +13,15 @@ authors = [
|
|
|
13
13
|
{ name = "AIYantra Engineering Team", email = "engineering@yantraos.com" }
|
|
14
14
|
]
|
|
15
15
|
dependencies = [
|
|
16
|
-
"mcp>=1.0.0",
|
|
16
|
+
"mcp>=1.0.0,<2",
|
|
17
|
+
"websockets>=13.0",
|
|
17
18
|
"playwright>=1.47.0",
|
|
18
19
|
"pillow>=10.4.0",
|
|
19
20
|
"beautifulsoup4>=4.12.3",
|
|
20
21
|
"imagehash>=4.3.1",
|
|
21
22
|
"numpy>=1.26.0",
|
|
22
23
|
"psutil>=6.0.0",
|
|
23
|
-
"kuzu>=0.11.0",
|
|
24
|
+
"kuzu>=0.11.0; python_version < '3.14'",
|
|
24
25
|
"fastembed>=0.8.0",
|
|
25
26
|
"onnxruntime>=1.19.0",
|
|
26
27
|
"pywin32>=306; sys_platform == 'win32'",
|
|
@@ -36,6 +37,17 @@ dependencies = [
|
|
|
36
37
|
"jeepney>=0.8.0; sys_platform == 'linux'",
|
|
37
38
|
]
|
|
38
39
|
|
|
40
|
+
[project.optional-dependencies]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.0.0",
|
|
43
|
+
"pytest-asyncio>=0.24.0",
|
|
44
|
+
"ruff>=0.6.0",
|
|
45
|
+
"mypy>=1.11.0",
|
|
46
|
+
]
|
|
47
|
+
benchmark = [
|
|
48
|
+
"pytest-benchmark>=4.0.0",
|
|
49
|
+
]
|
|
50
|
+
|
|
39
51
|
[project.scripts]
|
|
40
52
|
extra = "extra.cli:main"
|
|
41
53
|
extra-desktop = "extra.cli:main"
|
|
@@ -45,17 +57,20 @@ Homepage = "https://extra.yantraos.com"
|
|
|
45
57
|
Repository = "https://github.com/AIYantra/extra"
|
|
46
58
|
Documentation = "https://extra.yantraos.com/docs"
|
|
47
59
|
|
|
48
|
-
[tool.setuptools.
|
|
49
|
-
|
|
50
|
-
"extra.core" = "core"
|
|
51
|
-
"extra.core.platform" = "core/platform"
|
|
52
|
-
"extra.core.platform.windows" = "core/platform/windows"
|
|
53
|
-
"extra.core.platform.macos" = "core/platform/macos"
|
|
54
|
-
"extra.core.platform.linux" = "core/platform/linux"
|
|
55
|
-
"extra.fastpath" = "fastpath"
|
|
56
|
-
"extra.mcp" = "mcp"
|
|
60
|
+
[tool.setuptools.packages.find]
|
|
61
|
+
where = ["src"]
|
|
57
62
|
|
|
58
63
|
[tool.pytest.ini_options]
|
|
59
64
|
testpaths = ["tests"]
|
|
65
|
+
pythonpath = ["src"]
|
|
60
66
|
addopts = "-p no:faulthandler"
|
|
67
|
+
markers = [
|
|
68
|
+
"unit: Fast isolated unit tests with zero system dependencies",
|
|
69
|
+
"integration: Subsystem integration tests",
|
|
70
|
+
"windows: Tests requiring Windows Win32 / UIA subsystems",
|
|
71
|
+
"linux: Tests requiring Linux X11 / Wayland / AT-SPI2 subsystems",
|
|
72
|
+
"macos: Tests requiring macOS Quartz / Accessibility subsystems",
|
|
73
|
+
"benchmark: Performance profiling and stress benchmark suites",
|
|
74
|
+
"security: Security audit and vulnerability verification tests",
|
|
75
|
+
]
|
|
61
76
|
|
|
@@ -22,7 +22,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
22
22
|
try:
|
|
23
23
|
from extra import __version__
|
|
24
24
|
except Exception:
|
|
25
|
-
__version__ = "0.3.
|
|
25
|
+
__version__ = "0.3.4"
|
|
26
26
|
|
|
27
27
|
from extra.core.capture import capture_screen
|
|
28
28
|
from extra.core.focus import (
|
|
@@ -359,8 +359,45 @@ def cmd_run(args: argparse.Namespace) -> int:
|
|
|
359
359
|
os.environ["EXTRA_ISOLATED_DESKTOP"] = "1"
|
|
360
360
|
if getattr(args, "pip", False):
|
|
361
361
|
os.environ["EXTRA_PIP_PREVIEW"] = "1"
|
|
362
|
+
|
|
363
|
+
transport = getattr(args, "transport", "stdio")
|
|
364
|
+
host = getattr(args, "host", "127.0.0.1")
|
|
365
|
+
port = getattr(args, "port", 8000)
|
|
366
|
+
auth_token = getattr(args, "auth_token", None)
|
|
367
|
+
allowed_hosts = getattr(args, "allowed_hosts", None)
|
|
368
|
+
tunnel = getattr(args, "tunnel", False)
|
|
369
|
+
if allowed_hosts and isinstance(allowed_hosts, str):
|
|
370
|
+
allowed_hosts = [h.strip() for h in allowed_hosts.split(",") if h.strip()]
|
|
371
|
+
|
|
362
372
|
from extra.mcp.server import main
|
|
363
|
-
main()
|
|
373
|
+
main(transport=transport, host=host, port=port, auth_token=auth_token, allowed_hosts=allowed_hosts, tunnel=tunnel)
|
|
374
|
+
return 0
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def cmd_serve(args: argparse.Namespace) -> int:
|
|
378
|
+
"""Starts the Extra MCP server over SSE HTTP transport (for ChatGPT plugins & web agents)."""
|
|
379
|
+
setattr(args, "transport", "sse")
|
|
380
|
+
return cmd_run(args)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def cmd_connect(args: argparse.Namespace) -> int:
|
|
384
|
+
"""Connects this desktop to the Extra Cloud Hub for ChatGPT automation."""
|
|
385
|
+
from extra.relay import start_relay, DEFAULT_RELAY_URL
|
|
386
|
+
hub_url = getattr(args, "hub", None) or os.environ.get("EXTRA_HUB_URL") or DEFAULT_RELAY_URL
|
|
387
|
+
token = getattr(args, "token", None)
|
|
388
|
+
if not token or token == "anonymous":
|
|
389
|
+
token = os.environ.get("EXTRA_KEY") or os.environ.get("EXTRA_RELAY_KEY")
|
|
390
|
+
if not token or token == "anonymous":
|
|
391
|
+
print("[!] Error: Workstation link key is required to connect to the Extra Cloud Hub.")
|
|
392
|
+
print(" Get your key from your dashboard at: https://extra.yantraos.com/dashboard")
|
|
393
|
+
print(" Then run:")
|
|
394
|
+
print(" extra connect --key <your_key>")
|
|
395
|
+
return 1
|
|
396
|
+
start_relay(
|
|
397
|
+
hub_url=hub_url,
|
|
398
|
+
token=token,
|
|
399
|
+
device_name=getattr(args, "name", None),
|
|
400
|
+
)
|
|
364
401
|
return 0
|
|
365
402
|
|
|
366
403
|
|
|
@@ -836,7 +873,7 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
836
873
|
if pyproject_file.exists():
|
|
837
874
|
try:
|
|
838
875
|
subprocess.run(
|
|
839
|
-
[sys.executable, "-m", "pip", "install", "--quiet", "-e", str(repo_dir)],
|
|
876
|
+
[sys.executable, "-m", "pip", "install", "--quiet", "--no-deps", "-e", str(repo_dir)],
|
|
840
877
|
check=True,
|
|
841
878
|
)
|
|
842
879
|
print(" [OK] Package editable link verified.")
|
|
@@ -845,6 +882,32 @@ def cmd_update(args: argparse.Namespace) -> int:
|
|
|
845
882
|
else:
|
|
846
883
|
print("\n[Dependency Refresh] Skipped (--skip-deps specified).")
|
|
847
884
|
|
|
885
|
+
# Phase 2b: Refresh CLI executable wrappers with updated PYTHONPATH
|
|
886
|
+
try:
|
|
887
|
+
bin_dir = Path.home() / ".extra" / "bin"
|
|
888
|
+
if bin_dir.exists():
|
|
889
|
+
if platform.system() == "Windows":
|
|
890
|
+
cmd_wrapper = bin_dir / "extra.cmd"
|
|
891
|
+
cmd_content = (
|
|
892
|
+
f"@echo off\n"
|
|
893
|
+
f"set PYTHONPATH={repo_dir}\\src;{repo_dir};%PYTHONPATH%\n"
|
|
894
|
+
f'"{sys.executable}" -m extra.cli %*\n'
|
|
895
|
+
)
|
|
896
|
+
cmd_wrapper.write_text(cmd_content, encoding="ascii")
|
|
897
|
+
print(" [OK] Updated Windows CLI wrapper in ~/.extra/bin/extra.cmd.")
|
|
898
|
+
else:
|
|
899
|
+
sh_wrapper = bin_dir / "extra"
|
|
900
|
+
sh_content = (
|
|
901
|
+
f"#!/usr/bin/env bash\n"
|
|
902
|
+
f'export PYTHONPATH="{repo_dir}/src:{repo_dir}:$PYTHONPATH"\n'
|
|
903
|
+
f'exec "{sys.executable}" -m extra.cli "$@"\n'
|
|
904
|
+
)
|
|
905
|
+
sh_wrapper.write_text(sh_content, encoding="utf-8")
|
|
906
|
+
sh_wrapper.chmod(0o755)
|
|
907
|
+
print(" [OK] Updated Unix CLI wrapper in ~/.extra/bin/extra.")
|
|
908
|
+
except Exception as ex:
|
|
909
|
+
print(f" [WARN] Could not refresh CLI wrapper: {ex}")
|
|
910
|
+
|
|
848
911
|
# Phase 3: AI Rules & Skills Synchronization
|
|
849
912
|
sync_ai_rules_and_skills(repo_dir)
|
|
850
913
|
|
|
@@ -995,6 +1058,53 @@ def cmd_audit(args) -> int:
|
|
|
995
1058
|
return 1
|
|
996
1059
|
|
|
997
1060
|
|
|
1061
|
+
def cmd_mode(args: argparse.Namespace) -> int:
|
|
1062
|
+
"""View or change the Extra automation execution speed mode."""
|
|
1063
|
+
from extra.core.mode import (
|
|
1064
|
+
ExecutionMode,
|
|
1065
|
+
get_execution_mode,
|
|
1066
|
+
set_execution_mode,
|
|
1067
|
+
get_mode_config,
|
|
1068
|
+
)
|
|
1069
|
+
|
|
1070
|
+
target_mode = getattr(args, "mode", None)
|
|
1071
|
+
if not target_mode:
|
|
1072
|
+
curr = get_execution_mode()
|
|
1073
|
+
cfg = get_mode_config(curr)
|
|
1074
|
+
print("\n" + "=" * 60)
|
|
1075
|
+
print(f" [Extra] EXECUTION MODE: {curr.value.upper()}")
|
|
1076
|
+
print("=" * 60)
|
|
1077
|
+
print(f" * Active Profile : {cfg.mode.value}")
|
|
1078
|
+
print(f" * Settle Delay Timeout : {cfg.settle_timeout_sec}s")
|
|
1079
|
+
print(f" * Max Inspected Elements : {cfg.max_inspect_elements}")
|
|
1080
|
+
print(f" * Compact UI Serialization: {cfg.compact_ui}")
|
|
1081
|
+
print(f" * Sleep Scale Factor : {cfg.sleep_scale}x (max {cfg.max_sleep_ms}ms)")
|
|
1082
|
+
print(f" * Proactive Memory Recall : {cfg.proactive_memory_recall}")
|
|
1083
|
+
print(f" * Dual-Plane Verification : {cfg.dual_plane_verification}")
|
|
1084
|
+
print("-" * 60)
|
|
1085
|
+
print(" Available Modes:")
|
|
1086
|
+
print(" - turbo (low, fast) : Sub-50ms dispatch, 0ms settle, <800B UI")
|
|
1087
|
+
print(" - balanced (medium, default): ~15ms settle, balanced UI & safety gates")
|
|
1088
|
+
print(" - smart (high, verify) : Full SOUL visual critic & memory recall")
|
|
1089
|
+
print("-" * 60)
|
|
1090
|
+
print(" Usage: extra mode <turbo|balanced|smart> or extra modeset <mode>\n")
|
|
1091
|
+
return 0
|
|
1092
|
+
|
|
1093
|
+
try:
|
|
1094
|
+
resolved = ExecutionMode.from_string(target_mode)
|
|
1095
|
+
except Exception as e:
|
|
1096
|
+
print(f"Error: Invalid mode '{target_mode}': {e}", file=sys.stderr)
|
|
1097
|
+
return 1
|
|
1098
|
+
|
|
1099
|
+
cfg = set_execution_mode(resolved, persist=True)
|
|
1100
|
+
print(f"\n[Extra] Execution mode set to: {resolved.value.upper()} (saved to ~/.extra/config.json)")
|
|
1101
|
+
print(f" * Settle Timeout : {cfg.settle_timeout_sec}s")
|
|
1102
|
+
print(f" * Sleep Scale : {cfg.sleep_scale}x")
|
|
1103
|
+
print(f" * Compact UI : {cfg.compact_ui}")
|
|
1104
|
+
print(f" * Proactive Recall : {cfg.proactive_memory_recall}\n")
|
|
1105
|
+
return 0
|
|
1106
|
+
|
|
1107
|
+
|
|
998
1108
|
def check_first_run_consent() -> None:
|
|
999
1109
|
"""Checks and prompts for first-run interactive telemetry consent."""
|
|
1000
1110
|
from extra.core.metrics.config import (
|
|
@@ -1035,7 +1145,8 @@ def check_first_run_consent() -> None:
|
|
|
1035
1145
|
save_config(cfg)
|
|
1036
1146
|
|
|
1037
1147
|
|
|
1038
|
-
def
|
|
1148
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
1149
|
+
"""Builds and returns the top-level ArgumentParser for Extra CLI."""
|
|
1039
1150
|
parser = argparse.ArgumentParser(
|
|
1040
1151
|
prog="extra",
|
|
1041
1152
|
description="Extra — Flashless macOS, Windows & Linux Computer-Use Engine & MCP Server",
|
|
@@ -1045,6 +1156,13 @@ def main() -> None:
|
|
|
1045
1156
|
)
|
|
1046
1157
|
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
1047
1158
|
|
|
1159
|
+
# mode / modeset
|
|
1160
|
+
mode_parser = subparsers.add_parser("mode", help="View or set the Extra automation speed mode (turbo, balanced, smart)")
|
|
1161
|
+
mode_parser.add_argument("mode", nargs="?", default=None, help="Speed mode to activate: turbo (low/fast), balanced (medium/default), smart (high/deliberate)")
|
|
1162
|
+
|
|
1163
|
+
modeset_parser = subparsers.add_parser("modeset", help="Set the Extra automation speed mode (alias for 'extra mode')")
|
|
1164
|
+
modeset_parser.add_argument("mode", nargs="?", default=None, help="Speed mode to activate: turbo (low/fast), balanced (medium/default), smart (high/deliberate)")
|
|
1165
|
+
|
|
1048
1166
|
# doctor
|
|
1049
1167
|
doctor_parser = subparsers.add_parser("doctor", help="Run system health and capability diagnostics")
|
|
1050
1168
|
doctor_parser.add_argument("--open", "-o", action="store_true", help="Open System Settings privacy panes if permissions missing")
|
|
@@ -1069,11 +1187,32 @@ def main() -> None:
|
|
|
1069
1187
|
update_parser.add_argument("--force", action="store_true", help="Force update and reset local changes to upstream")
|
|
1070
1188
|
|
|
1071
1189
|
# run
|
|
1072
|
-
run_parser = subparsers.add_parser("run", help="Start the MCP Server on stdio")
|
|
1073
|
-
run_parser.add_argument("--transport", default="stdio", choices=["stdio"], help="Transport mode")
|
|
1190
|
+
run_parser = subparsers.add_parser("run", help="Start the MCP Server on stdio or SSE")
|
|
1191
|
+
run_parser.add_argument("--transport", default="stdio", choices=["stdio", "sse", "streamable-http"], help="Transport mode (default: stdio)")
|
|
1192
|
+
run_parser.add_argument("--host", default="127.0.0.1", help="Host IP to bind to when running SSE or HTTP transport (default: 127.0.0.1)")
|
|
1193
|
+
run_parser.add_argument("--port", "-p", type=int, default=8000, help="Port to bind to when running SSE or HTTP transport (default: 8000)")
|
|
1194
|
+
run_parser.add_argument("--auth-token", "--auth", default=None, help="Bearer authorization token to secure SSE transport")
|
|
1195
|
+
run_parser.add_argument("--allowed-hosts", default=None, help="Comma-separated allowed host header values for DNS rebinding protection")
|
|
1196
|
+
run_parser.add_argument("--tunnel", "-t", action="store_true", help="Launch secure Cloudflare Quick Tunnel (public HTTPS) for pairing with ChatGPT or remote agents")
|
|
1074
1197
|
run_parser.add_argument("--isolate", action="store_true", help="Confine automation to isolated child session / virtual desktop")
|
|
1075
1198
|
run_parser.add_argument("--pip", action="store_true", help="Launch live Picture-in-Picture floating preview window")
|
|
1076
1199
|
|
|
1200
|
+
# serve (ChatGPT Plugin & Remote Web Agent bridge)
|
|
1201
|
+
serve_parser = subparsers.add_parser("serve", help="Start the Extra MCP Server over SSE HTTP transport (for ChatGPT plugins & web agents)")
|
|
1202
|
+
serve_parser.add_argument("--host", default="127.0.0.1", help="Host IP to bind to (default: 127.0.0.1; use 0.0.0.0 for public/tunnel)")
|
|
1203
|
+
serve_parser.add_argument("--port", "-p", type=int, default=8000, help="Port to bind to (default: 8000)")
|
|
1204
|
+
serve_parser.add_argument("--auth-token", "--auth", default=None, help="Bearer authorization token to secure SSE transport")
|
|
1205
|
+
serve_parser.add_argument("--allowed-hosts", default=None, help="Comma-separated allowed host headers (e.g. *.trycloudflare.com)")
|
|
1206
|
+
serve_parser.add_argument("--tunnel", "-t", action="store_true", help="Launch secure Cloudflare Quick Tunnel (public HTTPS) for pairing with ChatGPT or remote agents")
|
|
1207
|
+
serve_parser.add_argument("--isolate", action="store_true", help="Confine automation to isolated child session / virtual desktop")
|
|
1208
|
+
serve_parser.add_argument("--pip", action="store_true", help="Launch live Picture-in-Picture floating preview window")
|
|
1209
|
+
|
|
1210
|
+
# connect (Desktop Relay Client for ChatGPT & Cloud Hub)
|
|
1211
|
+
connect_parser = subparsers.add_parser("connect", help="Connect this desktop to the Extra Cloud Hub for ChatGPT automation")
|
|
1212
|
+
connect_parser.add_argument("--hub", default=None, help="WebSocket Relay Hub URL (default: official extra.yantraos.com relay)")
|
|
1213
|
+
connect_parser.add_argument("--key", "--token", dest="token", default="anonymous", help="Setup key or authentication token from extra.yantraos.com account")
|
|
1214
|
+
connect_parser.add_argument("--name", default=None, help="Custom friendly device name for this workstation")
|
|
1215
|
+
|
|
1077
1216
|
# pip (Picture-in-Picture floating preview window)
|
|
1078
1217
|
pip_parser = subparsers.add_parser("pip", help="Control hardware-accelerated Picture-in-Picture floating preview window")
|
|
1079
1218
|
pip_parser.add_argument("action", nargs="?", default="demo", choices=["demo", "start", "stop"], help="Action: demo (live 3s preview), start, stop")
|
|
@@ -1154,6 +1293,11 @@ def main() -> None:
|
|
|
1154
1293
|
audit_parser.add_argument("--record", "-r", action="store_true", help="Record audited mission metrics into local impact_ledger.json")
|
|
1155
1294
|
audit_parser.add_argument("--json", action="store_true", help="Output audit results in raw JSON")
|
|
1156
1295
|
|
|
1296
|
+
return parser
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
def main() -> None:
|
|
1300
|
+
parser = build_parser()
|
|
1157
1301
|
args = parser.parse_args()
|
|
1158
1302
|
|
|
1159
1303
|
if not args.command:
|
|
@@ -1171,7 +1315,9 @@ def main() -> None:
|
|
|
1171
1315
|
except Exception:
|
|
1172
1316
|
pass
|
|
1173
1317
|
|
|
1174
|
-
if args.command
|
|
1318
|
+
if args.command in ("mode", "modeset"):
|
|
1319
|
+
sys.exit(cmd_mode(args))
|
|
1320
|
+
elif args.command == "stats":
|
|
1175
1321
|
sys.exit(cmd_stats(args))
|
|
1176
1322
|
elif args.command == "dashboard":
|
|
1177
1323
|
sys.exit(cmd_dashboard(args))
|
|
@@ -1195,6 +1341,10 @@ def main() -> None:
|
|
|
1195
1341
|
sys.exit(cmd_uninstall(args))
|
|
1196
1342
|
elif args.command == "run":
|
|
1197
1343
|
sys.exit(cmd_run(args))
|
|
1344
|
+
elif args.command == "serve":
|
|
1345
|
+
sys.exit(cmd_serve(args))
|
|
1346
|
+
elif args.command == "connect":
|
|
1347
|
+
sys.exit(cmd_connect(args))
|
|
1198
1348
|
elif args.command == "pip":
|
|
1199
1349
|
sys.exit(cmd_pip(args))
|
|
1200
1350
|
elif args.command == "inspect":
|
|
@@ -74,6 +74,13 @@ from extra.core.subtask import (
|
|
|
74
74
|
SubtaskRunner,
|
|
75
75
|
run_subtask,
|
|
76
76
|
)
|
|
77
|
+
from extra.core.mode import (
|
|
78
|
+
ExecutionMode,
|
|
79
|
+
ModeConfig,
|
|
80
|
+
get_execution_mode,
|
|
81
|
+
set_execution_mode,
|
|
82
|
+
get_mode_config,
|
|
83
|
+
)
|
|
77
84
|
from extra.core.soul import (
|
|
78
85
|
DecisionType,
|
|
79
86
|
SoulDecision,
|
|
@@ -156,4 +163,10 @@ __all__ = [
|
|
|
156
163
|
"SubtaskResult",
|
|
157
164
|
"SubtaskRunner",
|
|
158
165
|
"run_subtask",
|
|
166
|
+
# Sovereign Execution Mode Controller
|
|
167
|
+
"ExecutionMode",
|
|
168
|
+
"ModeConfig",
|
|
169
|
+
"get_execution_mode",
|
|
170
|
+
"set_execution_mode",
|
|
171
|
+
"get_mode_config",
|
|
159
172
|
]
|