mcpywrap 0.6.0__tar.gz → 0.6.2__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.
Files changed (224) hide show
  1. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/CHANGELOG.md +17 -0
  2. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/MANIFEST.in +1 -1
  3. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/PKG-INFO +13 -3
  4. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/README.md +11 -1
  5. mcpywrap-0.6.2/core/mcpywrap_core/_version.py +1 -0
  6. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/PKG-INFO +13 -3
  7. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/SOURCES.txt +23 -0
  8. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/requires.txt +1 -1
  9. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/bridge_payload/Injector.exe +0 -0
  10. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/bridge_payload/Loader.dll +0 -0
  11. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/bridge_payload/McpyMcsAuth.dll +0 -0
  12. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/bridge_payload/manifest.json +3 -3
  13. mcpywrap-0.6.2/desktop/mcpywrap_assets/window_activation/manifest.json +6 -0
  14. mcpywrap-0.6.2/desktop/mcpywrap_assets/window_activation/mcpy-window-activation.dll +0 -0
  15. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/window_capture/manifest.json +1 -1
  16. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/window_capture/mcpy-window-capture.exe +0 -0
  17. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/game-backends.md +3 -1
  18. mcpywrap-0.6.2/native/background_window/README.md +65 -0
  19. mcpywrap-0.6.2/native/background_window/apply.py +41 -0
  20. mcpywrap-0.6.2/native/background_window/client-background.patch +35 -0
  21. mcpywrap-0.6.2/native/background_window/game-window-background.patch +58 -0
  22. mcpywrap-0.6.2/native/background_window/libc-shim-background.patch +25 -0
  23. mcpywrap-0.6.2/native/background_window/manifest-background.patch +112 -0
  24. mcpywrap-0.6.2/native/background_window/test_window.cpp +32 -0
  25. mcpywrap-0.6.2/native/window_activation/README.md +9 -0
  26. mcpywrap-0.6.2/native/window_activation/window_activation.cpp +67 -0
  27. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/pyproject.toml +1 -1
  28. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/build_all_native.py +5 -2
  29. mcpywrap-0.6.2/scripts/build_window_activation.py +38 -0
  30. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/check_release.py +9 -1
  31. mcpywrap-0.6.2/scripts/check_window_activation.py +25 -0
  32. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/SKILL.md +4 -2
  33. mcpywrap-0.6.2/skills/mcpywrap/references/application-host.md +88 -0
  34. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/capture.md +1 -1
  35. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/local-development.md +7 -2
  36. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/macos-local.md +3 -2
  37. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/network-sessions.md +1 -1
  38. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/runtime-input.md +1 -1
  39. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/setup.md +5 -0
  40. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/scripts/bootstrap.py +29 -3
  41. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/README.md +2 -0
  42. mcpywrap-0.6.2/tests/manual_background_launch.py +170 -0
  43. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_build_replace_retry.py +12 -0
  44. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_core_api.py +17 -0
  45. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_deployment_cli.py +5 -0
  46. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_deployment_recovery.py +1 -1
  47. mcpywrap-0.6.2/tests/test_execution_boundaries.py +104 -0
  48. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_game_window_skill.py +4 -2
  49. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_host_input.py +1 -0
  50. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_lifecycle_audit.py +1 -0
  51. mcpywrap-0.6.2/tests/test_log_query.py +80 -0
  52. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_macos_network.py +11 -1
  53. mcpywrap-0.6.2/tests/test_mobile_diagnostics.py +164 -0
  54. mcpywrap-0.6.2/tests/test_mobile_host.py +124 -0
  55. mcpywrap-0.6.2/tests/test_mobile_pairing.py +109 -0
  56. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_modsdk_environment.py +1 -1
  57. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_project_scripts.py +8 -0
  58. mcpywrap-0.6.2/tests/test_restricted_process_identity.py +37 -0
  59. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_skill_workflows.py +20 -0
  60. mcpywrap-0.6.2/tests/test_window_activation.py +59 -0
  61. mcpywrap-0.6.2/tests/test_window_policy.py +166 -0
  62. mcpywrap-0.6.0/core/mcpywrap_core/_version.py +0 -1
  63. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/CONTRIBUTING.md +0 -0
  64. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/LICENSE +0 -0
  65. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/RELEASING.md +0 -0
  66. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/THIRD_PARTY_NOTICES.md +0 -0
  67. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/dependency_links.txt +0 -0
  68. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/entry_points.txt +0 -0
  69. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap.egg-info/top_level.txt +0 -0
  70. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/__init__.py +0 -0
  71. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/desktop/mcpywrap_assets/bridge_payload/publisher.cer +0 -0
  72. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/code-libraries.md +0 -0
  73. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/deployment-recovery.md +0 -0
  74. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/engine-discovery.md +0 -0
  75. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/git-dependencies.md +0 -0
  76. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/input-sequence.md +0 -0
  77. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/instance-world-settings.md +0 -0
  78. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/launcher-client-python.md +0 -0
  79. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/local-dependencies.md +0 -0
  80. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/macos-resource-reload.md +0 -0
  81. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/mcs-auth.md +0 -0
  82. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/project-scripts.md +0 -0
  83. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/qt6-development.md +0 -0
  84. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/qumod.md +0 -0
  85. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/runtime-debug.md +0 -0
  86. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/runtime-input.md +0 -0
  87. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/runtime-player.md +0 -0
  88. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/runtime-ui.md +0 -0
  89. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/shared-core.md +0 -0
  90. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/docs/shared-log-ui.md +0 -0
  91. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/examples/consumer_prepare/README.md +0 -0
  92. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/mcs_auth/Bridge.cs +0 -0
  93. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/mcs_auth/Injector.cs +0 -0
  94. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/mcs_auth/Loader.c +0 -0
  95. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/mcs_auth/publisher.cer +0 -0
  96. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/mcs_auth/publisher.json +0 -0
  97. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/runtime_input/README.md +0 -0
  98. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/runtime_input/launcher-monotonic.patch +0 -0
  99. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/runtime_input/manifest-monotonic.patch +0 -0
  100. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/runtime_input/steady_clock.h +0 -0
  101. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/window_capture/video_capture.h +0 -0
  102. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/native/window_capture/window_capture.cpp +0 -0
  103. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/build_app_icon.py +0 -0
  104. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/build_distributions.py +0 -0
  105. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/build_mcs_auth_bridge.py +0 -0
  106. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/build_window_capture.py +0 -0
  107. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/check_mcs_auth_bridge.py +0 -0
  108. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/check_window_capture.py +0 -0
  109. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/pypi_release.py +0 -0
  110. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/sign_mcs_auth_ci.ps1 +0 -0
  111. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/verify_core_release.py +0 -0
  112. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/verify_distributions.py +0 -0
  113. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/scripts/version.py +0 -0
  114. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/setup.cfg +0 -0
  115. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/setup.py +0 -0
  116. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/agents/openai.yaml +0 -0
  117. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/behavior_pack/CatalogRuntime/__init__.py +0 -0
  118. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/behavior_pack/manifest.json +0 -0
  119. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/build_tools/example.toml +0 -0
  120. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/build_tools/prepare.py +0 -0
  121. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/build_tools/schema.json +0 -0
  122. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/framework/pyproject.toml +0 -0
  123. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/game/.gitignore +0 -0
  124. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/game/behavior_pack/manifest.json +0 -0
  125. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/game/data/items.json +0 -0
  126. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/game/pyproject.toml +0 -0
  127. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/assets/consumer-prepare/game/resource_pack/manifest.json +0 -0
  128. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/consumer-prepare-author.md +0 -0
  129. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/consumer-prepare.md +0 -0
  130. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/dual-clients.md +0 -0
  131. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/input-sequence.md +0 -0
  132. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/input-writing.md +0 -0
  133. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/instance-world-settings.md +0 -0
  134. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/project-dependencies.md +0 -0
  135. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/project-scripts.md +0 -0
  136. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/project-workflow.md +0 -0
  137. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/remote-testing.md +0 -0
  138. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/runtime-debug.md +0 -0
  139. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/runtime-key-timeline.md +0 -0
  140. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/runtime-player.md +0 -0
  141. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/runtime-ui.md +0 -0
  142. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/script-example.md +0 -0
  143. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/references/troubleshooting.md +0 -0
  144. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/scripts/bootstrap.ps1 +0 -0
  145. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/scripts/game_window.py +0 -0
  146. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/skills/mcpywrap/scripts/smoke.py +0 -0
  147. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/core_fixture.py +0 -0
  148. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/embedded_upgrade_probe.py +0 -0
  149. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/consumer_prepare_acceptance.py +0 -0
  150. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/lifecycle_dependency_audit.py +0 -0
  151. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/README.md +0 -0
  152. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/client_probe.py +0 -0
  153. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/input_probe.py +0 -0
  154. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/key_timeline_probe.py +0 -0
  155. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/movement.json +0 -0
  156. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/run.py +0 -0
  157. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/server_fixture.py +0 -0
  158. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual/runtime_controls/support.py +0 -0
  159. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_dependency_boundaries.py +0 -0
  160. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_input_window.py +0 -0
  161. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_integration.py +0 -0
  162. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_native_recording.py +0 -0
  163. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_remote_recording.py +0 -0
  164. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_runtime_input.py +0 -0
  165. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_runtime_input_unified.py +0 -0
  166. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_runtime_key_timeline.py +0 -0
  167. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_runtime_player.py +0 -0
  168. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/manual_runtime_ui.py +0 -0
  169. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/runtime_support.py +0 -0
  170. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_application_icons.py +0 -0
  171. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_auth_interaction.py +0 -0
  172. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_automation.py +0 -0
  173. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_builder_import_boundary.py +0 -0
  174. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_code_libraries.py +0 -0
  175. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_consumer_prepare.py +0 -0
  176. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_core_updates.py +0 -0
  177. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_dependency_boundaries.py +0 -0
  178. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_deployment_encoding.py +0 -0
  179. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_distribution_layout.py +0 -0
  180. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_engine_backends.py +0 -0
  181. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_engine_compatibility.py +0 -0
  182. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_engine_discovery.py +0 -0
  183. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_engine_install.py +0 -0
  184. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_git_projects.py +0 -0
  185. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_host_services.py +0 -0
  186. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_input_sequence.py +0 -0
  187. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_instance_cppconfig.py +0 -0
  188. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_launch_encoding.py +0 -0
  189. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_launcher_python.py +0 -0
  190. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_lifecycle_races.py +0 -0
  191. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_local_auth_session.py +0 -0
  192. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_local_dependencies.py +0 -0
  193. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_lock_storage.py +0 -0
  194. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_log_stream.py +0 -0
  195. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_manual_runtime_controls.py +0 -0
  196. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_mcs_auth.py +0 -0
  197. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_mouse.py +0 -0
  198. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_native_input_sequence.py +0 -0
  199. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_native_preferences.py +0 -0
  200. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_native_recording.py +0 -0
  201. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_network.py +0 -0
  202. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_network_sessions.py +0 -0
  203. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_pack_uuid_conflicts.py +0 -0
  204. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_package.py +0 -0
  205. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_qt_sessions.py +0 -0
  206. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_qumod_workflow.py +0 -0
  207. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_recordings.py +0 -0
  208. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_remote.py +0 -0
  209. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_remote_scripts.py +0 -0
  210. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_resource_reload.py +0 -0
  211. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_debug.py +0 -0
  212. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_deployment.py +0 -0
  213. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_groups.py +0 -0
  214. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_input.py +0 -0
  215. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_key_timeline.py +0 -0
  216. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_player.py +0 -0
  217. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_profiles.py +0 -0
  218. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_ui.py +0 -0
  219. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_runtime_ui_outline.py +0 -0
  220. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_screenshot.py +0 -0
  221. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_session_capabilities.py +0 -0
  222. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_shared_logs.py +0 -0
  223. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_unified_skill_contract.py +0 -0
  224. {mcpywrap-0.6.0 → mcpywrap-0.6.2}/tests/test_window_focus.py +0 -0
@@ -1,5 +1,22 @@
1
1
  # 更新记录
2
2
 
3
+ ## 0.6.2
4
+
5
+ - 日志新增字面过滤与重复消息统计,明确扫描范围;支持结构化日志的 App 宿主另提供端侧和毫秒时间范围筛选。
6
+ - 单会话重启明确交接旧、新 session;缓存信息显示年龄,Android 启动支持分阶段证据、后台尝试历史和独立的确认等待配置。
7
+
8
+ - 标准 CLI 与同一份 skill 支持配对 Android 本机宿主;工程解析、构建和组装由 App 内核心执行,开发端按阶段完成工具准备,连接失败不回退本地构建。
9
+ - 配对和准备结果支持中断恢复;最近操作保存最后观察到的状态,启动结果未知时可查询关联会话的新证据,不重放副作用。
10
+ - 手机日志支持分源聚合,截图可自动保存到作品 captures 目录;补全库工具在开发端执行,版本目录支持离线缓存和有界联网刷新。
11
+ - 两个发行包继续使用相同版本号,默认完整安装入口保持不变。
12
+
13
+ ## 0.6.1
14
+
15
+ - 自动化启动默认保留后台窗口,不抢前台应用;提供 `--background` / `--foreground` 显式选择,重启和联调组保留策略。
16
+ - 后台会话截图禁止回退前台,桌面键鼠入口明确拒绝;游戏内统一输入继续可用。
17
+ - macOS 默认运行包升级到 0.4.6,支持后台窗口、全屏偏好隔离和光标保护;修复退出信号打断信号量等待时的错误码转换,避免 Python 锁状态异常。旧实例保留原运行包绑定。
18
+ - 补齐 macOS CI 的后台策略测试,隔离 Windows 部署测试的平台选择,并提供可选的原生 ES2 回退验收。
19
+
3
20
  ## 0.6.0
4
21
 
5
22
  - 拆分为同版本的 `mcpywrap-core` 与完整 `mcpywrap`;默认 `pip install mcpywrap` / `uv tool install mcpywrap` 继续安装完整桌面依赖。
@@ -3,7 +3,7 @@ include setup.py
3
3
  include core/mcpywrap_core/_version.py
4
4
  recursive-include desktop *.py *.exe *.dll *.cer *.json
5
5
  recursive-include scripts *.py *.ps1
6
- recursive-include native *.cs *.c *.cpp *.h *.cer *.json *.md *.patch
6
+ recursive-include native *.cs *.c *.cpp *.h *.cer *.json *.md *.patch *.py
7
7
  recursive-include docs *.md
8
8
  recursive-include tests *.py *.md *.json
9
9
  recursive-include skills *.md *.yaml *.ps1 *.py *.toml *.json .gitignore
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpywrap
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Complete mcpy desktop tools, powered by the shared mcpywrap-core
5
5
  Author-email: boybook <boybook@easecation.net>
6
6
  License-Expression: MIT
@@ -10,7 +10,7 @@ Requires-Python: >=3.9
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  License-File: THIRD_PARTY_NOTICES.md
13
- Requires-Dist: mcpywrap-core==0.6.0
13
+ Requires-Dist: mcpywrap-core==0.6.2
14
14
  Requires-Dist: pip>=23
15
15
  Requires-Dist: build>=1.0
16
16
  Requires-Dist: watchdog>=2.0.0
@@ -134,9 +134,19 @@ Git 项目使用 `[[tool.mcpywrap.git_dependencies]]` 声明,支持 Addon 与
134
134
 
135
135
  外部服务器连接、可选 MCS 身份与进服判断见 [网络会话](skills/mcpywrap/references/network-sessions.md)。需要另一台 Windows 执行游戏时,再按 [远程执行端](skills/mcpywrap/references/remote-testing.md) 配置服务。远程连接不部署本地 Mod,也不提供世界实例管理。
136
136
 
137
+ ## Android 本机宿主
138
+
139
+ 仅在手机上使用外部开发工具时,按[本机 App 接入](skills/mcpywrap/references/application-host.md)完成配对。绑定工作区使用标准命令,由 App 核心执行工程操作;离线时不回退本地构建。普通 Windows/macOS 项目继续使用原本的桌面流程,无需安装手机应用或配置手机权限。
140
+
137
141
  ## AI Agent 使用
138
142
 
139
- 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。
143
+ 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。0.6.2 起也可从已安装的发行包导出完整同版本 Skill:
144
+
145
+ ```bash
146
+ mcpy skill install --directory <Agent技能目录>/mcpywrap
147
+ ```
148
+
149
+ 更新已有技能目录加 `--replace`。只维护这份标准 Skill,按任务加载平台参考。
140
150
 
141
151
  Skill 按当前任务选择参考,不要求 AI 通读产品文档。可直接描述:
142
152
 
@@ -109,9 +109,19 @@ Git 项目使用 `[[tool.mcpywrap.git_dependencies]]` 声明,支持 Addon 与
109
109
 
110
110
  外部服务器连接、可选 MCS 身份与进服判断见 [网络会话](skills/mcpywrap/references/network-sessions.md)。需要另一台 Windows 执行游戏时,再按 [远程执行端](skills/mcpywrap/references/remote-testing.md) 配置服务。远程连接不部署本地 Mod,也不提供世界实例管理。
111
111
 
112
+ ## Android 本机宿主
113
+
114
+ 仅在手机上使用外部开发工具时,按[本机 App 接入](skills/mcpywrap/references/application-host.md)完成配对。绑定工作区使用标准命令,由 App 核心执行工程操作;离线时不回退本地构建。普通 Windows/macOS 项目继续使用原本的桌面流程,无需安装手机应用或配置手机权限。
115
+
112
116
  ## AI Agent 使用
113
117
 
114
- 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。
118
+ 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。0.6.2 起也可从已安装的发行包导出完整同版本 Skill:
119
+
120
+ ```bash
121
+ mcpy skill install --directory <Agent技能目录>/mcpywrap
122
+ ```
123
+
124
+ 更新已有技能目录加 `--replace`。只维护这份标准 Skill,按任务加载平台参考。
115
125
 
116
126
  Skill 按当前任务选择参考,不要求 AI 通读产品文档。可直接描述:
117
127
 
@@ -0,0 +1 @@
1
+ __version__ = '0.6.2'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcpywrap
3
- Version: 0.6.0
3
+ Version: 0.6.2
4
4
  Summary: Complete mcpy desktop tools, powered by the shared mcpywrap-core
5
5
  Author-email: boybook <boybook@easecation.net>
6
6
  License-Expression: MIT
@@ -10,7 +10,7 @@ Requires-Python: >=3.9
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  License-File: THIRD_PARTY_NOTICES.md
13
- Requires-Dist: mcpywrap-core==0.6.0
13
+ Requires-Dist: mcpywrap-core==0.6.2
14
14
  Requires-Dist: pip>=23
15
15
  Requires-Dist: build>=1.0
16
16
  Requires-Dist: watchdog>=2.0.0
@@ -134,9 +134,19 @@ Git 项目使用 `[[tool.mcpywrap.git_dependencies]]` 声明,支持 Addon 与
134
134
 
135
135
  外部服务器连接、可选 MCS 身份与进服判断见 [网络会话](skills/mcpywrap/references/network-sessions.md)。需要另一台 Windows 执行游戏时,再按 [远程执行端](skills/mcpywrap/references/remote-testing.md) 配置服务。远程连接不部署本地 Mod,也不提供世界实例管理。
136
136
 
137
+ ## Android 本机宿主
138
+
139
+ 仅在手机上使用外部开发工具时,按[本机 App 接入](skills/mcpywrap/references/application-host.md)完成配对。绑定工作区使用标准命令,由 App 核心执行工程操作;离线时不回退本地构建。普通 Windows/macOS 项目继续使用原本的桌面流程,无需安装手机应用或配置手机权限。
140
+
137
141
  ## AI Agent 使用
138
142
 
139
- 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。
143
+ 安装仓库内完整的 [mcpywrap Skill](skills/mcpywrap/SKILL.md)。可让 Agent 安装 `EaseCation/mcpywrap` 的 `skills/mcpywrap` 目录,或将整个文件夹复制到其技能目录。CLI 与 Skill 分别安装,安装 Python 包不会自动注册 Skill。0.6.2 起也可从已安装的发行包导出完整同版本 Skill:
144
+
145
+ ```bash
146
+ mcpy skill install --directory <Agent技能目录>/mcpywrap
147
+ ```
148
+
149
+ 更新已有技能目录加 `--replace`。只维护这份标准 Skill,按任务加载平台参考。
140
150
 
141
151
  Skill 按当前任务选择参考,不要求 AI 通读产品文档。可直接描述:
142
152
 
@@ -20,6 +20,8 @@ desktop/mcpywrap_assets/bridge_payload/Loader.dll
20
20
  desktop/mcpywrap_assets/bridge_payload/McpyMcsAuth.dll
21
21
  desktop/mcpywrap_assets/bridge_payload/manifest.json
22
22
  desktop/mcpywrap_assets/bridge_payload/publisher.cer
23
+ desktop/mcpywrap_assets/window_activation/manifest.json
24
+ desktop/mcpywrap_assets/window_activation/mcpy-window-activation.dll
23
25
  desktop/mcpywrap_assets/window_capture/manifest.json
24
26
  desktop/mcpywrap_assets/window_capture/mcpy-window-capture.exe
25
27
  docs/code-libraries.md
@@ -43,6 +45,13 @@ docs/runtime-ui.md
43
45
  docs/shared-core.md
44
46
  docs/shared-log-ui.md
45
47
  examples/consumer_prepare/README.md
48
+ native/background_window/README.md
49
+ native/background_window/apply.py
50
+ native/background_window/client-background.patch
51
+ native/background_window/game-window-background.patch
52
+ native/background_window/libc-shim-background.patch
53
+ native/background_window/manifest-background.patch
54
+ native/background_window/test_window.cpp
46
55
  native/mcs_auth/Bridge.cs
47
56
  native/mcs_auth/Injector.cs
48
57
  native/mcs_auth/Loader.c
@@ -52,15 +61,19 @@ native/runtime_input/README.md
52
61
  native/runtime_input/launcher-monotonic.patch
53
62
  native/runtime_input/manifest-monotonic.patch
54
63
  native/runtime_input/steady_clock.h
64
+ native/window_activation/README.md
65
+ native/window_activation/window_activation.cpp
55
66
  native/window_capture/video_capture.h
56
67
  native/window_capture/window_capture.cpp
57
68
  scripts/build_all_native.py
58
69
  scripts/build_app_icon.py
59
70
  scripts/build_distributions.py
60
71
  scripts/build_mcs_auth_bridge.py
72
+ scripts/build_window_activation.py
61
73
  scripts/build_window_capture.py
62
74
  scripts/check_mcs_auth_bridge.py
63
75
  scripts/check_release.py
76
+ scripts/check_window_activation.py
64
77
  scripts/check_window_capture.py
65
78
  scripts/pypi_release.py
66
79
  scripts/sign_mcs_auth_ci.ps1
@@ -80,6 +93,7 @@ skills/mcpywrap/assets/consumer-prepare/game/pyproject.toml
80
93
  skills/mcpywrap/assets/consumer-prepare/game/behavior_pack/manifest.json
81
94
  skills/mcpywrap/assets/consumer-prepare/game/data/items.json
82
95
  skills/mcpywrap/assets/consumer-prepare/game/resource_pack/manifest.json
96
+ skills/mcpywrap/references/application-host.md
83
97
  skills/mcpywrap/references/capture.md
84
98
  skills/mcpywrap/references/consumer-prepare-author.md
85
99
  skills/mcpywrap/references/consumer-prepare.md
@@ -109,6 +123,7 @@ skills/mcpywrap/scripts/smoke.py
109
123
  tests/README.md
110
124
  tests/core_fixture.py
111
125
  tests/embedded_upgrade_probe.py
126
+ tests/manual_background_launch.py
112
127
  tests/manual_dependency_boundaries.py
113
128
  tests/manual_input_window.py
114
129
  tests/manual_integration.py
@@ -138,6 +153,7 @@ tests/test_engine_backends.py
138
153
  tests/test_engine_compatibility.py
139
154
  tests/test_engine_discovery.py
140
155
  tests/test_engine_install.py
156
+ tests/test_execution_boundaries.py
141
157
  tests/test_game_window_skill.py
142
158
  tests/test_git_projects.py
143
159
  tests/test_host_input.py
@@ -151,10 +167,14 @@ tests/test_lifecycle_races.py
151
167
  tests/test_local_auth_session.py
152
168
  tests/test_local_dependencies.py
153
169
  tests/test_lock_storage.py
170
+ tests/test_log_query.py
154
171
  tests/test_log_stream.py
155
172
  tests/test_macos_network.py
156
173
  tests/test_manual_runtime_controls.py
157
174
  tests/test_mcs_auth.py
175
+ tests/test_mobile_diagnostics.py
176
+ tests/test_mobile_host.py
177
+ tests/test_mobile_pairing.py
158
178
  tests/test_modsdk_environment.py
159
179
  tests/test_mouse.py
160
180
  tests/test_native_input_sequence.py
@@ -171,6 +191,7 @@ tests/test_recordings.py
171
191
  tests/test_remote.py
172
192
  tests/test_remote_scripts.py
173
193
  tests/test_resource_reload.py
194
+ tests/test_restricted_process_identity.py
174
195
  tests/test_runtime_debug.py
175
196
  tests/test_runtime_deployment.py
176
197
  tests/test_runtime_groups.py
@@ -185,7 +206,9 @@ tests/test_session_capabilities.py
185
206
  tests/test_shared_logs.py
186
207
  tests/test_skill_workflows.py
187
208
  tests/test_unified_skill_contract.py
209
+ tests/test_window_activation.py
188
210
  tests/test_window_focus.py
211
+ tests/test_window_policy.py
189
212
  tests/manual/consumer_prepare_acceptance.py
190
213
  tests/manual/lifecycle_dependency_audit.py
191
214
  tests/manual/runtime_controls/README.md
@@ -1,4 +1,4 @@
1
- mcpywrap-core==0.6.0
1
+ mcpywrap-core==0.6.2
2
2
  pip>=23
3
3
  build>=1.0
4
4
  watchdog>=2.0.0
@@ -11,9 +11,9 @@
11
11
  "Loader.c": "f2f1f781ce82fc30c62a6ce22bb048d3b023f6ff500e6ec8228da28b4dbf1b4a"
12
12
  },
13
13
  "files": {
14
- "Injector.exe": "ba3caeae28560fcf49c89a1e5562d7e9f4d5a9ac66639abca7dda0cc51462706",
15
- "Loader.dll": "abc1715947c505ffb7df7e63f62603156180961a2a86320b2b8c580bd4d65ac2",
16
- "McpyMcsAuth.dll": "42af0e2376e6f0a8c2e4829793cf3ce73e751cd0e0a6302ed069efb161599151",
14
+ "Injector.exe": "05806de2bd8143d690f4136451dd495b892d47036481b5af170576edeacd1d60",
15
+ "Loader.dll": "7f45d503eb7f06bf535bb564cda2d3b8dc7c38118d4433f514ca57fe94040cce",
16
+ "McpyMcsAuth.dll": "d7bf8957a2bdcac92bbef80ff0ef5709ffdebfb9ece237a65caf8e244483acce",
17
17
  "publisher.cer": "e5aa2ac39df40804ed8b08fe8e43c4a2b8923f0d02a360708486b2db5b6303d7"
18
18
  }
19
19
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "background_window_protocol": 1,
3
+ "architecture": "x64",
4
+ "dll_sha256": "e05ff1d30f809621dd104d87a63f26d7c725864a43c0989d9035ed2647879cb4",
5
+ "source_sha256": "03c1aab9e8d46c162e11f9448903c4907fbe3b87d1e77d8118b72c3e6b250ec5"
6
+ }
@@ -1,5 +1,5 @@
1
1
  {
2
- "executable_sha256": "1d2721067ad63c12787b5d3a5ff7461decb72f1a250496bafc65e4fad5802e64",
2
+ "executable_sha256": "74a0ecfbcb266a0e6689ac8c981058cbd59382e9adf7a92aae832836e10e1b3b",
3
3
  "source_sha256": "0c0b2a02bfecea68b824a486ac1d88cde6bd9fc8ee8e4c9a6939870bd8e710d1",
4
4
  "sources": {
5
5
  "video_capture.h": "f766d4234e41a554a8eb8ecae93fd818c2fb8877fbd1795f3915dcc8771e7909",
@@ -36,7 +36,9 @@ Windows 联调成员的生命周期记录、角色归属及占用锁仍位于项
36
36
  首次迁移在角色占用锁内复制旧 AppData 到临时目录,完成归属标记后原子改名,原副本保留。后续启动复用新位置;目标缺失、归属不符或遗留未完成迁移时停止,不回退到旧身份。旧资料的长路径用宿主扩展路径形式复制,传给游戏的仍是标准短路径。需要项目所在磁盘根目录允许创建 `mcpy-profiles`;不支持 UNC 或被替换为目录链接的位置,不自动提权。用户搬迁项目时需保留组记录及其指向的 profile,不能只把外部目录当缓存删除。
37
37
 
38
38
 
39
- Windows/macOS 共同基线是 `--local --project <目录> --non-interactive run --no-gui --detach --json`,后续统一 status/logs/runtime py/runtime reload/stop。控制端不打开 Qt、小窗或 TUI,游戏本身仍需要显示服务及原生窗口。完整操作顺序维护在 [技能的公共流程](../skills/mcpywrap/references/local-development.md)。
39
+ Windows/macOS 共同基线是 `--local --project <目录> --non-interactive run --no-gui --detach --json`,后续统一 status/logs/runtime py/runtime reload/stop。非交互、JSON、no-gui 或 detach 默认请求后台窗口,`--background / --foreground` 可覆盖;普通交互式 run 和 Qt 默认保留前台聚焦。策略写入会话并随双客户端、重启和部署重试传递,复用已有会话不改变其策略。
40
+
41
+ Windows 后台启动使用独立桌面包提供的进程内线程级 CBT 保护及非激活启动参数;保护范围与构建见 [窗口保护](../native/window_activation/README.md)。macOS 通过运行包 helper 的 `--background` 传到 GLFW,要求 `background_window_protocol=1`,旧包在创建实例/进程前拒绝;配套源码见 [原生补丁](../native/background_window/README.md)。后台会话强制后台截图并拒绝会激活窗口的桌面键鼠输入。游戏仍需显示服务及原生窗口,完整用法维护在 [技能公共流程](../skills/mcpywrap/references/local-development.md)。
40
42
 
41
43
  `runtime capabilities --session <id> --json` 返回 schema_version=1:control 描述控制端要求,python 提供执行端侧与 worker 队列声明,reload 按同一后端限制返回 available/unsupported/unavailable。查询不执行游戏代码、不返回控制凭据,available 只说明允许调用。旧 worker 缺少队列声明时返回 null,不能推断支持。Windows 已知 Shader 限制也由 WindowsBackend 提供,实际重载与查询没有两份规则。
42
44
 
@@ -0,0 +1,65 @@
1
+ # macOS 后台窗口运行包
2
+
3
+ CLI 的后台窗口接口需要运行包 `background_window_protocol=1`。旧包返回 `background_window_unavailable`;允许占用前台时可显式 `--foreground`。这些补丁针对源码构建,不修改已签名应用或旧实例绑定。
4
+
5
+ ## 补丁与基线
6
+
7
+ - `game-window-background.patch`:在初次创建及 ES2 回退的 hints 重置后关闭 `GLFW_FOCUSED` / `GLFW_FOCUS_ON_SHOW`,后台时禁止全屏和光标锁定、隐藏、重定位。
8
+ - `client-background.patch`:跳过后台会话的全屏偏好和请求,保留用户偏好。
9
+ - `manifest-background.patch`:helper 接受 `--background`,显式传入 `MCPY_GAME_BACKGROUND=1/0`,普通运行不继承遗留环境开关;构建检查补丁后声明协议。
10
+ - `libc-shim-background.patch`:信号打断 Mach 信号量等待时转换为 `-1/EINTR`,避免退出信号破坏 Python 锁处理;manifest 补丁包含原生回归测试。
11
+ - `apply.py`:四份补丁全部预检后才应用,已应用项可跳过;不下载、构建或启动游戏。
12
+
13
+ 核对基线:manifest `8b624579618a121c345dd4ff05748d426a0141fa`,client `350eb36f499fbb4bc2bcaf413bd7b2fefa1fb782`,game-window `d073c2aace1521ae32d239ca4fc26b97e4b4a27e`,libc-shim `8ca149814eba0c42fa0c1f945b76fb526f6f0694`。
14
+
15
+ ## 在 Mac 构建测试包
16
+
17
+ 在 Apple Silicon Mac 按 manifest 的说明准备 Xcode Command Line Tools、Python、CMake、Ninja 等依赖。可使用已有初始化的开发 checkout;首次准备使用核对基线:
18
+
19
+ ```sh
20
+ git clone https://github.com/EaseCation/mcpelauncher-manifest.git /path/to/runtime-source
21
+ git -C /path/to/runtime-source checkout 8b624579618a121c345dd4ff05748d426a0141fa
22
+ git -C /path/to/runtime-source submodule update --init --recursive
23
+ python3 native/background_window/apply.py --manifest /path/to/runtime-source
24
+ ```
25
+
26
+ 选择尚不存在的应用和发行输出目录;APK 应与构建使用的 profile 匹配:
27
+
28
+ ```sh
29
+ python3 /path/to/runtime-source/tools/build_macos_runtime.py \
30
+ --output /path/to/background-build/McpyRuntime.app \
31
+ --work-dir /path/to/background-build/portable \
32
+ --build-dir /path/to/background-build/client
33
+ python3 /path/to/runtime-source/tools/package_macos_release.py \
34
+ --runtime /path/to/background-build/McpyRuntime.app \
35
+ --version 0.6.0-background.1 --output /path/to/background-release
36
+ mcpy --local --non-interactive engine install \
37
+ --catalog /path/to/background-release/catalog.json --apk /path/to/developer.apk --json
38
+ ```
39
+
40
+ mcpywrap 开发 checkout 同时安装 `./core` 与完整包:在开发虚拟环境执行 `python -m pip install -e ./core -e .`。安装新运行包后使用独立项目 `run --new`,旧实例不会自动换包。
41
+
42
+ ## Mac 验收
43
+
44
+ 1. 保持其他应用前台,执行标准 AI 命令 `mcpy --local --project <独立项目> --non-interactive run --new --no-gui --detach --json`。应返回 `background=true`;到 HUD 期间不切应用、不切 Space、不锁定光标。
45
+ 2. `status` 确认 `world_ready`,`screenshot --session <sid> --output <新PNG> --json` 应获得新帧。后台会话禁止截图回退前台。
46
+ 3. `runtime install` 后用统一输入的默认 `game` 后端验证游戏内动作和效果,覆盖遮挡、菜单及取消释放。`restart --session <sid> --json` 应产生新 session 并保留后台策略。
47
+ 4. 停止自己的会话,再从交互终端执行普通 `mcpy run`,确认正常聚焦;显式 `run --foreground --no-gui --detach --json` 应返回 `background=false`。
48
+ 5. 覆盖之前已开启全屏的偏好、光标锁定请求及 ES3→ES2 回退;后台退出后原有全屏偏好保持。
49
+
50
+ 此模式保留可见窗口和 GPU 渲染,不承诺隐藏、最小化或锁屏后继续产生帧。公开启动用法见 [本地会话](../../skills/mcpywrap/references/local-development.md)。
51
+
52
+ ### 可选原生回退测试
53
+
54
+ `test_window.cpp` 只用于交互式 Mac 桌面验收,不接入默认测试或游戏启动。它编译实际的 `window_glfw.cpp`,仅让第一次窗口创建返回失败,然后使用真实 GLFW/ANGLE 创建 ES2 窗口,断言回退后不聚焦、光标锁定请求被抑制、全屏请求被抑制。保持其他应用前台,并同时观察应用激活和 Space 事件;窗口属性断言本身不能证明没有短暂抢焦点。
55
+
56
+ 在已完成上述构建的终端中设置 `source` 为 manifest 目录、`build` 为该次 CMake 构建目录、`runtime` 为新应用路径:
57
+
58
+ ```sh
59
+ c++ -std=c++17 -I "$source/game-window/src" -I "$source/game-window/include" \
60
+ -I "$build/_deps/glfw3_ext-src/include" native/background_window/test_window.cpp \
61
+ "$build/game-window/libgamewindow.a" "$build/_deps/glfw3_ext-build/src/libglfw3.a" \
62
+ -framework Cocoa -framework OpenGL -framework IOKit -framework QuartzCore \
63
+ -o /tmp/mcpy-background-window-test
64
+ DYLD_LIBRARY_PATH="$runtime/Contents/Frameworks" /tmp/mcpy-background-window-test
65
+ ```
@@ -0,0 +1,41 @@
1
+ """Apply background-window and safe-stop patches to an initialized runtime source tree."""
2
+ import argparse
3
+ from pathlib import Path
4
+ import subprocess
5
+
6
+
7
+ def apply(manifest):
8
+ root = Path(manifest).resolve(strict=True)
9
+ patches = Path(__file__).resolve().parent
10
+ targets = [(root/'game-window', patches/'game-window-background.patch'),
11
+ (root/'mcpelauncher-client', patches/'client-background.patch'),
12
+ (root/'libc-shim', patches/'libc-shim-background.patch'),
13
+ (root, patches/'manifest-background.patch')]
14
+ pending = []
15
+ for repo, patch in targets:
16
+ if not (repo/'.git').exists():
17
+ raise RuntimeError('Initialize the Git checkout/submodule first: ' + str(repo))
18
+ command = ['git', '-C', str(repo), 'apply']
19
+ if subprocess.run(command + ['--reverse', '--check', str(patch)], capture_output=True).returncode == 0:
20
+ continue
21
+ result = subprocess.run(command + ['--check', str(patch)], capture_output=True, text=True)
22
+ if result.returncode:
23
+ raise RuntimeError('Patch preflight failed: ' + str(patch) + '\n' + result.stderr)
24
+ pending.append((command, patch))
25
+ applied = []
26
+ try:
27
+ for command, patch in pending:
28
+ subprocess.run(command + [str(patch)], check=True)
29
+ applied.append((command, patch))
30
+ except BaseException:
31
+ for command, patch in reversed(applied):
32
+ subprocess.run(command + ['--reverse', str(patch)], check=True)
33
+ raise
34
+ return len(applied)
35
+
36
+
37
+ if __name__ == '__main__':
38
+ parser = argparse.ArgumentParser(description=__doc__)
39
+ parser.add_argument('--manifest', required=True, type=Path)
40
+ args = parser.parse_args()
41
+ print('Applied', apply(args.manifest), 'patches; build a new runtime before testing.')
@@ -0,0 +1,35 @@
1
+ diff --git a/src/window_callbacks.cpp b/src/window_callbacks.cpp
2
+ index 6721d73..c60015c 100644
3
+ --- a/src/window_callbacks.cpp
4
+ +++ b/src/window_callbacks.cpp
5
+ @@ -11,6 +11,13 @@
6
+ #include <string>
7
+ #include "settings.h"
8
+ #include "util.h"
9
+ +
10
+ +namespace {
11
+ +bool backgroundWindow() {
12
+ + const char* value = std::getenv("MCPY_GAME_BACKGROUND");
13
+ + return value && std::string(value) == "1";
14
+ +}
15
+ +}
16
+ #ifdef USE_IMGUI
17
+ #include "imgui_ui.h"
18
+ #endif
19
+ @@ -18,7 +25,7 @@
20
+ WindowCallbacks::WindowCallbacks(GameWindow& window, JniSupport& jniSupport, FakeInputQueue& inputQueue) : window(window), jniSupport(jniSupport), inputQueue(inputQueue) {
21
+ useDirectMouseInput = Mouse::feed;
22
+ useDirectKeyboardInput = (Keyboard::_states && (Keyboard::_inputs || Keyboard::_inputsLegacy) && Keyboard::_gameControllerId);
23
+ - if(Settings::fullscreen) {
24
+ + if(Settings::fullscreen && !backgroundWindow()) {
25
+ window.setFullscreen(true);
26
+ }
27
+ useRawInput = ReadEnvFlag("MCPELAUNCHER_CLIENT_RAW_INPUT");
28
+ @@ -89,6 +96,7 @@ void WindowCallbacks::onClose() {
29
+ }
30
+
31
+ void WindowCallbacks::setFullscreen(bool isFs) {
32
+ + if (backgroundWindow()) return;
33
+ if(Settings::fullscreen != isFs) {
34
+ window.setFullscreen(isFs);
35
+ Settings::fullscreen = isFs;
@@ -0,0 +1,58 @@
1
+ diff --git a/src/window_glfw.cpp b/src/window_glfw.cpp
2
+ index 7e0a85b..ca8e524 100644
3
+ --- a/src/window_glfw.cpp
4
+ +++ b/src/window_glfw.cpp
5
+ @@ -8,12 +8,27 @@
6
+ #include <sstream>
7
+
8
+ #include <math.h>
9
+ +#include <cstdlib>
10
+ +#include <cstring>
11
+ +
12
+ +namespace {
13
+ +bool backgroundWindow() {
14
+ + const char* value = std::getenv("MCPY_GAME_BACKGROUND");
15
+ + return value && std::strcmp(value, "1") == 0;
16
+ +}
17
+ +void backgroundWindowHints() {
18
+ + if (!backgroundWindow()) return;
19
+ + glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
20
+ + glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
21
+ +}
22
+ +}
23
+
24
+ GLFWGameWindow::GLFWGameWindow(const std::string& title, int width, int height, GraphicsApi api) : GameWindow(title, width, height, api), width(width), height(height), windowedWidth(width), windowedHeight(height) {
25
+ #ifdef GAMEWINDOW_X11_LOCK
26
+ std::lock_guard<std::recursive_mutex> lock(x11_sync);
27
+ #endif
28
+ glfwDefaultWindowHints();
29
+ + backgroundWindowHints();
30
+ if(api == GraphicsApi::OPENGL_ES2) {
31
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
32
+ glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
33
+ @@ -29,6 +44,7 @@ GLFWGameWindow::GLFWGameWindow(const std::string& title, int width, int height,
34
+ if(window == nullptr && api == GraphicsApi::OPENGL_ES2) {
35
+ // Failed to get es3 request es2
36
+ glfwDefaultWindowHints();
37
+ + backgroundWindowHints();
38
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
39
+ glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
40
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
41
+ @@ -172,6 +188,8 @@ bool GLFWGameWindow::getCursorDisabled() {
42
+ }
43
+
44
+ void GLFWGameWindow::setCursorDisabled(bool disabled) {
45
+ + // A background test must never grab, hide or recenter the user's cursor.
46
+ + if (backgroundWindow()) disabled = false;
47
+ #ifdef GAMEWINDOW_X11_LOCK
48
+ std::lock_guard<std::recursive_mutex> lock(x11_sync);
49
+ #endif
50
+ @@ -199,7 +217,7 @@ void GLFWGameWindow::setFullscreen(bool fullscreen) {
51
+ #ifdef GAMEWINDOW_X11_LOCK
52
+ std::lock_guard<std::recursive_mutex> lock(x11_sync);
53
+ #endif
54
+ - requestFullscreen = fullscreen;
55
+ + requestFullscreen = fullscreen && !backgroundWindow();
56
+ }
57
+
58
+ void GLFWGameWindow::setClipboardText(std::string const& text) {
@@ -0,0 +1,25 @@
1
+ diff --git a/src/semaphore.cpp b/src/semaphore.cpp
2
+ index 1388f93..4adad85 100644
3
+ --- a/src/semaphore.cpp
4
+ +++ b/src/semaphore.cpp
5
+ @@ -56,7 +56,12 @@ int shim::sem_destroy(host_sem_t *sem) {
6
+ }
7
+
8
+ int shim::sem_wait(host_sem_t *sem) {
9
+ - return semaphore_wait(*sem);
10
+ + auto result = semaphore_wait(*sem);
11
+ + if(result == KERN_SUCCESS) return 0;
12
+ + // POSIX 调用方不能接收 Mach 错误码,否则会误用未持有的锁。
13
+ + errno = result == KERN_ABORTED ? EINTR : EINVAL;
14
+ + bionic::update_errno();
15
+ + return -1;
16
+ }
17
+
18
+ int shim::sem_trywait(host_sem_t *sem) {
19
+ @@ -113,4 +118,4 @@ void shim::add_sem_shimmed_symbols(std::vector<shim::shimmed_symbol> &list) {
20
+ {"sem_timedwait", &detail::arg_rewrite_helper<int (::sem_t *, const struct timespec *)>::rewrite<sem_timedwait>},
21
+ {"sem_post", &detail::arg_rewrite_helper<int (::sem_t *)>::rewrite<sem_post>},
22
+ });
23
+ -}
24
+
25
+ +}
@@ -0,0 +1,112 @@
1
+ diff --git a/tests/libc_compat_smoke.cpp b/tests/libc_compat_smoke.cpp
2
+ index 2ea481f..83cc704 100644
3
+ --- a/tests/libc_compat_smoke.cpp
4
+ +++ b/tests/libc_compat_smoke.cpp
5
+ @@ -12,6 +12,11 @@
6
+ #include <sys/socket.h>
7
+ #include <sys/mman.h>
8
+ #include <unistd.h>
9
+ +#include <atomic>
10
+ +#include <chrono>
11
+ +#include <csignal>
12
+ +#include <thread>
13
+ +#include <pthread.h>
14
+
15
+ int main() {
16
+ std::unordered_map<std::string, void*> symbols;
17
+ @@ -38,6 +43,29 @@ int main() {
18
+ assert(post(sem) == 0);
19
+ assert(wait(sem) == 0);
20
+ assert(wait(sem) == -1 && *error() == 11);
21
+ +#ifdef __APPLE__
22
+ + // 信号打断 Mach 等待时,Android 调用方必须收到 -1/EINTR。
23
+ + struct sigaction action{}, previous{};
24
+ + action.sa_handler = +[](int) {};
25
+ + sigemptyset(&action.sa_mask);
26
+ + assert(sigaction(SIGUSR1, &action, &previous) == 0);
27
+ + auto blockingWait = reinterpret_cast<int(*)(void*)>(symbols.at("sem_wait"));
28
+ + auto waitingThread = pthread_self();
29
+ + std::atomic<bool> finished{false};
30
+ + std::thread interrupter([&] {
31
+ + for(int i = 0; i < 100 && !finished; ++i) {
32
+ + std::this_thread::sleep_for(std::chrono::milliseconds(10));
33
+ + pthread_kill(waitingThread, SIGUSR1);
34
+ + }
35
+ + if(!finished) post(sem);
36
+ + });
37
+ + int interrupted = blockingWait(sem);
38
+ + int interruptedError = *error();
39
+ + finished = true;
40
+ + interrupter.join();
41
+ + assert(sigaction(SIGUSR1, &previous, nullptr) == 0);
42
+ + assert(interrupted == -1 && interruptedError == 4);
43
+ +#endif
44
+ assert(destroy(sem) == 0);
45
+ auto androidFcntl = reinterpret_cast<int(*)(int, int, void*)>(symbols.at("fcntl"));
46
+ int sockets[2];
47
+ diff --git a/tools/build_macos_runtime.py b/tools/build_macos_runtime.py
48
+ index 9b25aba..2c80ab2 100644
49
+ --- a/tools/build_macos_runtime.py
50
+ +++ b/tools/build_macos_runtime.py
51
+ @@ -127,6 +127,10 @@ def main():
52
+ run(['make', '-j' + str(args.jobs)], cwd=source, env=env, stdout=log, stderr=subprocess.STDOUT)
53
+ run(['make', 'install_sw'], cwd=source, env=env, stdout=log, stderr=subprocess.STDOUT)
54
+ stamp.write_text(json.dumps(recipe, indent=2) + '\n')
55
+ + # Advertise this protocol only when every native implementation is present.
56
+ + for source in ('game-window/src/window_glfw.cpp', 'mcpelauncher-client/src/window_callbacks.cpp'):
57
+ + if 'MCPY_GAME_BACKGROUND' not in (ROOT / source).read_text():
58
+ + raise RuntimeError('Missing background-window source patch: ' + source)
59
+ build = args.build_dir.resolve() if args.build_dir else work / 'client'
60
+ config = ['cmake', '-S', ROOT, '-B', build, '-G', 'Ninja', '-DCMAKE_BUILD_TYPE=RelWithDebInfo',
61
+ '-DCMAKE_POLICY_VERSION_MINIMUM=3.5',
62
+ @@ -198,7 +202,7 @@ def main():
63
+ 'LSMinimumSystemVersion': args.minimum_macos, 'NSHighResolutionCapable': True}))
64
+ metadata = {'schema': 1, 'platform': 'darwin-arm64', 'minimum_macos': args.minimum_macos,
65
+ 'client_python_protocol': 1, 'json_ui_reload_protocol': 1, 'input_monotonic_clock_protocol': 1,
66
+ - 'screenshot_protocol': 1,
67
+ + 'screenshot_protocol': 1, 'background_window_protocol': 1,
68
+ 'launch_protocol': 1, 'addon_link_protocol': 1, 'cppconfig_protocol': 1, 'network_connect_protocol': 1,
69
+ 'game_compatibility': {'elf_rules_schema': 1, 'package_name': 'com.netease.mctest', 'abi': 'arm64-v8a',
70
+ 'rules_sha256': digest(ROOT/'tools/developer_binary_rules.json')}, 'game_profile': json.loads(args.profile.read_text()),
71
+ diff --git a/tools/run_netease_dev.py b/tools/run_netease_dev.py
72
+ index 85c9d2a..46beff2 100644
73
+ --- a/tools/run_netease_dev.py
74
+ +++ b/tools/run_netease_dev.py
75
+ @@ -219,9 +219,9 @@ def prepare(args):
76
+ return game, data, cache, client, angle, commands
77
+
78
+
79
+ -def launch_command(game, data, cache, client, angle, commands, session=None, debug_loopback=False, angle_backend=None, server_target=None):
80
+ +def launch_command(game, data, cache, client, angle, commands, session=None, debug_loopback=False, angle_backend=None, server_target=None, background=False):
81
+ policy = network_policy(*server_target) if server_target else (DEBUG_POLICY if debug_loopback else POLICY)
82
+ - command = ([] if session else ['/usr/bin/sandbox-exec', '-p', policy]) + ['/usr/bin/env', 'DYLD_LIBRARY_PATH='+str(angle)]
83
+ + command = ([] if session else ['/usr/bin/sandbox-exec', '-p', policy]) + ['/usr/bin/env', 'MCPY_GAME_BACKGROUND=' + ('1' if background else '0'), 'DYLD_LIBRARY_PATH='+str(angle)]
84
+ if angle_backend:
85
+ command += ['ANGLE_DEFAULT_PLATFORM='+angle_backend]
86
+ command += [str(client), '--netease-dev', '--force-opengles', '--game-dir', str(game),
87
+ @@ -259,6 +259,7 @@ def main():
88
+ parser.add_argument('--prepare-only', action='store_true')
89
+ parser.add_argument('--run-seconds', type=int, help='Bounded smoke run; stops after this time, not a save/quit test')
90
+ parser.add_argument('--log', type=Path)
91
+ + parser.add_argument('--background', action='store_true', help='Show the game without activating it or grabbing the cursor')
92
+ parser.add_argument('--exec-client', action='store_true', help=argparse.SUPPRESS)
93
+ args = parser.parse_args()
94
+ args.client = args.client or args.runtime/'Contents/MacOS/mcpelauncher-client'
95
+ @@ -297,7 +298,7 @@ def main():
96
+ parser.error(str(error))
97
+ log = args.log.resolve()
98
+ log.parent.mkdir(parents=True, exist_ok=True)
99
+ - command = launch_command(game, data, cache, client, angle, commands, args.session_file.resolve() if args.online else None, args.debug_loopback, args.angle_backend, getattr(args, 'server_target', None))
100
+ + command = launch_command(game, data, cache, client, angle, commands, args.session_file.resolve() if args.online else None, args.debug_loopback, args.angle_backend, getattr(args, 'server_target', None), background=args.background)
101
+ command += ['--netease-compat', str(args.compat_report)]
102
+ (log.parent/'commands.json').write_text(json.dumps(commands, ensure_ascii=False, indent=2)+'\n')
103
+ if args.make_app:
104
+ @@ -328,7 +329,7 @@ def main():
105
+ script = mac/'Launch'
106
+ wrapper = [sys.executable, str(Path(__file__).resolve()), '--game-dir', str(game), '--data-dir', str(data),
107
+ '--cache-dir', str(cache), '--client', str(mac/'mcpelauncher-client'), '--angle-dir', str(app/'Contents/Frameworks'),
108
+ - '--world-id', args.world_id, '--world-name', args.world_name, '--log', str(log), '--exec-client']
109
+ + '--world-id', args.world_id, '--world-name', args.world_name, '--log', str(log), '--exec-client'] + (['--background'] if args.background else [])
110
+ if args.cppconfig:
111
+ wrapper += ['--cppconfig', str(args.cppconfig.resolve())]
112
+ if args.compat_report: