agentenv-framework-protocol 0.1.469__tar.gz → 0.1.471__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 (161) hide show
  1. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/PKG-INFO +4 -1
  2. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/README.md +5 -2
  3. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/pyproject.toml +6 -1
  4. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/__init__.py +4 -1
  5. agentenv_framework_protocol-0.1.471/src/agentenv_protocol/computer/_x11.py +395 -0
  6. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/.gitignore +0 -0
  7. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/LICENSE +0 -0
  8. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/NOTICE +0 -0
  9. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/README.md +0 -0
  10. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/THIRD_PARTY_NOTICES.md +0 -0
  11. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/__init__.py +0 -0
  12. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/advanced_agent.py +0 -0
  13. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/basic_agent.py +0 -0
  14. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/custom_extensions_agent.py +0 -0
  15. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/multimodal_agent.py +0 -0
  16. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/reference_model.py +0 -0
  17. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/streaming_agent.py +0 -0
  18. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/.gitignore +0 -0
  19. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/Dockerfile +0 -0
  20. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/Dockerfile.dockerignore +0 -0
  21. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/data/seed.json +0 -0
  22. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/env.toml +0 -0
  23. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/site.py +0 -0
  24. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/index.html +0 -0
  25. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/package-lock.json +0 -0
  26. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/package.json +0 -0
  27. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/src/main.js +0 -0
  28. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/src/style.css +0 -0
  29. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/examples/website/notes/web/vite.config.js +0 -0
  30. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/__init__.py +0 -0
  31. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
  32. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
  33. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
  34. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
  35. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
  36. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
  37. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
  38. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
  39. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
  40. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
  41. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
  42. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/agent_env_environment.py +0 -0
  43. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/browser_cdp.py +0 -0
  44. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/client.py +0 -0
  45. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/_declare.py +0 -0
  46. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/_linux.py +0 -0
  47. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/_load.py +0 -0
  48. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/_macos.py +0 -0
  49. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/_with_fds.py +0 -0
  50. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/app.py +0 -0
  51. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/app_data.py +0 -0
  52. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/app_runtime.py +0 -0
  53. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/apps.py +0 -0
  54. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/card.py +0 -0
  55. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/checks.py +0 -0
  56. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
  57. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
  58. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
  59. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/client.py +0 -0
  60. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
  61. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
  62. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/page_fixture.py +0 -0
  63. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/conformance/report.py +0 -0
  64. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/dataplane.py +0 -0
  65. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/driver.py +0 -0
  66. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/errors.py +0 -0
  67. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/extensions.py +0 -0
  68. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/frames.py +0 -0
  69. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/keys.py +0 -0
  70. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/launch.py +0 -0
  71. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/manifest.py +0 -0
  72. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/operations.py +0 -0
  73. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/platform.py +0 -0
  74. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/queue.py +0 -0
  75. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/recording.py +0 -0
  76. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/results.py +0 -0
  77. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/run_install_step.py +0 -0
  78. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/runtime.py +0 -0
  79. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/seed.py +0 -0
  80. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/serve.py +0 -0
  81. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/serve_app.py +0 -0
  82. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/session.py +0 -0
  83. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/settings.py +0 -0
  84. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/skill.py +0 -0
  85. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/spaces.py +0 -0
  86. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/svc.py +0 -0
  87. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/computer/tools.py +0 -0
  88. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/errors.py +0 -0
  89. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/manifest.py +0 -0
  90. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/preflight.py +0 -0
  91. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/tool_access.py +0 -0
  92. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/tool_client.py +0 -0
  93. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/tool_context.py +0 -0
  94. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/transfers.py +0 -0
  95. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/types.py +0 -0
  96. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/__init__.py +0 -0
  97. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/clock.py +0 -0
  98. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/conformance.py +0 -0
  99. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/environment.py +0 -0
  100. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/errors.py +0 -0
  101. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/readiness.py +0 -0
  102. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/routes.py +0 -0
  103. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website/session.py +0 -0
  104. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website_browser/__init__.py +0 -0
  105. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website_browser/control.py +0 -0
  106. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website_browser/devtools.py +0 -0
  107. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website_browser/environment.py +0 -0
  108. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/src/agentenv_protocol/website_browser/shapes.py +0 -0
  109. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/computer_fake.py +0 -0
  110. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/probe_fake.py +0 -0
  111. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_agent.py +0 -0
  112. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_agent_examples.py +0 -0
  113. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_cdp_config.py +0 -0
  114. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_object_transfers.py +0 -0
  115. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_peer_agents.py +0 -0
  116. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_proxy.py +0 -0
  117. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_staging.py +0 -0
  118. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_a2a_trajectory_log.py +0 -0
  119. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_agent_env_environment.py +0 -0
  120. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_browser_cdp.py +0 -0
  121. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_browser_state.py +0 -0
  122. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_client.py +0 -0
  123. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_app_data.py +0 -0
  124. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_app_server.py +0 -0
  125. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_conformance.py +0 -0
  126. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_conformance_checks.py +0 -0
  127. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_conformance_page.py +0 -0
  128. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_conformance_recording.py +0 -0
  129. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_dataplane.py +0 -0
  130. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_declare.py +0 -0
  131. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_driver.py +0 -0
  132. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_extensions.py +0 -0
  133. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_frames.py +0 -0
  134. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_macos.py +0 -0
  135. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_page.py +0 -0
  136. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_queue.py +0 -0
  137. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_recording.py +0 -0
  138. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_seed.py +0 -0
  139. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_serve.py +0 -0
  140. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_spaces.py +0 -0
  141. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_computer_svc_forward.py +0 -0
  142. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_control_token.py +0 -0
  143. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_data_objects.py +0 -0
  144. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_errors.py +0 -0
  145. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_extension_methods.py +0 -0
  146. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_intake.py +0 -0
  147. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_manifest.py +0 -0
  148. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_preflight.py +0 -0
  149. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_access.py +0 -0
  150. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_annotations.py +0 -0
  151. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_client.py +0 -0
  152. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_context.py +0 -0
  153. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_context_fastmcp.py +0 -0
  154. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_tool_context_injection.py +0 -0
  155. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_api.py +0 -0
  156. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_browser.py +0 -0
  157. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_conformance.py +0 -0
  158. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_environment.py +0 -0
  159. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_mcp.py +0 -0
  160. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_notes_example.py +0 -0
  161. {agentenv_framework_protocol-0.1.469 → agentenv_framework_protocol-0.1.471}/tests/test_website_readiness.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentenv-framework-protocol
3
- Version: 0.1.469
3
+ Version: 0.1.471
4
4
  Summary: Open data-plane protocol and server SDK for agent environments.
5
5
  Project-URL: Homepage, https://www.agentenvframework.com
6
6
  Project-URL: Documentation, https://www.agentenvframework.com/docs
@@ -58,6 +58,9 @@ Requires-Dist: websockets>=13; extra == 'dev'
58
58
  Provides-Extra: macos
59
59
  Requires-Dist: pyobjc-framework-quartz>=11; (sys_platform == 'darwin') and extra == 'macos'
60
60
  Requires-Dist: pyobjc-framework-screencapturekit>=11; (sys_platform == 'darwin') and extra == 'macos'
61
+ Provides-Extra: x11
62
+ Requires-Dist: mss<11,>=9; extra == 'x11'
63
+ Requires-Dist: python-xlib<0.34,>=0.33; extra == 'x11'
61
64
  Description-Content-Type: text/markdown
62
65
 
63
66
  # agentenv-framework-protocol
@@ -80,8 +80,11 @@ the container before using it.
80
80
  ## Register it
81
81
 
82
82
  In a bundle, `env.toml` declares the env: copied to a bundle's `envs/notes/`, `agent-env bundle register <bundle>`
83
- builds the image with that folder as its context. Its keys are `type`, `environment_name` and `backend_image`; domains
84
- are not one of them, as they come from the card. Without a bundle:
83
+ builds the image with that folder as its context. Its keys are `type`, `environment_name` and `backend_image`, and it
84
+ may name `domains`, the names the site is reached by, such as `domains = ["notes.example"]`. These win over the
85
+ card's; without them a computer reaches the site by the names its card declares (`notes.test`), or as
86
+ `notes.localhost` when it declares none. Two sites of one multi env can't claim one name. Without a bundle (`--domain`
87
+ names the site, and can be repeated):
85
88
 
86
89
  ```bash
87
90
  agent-env env website put --id notes-site --server-dockerfile Dockerfile --server-docker-context .
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentenv-framework-protocol"
3
- version = "0.1.469"
3
+ version = "0.1.471"
4
4
  description = "Open data-plane protocol and server SDK for agent environments."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -56,6 +56,11 @@ macos = [
56
56
  "pyobjc-framework-Quartz>=11; sys_platform == 'darwin'",
57
57
  "pyobjc-framework-ScreenCaptureKit>=11; sys_platform == 'darwin'",
58
58
  ]
59
+ # A Linux driver on X11Driver: mss captures the X display and XTEST sends its input, through python-xlib.
60
+ x11 = [
61
+ "mss>=9,<11",
62
+ "python-xlib>=0.33,<0.34",
63
+ ]
59
64
  dev = [
60
65
  "a2a-sdk[http-server]>=0.3.26,<0.4",
61
66
  "python-multipart>=0.0.13",
@@ -98,16 +98,18 @@ if TYPE_CHECKING:
98
98
  )
99
99
  from .driver import DEFAULT_IDENTITY, ComputerDriverEnvironment, DriverDeclaration, computer_driver
100
100
  from ._macos import MacOSDriver
101
+ from ._x11 import X11Driver
101
102
  from .recording import RecordedFrame, RecordedSegment, RecordHints, Recording, frames_in_thread
102
103
 
103
104
  # The names whose modules need the computer extra (mcp, av and Pillow), by module; MacOSDriver's, the macos extra too,
104
- # on first use of the Mac.
105
+ # on first use of the Mac, and X11Driver's, the x11 extra.
105
106
  _ON_USE = {
106
107
  "driver": ("ComputerDriverEnvironment", "computer_driver", "DEFAULT_IDENTITY", "DriverDeclaration"),
107
108
  "card": ("COMPUTER", "COMPUTER_READY", "COMPUTER_DISPLAY", "COMPUTER_SPACES", "COMPUTER_POINTER",
108
109
  "COMPUTER_KEYBOARD", "COMPUTER_PAGE", "COMPUTER_EXEC", "COMPUTER_RECORDING"),
109
110
  "recording": ("Recording", "RecordHints", "RecordedFrame", "RecordedSegment", "frames_in_thread"),
110
111
  "_macos": ("MacOSDriver",),
112
+ "_x11": ("X11Driver",),
111
113
  }
112
114
 
113
115
 
@@ -120,6 +122,7 @@ def __getattr__(name: str) -> Any:
120
122
 
121
123
  __all__ = [
122
124
  "ComputerDriverEnvironment", "computer_driver", "DEFAULT_IDENTITY", "DriverDeclaration", "MacOSDriver",
125
+ "X11Driver",
123
126
  "ComputerAppEnvironment", "computer_app", "install", "linux", "install_step", "ready_check", "Linux", "Service",
124
127
  "Launch", "Ready", "Packages", "AptSource", "Download", "RunScript",
125
128
  "AppDeclaration", "AppOs",
@@ -0,0 +1,395 @@
1
+ """computer/v1 on an X11 desktop on Linux, for the reference driver and for a driver whose software serves tools of its
2
+ own, as agent-desktop's does: mss captures the screen and XTEST, through python-xlib, sends the input. X calls run off
3
+ the event loop, one at a time, on a connection checked before each call and reopened when it drops, so the driver
4
+ outlives a restarted X server, and input that lets go of a button returns once the server has let go of it. It records
5
+ the display through FFmpeg's ``x11grab``, by PyAV. A driver subclasses ``X11Driver``, declares itself with
6
+ ``computer_driver``, and serves its own tools beside these. Needs the ``x11`` extra: mss and python-xlib."""
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import contextlib
11
+ import math
12
+ import os
13
+ import threading
14
+ import time
15
+ from collections import OrderedDict
16
+ from datetime import datetime, timezone
17
+ from typing import Any, AsyncIterator, Callable, Iterator
18
+
19
+ import av
20
+ import mss
21
+ from Xlib import X, XK
22
+ from Xlib import display as xdisplay
23
+ from Xlib.error import ConnectionClosedError, DisplayConnectionError
24
+ from Xlib.ext import xtest
25
+
26
+ from .driver import ComputerDriverEnvironment
27
+ from .errors import DeliveryFailed, DeviceUnavailable, Unsupported
28
+ from .operations import (Display, Image, ReadyCheck, capture, click, display, drag, key_down, key_up, pointer_down,
29
+ pointer_move, pointer_position, pointer_up, press, record, scroll, type_text)
30
+ from .platform import Platform
31
+ from .recording import RecordedFrame, RecordHints, Recording, frames_in_thread
32
+ from .settings import ComputerSettings
33
+
34
+ BUTTONS = {"left": 1, "middle": 2, "right": 3, "back": 8, "forward": 9}
35
+ #: The pointer state's bit for each button that has one.
36
+ BUTTON_MASKS = {"left": X.Button1Mask, "middle": X.Button2Mask, "right": X.Button3Mask}
37
+ SCROLL = {"up": 4, "down": 5, "left": 6, "right": 7}
38
+ #: W3C key values and their X keysym names; any other single character is typed as its own keysym.
39
+ KEYSYMS = {
40
+ "Enter": "Return", "Tab": "Tab", "Escape": "Escape", "Backspace": "BackSpace", "Delete": "Delete",
41
+ "ArrowUp": "Up", "ArrowDown": "Down", "ArrowLeft": "Left", "ArrowRight": "Right", "Home": "Home", "End": "End",
42
+ "PageUp": "Prior", "PageDown": "Next", "Insert": "Insert", "Control": "Control_L", "Shift": "Shift_L",
43
+ "Alt": "Alt_L", "Meta": "Super_L", "Super": "Super_L", "CapsLock": "Caps_Lock", "ContextMenu": "Menu",
44
+ "PrintScreen": "Print", "Pause": "Pause", " ": "space", **{f"F{n}": f"F{n}" for n in range(1, 25)},
45
+ }
46
+ TYPED = {"\n": "Return", "\t": "Tab"}
47
+ #: The pause between the presses of a double or triple click, in seconds.
48
+ CLICK_GAP_S = 0.04
49
+ #: How long a button's release may take to reach the app, and how often the driver looks.
50
+ RELEASE_WAIT_S = 5.0
51
+ RELEASE_POLL_S = 0.005
52
+ #: How far apart a drag's pointer moves are, in pixels.
53
+ DRAG_STEP_PX = 20
54
+ DROPPED = (ConnectionClosedError, DisplayConnectionError, OSError)
55
+
56
+
57
+ class X11Driver(ComputerDriverEnvironment):
58
+ """The computer/v1 operations, the pointer and keyboard groups among them, on an X11 desktop."""
59
+
60
+ buttons = ("left", "right", "middle", "back", "forward")
61
+ max_click_count = 3
62
+ max_drag_points = 50
63
+ recording = Recording(max_fps=30)
64
+
65
+ def __init__(self, settings: ComputerSettings | None = None, platform: Platform | None = None) -> None:
66
+ super().__init__(settings, platform)
67
+ self._x: _Connection | None = None
68
+ self._x_lock = threading.Lock()
69
+ #: The keycodes each key held by @key_down pressed, which @key_up releases.
70
+ self._held: dict[str, list[int]] = {}
71
+
72
+ @display
73
+ async def screen(self) -> Display:
74
+ def read(c):
75
+ s = c.d.screen()
76
+ return Display(s.width_in_pixels, s.height_in_pixels, 1.0)
77
+ return await self._read(read)
78
+
79
+ @capture
80
+ async def grab(self) -> Image:
81
+ return await asyncio.to_thread(_grab)
82
+
83
+ @record
84
+ async def stream(self, hints: RecordHints) -> AsyncIterator[RecordedFrame]:
85
+ """The display through FFmpeg's ``x11grab``. Its frames carry the wall clock, so each one's time is when it
86
+ was captured."""
87
+ size = await self.screen()
88
+ options = {"framerate": str(hints.fps), "video_size": f"{size.width}x{size.height}",
89
+ "draw_mouse": "1" if hints.cursor else "0"}
90
+
91
+ def frames() -> Iterator[RecordedFrame]:
92
+ with av.open(os.environ.get("DISPLAY", ":0"), format="x11grab", options=options) as source:
93
+ for frame in source.decode(video=0):
94
+ yield RecordedFrame(frame, datetime.fromtimestamp(frame.time, timezone.utc))
95
+
96
+ async for frame in frames_in_thread(frames):
97
+ yield frame
98
+
99
+ async def ready_checks(self) -> list[ReadyCheck]:
100
+ try:
101
+ has = await self._read(lambda c: c.d.has_extension("XTEST"))
102
+ except DeviceUnavailable as e:
103
+ return [ReadyCheck("xtest", False, e.message)]
104
+ return [ReadyCheck("xtest", bool(has), "XTEST available" if has else "XTEST missing")]
105
+
106
+ @click
107
+ async def click_at(self, x, y, button, count, modifiers) -> None:
108
+ syms = [_keysym(k) for k in modifiers]
109
+
110
+ def act(c):
111
+ held = c.hold(syms)
112
+ c.move(x, y)
113
+ for i in range(count):
114
+ c.button(button, True)
115
+ c.button(button, False)
116
+ if i + 1 < count:
117
+ c.d.sync()
118
+ time.sleep(CLICK_GAP_S)
119
+ c.released(button)
120
+ c.release(reversed(held))
121
+ await self._send(act)
122
+
123
+ @drag
124
+ async def drag_along(self, path, button, duration_ms, modifiers) -> None:
125
+ syms = [_keysym(k) for k in modifiers]
126
+ steps = _steps(path)
127
+ pause = duration_ms / 1000 / len(steps)
128
+ held: list[int] = []
129
+
130
+ def start(c):
131
+ held.extend(c.hold(syms))
132
+ c.move(*path[0])
133
+ c.button(button, True)
134
+
135
+ def finish(c):
136
+ c.button(button, False)
137
+ c.released(button)
138
+ c.release(reversed(held))
139
+
140
+ try:
141
+ await self._send(start)
142
+ for px, py in steps:
143
+ await self._send(lambda c, px=px, py=py: c.move(px, py))
144
+ await asyncio.sleep(pause)
145
+ except BaseException:
146
+ with contextlib.suppress(Exception):
147
+ await self._send(finish)
148
+ raise
149
+ await self._send(finish)
150
+
151
+ @scroll
152
+ async def scroll_at(self, x, y, direction, amount, modifiers) -> None:
153
+ syms = [_keysym(k) for k in modifiers]
154
+
155
+ def act(c):
156
+ held = c.hold(syms)
157
+ c.move(x, y)
158
+ for _ in range(amount):
159
+ xtest.fake_input(c.d, X.ButtonPress, SCROLL[direction])
160
+ xtest.fake_input(c.d, X.ButtonRelease, SCROLL[direction])
161
+ c.release(reversed(held))
162
+ await self._send(act)
163
+
164
+ @pointer_move
165
+ async def move(self, x, y) -> None:
166
+ await self._send(lambda c: c.move(x, y))
167
+
168
+ @pointer_down
169
+ async def down(self, button) -> None:
170
+ await self._send(lambda c: c.button(button, True))
171
+
172
+ @pointer_up
173
+ async def up(self, button) -> None:
174
+ def act(c):
175
+ c.button(button, False)
176
+ c.released(button)
177
+ await self._send(act)
178
+
179
+ @pointer_position
180
+ async def where(self) -> tuple[int, int]:
181
+ def read(c):
182
+ p = c.d.screen().root.query_pointer()
183
+ return p.root_x, p.root_y
184
+ return await self._read(read)
185
+
186
+ @type_text
187
+ async def type_in(self, text) -> None:
188
+ syms = [XK.string_to_keysym(TYPED[ch]) if ch in TYPED else _keysym(ch) for ch in text]
189
+ await self._read(lambda c: c.check(syms))
190
+ for sym in syms:
191
+ hold = self.settings.tap_hold_ms / 1000
192
+ await self._send(lambda c, sym=sym: c.tap(sym, hold))
193
+ await asyncio.sleep(self.settings.type_delay_ms / 1000)
194
+
195
+ @press
196
+ async def press_keys(self, keys) -> None:
197
+ syms = [_keysym(k) for k in keys]
198
+ hold = self.settings.tap_hold_ms / 1000
199
+
200
+ def act(c):
201
+ pressed = c.hold(syms)
202
+ c.d.sync()
203
+ time.sleep(hold)
204
+ c.release(reversed(pressed))
205
+ await self._send(act)
206
+
207
+ @key_down
208
+ async def keys_down(self, keys) -> None:
209
+ syms = [_keysym(k) for k in keys]
210
+
211
+ def act(c):
212
+ for key, pressed in zip(keys, c.hold_each(syms)):
213
+ self._held.setdefault(key, []).extend(pressed)
214
+ await self._send(act)
215
+
216
+ @key_up
217
+ async def keys_up(self, keys) -> None:
218
+ def act(c):
219
+ for key in keys:
220
+ c.release(reversed(self._held.pop(key, None) or c.codes(_keysym(key))[-1:]))
221
+ await self._send(act)
222
+
223
+ async def _read(self, fn: Callable[[_Connection], Any]) -> Any:
224
+ return await asyncio.to_thread(self._x_call, fn, False)
225
+
226
+ async def _send(self, fn: Callable[[_Connection], Any]) -> Any:
227
+ return await asyncio.to_thread(self._x_call, fn, True)
228
+
229
+ def _x_call(self, fn: Callable[[_Connection], Any], sends_input: bool) -> Any:
230
+ """``fn`` on a live connection. When the connection drops, a read is retried once on a new one; input is not
231
+ sent again, since some of it may have arrived."""
232
+ with self._x_lock:
233
+ for attempt in (1, 2):
234
+ c = self._connected()
235
+ try:
236
+ result = fn(c)
237
+ c.d.sync()
238
+ return result
239
+ except DROPPED as e:
240
+ self._x = None
241
+ if sends_input:
242
+ raise DeliveryFailed(f"the X connection dropped while sending input: {type(e).__name__}") from None
243
+ if attempt == 2:
244
+ raise DeviceUnavailable(f"the X server is unavailable: {type(e).__name__}") from None
245
+
246
+ def _connected(self) -> _Connection:
247
+ """The connection, opened or reopened as needed and checked with a round trip before anything is sent."""
248
+ for attempt in (1, 2):
249
+ try:
250
+ if self._x is None:
251
+ self._x = _Connection()
252
+ self._held.clear()
253
+ self._x.d.sync()
254
+ return self._x
255
+ except DROPPED as e:
256
+ self._x = None
257
+ if attempt == 2:
258
+ raise DeviceUnavailable(f"the X server is unavailable: {type(e).__name__}") from None
259
+
260
+
261
+ class _Connection:
262
+ """One connection to the X server, with XTEST input on it. A character the keymap lacks is typed through a spare
263
+ keycode mapped to it, kept for that character and reused; once all are taken, the least recently used one that
264
+ no key holds down is mapped again."""
265
+
266
+ def __init__(self) -> None:
267
+ self.d = xdisplay.Display()
268
+ first = self.d.display.info.min_keycode
269
+ mapping = self.d.get_keyboard_mapping(first, self.d.display.info.max_keycode - first + 1)
270
+ self.width = len(mapping[0])
271
+ self.spare = [first + i for i, syms in enumerate(mapping) if not any(syms)]
272
+ self.mapped: OrderedDict[int, int] = OrderedDict()
273
+ self.shift = self.d.keysym_to_keycode(XK.string_to_keysym("Shift_L"))
274
+
275
+ def move(self, x, y) -> None:
276
+ xtest.fake_input(self.d, X.MotionNotify, x=int(x), y=int(y))
277
+
278
+ def button(self, button: str, down: bool) -> None:
279
+ xtest.fake_input(self.d, X.ButtonPress if down else X.ButtonRelease, BUTTONS[button])
280
+
281
+ def released(self, button: str) -> None:
282
+ """Wait, up to RELEASE_WAIT_S, until the server has let go of ``button``. A window manager's passive grab holds
283
+ a click on a window until it replays it to the app, while keys reach the app at once, so a key sent before then
284
+ overtakes the click, and so do the next click's moves."""
285
+ deadline = time.monotonic() + RELEASE_WAIT_S
286
+ while self.d.screen().root.query_pointer().mask & BUTTON_MASKS.get(button, 0) and time.monotonic() < deadline:
287
+ time.sleep(RELEASE_POLL_S)
288
+
289
+ def hold(self, keysyms: list[int]) -> list[int]:
290
+ """``hold_each``'s keycodes, in the order they were pressed."""
291
+ return [code for pressed in self.hold_each(keysyms) for code in pressed]
292
+
293
+ def hold_each(self, keysyms: list[int]) -> list[list[int]]:
294
+ """Press what the keysyms need that isn't down already, Shift first where a character needs it; for each
295
+ keysym, the keycodes this pressed, so the caller releases only those. Every keycode is found before the first
296
+ press, so keysyms that can't all be held at once are refused with nothing sent."""
297
+ down = self._down()
298
+ planned: list[list[int]] = []
299
+ for keysym in keysyms:
300
+ planned.append(self.codes(keysym, busy=down | {code for codes in planned for code in codes}))
301
+ pressed = []
302
+ for codes in planned:
303
+ pressed.append([code for code in codes if code not in down])
304
+ for code in pressed[-1]:
305
+ xtest.fake_input(self.d, X.KeyPress, code)
306
+ down.add(code)
307
+ return pressed
308
+
309
+ def release(self, codes) -> None:
310
+ for code in codes:
311
+ xtest.fake_input(self.d, X.KeyRelease, code)
312
+
313
+ def tap(self, keysym: int, hold_s: float) -> None:
314
+ """Type one character: its key pressed and released, with Shift around it when it needs Shift and nothing
315
+ holds Shift already."""
316
+ down = self._down()
317
+ *modifiers, code = self.codes(keysym, busy=down)
318
+ pressed = [m for m in modifiers if m not in down]
319
+ for m in pressed:
320
+ xtest.fake_input(self.d, X.KeyPress, m)
321
+ xtest.fake_input(self.d, X.KeyPress, code)
322
+ self.d.sync()
323
+ time.sleep(hold_s)
324
+ xtest.fake_input(self.d, X.KeyRelease, code)
325
+ self.release(reversed(pressed))
326
+
327
+ def codes(self, keysym: int, busy: set[int] = frozenset()) -> list[int]:
328
+ """The keycodes that make ``keysym``: Shift and the key when it is the key's second level, else one key; a
329
+ keysym off the keymap is mapped to a spare keycode not in ``busy``."""
330
+ codes = self._on_keymap(keysym)
331
+ if codes is not None:
332
+ return codes
333
+ code = self._free(busy)
334
+ self.d.change_keyboard_mapping(code, [(keysym,) * self.width])
335
+ self.d.sync()
336
+ self.mapped[keysym] = code
337
+ return [code]
338
+
339
+ def check(self, keysyms: list[int]) -> None:
340
+ """Refuse, before anything is sent, text with a character off the keymap when no spare keycode is free."""
341
+ if any(self._on_keymap(k) is None for k in keysyms):
342
+ self._free(self._down(), take=False)
343
+
344
+ def _free(self, busy: set[int], take: bool = True) -> int:
345
+ """A spare keycode not in ``busy``, the least recently used mapped one when none is unmapped."""
346
+ if self.spare:
347
+ return self.spare.pop() if take else self.spare[-1]
348
+ for keysym, code in self.mapped.items():
349
+ if code not in busy:
350
+ if take:
351
+ del self.mapped[keysym]
352
+ return code
353
+ raise Unsupported("no spare keycode is free for a character off the X keymap: the server has none, or keys "
354
+ "hold them all down")
355
+
356
+ def _on_keymap(self, keysym: int) -> list[int] | None:
357
+ if keysym in self.mapped:
358
+ self.mapped.move_to_end(keysym)
359
+ return [self.mapped[keysym]]
360
+ code = self.d.keysym_to_keycode(keysym)
361
+ if code and self.d.keycode_to_keysym(code, 0) == keysym:
362
+ return [code]
363
+ if code and self.d.keycode_to_keysym(code, 1) == keysym:
364
+ return [self.shift, code]
365
+ return None
366
+
367
+ def _down(self) -> set[int]:
368
+ return {8 * i + bit for i, byte in enumerate(self.d.query_keymap()) for bit in range(8) if byte >> bit & 1}
369
+
370
+
371
+ def _grab() -> Image:
372
+ try:
373
+ with mss.MSS() as m:
374
+ shot = m.grab(m.monitors[0])
375
+ return Image(shot.width, shot.height, bytes(shot.bgra), "BGRA")
376
+ except Exception as e:
377
+ raise DeviceUnavailable(f"capture failed: {type(e).__name__}: {e}") from None
378
+
379
+
380
+ def _steps(path: list) -> list[tuple[float, float]]:
381
+ """The points a drag moves through after its start, about every DRAG_STEP_PX pixels."""
382
+ steps = []
383
+ for (x0, y0), (x1, y1) in zip(path, path[1:]):
384
+ n = max(2, int(math.hypot(x1 - x0, y1 - y0) / DRAG_STEP_PX))
385
+ steps += [(x0 + (x1 - x0) * k / n, y0 + (y1 - y0) * k / n) for k in range(1, n + 1)]
386
+ return steps
387
+
388
+
389
+ def _keysym(key: str) -> int:
390
+ if key in KEYSYMS:
391
+ return XK.string_to_keysym(KEYSYMS[key])
392
+ if len(key) == 1:
393
+ code = ord(key)
394
+ return code if code < 0x100 else 0x01000000 | code
395
+ raise Unsupported(f"this driver has no X keysym for {key!r}")