agentenv-framework-protocol 0.1.482__tar.gz → 0.1.483__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.
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/PKG-INFO +1 -1
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/pyproject.toml +1 -1
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/agent_env_environment.py +22 -3
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/__init__.py +2 -2
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/driver.py +28 -8
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/extensions.py +2 -2
- agentenv_framework_protocol-0.1.483/src/agentenv_protocol/computer/prefix.py +51 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/runtime.py +1 -1
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/settings.py +17 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/skill.py +6 -3
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/tools.py +7 -2
- agentenv_framework_protocol-0.1.483/tests/test_computer_tool_prefix.py +153 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/.gitignore +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/LICENSE +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/NOTICE +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/README.md +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/THIRD_PARTY_NOTICES.md +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/advanced_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/basic_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/custom_extensions_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/multimodal_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/reference_model.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/streaming_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/.gitignore +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/Dockerfile +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/Dockerfile.dockerignore +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/README.md +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/data/seed.json +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/env.toml +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/site.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/index.html +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/package-lock.json +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/package.json +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/src/main.js +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/src/style.css +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/website/notes/web/vite.config.js +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/browser_cdp.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/client.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_declare.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_linux.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_load.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_macos.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_with_fds.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/_x11.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/app.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/app_data.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/app_runtime.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/apps.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/card.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/checks.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/client.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/page_fixture.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/conformance/report.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/dataplane.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/errors.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/frames.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/keys.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/launch.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/manifest.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/operations.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/platform.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/queue.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/recording.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/results.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/run_install_step.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/seed.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/serve.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/serve_app.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/session.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/spaces.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/computer/svc.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/errors.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/manifest.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/preflight.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/tool_access.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/tool_client.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/tool_context.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/transfers.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/types.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/clock.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/conformance.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/environment.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/errors.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/readiness.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/routes.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website/session.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/control.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/data.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/devtools.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/environment.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/src/agentenv_protocol/website_browser/shapes.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/computer_fake.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/probe_fake.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_agent.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_agent_examples.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_cdp_config.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_object_transfers.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_peer_agents.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_proxy.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_staging.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_trajectory_log.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_agent_env_environment.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_browser_cdp.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_browser_data.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_browser_state.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_client.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_app_data.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_app_server.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_conformance.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_conformance_checks.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_conformance_page.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_conformance_recording.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_dataplane.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_declare.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_driver.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_extensions.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_frames.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_macos.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_page.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_queue.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_recording.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_seed.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_serve.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_spaces.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_computer_svc_forward.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_control_token.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_data_objects.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_errors.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_extension_methods.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_intake.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_manifest.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_preflight.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_access.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_annotations.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_client.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_context.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_context_fastmcp.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_tool_context_injection.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_api.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_browser.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_conformance.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_environment.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_mcp.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_website_notes_example.py +0 -0
- {agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/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.
|
|
3
|
+
Version: 0.1.483
|
|
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
|
|
@@ -309,7 +309,8 @@ class AgentEnvApplication(ABC):
|
|
|
309
309
|
self._app: Any = None
|
|
310
310
|
ext_handlers = _served_extensions(handler, _discover_extensions(handler))
|
|
311
311
|
environment_card = _merge_extensions(environment_card, ext_handlers + _declared_extensions(handler, ext_handlers))
|
|
312
|
-
tool_handlers =
|
|
312
|
+
tool_handlers = _named_tools(handler, _served_tools(
|
|
313
|
+
handler, _with_forwarded(_discover_tools(handler, environment_card.name), handler)))
|
|
313
314
|
if tool_handlers and not self.supports_tools:
|
|
314
315
|
raise ValueError(f"@tool methods require a FastMCP-backed application; {type(self).__name__} cannot serve MCP tools")
|
|
315
316
|
self._resources = _discover_resources(handler)
|
|
@@ -1107,11 +1108,15 @@ def _with_parts(method: Callable, parts: dict[str, str]) -> Callable:
|
|
|
1107
1108
|
|
|
1108
1109
|
|
|
1109
1110
|
def _instructions(handler: Any) -> str | None:
|
|
1110
|
-
"""What the handler's @server_instructions method returns; None without
|
|
1111
|
+
"""What the handler's @server_instructions method returns, as its ``served_instructions`` serves it; None without
|
|
1112
|
+
one."""
|
|
1111
1113
|
marked = [method for method, _marker in _marked_members(handler, _INSTRUCTIONS_ATTR)]
|
|
1112
1114
|
if len(marked) > 1:
|
|
1113
1115
|
raise ValueError(f"an environment has one @server_instructions method, not {sorted(m.__name__ for m in marked)}")
|
|
1114
|
-
|
|
1116
|
+
if not marked:
|
|
1117
|
+
return None
|
|
1118
|
+
hook = getattr(handler, "served_instructions", None)
|
|
1119
|
+
return hook(marked[0]()) if hook is not None else marked[0]()
|
|
1115
1120
|
|
|
1116
1121
|
|
|
1117
1122
|
def _discover_methods(handler: Any) -> dict:
|
|
@@ -1320,6 +1325,20 @@ def _served_tools(handler: Any, tool_handlers: list) -> list:
|
|
|
1320
1325
|
return [(descriptor, by_name[descriptor.name]) for descriptor in chosen]
|
|
1321
1326
|
|
|
1322
1327
|
|
|
1328
|
+
def _named_tools(handler: Any, tool_handlers: list) -> list:
|
|
1329
|
+
"""The tools as the handler's ``serve_tools_as`` names and describes them, in their order; as they are without one."""
|
|
1330
|
+
hook = getattr(handler, "serve_tools_as", None)
|
|
1331
|
+
if hook is None:
|
|
1332
|
+
return tool_handlers
|
|
1333
|
+
named = list(hook([descriptor for descriptor, _fn in tool_handlers]))
|
|
1334
|
+
if len(named) != len(tool_handlers):
|
|
1335
|
+
raise ValueError(f"serve_tools_as returned {len(named)} tools for {len(tool_handlers)}")
|
|
1336
|
+
names = [descriptor.name for descriptor in named]
|
|
1337
|
+
if len(set(names)) != len(names):
|
|
1338
|
+
raise ValueError(f"serve_tools_as named two tools alike: {sorted({n for n in names if names.count(n) > 1})}")
|
|
1339
|
+
return [(descriptor, fn) for descriptor, (_old, fn) in zip(named, tool_handlers)]
|
|
1340
|
+
|
|
1341
|
+
|
|
1323
1342
|
def _merge_tools(card: EnvironmentCard, tool_handlers: list) -> EnvironmentCard:
|
|
1324
1343
|
"""Advertise decorator-declared tools under card.capabilities; card-declared names win."""
|
|
1325
1344
|
if not tool_handlers:
|
|
@@ -82,7 +82,7 @@ from .dataplane import part_bytes
|
|
|
82
82
|
from .keys import PRINTABLE_KEYS
|
|
83
83
|
from .manifest import ManifestSegment, RecordingManifest
|
|
84
84
|
from .platform import Platform
|
|
85
|
-
from .settings import SETTINGS_ENV, ComputerSettings
|
|
85
|
+
from .settings import SETTINGS_ENV, TOOL_PREFIX_ENV, ComputerSettings, tool_prefix_problem
|
|
86
86
|
|
|
87
87
|
if TYPE_CHECKING:
|
|
88
88
|
from .card import (
|
|
@@ -127,7 +127,7 @@ __all__ = [
|
|
|
127
127
|
"Launch", "Ready", "Packages", "AptSource", "Download", "RunScript",
|
|
128
128
|
"AppDeclaration", "AppOs",
|
|
129
129
|
"APP_SETTINGS_ENV", "part_bytes",
|
|
130
|
-
"Display", "Image", "Effect", "ExecResult", "ReadyCheck", "Platform", "ComputerSettings", "SETTINGS_ENV",
|
|
130
|
+
"Display", "Image", "Effect", "ExecResult", "ReadyCheck", "Platform", "ComputerSettings", "SETTINGS_ENV", "TOOL_PREFIX_ENV", "tool_prefix_problem",
|
|
131
131
|
"Tab", "PageState", "PageDialog", "FileChooser",
|
|
132
132
|
"PRINTABLE_KEYS",
|
|
133
133
|
"display", "set_display", "capture", "click", "drag", "scroll", "type_text", "press",
|
|
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
|
|
6
6
|
import asyncio
|
|
7
7
|
import logging
|
|
8
|
+
import os
|
|
8
9
|
from pathlib import Path
|
|
9
10
|
from typing import Any, Callable, ClassVar, Literal, Optional
|
|
10
11
|
|
|
@@ -13,9 +14,9 @@ from starlette.requests import Request
|
|
|
13
14
|
from starlette.responses import Response
|
|
14
15
|
from starlette.websockets import WebSocket
|
|
15
16
|
|
|
16
|
-
from ..agent_env_environment import (_CARD_CONFIG_ATTR, AgentEnvEnvironment, AgentEnvFastMCPApplication,
|
|
17
|
-
AgentEnvError, _error_response,
|
|
18
|
-
environment_card)
|
|
17
|
+
from ..agent_env_environment import (_CARD_CONFIG_ATTR, _TOOL_ATTR, AgentEnvEnvironment, AgentEnvFastMCPApplication,
|
|
18
|
+
AgentEnvError, _error_response, _marked_members, add_websocket_route,
|
|
19
|
+
control_check, environment_card)
|
|
19
20
|
from ..tool_context import ToolContext
|
|
20
21
|
from ..types import EnvironmentCard, EnvironmentExtension, EnvironmentTool
|
|
21
22
|
from . import _linux, apps, card, svc
|
|
@@ -27,8 +28,9 @@ from .operations import ReadyCheck, check_class, default_for
|
|
|
27
28
|
from .platform import Platform, detect
|
|
28
29
|
from .recording import Recording
|
|
29
30
|
from .runtime import ComputerRuntime
|
|
30
|
-
from .
|
|
31
|
-
from .
|
|
31
|
+
from .prefix import ToolPrefix
|
|
32
|
+
from .settings import TOOL_PREFIX_ENV, ComputerSettings, load_settings, tool_prefix_problem
|
|
33
|
+
from .tools import COMPUTER_TOOLS, Tools
|
|
32
34
|
|
|
33
35
|
#: The caller every call comes from until agents carry an identity of their own.
|
|
34
36
|
DEFAULT_IDENTITY = "default"
|
|
@@ -99,9 +101,15 @@ class ComputerDriverEnvironment(Tools, Extensions, DataPlane, AgentEnvEnvironmen
|
|
|
99
101
|
check_class(cls)
|
|
100
102
|
check_features(cls)
|
|
101
103
|
|
|
102
|
-
def __init__(self, settings: ComputerSettings | None = None, platform: Platform | None = None
|
|
104
|
+
def __init__(self, settings: ComputerSettings | None = None, platform: Platform | None = None,
|
|
105
|
+
tool_prefix: str | None = None) -> None:
|
|
103
106
|
self.settings = settings if settings is not None else load_settings(model=type(self).Settings)
|
|
104
107
|
self.platform = platform if platform is not None else detect()
|
|
108
|
+
prefix = os.environ.get(TOOL_PREFIX_ENV, "") if tool_prefix is None else tool_prefix
|
|
109
|
+
if problem := tool_prefix_problem(prefix):
|
|
110
|
+
raise ValueError(problem)
|
|
111
|
+
#: The start of every name it serves a tool under: the deploy's ``AGENTENV_TOOL_PREFIX``, none by default.
|
|
112
|
+
self._computer_prefix = ToolPrefix(prefix)
|
|
105
113
|
self._computer = ComputerRuntime(self)
|
|
106
114
|
#: The routes each app's card opens to agents, by app, read once it answers.
|
|
107
115
|
self._computer_agent_routes: dict[str, list[str]] = {}
|
|
@@ -113,7 +121,7 @@ class ComputerDriverEnvironment(Tools, Extensions, DataPlane, AgentEnvEnvironmen
|
|
|
113
121
|
running its ``__init__``: what a ``computer_driver`` env records for each platform it supports. The card
|
|
114
122
|
hooks may read the class and the base class's state, not what a subclass's ``__init__`` sets."""
|
|
115
123
|
driver = cls.__new__(cls)
|
|
116
|
-
ComputerDriverEnvironment.__init__(driver, settings=cls.Settings(), platform=platform)
|
|
124
|
+
ComputerDriverEnvironment.__init__(driver, settings=cls.Settings(), platform=platform, tool_prefix="")
|
|
117
125
|
config = dict(getattr(cls, _CARD_CONFIG_ATTR, None) or {})
|
|
118
126
|
card = EnvironmentCard(**{**config, "name": config.get("name") or cls.__name__})
|
|
119
127
|
return AgentEnvFastMCPApplication(card, driver).environment_card
|
|
@@ -203,6 +211,17 @@ class ComputerDriverEnvironment(Tools, Extensions, DataPlane, AgentEnvEnvironmen
|
|
|
203
211
|
def served_tools(self, tools: list[EnvironmentTool]) -> list[EnvironmentTool]:
|
|
204
212
|
return card.served_tools(self, tools)
|
|
205
213
|
|
|
214
|
+
def serve_tools_as(self, tools: list[EnvironmentTool]) -> list[EnvironmentTool]:
|
|
215
|
+
return self._computer_prefix.tools(tools)
|
|
216
|
+
|
|
217
|
+
def served_instructions(self, text: str) -> str:
|
|
218
|
+
return self._computer_prefix.instructions(text, self._computer_other_tools())
|
|
219
|
+
|
|
220
|
+
def _computer_other_tools(self) -> list[str]:
|
|
221
|
+
"""Its driver's own and forwarded tools, whose text stays as written, by their own names."""
|
|
222
|
+
return [marker.name for _member, marker in _marked_members(self, _TOOL_ATTR) if marker.name not in COMPUTER_TOOLS] + [
|
|
223
|
+
forwarded.tool.name for forwarded in self.forwarded_tools()]
|
|
224
|
+
|
|
206
225
|
def served_extensions(self, extensions: list[EnvironmentExtension]) -> list[EnvironmentExtension]:
|
|
207
226
|
return card.served_extensions(self, extensions)
|
|
208
227
|
|
|
@@ -213,7 +232,8 @@ class ComputerDriverEnvironment(Tools, Extensions, DataPlane, AgentEnvEnvironmen
|
|
|
213
232
|
return card.extension_params(self, uri)
|
|
214
233
|
|
|
215
234
|
def declared_extensions(self) -> list[EnvironmentExtension]:
|
|
216
|
-
return
|
|
235
|
+
return [extension.model_copy(update={"description": self._computer_prefix.text(extension.description)})
|
|
236
|
+
for extension in card.declared_extensions(self)]
|
|
217
237
|
|
|
218
238
|
def _computer_require_init(self) -> None:
|
|
219
239
|
if self._computer is None:
|
|
@@ -79,8 +79,8 @@ class Extensions:
|
|
|
79
79
|
self.settings.default_norm_scale)
|
|
80
80
|
self.settings = self.settings.model_copy(update={"default_space": space, "default_norm_scale": scale})
|
|
81
81
|
for tool in self.mounted_card().capabilities.tools or []:
|
|
82
|
-
if tool.name in card.POINT_TOOLS:
|
|
83
|
-
await self.update_tool(tool.name, description=card.point_description(self,
|
|
82
|
+
if (own := self._computer_prefix.own(tool.name)) in card.POINT_TOOLS:
|
|
83
|
+
await self.update_tool(tool.name, description=self._computer_prefix.text(card.point_description(self, own)))
|
|
84
84
|
return await self._computer_spaces_get()
|
|
85
85
|
|
|
86
86
|
@extension(COMPUTER_KEYBOARD, op="get", method="GET",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""A computer's tool prefix: the names it serves its tools under, so several computers serve theirs side by side on
|
|
2
|
+
one gateway. The SDK's ``computer_*`` names in its text are rewritten to them; its driver's own and forwarded tools
|
|
3
|
+
keep their text as written, and a sentence tells an agent how those are named."""
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
|
|
9
|
+
from ..types import EnvironmentTool
|
|
10
|
+
from .tools import COMPUTER_TOOLS
|
|
11
|
+
|
|
12
|
+
#: The SDK's tool names, and a ``computer_*`` family of them, each as a whole word.
|
|
13
|
+
_SDK_NAMES = re.compile(r"(?<![\w-])(?:" + "|".join([*map(re.escape, sorted(COMPUTER_TOOLS, key=len, reverse=True)),
|
|
14
|
+
r"computer_(?:[a-z]+_)*\*"]) + r")(?![\w-])")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ToolPrefix:
|
|
18
|
+
"""``prefix``, the start of every name a computer serves a tool under; none leaves every name as it is."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, prefix: str) -> None:
|
|
21
|
+
self.prefix = prefix
|
|
22
|
+
|
|
23
|
+
def served(self, name: str) -> str:
|
|
24
|
+
"""The name the tool ``name`` is served under."""
|
|
25
|
+
return f"{self.prefix}{name}"
|
|
26
|
+
|
|
27
|
+
def own(self, served: str) -> str:
|
|
28
|
+
"""A served tool's own name."""
|
|
29
|
+
return served.removeprefix(self.prefix)
|
|
30
|
+
|
|
31
|
+
def text(self, text: str | None) -> str | None:
|
|
32
|
+
"""``text`` naming the SDK's tools as they are served; any other name stays as written."""
|
|
33
|
+
return _SDK_NAMES.sub(lambda m: self.prefix + m.group(0), text) if self.prefix and text else text
|
|
34
|
+
|
|
35
|
+
def tools(self, tools: list[EnvironmentTool]) -> list[EnvironmentTool]:
|
|
36
|
+
"""``tools`` under their served names, the SDK's own with their descriptions' names served too."""
|
|
37
|
+
return [tool.model_copy(update={"name": self.served(tool.name), **(
|
|
38
|
+
{"description": self.text(tool.description)} if tool.name in COMPUTER_TOOLS else {})}) for tool in tools]
|
|
39
|
+
|
|
40
|
+
def rule(self, others: Iterable[str]) -> str | None:
|
|
41
|
+
"""The sentence telling an agent how ``others``, the tools whose text stays as written, are served; None
|
|
42
|
+
without a prefix or any of them."""
|
|
43
|
+
example = next(iter(others), None)
|
|
44
|
+
if not self.prefix or example is None:
|
|
45
|
+
return None
|
|
46
|
+
return (f"This computer serves its tools under `{self.prefix}`: a tool this text names without `{self.prefix}` is "
|
|
47
|
+
f"served with it, so `{example}` is `{self.prefix}{example}`. Names inside a tool's arguments stay as written.")
|
|
48
|
+
|
|
49
|
+
def instructions(self, text: str, others: Iterable[str]) -> str:
|
|
50
|
+
"""An MCP server's instructions as the computer serves them: after the rule, if there is one, its names served."""
|
|
51
|
+
return "\n\n".join(part for part in (self.rule(others), self.text(text)) if part)
|
|
@@ -116,7 +116,7 @@ class ComputerRuntime:
|
|
|
116
116
|
async with self.queue.turn(self.driver.settings.queue_wait_s):
|
|
117
117
|
if operation in DIALOG_BLOCKS and self.has("page") and (dialog := (await self.page_now()).dialog):
|
|
118
118
|
raise DialogOpen(f'a {dialog.type} dialog is open on the page: "{dialog.message}"; answer it with '
|
|
119
|
-
"computer_dialog first")
|
|
119
|
+
f"{self.driver._computer_prefix.served('computer_dialog')} first")
|
|
120
120
|
if mapped and frame is not None:
|
|
121
121
|
self.frames.check_current(frame, await self.display_now())
|
|
122
122
|
if at_pointer:
|
|
@@ -3,12 +3,29 @@ from __future__ import annotations
|
|
|
3
3
|
|
|
4
4
|
import json
|
|
5
5
|
import os
|
|
6
|
+
import re
|
|
6
7
|
from typing import Literal
|
|
7
8
|
|
|
8
9
|
from pydantic import BaseModel, ConfigDict, Field, ValidationError
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
SETTINGS_ENV = "AGENTENV_COMPUTER_SETTINGS"
|
|
13
|
+
#: The prefix a deploy gives the names of the computer's tools, so several computers serve them side by side.
|
|
14
|
+
TOOL_PREFIX_ENV = "AGENTENV_TOOL_PREFIX"
|
|
15
|
+
_TOOL_PREFIX = re.compile(r"[A-Za-z0-9_-]*")
|
|
16
|
+
#: The longest a tool prefix may be, its separator included, so a prefixed name stays well within the 64 characters
|
|
17
|
+
#: model APIs take for a tool's name.
|
|
18
|
+
MAX_TOOL_PREFIX = 16
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def tool_prefix_problem(prefix: str) -> str | None:
|
|
22
|
+
"""What's wrong with ``prefix`` as a tool prefix, or None: only what a tool's name may hold, at most
|
|
23
|
+
``MAX_TOOL_PREFIX`` characters."""
|
|
24
|
+
if not _TOOL_PREFIX.fullmatch(prefix):
|
|
25
|
+
return f"tool prefix {prefix!r} holds characters a tool's name can't"
|
|
26
|
+
if len(prefix) > MAX_TOOL_PREFIX:
|
|
27
|
+
return f"tool prefix {prefix!r} is {len(prefix)} characters, and a tool prefix is at most {MAX_TOOL_PREFIX}"
|
|
28
|
+
return None
|
|
12
29
|
|
|
13
30
|
Space = Literal["frame", "norm"]
|
|
14
31
|
|
|
@@ -61,11 +61,14 @@ async def skill(driver: ComputerDriverEnvironment) -> tuple[str, str, dict[str,
|
|
|
61
61
|
if notes := driver.notes.strip():
|
|
62
62
|
sections += ["## Notes", notes]
|
|
63
63
|
body = "\n\n".join(sections) + "\n"
|
|
64
|
+
prefix = driver._computer_prefix
|
|
65
|
+
lead = f"{rule}\n\n" if (rule := prefix.rule(driver._computer_other_tools())) else ""
|
|
64
66
|
if bundled is None:
|
|
65
|
-
return description, body, {}
|
|
67
|
+
return prefix.text(description), prefix.text(lead + body), {}
|
|
66
68
|
own_description, own_body, files = bundled
|
|
67
|
-
return (f"{own_description} This computer: {system}, {display.width}x{display.height}, and its
|
|
68
|
-
|
|
69
|
+
return (prefix.text(f"{own_description} This computer: {system}, {display.width}x{display.height}, and its "
|
|
70
|
+
"computer_* tools."),
|
|
71
|
+
prefix.text(lead + own_body.rstrip() + "\n\n" + body), files)
|
|
69
72
|
|
|
70
73
|
|
|
71
74
|
def _input(driver: ComputerDriverEnvironment) -> str:
|
|
@@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Annotated, Any, Callable, Literal, Optional
|
|
|
9
9
|
from mcp.types import CallToolResult
|
|
10
10
|
from pydantic import Field
|
|
11
11
|
|
|
12
|
-
from ..agent_env_environment import tool
|
|
12
|
+
from ..agent_env_environment import _TOOL_ATTR, tool
|
|
13
13
|
from ..tool_context import ToolContext
|
|
14
14
|
from .errors import InvalidArgument, Unsupported
|
|
15
15
|
from .frames import Frame
|
|
@@ -201,7 +201,8 @@ class Tools:
|
|
|
201
201
|
raise InvalidArgument(f"text is at most {self.max_text_length} characters on this computer, got {len(text)}")
|
|
202
202
|
control = sorted({f"U+{ord(c):04X}" for c in text if c not in "\n\t" and unicodedata.category(c) == "Cc"})
|
|
203
203
|
if control:
|
|
204
|
-
raise InvalidArgument(f"text has control characters {control}; press keys with
|
|
204
|
+
raise InvalidArgument(f"text has control characters {control}; press keys with "
|
|
205
|
+
f"{self._computer_prefix.served('computer_key')}")
|
|
205
206
|
return await computer.act(ctx, "type_text", (text,), frame=computer.frames.latest(self.caller_identity(ctx)),
|
|
206
207
|
screenshot=screenshot, summary=f"Typed {len(text)} characters")
|
|
207
208
|
|
|
@@ -509,3 +510,7 @@ def _check_range(name: str, value: int, low: int, high: int) -> None:
|
|
|
509
510
|
def _display(frame: Frame) -> str:
|
|
510
511
|
d = frame.display
|
|
511
512
|
return f"{d.width}×{d.height}" + (f" at scale {d.scale:g}" if d.scale != 1 else "")
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
#: The tools the SDK serves on every computer, by their own names.
|
|
516
|
+
COMPUTER_TOOLS: tuple[str, ...] = tuple(sorted(name for name, member in vars(Tools).items() if hasattr(member, _TOOL_ATTR)))
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"""A computer deployed with a tool prefix serves every tool under it, and names its tools that way wherever it names
|
|
2
|
+
them: the card, tools/list, its skill, its extensions' descriptions and its errors. Without one, nothing changes."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
pytest.importorskip("mcp.server.fastmcp")
|
|
10
|
+
pytest.importorskip("PIL")
|
|
11
|
+
|
|
12
|
+
from computer_fake import LINUX, FakeDriver, http_client, mcp_session # noqa: E402
|
|
13
|
+
from mcp.types import CallToolResult, TextContent # noqa: E402
|
|
14
|
+
|
|
15
|
+
from agentenv_protocol import EnvironmentTool, ForwardedTool, server_instructions # noqa: E402
|
|
16
|
+
from agentenv_protocol.computer import TOOL_PREFIX_ENV # noqa: E402
|
|
17
|
+
|
|
18
|
+
PREFIX = "desktop_"
|
|
19
|
+
UNPREFIXED = re.compile(r"(?<![\w-])computer_")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def _names(driver) -> tuple[set, set]:
|
|
23
|
+
async with http_client(driver) as http, mcp_session(driver) as session:
|
|
24
|
+
card = (await http.get("/.well-known/agent-env.json")).json()
|
|
25
|
+
listed = {tool.name for tool in (await session.list_tools()).tools}
|
|
26
|
+
return {tool["name"] for tool in card["capabilities"]["tools"]}, listed
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.asyncio
|
|
30
|
+
async def test_a_deploys_tool_prefix_names_every_tool_on_the_card_and_in_tools_list(monkeypatch):
|
|
31
|
+
own_card, own_listed = await _names(FakeDriver())
|
|
32
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
33
|
+
driver = FakeDriver()
|
|
34
|
+
card, listed = await _names(driver)
|
|
35
|
+
assert card == listed == {PREFIX + name for name in own_card} and own_card == own_listed
|
|
36
|
+
async with mcp_session(driver) as session:
|
|
37
|
+
shot = await session.call_tool(f"{PREFIX}computer_screenshot", {})
|
|
38
|
+
unknown = await session.call_tool("computer_screenshot", {})
|
|
39
|
+
assert not shot.isError and any(part.type == "image" for part in shot.content)
|
|
40
|
+
assert unknown.isError
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def test_the_declaration_a_driver_env_stores_names_the_tools_without_the_deploys_prefix(monkeypatch):
|
|
44
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
45
|
+
names = {tool.name for tool in FakeDriver.declaration(LINUX).capabilities.tools}
|
|
46
|
+
assert "computer_screenshot" in names and not any(name.startswith(PREFIX) for name in names)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@pytest.mark.asyncio
|
|
50
|
+
async def test_its_skill_its_extensions_and_its_notes_name_the_tools_as_it_serves_them(monkeypatch):
|
|
51
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
52
|
+
monkeypatch.setattr(FakeDriver, "notes", "Take a computer_screenshot first; desktop_computer_click is already right.")
|
|
53
|
+
async with http_client(FakeDriver()) as http:
|
|
54
|
+
skill = (await http.get("/agentenv/ext/skill/get", params={"name": "desktop"})).json()
|
|
55
|
+
card = (await http.get("/.well-known/agent-env.json")).json()
|
|
56
|
+
text = skill["description"] + skill["skill_md"]
|
|
57
|
+
assert f"`{PREFIX}computer_screenshot`" in text and f"`{PREFIX}computer_*`" in text and f"`{PREFIX}computer_click`" in text
|
|
58
|
+
assert "Take a desktop_computer_screenshot first; desktop_computer_click is already right." in text
|
|
59
|
+
assert not UNPREFIXED.search(text) and "desktop_desktop_" not in text and "serves its tools under" not in text
|
|
60
|
+
descriptions = " ".join(e["description"] for e in card["capabilities"]["extensions"] if e.get("description"))
|
|
61
|
+
assert f"The seven {PREFIX}computer_* tools" in descriptions and not UNPREFIXED.search(descriptions)
|
|
62
|
+
tools = " ".join(t.get("description") or "" for t in card["capabilities"]["tools"])
|
|
63
|
+
assert not UNPREFIXED.search(tools)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@pytest.mark.asyncio
|
|
67
|
+
async def test_an_error_names_the_tool_to_use_instead_as_it_is_served(monkeypatch):
|
|
68
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
69
|
+
async with mcp_session(FakeDriver()) as session:
|
|
70
|
+
refused = await session.call_tool(f"{PREFIX}computer_type", {"text": "a\x07b"})
|
|
71
|
+
assert refused.isError and f"press keys with {PREFIX}computer_key" in refused.content[0].text
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@pytest.mark.asyncio
|
|
75
|
+
async def test_tool_access_rules_name_the_tools_as_it_serves_them(monkeypatch):
|
|
76
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
77
|
+
driver = FakeDriver()
|
|
78
|
+
async with http_client(driver) as http, mcp_session(driver) as session:
|
|
79
|
+
disabled = await http.post("/tools/disable", json={"role": "default", "tools": [f"{PREFIX}computer_click"]})
|
|
80
|
+
listed = {tool.name for tool in (await session.list_tools()).tools}
|
|
81
|
+
refused = await session.call_tool(f"{PREFIX}computer_click", {"x": 1, "y": 1})
|
|
82
|
+
assert disabled.status_code == 200
|
|
83
|
+
assert f"{PREFIX}computer_click" not in listed and f"{PREFIX}computer_screenshot" in listed
|
|
84
|
+
assert refused.isError and "is disabled for role 'default'" in refused.content[0].text
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@pytest.mark.asyncio
|
|
88
|
+
async def test_setting_the_default_space_rewrites_the_prefixed_point_tools(monkeypatch):
|
|
89
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
90
|
+
driver = FakeDriver()
|
|
91
|
+
async with http_client(driver) as http, mcp_session(driver) as session:
|
|
92
|
+
await http.post("/agentenv/ext/computer-spaces/set", json={"default_space": "norm", "default_norm_scale": 1000})
|
|
93
|
+
after = {t.name: t.description for t in (await session.list_tools()).tools}
|
|
94
|
+
assert "norm space by default: 0 to 1000" in after[f"{PREFIX}computer_click"]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.parametrize("prefix, problem", [
|
|
98
|
+
("desk top_", "holds characters a tool's name can't"),
|
|
99
|
+
("desktop/", "holds characters a tool's name can't"),
|
|
100
|
+
("décor_", "holds characters a tool's name can't"),
|
|
101
|
+
("accounting-desk1_", "is 17 characters, and a tool prefix is at most 16"),
|
|
102
|
+
])
|
|
103
|
+
def test_a_prefix_a_tool_name_cant_hold_or_that_is_too_long_is_refused(monkeypatch, prefix, problem):
|
|
104
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, prefix)
|
|
105
|
+
with pytest.raises(ValueError, match=problem):
|
|
106
|
+
FakeDriver()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.asyncio
|
|
110
|
+
async def test_a_prefix_of_sixteen_characters_is_taken(monkeypatch):
|
|
111
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, "accounting-desk_")
|
|
112
|
+
card, _listed = await _names(FakeDriver())
|
|
113
|
+
assert "accounting-desk_computer_pointer_position" in card
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class Forwarding(FakeDriver):
|
|
117
|
+
"""A driver forwarding another program's batch tool, whose steps name that program's own actions."""
|
|
118
|
+
|
|
119
|
+
def forwarded_tools(self):
|
|
120
|
+
schema = {"type": "object", "properties": {"tool": {"type": "string", "enum": ["click", "double_click"]}}}
|
|
121
|
+
return [ForwardedTool(EnvironmentTool(name="run_steps", description="Run click or double_click in one call.",
|
|
122
|
+
inputSchema=schema), self.steps)]
|
|
123
|
+
|
|
124
|
+
async def steps(self, tool):
|
|
125
|
+
return CallToolResult(content=[TextContent(type="text", text=f"ran {tool}")])
|
|
126
|
+
|
|
127
|
+
@server_instructions
|
|
128
|
+
def instructions(self):
|
|
129
|
+
return "Act through run_steps, and take a computer_screenshot first."
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@pytest.mark.asyncio
|
|
133
|
+
async def test_a_forwarded_tool_keeps_its_own_text_and_the_skill_and_instructions_lead_with_the_prefix_rule(monkeypatch):
|
|
134
|
+
monkeypatch.setenv(TOOL_PREFIX_ENV, PREFIX)
|
|
135
|
+
driver = Forwarding()
|
|
136
|
+
instructions = driver.create_app().instructions
|
|
137
|
+
async with http_client(driver) as http, mcp_session(driver) as session:
|
|
138
|
+
tools = {tool.name: tool for tool in (await session.list_tools()).tools}
|
|
139
|
+
ran = await session.call_tool(f"{PREFIX}run_steps", {"tool": "click"})
|
|
140
|
+
skill = (await http.get("/agentenv/ext/skill/get", params={"name": "desktop"})).json()
|
|
141
|
+
forwarded = tools[f"{PREFIX}run_steps"]
|
|
142
|
+
assert forwarded.description == "Run click or double_click in one call."
|
|
143
|
+
assert forwarded.inputSchema["properties"]["tool"]["enum"] == ["click", "double_click"]
|
|
144
|
+
assert not ran.isError and ran.content[0].text == "ran click"
|
|
145
|
+
rule = (f"This computer serves its tools under `{PREFIX}`: a tool this text names without `{PREFIX}` is served with it, "
|
|
146
|
+
f"so `run_steps` is `{PREFIX}run_steps`. Names inside a tool's arguments stay as written.")
|
|
147
|
+
assert skill["skill_md"].partition("---\n\n")[2].startswith(rule)
|
|
148
|
+
assert instructions == f"{rule}\n\nAct through run_steps, and take a {PREFIX}computer_screenshot first."
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_without_a_prefix_a_forwarding_drivers_instructions_are_its_own(monkeypatch):
|
|
152
|
+
monkeypatch.delenv(TOOL_PREFIX_ENV, raising=False)
|
|
153
|
+
assert Forwarding().create_app().instructions == "Act through run_steps, and take a computer_screenshot first."
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/THIRD_PARTY_NOTICES.md
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/examples/basic_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/computer_fake.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/probe_fake.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_a2a_proxy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_intake.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_manifest.py
RENAMED
|
File without changes
|
{agentenv_framework_protocol-0.1.482 → agentenv_framework_protocol-0.1.483}/tests/test_preflight.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|