agentenv-framework-protocol 0.1.491__tar.gz → 0.1.494__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 (174) hide show
  1. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/PKG-INFO +8 -3
  2. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/README.md +7 -2
  3. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/pyproject.toml +1 -1
  4. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/app.py +34 -22
  5. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/platform.py +29 -0
  6. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/run_install_step.py +2 -3
  7. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_declare.py +103 -3
  8. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/.gitignore +0 -0
  9. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/LICENSE +0 -0
  10. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/NOTICE +0 -0
  11. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/THIRD_PARTY_NOTICES.md +0 -0
  12. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/__init__.py +0 -0
  13. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/advanced_agent.py +0 -0
  14. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/basic_agent.py +0 -0
  15. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/custom_extensions_agent.py +0 -0
  16. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/multimodal_agent.py +0 -0
  17. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/reference_model.py +0 -0
  18. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/streaming_agent.py +0 -0
  19. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/.gitignore +0 -0
  20. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/Dockerfile +0 -0
  21. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/Dockerfile.dockerignore +0 -0
  22. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/README.md +0 -0
  23. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/data/seed.json +0 -0
  24. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/env.toml +0 -0
  25. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/site.py +0 -0
  26. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/index.html +0 -0
  27. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/package-lock.json +0 -0
  28. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/package.json +0 -0
  29. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/src/main.js +0 -0
  30. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/src/style.css +0 -0
  31. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/examples/website/notes/web/vite.config.js +0 -0
  32. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/__init__.py +0 -0
  33. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
  34. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
  35. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
  36. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
  37. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
  38. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
  39. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
  40. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
  41. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
  42. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
  43. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
  44. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/agent_env_environment.py +0 -0
  45. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/browser_cdp.py +0 -0
  46. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/client.py +0 -0
  47. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/__init__.py +0 -0
  48. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_declare.py +0 -0
  49. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_job.py +0 -0
  50. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_linux.py +0 -0
  51. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_load.py +0 -0
  52. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_macos.py +0 -0
  53. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_reaping.py +0 -0
  54. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_session_posix.py +0 -0
  55. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_session_windows.py +0 -0
  56. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_with_fds.py +0 -0
  57. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/_x11.py +0 -0
  58. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/app_data.py +0 -0
  59. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/app_runtime.py +0 -0
  60. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/apps.py +0 -0
  61. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/card.py +0 -0
  62. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/checks.py +0 -0
  63. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
  64. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
  65. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
  66. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/client.py +0 -0
  67. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/desk.py +0 -0
  68. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
  69. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
  70. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/page_fixture.py +0 -0
  71. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/report.py +0 -0
  72. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/conformance/wayland_fixture.py +0 -0
  73. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/dataplane.py +0 -0
  74. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/driver.py +0 -0
  75. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/errors.py +0 -0
  76. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/extensions.py +0 -0
  77. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/frames.py +0 -0
  78. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/keys.py +0 -0
  79. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/launch.py +0 -0
  80. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/manifest.py +0 -0
  81. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/operations.py +0 -0
  82. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/prefix.py +0 -0
  83. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/queue.py +0 -0
  84. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/recording.py +0 -0
  85. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/results.py +0 -0
  86. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/runtime.py +0 -0
  87. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/seed.py +0 -0
  88. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/serve.py +0 -0
  89. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/serve_app.py +0 -0
  90. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/served.py +0 -0
  91. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/session.py +0 -0
  92. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/settings.py +0 -0
  93. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/skill.py +0 -0
  94. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/spaces.py +0 -0
  95. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/svc.py +0 -0
  96. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/computer/tools.py +0 -0
  97. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/errors.py +0 -0
  98. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/manifest.py +0 -0
  99. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/preflight.py +0 -0
  100. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/tool_access.py +0 -0
  101. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/tool_client.py +0 -0
  102. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/tool_context.py +0 -0
  103. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/transfers.py +0 -0
  104. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/types.py +0 -0
  105. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/__init__.py +0 -0
  106. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/clock.py +0 -0
  107. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/conformance.py +0 -0
  108. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/environment.py +0 -0
  109. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/errors.py +0 -0
  110. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/readiness.py +0 -0
  111. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/routes.py +0 -0
  112. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website/session.py +0 -0
  113. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/__init__.py +0 -0
  114. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/control.py +0 -0
  115. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/data.py +0 -0
  116. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/devtools.py +0 -0
  117. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/environment.py +0 -0
  118. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/src/agentenv_protocol/website_browser/shapes.py +0 -0
  119. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/computer_fake.py +0 -0
  120. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/probe_fake.py +0 -0
  121. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_agent.py +0 -0
  122. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_agent_examples.py +0 -0
  123. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_cdp_config.py +0 -0
  124. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_object_transfers.py +0 -0
  125. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_peer_agents.py +0 -0
  126. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_proxy.py +0 -0
  127. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_staging.py +0 -0
  128. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_a2a_trajectory_log.py +0 -0
  129. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_agent_env_environment.py +0 -0
  130. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_browser_cdp.py +0 -0
  131. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_browser_data.py +0 -0
  132. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_browser_state.py +0 -0
  133. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_client.py +0 -0
  134. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_app_data.py +0 -0
  135. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_app_server.py +0 -0
  136. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_conformance.py +0 -0
  137. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_conformance_checks.py +0 -0
  138. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_conformance_page.py +0 -0
  139. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_conformance_recording.py +0 -0
  140. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_dataplane.py +0 -0
  141. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_driver.py +0 -0
  142. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_extensions.py +0 -0
  143. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_frames.py +0 -0
  144. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_macos.py +0 -0
  145. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_page.py +0 -0
  146. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_queue.py +0 -0
  147. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_recording.py +0 -0
  148. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_seed.py +0 -0
  149. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_serve.py +0 -0
  150. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_served.py +0 -0
  151. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_session_windows.py +0 -0
  152. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_spaces.py +0 -0
  153. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_svc_forward.py +0 -0
  154. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_computer_tool_prefix.py +0 -0
  155. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_control_token.py +0 -0
  156. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_data_objects.py +0 -0
  157. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_errors.py +0 -0
  158. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_extension_methods.py +0 -0
  159. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_intake.py +0 -0
  160. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_manifest.py +0 -0
  161. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_preflight.py +0 -0
  162. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_access.py +0 -0
  163. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_annotations.py +0 -0
  164. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_client.py +0 -0
  165. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_context.py +0 -0
  166. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_context_fastmcp.py +0 -0
  167. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_tool_context_injection.py +0 -0
  168. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_api.py +0 -0
  169. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_browser.py +0 -0
  170. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_conformance.py +0 -0
  171. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_environment.py +0 -0
  172. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_mcp.py +0 -0
  173. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/tests/test_website_notes_example.py +0 -0
  174. {agentenv_framework_protocol-0.1.491 → agentenv_framework_protocol-0.1.494}/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.491
3
+ Version: 0.1.494
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
@@ -854,8 +854,13 @@ class MailApp(ComputerAppEnvironment):
854
854
  models whose fields add to the class's `Settings` and `BuildSettings` on that OS. What's on the
855
855
  class applies to every OS. `@install(os_type, spec, launch=..., ...)` is the generic form, for an
856
856
  OS type a plugin adds, with that OS type's own install model as `spec`; `@linux(...)` is
857
- `@install("linux", Linux(...), ...)`. On the computer the class reads what's declared for the OS
858
- it runs on (`platform.detect()`).
857
+ `@install("linux", Linux(...), ...)`. `@linux(distribution="omarchy", ...)`, or
858
+ `@install("linux/omarchy", ...)`, declares for one distribution, by its /etc/os-release ID, what
859
+ replaces the OS type's declaration there. On the computer the class reads what's declared for the
860
+ platform its computer was composed for, which the composer sets as `AGENTENV_PLATFORM` for an app
861
+ that declares anything for a distribution, else the one it runs on (`platform.detect()`): its
862
+ distribution's, else its OS type's. An install step or ready check's `os=` names OS types or
863
+ distributions, and one for an OS type runs on all of it.
859
864
  - **`launch=Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
860
865
  the agent opens it (`"demand"`). `ready=Ready(...)` says when it's ready, within `timeout_s` of its
861
866
  launch: a window matching `launch.window` by its class, instance or title (on Hyprland, a Wayland
@@ -789,8 +789,13 @@ class MailApp(ComputerAppEnvironment):
789
789
  models whose fields add to the class's `Settings` and `BuildSettings` on that OS. What's on the
790
790
  class applies to every OS. `@install(os_type, spec, launch=..., ...)` is the generic form, for an
791
791
  OS type a plugin adds, with that OS type's own install model as `spec`; `@linux(...)` is
792
- `@install("linux", Linux(...), ...)`. On the computer the class reads what's declared for the OS
793
- it runs on (`platform.detect()`).
792
+ `@install("linux", Linux(...), ...)`. `@linux(distribution="omarchy", ...)`, or
793
+ `@install("linux/omarchy", ...)`, declares for one distribution, by its /etc/os-release ID, what
794
+ replaces the OS type's declaration there. On the computer the class reads what's declared for the
795
+ platform its computer was composed for, which the composer sets as `AGENTENV_PLATFORM` for an app
796
+ that declares anything for a distribution, else the one it runs on (`platform.detect()`): its
797
+ distribution's, else its OS type's. An install step or ready check's `os=` names OS types or
798
+ distributions, and one for an OS type runs on all of it.
794
799
  - **`launch=Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
795
800
  the agent opens it (`"demand"`). `ready=Ready(...)` says when it's ready, within `timeout_s` of its
796
801
  launch: a window matching `launch.window` by its class, instance or title (on Hyprland, a Wayland
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentenv-framework-protocol"
3
- version = "0.1.491"
3
+ version = "0.1.494"
4
4
  description = "Open data-plane protocol and server SDK for agent environments."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -29,7 +29,7 @@ from ..types import (METHOD_ADD, METHOD_GET, METHOD_RESET, SKILL_EXTENSION_URI,
29
29
  from .app_data import AppDataPlane
30
30
  from .app_runtime import AppRuntime
31
31
  from .errors import InvalidArgument
32
- from .platform import detect
32
+ from .platform import PLATFORM_ENV, applies, detect, entry_for, platform_key
33
33
 
34
34
  #: The environment variable a computer delivers its apps' settings in: JSON of each app's values by its name.
35
35
  APP_SETTINGS_ENV = "AGENTENV_APP_SETTINGS"
@@ -327,7 +327,9 @@ def install(os_type: str, spec: BaseModel, *, launch: Optional[Launch] = None, p
327
327
  the app's own there: its ``launch``; the ``paths`` it keeps its data in, relative to the session user's home, which
328
328
  serve its data plane when it has no data hooks; its ``skill``, a file of its folder, instead of the class's; and
329
329
  ``settings`` and ``build_settings``, models whose fields add to the class's ``Settings`` and ``BuildSettings`` there.
330
- ``@linux`` is this for Linux; an OS type a plugin adds is declared with it."""
330
+ ``os_type`` may name one of its distributions as ``<os>/<distribution>``, /etc/os-release's ID (``linux/omarchy``),
331
+ whose declaration replaces the OS type's there. ``@linux`` is this for Linux; an OS type a plugin adds is declared
332
+ with it."""
331
333
  try:
332
334
  owned = tuple(_PATHS.validate_python(list(paths or [])))
333
335
  except ValidationError:
@@ -344,16 +346,18 @@ def install(os_type: str, spec: BaseModel, *, launch: Optional[Launch] = None, p
344
346
  return deco
345
347
 
346
348
 
347
- def linux(*, files: str = ".", packages: Optional[Packages] = None, python: Optional[str] = None,
348
- sources: Optional[list[AptSource]] = None, downloads: Optional[list[Download]] = None,
349
- run: Optional[list[RunScript]] = None, services: Optional[list[Service]] = None,
350
- ports: Optional[list[int]] = None, launch: Optional[Launch] = None, paths: Optional[list[str]] = None,
351
- skill: Optional[str] = None, settings: Optional[type[BaseModel]] = None,
349
+ def linux(*, distribution: Optional[str] = None, files: str = ".", packages: Optional[Packages] = None,
350
+ python: Optional[str] = None, sources: Optional[list[AptSource]] = None,
351
+ downloads: Optional[list[Download]] = None, run: Optional[list[RunScript]] = None,
352
+ services: Optional[list[Service]] = None, ports: Optional[list[int]] = None, launch: Optional[Launch] = None,
353
+ paths: Optional[list[str]] = None, skill: Optional[str] = None, settings: Optional[type[BaseModel]] = None,
352
354
  build_settings: Optional[type[BaseModel]] = None) -> Callable:
353
- """``@install`` for Linux: how a Linux computer installs the app, ``Linux``'s fields, and what is its own there."""
354
- return install("linux", Linux(files=files, packages=packages, python=python, sources=sources, downloads=downloads,
355
- run=run, services=services or [], ports=ports),
356
- launch=launch, paths=paths, skill=skill, settings=settings, build_settings=build_settings)
355
+ """``@install`` for Linux, or with ``distribution`` for that distribution alone: how such a computer installs the
356
+ app, ``Linux``'s fields, and what is its own there."""
357
+ spec = Linux(files=files, packages=packages, python=python, sources=sources, downloads=downloads, run=run,
358
+ services=services or [], ports=ports)
359
+ return install(platform_key("linux", distribution), spec, launch=launch, paths=paths, skill=skill,
360
+ settings=settings, build_settings=build_settings)
357
361
 
358
362
 
359
363
  def windows(*, files: str = ".", python: Optional[str] = None, downloads: Optional[list[Download]] = None,
@@ -459,18 +463,18 @@ class ComputerAppEnvironment(AgentEnvEnvironment):
459
463
  app declares its own, which its install steps read too. None is a secret, since the image keeps them."""
460
464
 
461
465
  def __init__(self) -> None:
462
- cls, on = type(self), detect().os
466
+ cls, on = type(self), _here()
463
467
  values = json.loads(os.environ.get(APP_SETTINGS_ENV) or "{}").get(os.environ.get("ENVIRONMENT_NAME"), {})
464
468
  self.settings = cls.settings_on(on).model_validate(values)
465
469
  self.build_settings = _built_settings(cls, on)
466
- declared = cls._installs.get(on)
470
+ declared = entry_for(cls._installs, on)
467
471
  launch = declared.launch if declared is not None else None
468
472
  self.launch = self._launch_for(launch) if launch is not None else None
469
473
  self.paths = list(declared.paths) if declared is not None else []
470
474
  ready = launch.ready if launch is not None else None
471
475
  self._computer_app = AppRuntime(
472
476
  self.launch, {fn.__name__: getattr(self, fn.__name__) for fn in _methods(cls)
473
- if hasattr(fn, _READY_CHECK_ATTR) and _runs_on(getattr(fn, _READY_CHECK_ATTR), on)},
477
+ if hasattr(fn, _READY_CHECK_ATTR) and applies(getattr(fn, _READY_CHECK_ATTR), on)},
474
478
  ready.timeout_s if ready is not None else DEFAULT_TIMEOUT_S, desktop=self._on_desktop(),
475
479
  launch_fds=self._launch_fds, relaunch_on_start=self._relaunch_on_start(),
476
480
  launch_running=self._launch_running())
@@ -509,14 +513,15 @@ class ComputerAppEnvironment(AgentEnvEnvironment):
509
513
 
510
514
  @classmethod
511
515
  def settings_on(cls, os_type: Optional[str]) -> type[BaseModel]:
512
- """Its ``Settings`` on ``os_type``, with the fields its OS adds."""
513
- added = declared.settings if (declared := cls._installs.get(os_type)) is not None else None
516
+ """Its ``Settings`` on ``os_type``, an OS type or ``<os>/<distribution>``, with the fields it adds there."""
517
+ added = declared.settings if (declared := entry_for(cls._installs, os_type)) is not None else None
514
518
  return _added(added, cls.Settings) if added is not None else cls.Settings
515
519
 
516
520
  @classmethod
517
521
  def build_settings_on(cls, os_type: Optional[str]) -> type[BaseModel]:
518
- """Its ``BuildSettings`` on ``os_type``, with the fields its OS adds."""
519
- added = declared.build_settings if (declared := cls._installs.get(os_type)) is not None else None
522
+ """Its ``BuildSettings`` on ``os_type``, an OS type or ``<os>/<distribution>``, with the fields it adds
523
+ there."""
524
+ added = declared.build_settings if (declared := entry_for(cls._installs, os_type)) is not None else None
520
525
  return _added(added, cls.BuildSettings) if added is not None else cls.BuildSettings
521
526
 
522
527
  @extension(COMPUTER_APP, op="launch", description=(
@@ -588,7 +593,7 @@ class ComputerAppEnvironment(AgentEnvEnvironment):
588
593
 
589
594
  def _computer_app_skill_file(self) -> Optional[str]:
590
595
  """The file of the app's folder holding its skill on this OS, or the class's."""
591
- declared = type(self)._installs.get(detect().os)
596
+ declared = entry_for(type(self)._installs, _here())
592
597
  return declared.skill if declared is not None and declared.skill is not None else type(self).skill
593
598
 
594
599
  @classmethod
@@ -618,8 +623,10 @@ class ComputerAppEnvironment(AgentEnvEnvironment):
618
623
  if hasattr(fn, _INSTALL_STEP_ATTR) for scope, os_types in [getattr(fn, _INSTALL_STEP_ATTR)]]
619
624
  checks = [AppReadyCheck(name=fn.__name__, os=getattr(fn, _READY_CHECK_ATTR)) for fn in methods
620
625
  if hasattr(fn, _READY_CHECK_ATTR)]
626
+ installed_os = {key.partition("/")[0] for key in cls._installs}
621
627
  for method in [*steps, *checks]:
622
- if unknown := [os_type for os_type in method.os or [] if os_type not in cls._installs]:
628
+ if unknown := [os_type for os_type in method.os or []
629
+ if entry_for(cls._installs, os_type) is None and os_type not in installed_os]:
623
630
  raise ValueError(f"{cls.__name__}.{method.name} runs on {unknown[0]!r}, which {cls.__name__} declares "
624
631
  f"no install for; it declares {', '.join(cls._installs) or 'none'}")
625
632
  return AppDeclaration(
@@ -678,8 +685,13 @@ def _built_settings(cls: type[ComputerAppEnvironment], os_type: Optional[str]) -
678
685
  return cls.build_settings_on(os_type).model_validate(values)
679
686
 
680
687
 
681
- def _runs_on(os_types: Optional[list[str]], os_type: Optional[str]) -> bool:
682
- return os_types is None or os_type in os_types
688
+ def _here() -> Optional[str]:
689
+ """The platform this runs on, by the key an app's parts for it are under (``platform_key``): the one its computer
690
+ was composed for (``PLATFORM_ENV``), else what it detects."""
691
+ if composed := os.environ.get(PLATFORM_ENV):
692
+ return composed
693
+ running = detect()
694
+ return platform_key(running.os, running.distribution)
683
695
 
684
696
 
685
697
  @functools.cache
@@ -7,10 +7,15 @@ import platform as _platform
7
7
  import sys
8
8
  from dataclasses import dataclass
9
9
  from pathlib import Path
10
+ from typing import Iterable, Mapping, Optional, TypeVar
10
11
 
11
12
  PREDICATE_KEYS = ("os", "distribution", "version", "arch", "display")
12
13
 
13
14
  _ARCH = {"x86_64": "amd64", "amd64": "amd64", "aarch64": "arm64", "arm64": "arm64"}
15
+ _Entry = TypeVar("_Entry")
16
+ #: The platform (``platform_key``) the computer's composer built an app for, which its server and install steps read in
17
+ #: place of what /etc/os-release says, so they act on the install the image holds; unset outside a composed computer.
18
+ PLATFORM_ENV = "AGENTENV_PLATFORM"
14
19
  _OS = {"linux": "linux", "darwin": "macos", "win32": "windows"}
15
20
 
16
21
 
@@ -52,6 +57,30 @@ def detect(environ: dict | None = None, os_release: Path = Path("/etc/os-release
52
57
  arch=_ARCH.get(machine, machine or None), display=display)
53
58
 
54
59
 
60
+ def platform_key(os_type: Optional[str], distribution: Optional[str] = None) -> Optional[str]:
61
+ """What a platform's own install, launch or known failures are keyed by: ``<os>/<distribution>``, its distribution
62
+ being /etc/os-release's ID, or its OS type when it has none."""
63
+ if os_type is None:
64
+ return None
65
+ return f"{os_type}/{distribution}" if distribution else os_type
66
+
67
+
68
+ def entry_for(by_platform: Mapping[str, _Entry], key: Optional[str]) -> Optional[_Entry]:
69
+ """``by_platform``'s entry for the platform ``key`` names: its distribution's, which replaces its OS type's there,
70
+ else its OS type's."""
71
+ if key is None:
72
+ return None
73
+ return by_platform[key] if key in by_platform else by_platform.get(key.partition("/")[0])
74
+
75
+
76
+ def applies(keys: Optional[Iterable[str]], key: Optional[str]) -> bool:
77
+ """Whether what's declared for ``keys``, OS types or distributions, or for every OS when None, applies on the
78
+ platform ``key`` names: one names its OS type or its distribution."""
79
+ if keys is None:
80
+ return True
81
+ return key is not None and (key in keys or key.partition("/")[0] in keys)
82
+
83
+
55
84
  def supported(entry: dict) -> list[Platform]:
56
85
  """The platforms a ``supports`` entry names: its ``os`` type, with each of its displays and arches, and its
57
86
  distribution and version when it names one. ``{"os": {"type": "linux", "display": ["x11"]}, "arch": ["amd64"]}``
@@ -11,8 +11,7 @@ from pathlib import Path
11
11
  from typing import NoReturn
12
12
 
13
13
  from ._load import load_class
14
- from .app import ComputerAppEnvironment, _built_settings
15
- from .platform import detect
14
+ from .app import ComputerAppEnvironment, _built_settings, _here
16
15
 
17
16
  USAGE = "usage: python -m agentenv_protocol.computer.run_install_step <file>:<Class> <method>"
18
17
 
@@ -33,7 +32,7 @@ def main(argv: list[str]) -> None:
33
32
  if argv[1] not in {step.name for step in cls.declaration().install_steps}:
34
33
  raise SystemExit(f"{cls.__name__} has no @install_step method {argv[1]!r}")
35
34
  app = cls.__new__(cls)
36
- app.settings, app.build_settings = _NoDeploy(), _built_settings(cls, detect().os)
35
+ app.settings, app.build_settings = _NoDeploy(), _built_settings(cls, _here())
37
36
  done = getattr(app, argv[1])()
38
37
  if inspect.isawaitable(done):
39
38
  asyncio.run(done)
@@ -18,11 +18,11 @@ pytest.importorskip("PIL")
18
18
  from agentenv_protocol.computer import AppDeclaration # noqa: E402
19
19
  from agentenv_protocol.computer._declare import _Stub, _StubModule, declare, main # noqa: E402
20
20
  from agentenv_protocol.computer import (APP_SETTINGS_ENV, ComputerAppEnvironment, Launch, Linux, # noqa: E402
21
- Windows, install, linux, windows)
21
+ Windows, install, install_step, linux, ready_check, windows)
22
22
  from agentenv_protocol.computer import app as app_module # noqa: E402
23
23
  from agentenv_protocol.computer.app import BUILD_SETTINGS # noqa: E402
24
24
  from pydantic import BaseModel # noqa: E402
25
- from agentenv_protocol.computer.platform import Platform # noqa: E402
25
+ from agentenv_protocol.computer.platform import PLATFORM_ENV, Platform # noqa: E402
26
26
 
27
27
  DRIVER = '''import not_installed_here
28
28
  from not_installed_here.input import Base, Keyboard
@@ -337,6 +337,106 @@ def test_an_app_reads_its_settings_build_settings_and_launch_as_declared_for_the
337
337
  assert (type(notes.settings), notes.build_settings.edition, notes.launch) == (Notes.Settings, "home", None)
338
338
 
339
339
 
340
+ @pytest.mark.parametrize(("distribution", "launched", "checked"), [
341
+ ("omarchy", ["notes", "--wayland"], ["anywhere", "here"]), ("ubuntu", ["notes"], ["anywhere"]),
342
+ (None, ["notes"], ["anywhere"])])
343
+ def test_an_app_on_a_distribution_it_declares_for_takes_that_part_and_elsewhere_its_os_types(
344
+ monkeypatch, tmp_path, distribution, launched, checked):
345
+ class WaylandSettings(BaseModel):
346
+ portal: bool = True
347
+
348
+ @linux(distribution="omarchy", launch=Launch(command=["notes", "--wayland"]), settings=WaylandSettings)
349
+ @linux(launch=Launch(command=["notes"]))
350
+ class Notes(ComputerAppEnvironment):
351
+ @ready_check(os="linux")
352
+ def anywhere(self):
353
+ return True
354
+
355
+ @ready_check(os="linux/omarchy")
356
+ def here(self):
357
+ return True
358
+
359
+ monkeypatch.setattr(app_module, "detect", lambda: Platform(os="linux", distribution=distribution))
360
+ monkeypatch.setenv("ENVIRONMENT_NAME", "notes")
361
+ monkeypatch.delenv(APP_SETTINGS_ENV, raising=False)
362
+ monkeypatch.chdir(tmp_path)
363
+
364
+ notes = Notes()
365
+
366
+ assert set(Notes.declaration().os) == {"linux", "linux/omarchy"}
367
+ assert notes.launch.command == launched and hasattr(notes.settings, "portal") == (distribution == "omarchy")
368
+ assert sorted(notes._computer_app.ready_checks) == checked
369
+
370
+
371
+ def test_an_install_step_or_ready_check_on_no_os_type_the_app_installs_on_is_refused():
372
+ @linux(distribution="omarchy")
373
+ class Notes(ComputerAppEnvironment):
374
+ @ready_check(os="linux")
375
+ def anywhere(self):
376
+ return True
377
+
378
+ @ready_check(os="macos")
379
+ def mac(self):
380
+ return True
381
+
382
+ with pytest.raises(ValueError, match="Notes.mac runs on 'macos', which Notes declares no install for"):
383
+ Notes.declaration()
384
+
385
+
386
+ @pytest.mark.parametrize(("distribution", "checked"), [("ubuntu", ["anywhere", "on_ubuntu"]),
387
+ ("omarchy", ["anywhere"])])
388
+ def test_an_install_step_or_ready_check_for_a_distribution_runs_there_on_its_os_types_install(
389
+ monkeypatch, tmp_path, distribution, checked):
390
+ @linux(launch=Launch(command=["notes"]))
391
+ class Notes(ComputerAppEnvironment):
392
+ @install_step(os="linux/ubuntu")
393
+ def fonts(self):
394
+ pass
395
+
396
+ @ready_check(os="linux")
397
+ def anywhere(self):
398
+ return True
399
+
400
+ @ready_check(os="linux/ubuntu")
401
+ def on_ubuntu(self):
402
+ return True
403
+
404
+ monkeypatch.setattr(app_module, "detect", lambda: Platform(os="linux", distribution=distribution))
405
+ monkeypatch.setenv("ENVIRONMENT_NAME", "notes")
406
+ monkeypatch.delenv(APP_SETTINGS_ENV, raising=False)
407
+ monkeypatch.chdir(tmp_path)
408
+
409
+ assert [step.os for step in Notes.declaration().install_steps] == [["linux/ubuntu"]]
410
+ assert sorted(Notes()._computer_app.ready_checks) == checked
411
+
412
+
413
+ def test_an_app_reads_the_platform_its_computer_was_composed_for_over_what_it_detects(monkeypatch, tmp_path):
414
+ @linux(distribution="omarchy", launch=Launch(command=["notes", "--wayland"]))
415
+ @linux(launch=Launch(command=["notes"]))
416
+ class Notes(ComputerAppEnvironment):
417
+ pass
418
+
419
+ monkeypatch.setattr(app_module, "detect", lambda: Platform(os="linux", distribution="arch"))
420
+ monkeypatch.setenv("ENVIRONMENT_NAME", "notes")
421
+ monkeypatch.delenv(APP_SETTINGS_ENV, raising=False)
422
+ monkeypatch.chdir(tmp_path)
423
+ detected = Notes().launch.command
424
+ monkeypatch.setenv(PLATFORM_ENV, "linux/omarchy")
425
+
426
+ assert (detected, Notes().launch.command) == (["notes"], ["notes", "--wayland"])
427
+
428
+
429
+ def test_an_install_step_or_ready_check_for_a_distribution_with_no_install_of_its_own_or_its_os_types_is_refused():
430
+ @linux(distribution="omarchy")
431
+ class Notes(ComputerAppEnvironment):
432
+ @install_step(os="linux/ubuntu")
433
+ def fonts(self):
434
+ pass
435
+
436
+ with pytest.raises(ValueError, match="Notes.fonts runs on 'linux/ubuntu', which Notes declares no install for"):
437
+ Notes.declaration()
438
+
439
+
340
440
  def test_a_declaration_stored_before_each_os_had_its_own_part_reads_as_its_linux_part():
341
441
  stored = {"supports": LINUX, "permissions": [], "settings": {"type": "object"}, "data": [], "install_steps": [],
342
442
  "install": {"linux": {"files": ".", "services": [{"name": "imap", "command": "bin/imap"}]}},
@@ -353,7 +453,7 @@ def test_a_declaration_stored_before_each_os_had_its_own_part_reads_as_its_linux
353
453
  def test_linux_and_windows_take_every_field_of_their_install_and_what_install_adds_for_an_os():
354
454
  added = set(inspect.signature(install).parameters) - {"os_type", "spec"}
355
455
 
356
- assert set(inspect.signature(linux).parameters) == set(Linux.model_fields) | added
456
+ assert set(inspect.signature(linux).parameters) == set(Linux.model_fields) | added | {"distribution"}
357
457
  assert set(inspect.signature(windows).parameters) == set(Windows.model_fields) | added
358
458
 
359
459