agentenv-framework-protocol 0.1.395__tar.gz → 0.1.397__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.395 → agentenv_framework_protocol-0.1.397}/PKG-INFO +44 -1
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/README.md +43 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/pyproject.toml +1 -1
- agentenv_framework_protocol-0.1.397/src/agentenv_protocol/computer/__init__.py +112 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/_declare.py +26 -19
- agentenv_framework_protocol-0.1.397/src/agentenv_protocol/computer/app.py +178 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/driver.py +25 -0
- agentenv_framework_protocol-0.1.397/tests/test_computer_declare.py +222 -0
- agentenv_framework_protocol-0.1.395/src/agentenv_protocol/computer/__init__.py +0 -72
- agentenv_framework_protocol-0.1.395/tests/test_computer_declare.py +0 -116
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/.gitignore +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/LICENSE +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/NOTICE +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/THIRD_PARTY_NOTICES.md +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/advanced_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/basic_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/custom_extensions_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/multimodal_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/reference_model.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/examples/streaming_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/agent_env_environment.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/client.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/card.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/checks.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/client.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/conformance/report.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/dataplane.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/errors.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/extensions.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/frames.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/keys.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/linux.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/manifest.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/operations.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/platform.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/queue.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/recording.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/results.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/runtime.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/serve.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/settings.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/skill.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/spaces.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/computer/tools.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/errors.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/manifest.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/preflight.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/tool_access.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/tool_client.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/tool_context.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/transfers.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/src/agentenv_protocol/types.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/computer_fake.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/probe_fake.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_agent.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_agent_examples.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_object_transfers.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_peer_agents.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_proxy.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_staging.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_a2a_trajectory_log.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_agent_env_environment.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_client.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_conformance.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_conformance_checks.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_conformance_recording.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_dataplane.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_driver.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_extensions.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_frames.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_queue.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_recording.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_serve.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_computer_spaces.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_data_objects.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_errors.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_extension_methods.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_intake.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_manifest.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_preflight.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_access.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_annotations.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_client.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_context.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_context_fastmcp.py +0 -0
- {agentenv_framework_protocol-0.1.395 → agentenv_framework_protocol-0.1.397}/tests/test_tool_context_injection.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.397
|
|
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
|
|
@@ -590,6 +590,49 @@ leasing, and unverified for one with it until the probe has lease checks. The pr
|
|
|
590
590
|
default role; the tool-access check hides a tool from a role of its own, `agentenv-probe-<random>`,
|
|
591
591
|
and gives it back.
|
|
592
592
|
|
|
593
|
+
## Computer apps
|
|
594
|
+
|
|
595
|
+
A computer app is software an agent uses on a computer, beside the driver: a desktop app, a service
|
|
596
|
+
or both. Write one as a `ComputerAppEnvironment` subclass from `agentenv_protocol.computer`, an
|
|
597
|
+
`AgentEnvEnvironment` whose class also says what it is to a computer. It needs only the plain
|
|
598
|
+
package: `agentenv_protocol.computer` imports what a driver needs (mcp, uvicorn, Pillow, PyAV) only
|
|
599
|
+
when a driver's names are used.
|
|
600
|
+
|
|
601
|
+
```python
|
|
602
|
+
from pydantic import BaseModel, SecretStr
|
|
603
|
+
from agentenv_protocol.computer import ComputerAppEnvironment, Launch, Linux, Service, computer_app
|
|
604
|
+
|
|
605
|
+
@computer_app(supports=[{"os": {"type": "linux", "display": ["x11"]}, "arch": ["amd64", "arm64"]}])
|
|
606
|
+
class MailApp(ComputerAppEnvironment):
|
|
607
|
+
linux = Linux(python="requirements.txt", services=[Service(name="imap", command="venv/bin/python imap.py")])
|
|
608
|
+
launch = Launch(command=["thunderbird"], window={"class": "thunderbird"})
|
|
609
|
+
skill = "skill.md"
|
|
610
|
+
|
|
611
|
+
class Settings(BaseModel):
|
|
612
|
+
signature: str = ""
|
|
613
|
+
password: SecretStr = SecretStr("")
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
- **`@computer_app`** names the platforms the app supports, as a driver names them, and the
|
|
617
|
+
`permissions` it needs of the computer. Its env.toml names the rest: the app itself
|
|
618
|
+
(`environment_name`) and the `computer` and `driver` it deploys alone on.
|
|
619
|
+
- **`linux = Linux(...)`** is how a Linux computer installs it: `files`, a folder of the app's
|
|
620
|
+
copied under its prefix; `python`, a requirements file there installed into a venv beside them;
|
|
621
|
+
`services`, programs the computer's init runs from the prefix as the session user.
|
|
622
|
+
- **`launch = Launch(...)`** says how it starts in the desktop session, with it (`at="boot"`) or when
|
|
623
|
+
the agent opens it (`"demand"`), and `ready=Ready(...)` when it's ready; `@ready_check` marks a
|
|
624
|
+
method for readiness that needs logic, and `@install_step(scope=...)` one a computer runs as it
|
|
625
|
+
installs the app.
|
|
626
|
+
- **Its skill** is a file of its folder (`skill = "skill.md"`) or an `@agent_skill` method, not both;
|
|
627
|
+
its data hooks are the usual `@add_data`, `@get_data` and `@reset_data`.
|
|
628
|
+
- **`Settings`** is typed; a computer hands each app the values a deploy gives it, as one JSON value
|
|
629
|
+
in `APP_SETTINGS_ENV` (`AGENTENV_APP_SETTINGS`, the apps' values by name), and the base class reads
|
|
630
|
+
its own, by `ENVIRONMENT_NAME`, as `self.settings`. A `SecretStr` field is a secret.
|
|
631
|
+
|
|
632
|
+
`MailApp.declaration()` returns what the class declares, an `AppDeclaration`, which a `computer_app`
|
|
633
|
+
env stores, and `python -m agentenv_protocol.computer._declare <folder> <file> <class>` prints it as
|
|
634
|
+
JSON, or a driver's `DriverDeclaration`, without the class's own dependencies installed.
|
|
635
|
+
|
|
593
636
|
## A2A agent framework
|
|
594
637
|
|
|
595
638
|
The distribution exposes two unrelated decorators named `extension`:
|
|
@@ -537,6 +537,49 @@ leasing, and unverified for one with it until the probe has lease checks. The pr
|
|
|
537
537
|
default role; the tool-access check hides a tool from a role of its own, `agentenv-probe-<random>`,
|
|
538
538
|
and gives it back.
|
|
539
539
|
|
|
540
|
+
## Computer apps
|
|
541
|
+
|
|
542
|
+
A computer app is software an agent uses on a computer, beside the driver: a desktop app, a service
|
|
543
|
+
or both. Write one as a `ComputerAppEnvironment` subclass from `agentenv_protocol.computer`, an
|
|
544
|
+
`AgentEnvEnvironment` whose class also says what it is to a computer. It needs only the plain
|
|
545
|
+
package: `agentenv_protocol.computer` imports what a driver needs (mcp, uvicorn, Pillow, PyAV) only
|
|
546
|
+
when a driver's names are used.
|
|
547
|
+
|
|
548
|
+
```python
|
|
549
|
+
from pydantic import BaseModel, SecretStr
|
|
550
|
+
from agentenv_protocol.computer import ComputerAppEnvironment, Launch, Linux, Service, computer_app
|
|
551
|
+
|
|
552
|
+
@computer_app(supports=[{"os": {"type": "linux", "display": ["x11"]}, "arch": ["amd64", "arm64"]}])
|
|
553
|
+
class MailApp(ComputerAppEnvironment):
|
|
554
|
+
linux = Linux(python="requirements.txt", services=[Service(name="imap", command="venv/bin/python imap.py")])
|
|
555
|
+
launch = Launch(command=["thunderbird"], window={"class": "thunderbird"})
|
|
556
|
+
skill = "skill.md"
|
|
557
|
+
|
|
558
|
+
class Settings(BaseModel):
|
|
559
|
+
signature: str = ""
|
|
560
|
+
password: SecretStr = SecretStr("")
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
- **`@computer_app`** names the platforms the app supports, as a driver names them, and the
|
|
564
|
+
`permissions` it needs of the computer. Its env.toml names the rest: the app itself
|
|
565
|
+
(`environment_name`) and the `computer` and `driver` it deploys alone on.
|
|
566
|
+
- **`linux = Linux(...)`** is how a Linux computer installs it: `files`, a folder of the app's
|
|
567
|
+
copied under its prefix; `python`, a requirements file there installed into a venv beside them;
|
|
568
|
+
`services`, programs the computer's init runs from the prefix as the session user.
|
|
569
|
+
- **`launch = Launch(...)`** says how it starts in the desktop session, with it (`at="boot"`) or when
|
|
570
|
+
the agent opens it (`"demand"`), and `ready=Ready(...)` when it's ready; `@ready_check` marks a
|
|
571
|
+
method for readiness that needs logic, and `@install_step(scope=...)` one a computer runs as it
|
|
572
|
+
installs the app.
|
|
573
|
+
- **Its skill** is a file of its folder (`skill = "skill.md"`) or an `@agent_skill` method, not both;
|
|
574
|
+
its data hooks are the usual `@add_data`, `@get_data` and `@reset_data`.
|
|
575
|
+
- **`Settings`** is typed; a computer hands each app the values a deploy gives it, as one JSON value
|
|
576
|
+
in `APP_SETTINGS_ENV` (`AGENTENV_APP_SETTINGS`, the apps' values by name), and the base class reads
|
|
577
|
+
its own, by `ENVIRONMENT_NAME`, as `self.settings`. A `SecretStr` field is a secret.
|
|
578
|
+
|
|
579
|
+
`MailApp.declaration()` returns what the class declares, an `AppDeclaration`, which a `computer_app`
|
|
580
|
+
env stores, and `python -m agentenv_protocol.computer._declare <folder> <file> <class>` prints it as
|
|
581
|
+
JSON, or a driver's `DriverDeclaration`, without the class's own dependencies installed.
|
|
582
|
+
|
|
540
583
|
## A2A agent framework
|
|
541
584
|
|
|
542
585
|
The distribution exposes two unrelated decorators named `extension`:
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""The computer SDK. A driver subclasses ComputerDriverEnvironment, marks the methods that capture and send input, and
|
|
2
|
+
serve()s it, which needs the ``computer`` extra: ``pip install 'agentenv-framework-protocol[computer]'``. An app
|
|
3
|
+
subclasses ComputerAppEnvironment, which needs only the plain package, so what a driver needs is imported on first
|
|
4
|
+
use."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import importlib
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
from .app import (
|
|
12
|
+
APP_SETTINGS_ENV,
|
|
13
|
+
AppDeclaration,
|
|
14
|
+
ComputerAppEnvironment,
|
|
15
|
+
Launch,
|
|
16
|
+
Linux,
|
|
17
|
+
Ready,
|
|
18
|
+
Service,
|
|
19
|
+
computer_app,
|
|
20
|
+
install_step,
|
|
21
|
+
ready_check,
|
|
22
|
+
)
|
|
23
|
+
from .errors import (
|
|
24
|
+
BackgroundUnavailable,
|
|
25
|
+
ComputerError,
|
|
26
|
+
DeliveryFailed,
|
|
27
|
+
DeviceUnavailable,
|
|
28
|
+
InputBusy,
|
|
29
|
+
Internal,
|
|
30
|
+
InvalidArgument,
|
|
31
|
+
LimitExceeded,
|
|
32
|
+
OutOfBounds,
|
|
33
|
+
PermissionDenied,
|
|
34
|
+
StaleFrame,
|
|
35
|
+
TargetUnavailable,
|
|
36
|
+
Timeout,
|
|
37
|
+
Unsupported,
|
|
38
|
+
)
|
|
39
|
+
from .operations import (
|
|
40
|
+
Display,
|
|
41
|
+
Effect,
|
|
42
|
+
ExecResult,
|
|
43
|
+
Image,
|
|
44
|
+
ReadyCheck,
|
|
45
|
+
capture,
|
|
46
|
+
click,
|
|
47
|
+
display,
|
|
48
|
+
drag,
|
|
49
|
+
key_down,
|
|
50
|
+
key_up,
|
|
51
|
+
pointer_down,
|
|
52
|
+
pointer_move,
|
|
53
|
+
pointer_position,
|
|
54
|
+
pointer_up,
|
|
55
|
+
press,
|
|
56
|
+
record,
|
|
57
|
+
run_in_session,
|
|
58
|
+
scroll,
|
|
59
|
+
set_display,
|
|
60
|
+
type_text,
|
|
61
|
+
write_files,
|
|
62
|
+
)
|
|
63
|
+
from .manifest import ManifestSegment, RecordingManifest
|
|
64
|
+
from .platform import Platform
|
|
65
|
+
from .settings import SETTINGS_ENV, ComputerSettings
|
|
66
|
+
|
|
67
|
+
if TYPE_CHECKING:
|
|
68
|
+
from .card import (
|
|
69
|
+
COMPUTER,
|
|
70
|
+
COMPUTER_DISPLAY,
|
|
71
|
+
COMPUTER_EXEC,
|
|
72
|
+
COMPUTER_KEYBOARD,
|
|
73
|
+
COMPUTER_POINTER,
|
|
74
|
+
COMPUTER_READY,
|
|
75
|
+
COMPUTER_RECORDING,
|
|
76
|
+
COMPUTER_SPACES,
|
|
77
|
+
)
|
|
78
|
+
from .driver import DEFAULT_IDENTITY, ComputerDriverEnvironment, DriverDeclaration, computer_driver
|
|
79
|
+
from .recording import RecordedFrame, RecordedSegment, RecordHints, Recording, frames_in_thread
|
|
80
|
+
|
|
81
|
+
# The names whose modules need the computer extra (mcp, av and Pillow), by module.
|
|
82
|
+
_ON_USE = {
|
|
83
|
+
"driver": ("ComputerDriverEnvironment", "computer_driver", "DEFAULT_IDENTITY", "DriverDeclaration"),
|
|
84
|
+
"card": ("COMPUTER", "COMPUTER_READY", "COMPUTER_DISPLAY", "COMPUTER_SPACES", "COMPUTER_POINTER",
|
|
85
|
+
"COMPUTER_KEYBOARD", "COMPUTER_EXEC", "COMPUTER_RECORDING"),
|
|
86
|
+
"recording": ("Recording", "RecordHints", "RecordedFrame", "RecordedSegment", "frames_in_thread"),
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def __getattr__(name: str) -> Any:
|
|
91
|
+
module = next((module for module, names in _ON_USE.items() if name in names), None)
|
|
92
|
+
if module is None:
|
|
93
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
94
|
+
return getattr(importlib.import_module(f"{__name__}.{module}"), name)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = [
|
|
98
|
+
"ComputerDriverEnvironment", "computer_driver", "DEFAULT_IDENTITY", "DriverDeclaration",
|
|
99
|
+
"ComputerAppEnvironment", "computer_app", "install_step", "ready_check", "Linux", "Service", "Launch", "Ready",
|
|
100
|
+
"AppDeclaration",
|
|
101
|
+
"APP_SETTINGS_ENV",
|
|
102
|
+
"Display", "Image", "Effect", "ExecResult", "ReadyCheck", "Platform", "ComputerSettings", "SETTINGS_ENV",
|
|
103
|
+
"display", "set_display", "capture", "click", "drag", "scroll", "type_text", "press",
|
|
104
|
+
"pointer_move", "pointer_down", "pointer_up", "pointer_position", "key_down", "key_up",
|
|
105
|
+
"run_in_session", "write_files", "record", "Recording", "RecordHints", "RecordedFrame", "RecordedSegment",
|
|
106
|
+
"frames_in_thread", "RecordingManifest", "ManifestSegment",
|
|
107
|
+
"ComputerError", "InvalidArgument", "OutOfBounds", "StaleFrame", "InputBusy", "PermissionDenied", "Unsupported",
|
|
108
|
+
"BackgroundUnavailable", "TargetUnavailable", "DeviceUnavailable", "LimitExceeded", "Timeout", "DeliveryFailed",
|
|
109
|
+
"Internal",
|
|
110
|
+
"COMPUTER", "COMPUTER_READY", "COMPUTER_DISPLAY", "COMPUTER_SPACES", "COMPUTER_POINTER", "COMPUTER_KEYBOARD",
|
|
111
|
+
"COMPUTER_EXEC", "COMPUTER_RECORDING",
|
|
112
|
+
]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"""Read a computer driver class where its own dependencies may not be installed, as a ``computer_driver``
|
|
2
|
-
does: ``python -m agentenv_protocol.computer._declare <folder> <file> <class>`` imports the
|
|
3
|
-
not installed here standing in as an inert stub, and prints what the class declares
|
|
4
|
-
|
|
5
|
-
with why."""
|
|
1
|
+
"""Read a computer driver or app class where its own dependencies may not be installed, as a ``computer_driver`` or
|
|
2
|
+
``computer_app`` env's put does: ``python -m agentenv_protocol.computer._declare <folder> <file> <class>`` imports the
|
|
3
|
+
file with every module not installed here standing in as an inert stub, and prints what the class declares as JSON,
|
|
4
|
+
as its base class says. Nothing runs beyond defining the module and its classes, and a class that can't be defined
|
|
5
|
+
even so exits 1 with why."""
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
import contextlib
|
|
@@ -14,10 +14,14 @@ import sys
|
|
|
14
14
|
import types
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
|
|
17
|
+
from .app import AppDeclaration, ComputerAppEnvironment
|
|
17
18
|
from .card import COMPUTER
|
|
18
|
-
from .driver import ComputerDriverEnvironment
|
|
19
|
+
from .driver import ComputerDriverEnvironment, DriverDeclaration, DriverPlatform
|
|
19
20
|
from .platform import supported
|
|
20
21
|
|
|
22
|
+
#: The env type that stores each kind of declaration, which the printed JSON carries as ``type``.
|
|
23
|
+
_ENV_TYPES = {AppDeclaration: "computer_app", DriverDeclaration: "computer_driver"}
|
|
24
|
+
|
|
21
25
|
|
|
22
26
|
class _StubMeta(type):
|
|
23
27
|
def __getattr__(cls, name: str):
|
|
@@ -58,32 +62,35 @@ class _Stubs(importlib.abc.MetaPathFinder, importlib.abc.Loader):
|
|
|
58
62
|
return None
|
|
59
63
|
|
|
60
64
|
|
|
61
|
-
def declare(folder: Path, file: str, name: str) ->
|
|
62
|
-
"""What the class ``name`` in ``folder/file`` declares:
|
|
63
|
-
those name, the extensions it provides, its tools and
|
|
64
|
-
that
|
|
65
|
+
def declare(folder: Path, file: str, name: str) -> AppDeclaration | DriverDeclaration:
|
|
66
|
+
"""What the class ``name`` in ``folder/file`` declares: an app's ``ComputerAppEnvironment.declaration()``; a
|
|
67
|
+
driver's card name, its ``supports``, and for each platform those name, the extensions it provides, its tools and
|
|
68
|
+
the computer/v1 features. Raises ValueError for a class that is neither, or a driver that declares no platform."""
|
|
65
69
|
sys.path.insert(0, str(folder))
|
|
66
70
|
sys.meta_path.append(_Stubs())
|
|
67
71
|
spec = importlib.util.spec_from_file_location("computer_driver_module", folder / file)
|
|
68
72
|
module = importlib.util.module_from_spec(spec)
|
|
69
73
|
spec.loader.exec_module(module)
|
|
70
74
|
cls = getattr(module, name, None)
|
|
75
|
+
if isinstance(cls, type) and issubclass(cls, ComputerAppEnvironment):
|
|
76
|
+
return cls.declaration()
|
|
71
77
|
if not (isinstance(cls, type) and issubclass(cls, ComputerDriverEnvironment)):
|
|
72
|
-
raise ValueError(f"{file} has no ComputerDriverEnvironment subclass named {name}")
|
|
78
|
+
raise ValueError(f"{file} has no ComputerDriverEnvironment or ComputerAppEnvironment subclass named {name}")
|
|
73
79
|
platforms = [platform for entry in cls.supports for platform in supported(entry)]
|
|
74
80
|
if not platforms:
|
|
75
81
|
raise ValueError(f"{name} declares no platform: name them with @computer_driver(supports=[...])")
|
|
76
82
|
cards = [(platform, cls.declaration(platform)) for platform in platforms]
|
|
77
|
-
return
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for platform, card in cards]
|
|
83
|
+
return DriverDeclaration(name=cards[0][1].name, supports=list(cls.supports), platforms=[
|
|
84
|
+
DriverPlatform(platform=platform, provides=[e.uri for e in card.capabilities.extensions],
|
|
85
|
+
tools=[t.name for t in card.capabilities.tools],
|
|
86
|
+
features=next({k: v for k, v in e.params.items() if k not in ("endpoint", "methods")}
|
|
87
|
+
for e in card.capabilities.extensions if e.uri == COMPUTER))
|
|
88
|
+
for platform, card in cards])
|
|
83
89
|
|
|
84
90
|
|
|
85
91
|
def main(argv: list[str]) -> int:
|
|
86
|
-
"""Print the declaration as the only output
|
|
92
|
+
"""Print the declaration as the only output, its env type as ``type``; what the module prints while it loads goes
|
|
93
|
+
to stderr."""
|
|
87
94
|
folder, file, name = argv
|
|
88
95
|
try:
|
|
89
96
|
with contextlib.redirect_stdout(sys.stderr):
|
|
@@ -91,7 +98,7 @@ def main(argv: list[str]) -> int:
|
|
|
91
98
|
except Exception as e:
|
|
92
99
|
print(f"{type(e).__name__}: {e}", file=sys.stderr)
|
|
93
100
|
return 1
|
|
94
|
-
print(json.dumps(declared))
|
|
101
|
+
print(json.dumps({"type": _ENV_TYPES[type(declared)], **declared.model_dump(mode="json", exclude_none=True)}))
|
|
95
102
|
return 0
|
|
96
103
|
|
|
97
104
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""ComputerAppEnvironment: software on a computer, an AgentEnvEnvironment whose class also declares what it is for a
|
|
2
|
+
computer: the platforms it supports and the permissions it needs (``@computer_app``), how each OS installs it
|
|
3
|
+
(``linux = Linux(...)``), how it launches (``launch``), its install steps and ready checks, its skill, and its typed
|
|
4
|
+
``Settings``. A ``computer_app`` env's put reads that declaration from the class; its data hooks are the base class's.
|
|
5
|
+
Its name is its env's ``environment_name``."""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import inspect
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
from typing import Any, Callable, ClassVar, Literal, Optional
|
|
12
|
+
|
|
13
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
+
|
|
15
|
+
from ..agent_env_environment import _EXT_ATTR, _OP_ATTR, AgentEnvEnvironment
|
|
16
|
+
from ..types import METHOD_ADD, METHOD_GET, METHOD_RESET, SKILL_EXTENSION_URI
|
|
17
|
+
|
|
18
|
+
#: The environment variable a computer delivers its apps' settings in: JSON of each app's values by its name.
|
|
19
|
+
APP_SETTINGS_ENV = "AGENTENV_APP_SETTINGS"
|
|
20
|
+
_INSTALL_STEP_ATTR = "_aee_install_step"
|
|
21
|
+
_READY_CHECK_ATTR = "_aee_ready_check"
|
|
22
|
+
_DATA_METHODS = {"reset_data": METHOD_RESET, "add_data": METHOD_ADD, "get_data": METHOD_GET}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Service(BaseModel):
|
|
26
|
+
"""A program the computer's init runs from the app's folder as the session user; a relative program names one
|
|
27
|
+
there."""
|
|
28
|
+
|
|
29
|
+
model_config = ConfigDict(extra="forbid")
|
|
30
|
+
|
|
31
|
+
name: str
|
|
32
|
+
command: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class Linux(BaseModel):
|
|
36
|
+
"""How a Linux computer installs the app: ``files``, a folder of the app's copied under its prefix; ``python``, a
|
|
37
|
+
requirements file in that folder installed into a venv beside them; ``services``, programs its init runs."""
|
|
38
|
+
|
|
39
|
+
model_config = ConfigDict(extra="forbid")
|
|
40
|
+
|
|
41
|
+
files: str = "."
|
|
42
|
+
python: Optional[str] = None
|
|
43
|
+
services: list[Service] = Field(default_factory=list)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Ready(BaseModel):
|
|
47
|
+
"""When the app is ready: its window shown, a port answering or a command exiting 0, within ``timeout_s``."""
|
|
48
|
+
|
|
49
|
+
model_config = ConfigDict(extra="forbid")
|
|
50
|
+
|
|
51
|
+
window: bool = False
|
|
52
|
+
port: Optional[int] = None
|
|
53
|
+
command: Optional[list[str]] = None
|
|
54
|
+
timeout_s: float = 60
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Launch(BaseModel):
|
|
58
|
+
"""How the app starts in the desktop session: with it (``boot``) or when the agent opens it (``demand``)."""
|
|
59
|
+
|
|
60
|
+
model_config = ConfigDict(extra="forbid")
|
|
61
|
+
|
|
62
|
+
at: Literal["boot", "demand"] = "boot"
|
|
63
|
+
command: list[str]
|
|
64
|
+
window: Optional[dict[str, str]] = None
|
|
65
|
+
ready: Optional[Ready] = None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class AppSkill(BaseModel):
|
|
69
|
+
"""Where an app's skill for agents comes from: a ``file`` of its folder, or the ``@agent_skill`` ``method`` that
|
|
70
|
+
writes it."""
|
|
71
|
+
|
|
72
|
+
model_config = ConfigDict(extra="forbid")
|
|
73
|
+
|
|
74
|
+
file: Optional[str] = None
|
|
75
|
+
method: Optional[str] = None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class InstallStep(BaseModel):
|
|
79
|
+
"""An ``@install_step`` method, by name, and whom it runs as."""
|
|
80
|
+
|
|
81
|
+
model_config = ConfigDict(extra="forbid")
|
|
82
|
+
|
|
83
|
+
name: str
|
|
84
|
+
scope: Literal["system", "session"]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class AppDeclaration(BaseModel):
|
|
88
|
+
"""What a ComputerAppEnvironment class declares, as a ``computer_app`` env stores it: the platforms it ``supports``,
|
|
89
|
+
as a driver names them; its ``install`` by OS type; ``settings``, the JSON schema of its ``Settings``; and the
|
|
90
|
+
``data`` methods, ``install_steps`` and ``ready_checks`` it serves, by name."""
|
|
91
|
+
|
|
92
|
+
model_config = ConfigDict(extra="forbid")
|
|
93
|
+
|
|
94
|
+
supports: list[dict[str, Any]]
|
|
95
|
+
permissions: list[str]
|
|
96
|
+
install: dict[str, Linux]
|
|
97
|
+
launch: Optional[Launch] = None
|
|
98
|
+
settings: dict[str, Any]
|
|
99
|
+
skill: Optional[AppSkill] = None
|
|
100
|
+
data: list[str]
|
|
101
|
+
install_steps: list[InstallStep]
|
|
102
|
+
ready_checks: list[str]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def computer_app(*, supports: Optional[list] = None, permissions: Optional[list[str]] = None) -> Callable:
|
|
106
|
+
"""Declare what an app is: the platforms it supports, as a driver names them, and the permissions it needs of the
|
|
107
|
+
computer. Its env.toml names it and the computer and driver it deploys alone on."""
|
|
108
|
+
def deco(cls: type) -> type:
|
|
109
|
+
if not (isinstance(cls, type) and issubclass(cls, ComputerAppEnvironment)):
|
|
110
|
+
raise TypeError("@computer_app decorates a ComputerAppEnvironment subclass")
|
|
111
|
+
cls.supports, cls.permissions = list(supports or []), list(permissions or [])
|
|
112
|
+
return cls
|
|
113
|
+
return deco
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def install_step(scope: Literal["system", "session"] = "system") -> Callable:
|
|
117
|
+
"""Mark a method a computer runs as it installs the app, after its files, in the order the class defines them: as
|
|
118
|
+
root, or for ``session``, as the session user."""
|
|
119
|
+
def deco(fn: Callable) -> Callable:
|
|
120
|
+
setattr(fn, _INSTALL_STEP_ATTR, scope)
|
|
121
|
+
return fn
|
|
122
|
+
return deco
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def ready_check(fn: Callable) -> Callable:
|
|
126
|
+
"""Mark a method that says whether the app is ready, when ``launch``'s ``ready`` can't."""
|
|
127
|
+
setattr(fn, _READY_CHECK_ATTR, True)
|
|
128
|
+
return fn
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class ComputerAppEnvironment(AgentEnvEnvironment):
|
|
132
|
+
"""Subclass it, declare it with ``@computer_app``, and set ``linux``, ``launch`` and ``skill`` as class attributes;
|
|
133
|
+
a deploy's settings arrive as ``self.settings``."""
|
|
134
|
+
|
|
135
|
+
supports: ClassVar[list] = []
|
|
136
|
+
permissions: ClassVar[list[str]] = []
|
|
137
|
+
linux: ClassVar[Optional[Linux]] = None
|
|
138
|
+
launch: ClassVar[Optional[Launch]] = None
|
|
139
|
+
#: A file of the app's folder holding its skill for agents, when no ``@agent_skill`` method writes it.
|
|
140
|
+
skill: ClassVar[Optional[str]] = None
|
|
141
|
+
|
|
142
|
+
class Settings(BaseModel):
|
|
143
|
+
"""The app's settings: an app declares its own; a ``SecretStr`` field is a secret."""
|
|
144
|
+
|
|
145
|
+
def __init__(self) -> None:
|
|
146
|
+
values = json.loads(os.environ.get(APP_SETTINGS_ENV) or "{}").get(os.environ.get("ENVIRONMENT_NAME"), {})
|
|
147
|
+
self.settings = self.Settings.model_validate(values)
|
|
148
|
+
|
|
149
|
+
@classmethod
|
|
150
|
+
def declaration(cls) -> AppDeclaration:
|
|
151
|
+
"""What the class declares. Raises ValueError for a skill declared twice or an install that isn't a
|
|
152
|
+
``Linux``."""
|
|
153
|
+
if cls.linux is not None and not isinstance(cls.linux, Linux):
|
|
154
|
+
raise ValueError(f"{cls.__name__}.linux is a Linux(...), not {cls.linux!r}")
|
|
155
|
+
methods = _methods(cls)
|
|
156
|
+
skill_methods = [fn.__name__ for fn in methods
|
|
157
|
+
if getattr(getattr(fn, _EXT_ATTR, None), "uri", None) == SKILL_EXTENSION_URI]
|
|
158
|
+
if cls.skill is not None and skill_methods:
|
|
159
|
+
raise ValueError(f"{cls.__name__} declares its skill twice: skill = {cls.skill!r} and @agent_skill "
|
|
160
|
+
f"{skill_methods[0]}")
|
|
161
|
+
return AppDeclaration(
|
|
162
|
+
supports=cls.supports, permissions=cls.permissions,
|
|
163
|
+
install={"linux": cls.linux} if cls.linux is not None else {},
|
|
164
|
+
launch=cls.launch, settings=cls.Settings.model_json_schema(),
|
|
165
|
+
skill=AppSkill(file=cls.skill) if cls.skill is not None else
|
|
166
|
+
AppSkill(method=skill_methods[0]) if skill_methods else None,
|
|
167
|
+
data=sorted({_DATA_METHODS[op] for fn in methods if (op := getattr(fn, _OP_ATTR, None)) in _DATA_METHODS}),
|
|
168
|
+
install_steps=[InstallStep(name=fn.__name__, scope=getattr(fn, _INSTALL_STEP_ATTR)) for fn in methods
|
|
169
|
+
if hasattr(fn, _INSTALL_STEP_ATTR)],
|
|
170
|
+
ready_checks=[fn.__name__ for fn in methods if hasattr(fn, _READY_CHECK_ATTR)],
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _methods(cls: type) -> list[Callable]:
|
|
175
|
+
"""The class's methods, each as the class resolves its name, in the order they were first defined."""
|
|
176
|
+
names = dict.fromkeys(name for klass in reversed(cls.__mro__) for name, member in vars(klass).items()
|
|
177
|
+
if inspect.isfunction(member))
|
|
178
|
+
return [method for name in names if inspect.isfunction(method := getattr(cls, name))]
|
|
@@ -5,6 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
import asyncio
|
|
6
6
|
from typing import Any, Callable, ClassVar
|
|
7
7
|
|
|
8
|
+
from pydantic import BaseModel, ConfigDict
|
|
9
|
+
|
|
8
10
|
from ..agent_env_environment import _CARD_CONFIG_ATTR, AgentEnvEnvironment, AgentEnvFastMCPApplication, environment_card
|
|
9
11
|
from ..tool_context import ToolContext
|
|
10
12
|
from ..types import EnvironmentCard, EnvironmentExtension, EnvironmentTool
|
|
@@ -23,6 +25,29 @@ from .tools import Tools
|
|
|
23
25
|
DEFAULT_IDENTITY = "default"
|
|
24
26
|
|
|
25
27
|
|
|
28
|
+
class DriverPlatform(BaseModel):
|
|
29
|
+
"""What a driver serves on one platform its ``supports`` names: the extensions it ``provides``, its ``tools`` and
|
|
30
|
+
its computer/v1 ``features``."""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(extra="forbid")
|
|
33
|
+
|
|
34
|
+
platform: Platform
|
|
35
|
+
provides: list[str]
|
|
36
|
+
tools: list[str]
|
|
37
|
+
features: dict[str, Any]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class DriverDeclaration(BaseModel):
|
|
41
|
+
"""What a ComputerDriverEnvironment class declares, as a ``computer_driver`` env stores it: its card's ``name``, the
|
|
42
|
+
platforms it ``supports``, as predicates, and what it serves on each of them."""
|
|
43
|
+
|
|
44
|
+
model_config = ConfigDict(extra="forbid")
|
|
45
|
+
|
|
46
|
+
name: str
|
|
47
|
+
supports: list[dict[str, Any]]
|
|
48
|
+
platforms: list[DriverPlatform]
|
|
49
|
+
|
|
50
|
+
|
|
26
51
|
class ComputerDriverEnvironment(Tools, Extensions, DataPlane, AgentEnvEnvironment):
|
|
27
52
|
"""Subclass it and mark the methods that capture and send input (see ``operations``); the class is checked when
|
|
28
53
|
it is defined. Features are class attributes, on the card. A subclass's ``__init__`` calls ``super().__init__()``.
|