agentenv-framework-protocol 0.1.404__tar.gz → 0.1.406__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/PKG-INFO +49 -11
  2. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/README.md +48 -10
  3. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/pyproject.toml +1 -1
  4. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/__init__.py +10 -2
  5. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/_declare.py +2 -1
  6. agentenv_framework_protocol-0.1.406/src/agentenv_protocol/computer/app.py +482 -0
  7. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/driver.py +3 -3
  8. agentenv_framework_protocol-0.1.406/src/agentenv_protocol/computer/run_install_step.py +43 -0
  9. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/probe_fake.py +1 -1
  10. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_app_server.py +14 -5
  11. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_dataplane.py +1 -1
  12. agentenv_framework_protocol-0.1.406/tests/test_computer_declare.py +362 -0
  13. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_extensions.py +4 -4
  14. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_serve.py +57 -2
  15. agentenv_framework_protocol-0.1.404/src/agentenv_protocol/computer/app.py +0 -240
  16. agentenv_framework_protocol-0.1.404/tests/test_computer_declare.py +0 -241
  17. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/.gitignore +0 -0
  18. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/LICENSE +0 -0
  19. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/NOTICE +0 -0
  20. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/THIRD_PARTY_NOTICES.md +0 -0
  21. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/__init__.py +0 -0
  22. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/advanced_agent.py +0 -0
  23. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/basic_agent.py +0 -0
  24. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/custom_extensions_agent.py +0 -0
  25. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/multimodal_agent.py +0 -0
  26. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/reference_model.py +0 -0
  27. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/examples/streaming_agent.py +0 -0
  28. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/__init__.py +0 -0
  29. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
  30. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
  31. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
  32. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
  33. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
  34. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
  35. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
  36. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
  37. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
  38. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
  39. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
  40. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/agent_env_environment.py +0 -0
  41. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/client.py +0 -0
  42. /agentenv_framework_protocol-0.1.404/src/agentenv_protocol/computer/linux.py → /agentenv_framework_protocol-0.1.406/src/agentenv_protocol/computer/_linux.py +0 -0
  43. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/_load.py +0 -0
  44. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/app_runtime.py +0 -0
  45. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/apps.py +0 -0
  46. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/card.py +0 -0
  47. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/checks.py +0 -0
  48. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
  49. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
  50. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
  51. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/client.py +0 -0
  52. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
  53. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
  54. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/conformance/report.py +0 -0
  55. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/dataplane.py +0 -0
  56. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/errors.py +0 -0
  57. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/extensions.py +0 -0
  58. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/frames.py +0 -0
  59. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/keys.py +0 -0
  60. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/launch.py +0 -0
  61. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/manifest.py +0 -0
  62. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/operations.py +0 -0
  63. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/platform.py +0 -0
  64. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/queue.py +0 -0
  65. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/recording.py +0 -0
  66. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/results.py +0 -0
  67. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/runtime.py +0 -0
  68. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/serve.py +0 -0
  69. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/serve_app.py +0 -0
  70. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/session.py +0 -0
  71. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/settings.py +0 -0
  72. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/skill.py +0 -0
  73. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/spaces.py +0 -0
  74. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/computer/tools.py +0 -0
  75. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/errors.py +0 -0
  76. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/manifest.py +0 -0
  77. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/preflight.py +0 -0
  78. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/tool_access.py +0 -0
  79. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/tool_client.py +0 -0
  80. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/tool_context.py +0 -0
  81. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/transfers.py +0 -0
  82. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/src/agentenv_protocol/types.py +0 -0
  83. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/computer_fake.py +0 -0
  84. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_agent.py +0 -0
  85. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_agent_examples.py +0 -0
  86. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_object_transfers.py +0 -0
  87. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_peer_agents.py +0 -0
  88. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_proxy.py +0 -0
  89. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_staging.py +0 -0
  90. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_a2a_trajectory_log.py +0 -0
  91. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_agent_env_environment.py +0 -0
  92. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_client.py +0 -0
  93. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_conformance.py +0 -0
  94. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_conformance_checks.py +0 -0
  95. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_conformance_recording.py +0 -0
  96. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_driver.py +0 -0
  97. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_frames.py +0 -0
  98. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_queue.py +0 -0
  99. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_recording.py +0 -0
  100. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_computer_spaces.py +0 -0
  101. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_data_objects.py +0 -0
  102. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_errors.py +0 -0
  103. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_extension_methods.py +0 -0
  104. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_intake.py +0 -0
  105. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_manifest.py +0 -0
  106. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_preflight.py +0 -0
  107. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_tool_access.py +0 -0
  108. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_tool_annotations.py +0 -0
  109. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_tool_client.py +0 -0
  110. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_tool_context.py +0 -0
  111. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/tests/test_tool_context_fastmcp.py +0 -0
  112. {agentenv_framework_protocol-0.1.404 → agentenv_framework_protocol-0.1.406}/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.404
3
+ Version: 0.1.406
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
@@ -671,37 +671,75 @@ server, which needs the `app` extra (below).
671
671
 
672
672
  ```python
673
673
  from pydantic import BaseModel, SecretStr
674
- from agentenv_protocol.computer import ComputerAppEnvironment, Launch, Linux, Service, computer_app
674
+ from agentenv_protocol.computer import (ComputerAppEnvironment, Launch, Packages, Service, computer_app,
675
+ install_step, linux)
676
+
677
+ class LinuxSettings(BaseModel):
678
+ font: str = "DejaVu Sans"
675
679
 
676
680
  @computer_app(supports=[{"os": {"type": "linux", "display": ["x11"]}, "arch": ["amd64", "arm64"]}])
681
+ @linux(packages=Packages(apt=["thunderbird"]), python="requirements.txt",
682
+ services=[Service(name="imap", command="venv/bin/python imap.py")],
683
+ launch=Launch(command=["thunderbird"], window={"class": "thunderbird"}), settings=LinuxSettings)
677
684
  class MailApp(ComputerAppEnvironment):
678
- linux = Linux(python="requirements.txt", services=[Service(name="imap", command="venv/bin/python imap.py")])
679
- launch = Launch(command=["thunderbird"], window={"class": "thunderbird"})
680
685
  skill = "skill.md"
681
686
 
682
687
  class Settings(BaseModel):
683
688
  signature: str = ""
684
689
  password: SecretStr = SecretStr("")
690
+
691
+ class BuildSettings(BaseModel):
692
+ locale: str = "en_US"
693
+
694
+ @install_step(scope="session")
695
+ def profile(self) -> None: ...
685
696
  ```
686
697
 
687
698
  - **`@computer_app`** names the platforms the app supports, as a driver names them, and the
688
699
  `permissions` it needs of the computer. Its env.toml names the rest: the app itself
689
- (`environment_name`) and the `computer` and `driver` it deploys alone on.
690
- - **`linux = Linux(...)`** is how a Linux computer installs it: `files`, a folder of the app's
691
- copied under its prefix, which holds the class's file; `python`, a requirements file there,
692
- installed into the venv every app gets beside them; `services`, programs the computer's init runs
693
- from the prefix as the session user.
694
- - **`launch = Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
700
+ (`environment_name`), the `computer` and `driver` it deploys alone on, and `build_settings`, its
701
+ build settings' values (`build_settings = { locale = "fr_FR" }`).
702
+ - **`@linux(...)`** is how a Linux computer installs it, `Linux`'s fields: `files`, a folder of the app's
703
+ copied under its prefix, which holds the class's file; `packages`, the OS's, as apt takes them
704
+ (`Packages(apt=["name", "name=version", "name/suite"])`); `python`, a requirements file there,
705
+ installed into the venv every app gets beside them; `sources`, extra apt repositories
706
+ (`AptSource`, with a key file in the folder); `downloads`, files fetched by URL and checked by
707
+ sha256 (`Download`); `run`, scripts of the folder run as root or the session user (`RunScript`);
708
+ `services`, programs the computer's init runs from the prefix as the session user; and `ports`,
709
+ those it listens on. Packages, requirements and downloads are resolved and fetched once, when the
710
+ computer env is put, and every build installs only those stored files, with the network closed.
711
+ Each value is checked as the class is defined: a URL, a sha256, a path that stays in the folder.
712
+ Installs are exact: apt installs each package without its recommends, and the venv gets exactly
713
+ the wheels resolved for it (`pip install --no-deps`). A requirements file lists everything itself,
714
+ since its lock covers that file alone: a line including another file (`-r`, `-c`), an editable
715
+ install (`-e`), a local path or a local folder of wheels is refused at put.
716
+ - **Each OS has its own decorator,** and what differs by OS goes in it: `launch=` always; and
717
+ optionally `skill=`, a file used instead of the class's, and `settings=` and `build_settings=`,
718
+ models whose fields add to the class's `Settings` and `BuildSettings` on that OS. What's on the
719
+ class applies to every OS. `@install(os_type, spec, launch=..., ...)` is the generic form, for an
720
+ OS type a plugin adds, with that OS type's own install model as `spec`; `@linux(...)` is
721
+ `@install("linux", Linux(...), ...)`. On the computer the class reads what's declared for the OS
722
+ it runs on (`platform.detect()`).
723
+ - **`launch=Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
695
724
  the agent opens it (`"demand"`). `ready=Ready(...)` says when it's ready, within `timeout_s` of its
696
725
  launch: a window matching `launch.window` by its class, instance or title, a port answering on
697
726
  loopback, or a command exiting 0. `@ready_check` marks a method for readiness that needs logic (a
698
727
  sync one runs in a thread), and `@install_step(scope=...)` one a computer runs as it installs the
699
- app.
728
+ app, after its run scripts, offline and without the class's `__init__`. Each runs on every OS the
729
+ app installs on, or on those its `os=` names (`@install_step(os="linux")`, `@ready_check(os=[...])`);
730
+ naming one the app declares no install for is refused when the class is read. A step reads
731
+ `self.build_settings`; a deploy's `self.settings` aren't known at build, and reading one raises
732
+ `AttributeError` (`python -m agentenv_protocol.computer.run_install_step <file>:<Class> <method>`).
700
733
  - **Its skill** is a file of its folder (`skill = "skill.md"`) or an `@agent_skill` method, not both;
701
734
  its data hooks are the usual `@add_data`, `@get_data` and `@reset_data`.
702
735
  - **`Settings`** is typed; a computer hands each app the values a deploy gives it, as one JSON value
703
736
  in `APP_SETTINGS_ENV` (`AGENTENV_APP_SETTINGS`, the apps' values by name), and the base class reads
704
737
  its own, by `ENVIRONMENT_NAME`, as `self.settings`. A `SecretStr` field is a secret.
738
+ - **`BuildSettings`** is typed too: values the app's env fixes in its computer's image, which only
739
+ another image changes, so a deploy can't give one. The composer writes them to
740
+ `.agentenv/build_settings.json` in the app's folder, and the base class reads them, over the
741
+ defaults, as `self.build_settings`, in its install steps and on the computer alike. None is a
742
+ secret, since the image keeps them; `declaration()` refuses a `SecretStr` one.
705
743
 
706
744
  On a computer each app is its own server: `python -m agentenv_protocol.computer.serve_app
707
745
  <file>:<Class>`, a program the computer's init runs from the app's folder in the app's venv, which
@@ -615,37 +615,75 @@ server, which needs the `app` extra (below).
615
615
 
616
616
  ```python
617
617
  from pydantic import BaseModel, SecretStr
618
- from agentenv_protocol.computer import ComputerAppEnvironment, Launch, Linux, Service, computer_app
618
+ from agentenv_protocol.computer import (ComputerAppEnvironment, Launch, Packages, Service, computer_app,
619
+ install_step, linux)
620
+
621
+ class LinuxSettings(BaseModel):
622
+ font: str = "DejaVu Sans"
619
623
 
620
624
  @computer_app(supports=[{"os": {"type": "linux", "display": ["x11"]}, "arch": ["amd64", "arm64"]}])
625
+ @linux(packages=Packages(apt=["thunderbird"]), python="requirements.txt",
626
+ services=[Service(name="imap", command="venv/bin/python imap.py")],
627
+ launch=Launch(command=["thunderbird"], window={"class": "thunderbird"}), settings=LinuxSettings)
621
628
  class MailApp(ComputerAppEnvironment):
622
- linux = Linux(python="requirements.txt", services=[Service(name="imap", command="venv/bin/python imap.py")])
623
- launch = Launch(command=["thunderbird"], window={"class": "thunderbird"})
624
629
  skill = "skill.md"
625
630
 
626
631
  class Settings(BaseModel):
627
632
  signature: str = ""
628
633
  password: SecretStr = SecretStr("")
634
+
635
+ class BuildSettings(BaseModel):
636
+ locale: str = "en_US"
637
+
638
+ @install_step(scope="session")
639
+ def profile(self) -> None: ...
629
640
  ```
630
641
 
631
642
  - **`@computer_app`** names the platforms the app supports, as a driver names them, and the
632
643
  `permissions` it needs of the computer. Its env.toml names the rest: the app itself
633
- (`environment_name`) and the `computer` and `driver` it deploys alone on.
634
- - **`linux = Linux(...)`** is how a Linux computer installs it: `files`, a folder of the app's
635
- copied under its prefix, which holds the class's file; `python`, a requirements file there,
636
- installed into the venv every app gets beside them; `services`, programs the computer's init runs
637
- from the prefix as the session user.
638
- - **`launch = Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
644
+ (`environment_name`), the `computer` and `driver` it deploys alone on, and `build_settings`, its
645
+ build settings' values (`build_settings = { locale = "fr_FR" }`).
646
+ - **`@linux(...)`** is how a Linux computer installs it, `Linux`'s fields: `files`, a folder of the app's
647
+ copied under its prefix, which holds the class's file; `packages`, the OS's, as apt takes them
648
+ (`Packages(apt=["name", "name=version", "name/suite"])`); `python`, a requirements file there,
649
+ installed into the venv every app gets beside them; `sources`, extra apt repositories
650
+ (`AptSource`, with a key file in the folder); `downloads`, files fetched by URL and checked by
651
+ sha256 (`Download`); `run`, scripts of the folder run as root or the session user (`RunScript`);
652
+ `services`, programs the computer's init runs from the prefix as the session user; and `ports`,
653
+ those it listens on. Packages, requirements and downloads are resolved and fetched once, when the
654
+ computer env is put, and every build installs only those stored files, with the network closed.
655
+ Each value is checked as the class is defined: a URL, a sha256, a path that stays in the folder.
656
+ Installs are exact: apt installs each package without its recommends, and the venv gets exactly
657
+ the wheels resolved for it (`pip install --no-deps`). A requirements file lists everything itself,
658
+ since its lock covers that file alone: a line including another file (`-r`, `-c`), an editable
659
+ install (`-e`), a local path or a local folder of wheels is refused at put.
660
+ - **Each OS has its own decorator,** and what differs by OS goes in it: `launch=` always; and
661
+ optionally `skill=`, a file used instead of the class's, and `settings=` and `build_settings=`,
662
+ models whose fields add to the class's `Settings` and `BuildSettings` on that OS. What's on the
663
+ class applies to every OS. `@install(os_type, spec, launch=..., ...)` is the generic form, for an
664
+ OS type a plugin adds, with that OS type's own install model as `spec`; `@linux(...)` is
665
+ `@install("linux", Linux(...), ...)`. On the computer the class reads what's declared for the OS
666
+ it runs on (`platform.detect()`).
667
+ - **`launch=Launch(...)`** says how it starts in the desktop session: with it (`at="boot"`) or when
639
668
  the agent opens it (`"demand"`). `ready=Ready(...)` says when it's ready, within `timeout_s` of its
640
669
  launch: a window matching `launch.window` by its class, instance or title, a port answering on
641
670
  loopback, or a command exiting 0. `@ready_check` marks a method for readiness that needs logic (a
642
671
  sync one runs in a thread), and `@install_step(scope=...)` one a computer runs as it installs the
643
- app.
672
+ app, after its run scripts, offline and without the class's `__init__`. Each runs on every OS the
673
+ app installs on, or on those its `os=` names (`@install_step(os="linux")`, `@ready_check(os=[...])`);
674
+ naming one the app declares no install for is refused when the class is read. A step reads
675
+ `self.build_settings`; a deploy's `self.settings` aren't known at build, and reading one raises
676
+ `AttributeError` (`python -m agentenv_protocol.computer.run_install_step <file>:<Class> <method>`).
644
677
  - **Its skill** is a file of its folder (`skill = "skill.md"`) or an `@agent_skill` method, not both;
645
678
  its data hooks are the usual `@add_data`, `@get_data` and `@reset_data`.
646
679
  - **`Settings`** is typed; a computer hands each app the values a deploy gives it, as one JSON value
647
680
  in `APP_SETTINGS_ENV` (`AGENTENV_APP_SETTINGS`, the apps' values by name), and the base class reads
648
681
  its own, by `ENVIRONMENT_NAME`, as `self.settings`. A `SecretStr` field is a secret.
682
+ - **`BuildSettings`** is typed too: values the app's env fixes in its computer's image, which only
683
+ another image changes, so a deploy can't give one. The composer writes them to
684
+ `.agentenv/build_settings.json` in the app's folder, and the base class reads them, over the
685
+ defaults, as `self.build_settings`, in its install steps and on the computer alike. None is a
686
+ secret, since the image keeps them; `declaration()` refuses a `SecretStr` one.
649
687
 
650
688
  On a computer each app is its own server: `python -m agentenv_protocol.computer.serve_app
651
689
  <file>:<Class>`, a program the computer's init runs from the app's folder in the app's venv, which
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentenv-framework-protocol"
3
- version = "0.1.404"
3
+ version = "0.1.406"
4
4
  description = "Open data-plane protocol and server SDK for agent environments."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -11,13 +11,20 @@ from typing import TYPE_CHECKING, Any
11
11
  from .app import (
12
12
  APP_SETTINGS_ENV,
13
13
  AppDeclaration,
14
+ AppOs,
15
+ AptSource,
14
16
  ComputerAppEnvironment,
17
+ Download,
15
18
  Launch,
16
19
  Linux,
20
+ Packages,
17
21
  Ready,
22
+ RunScript,
18
23
  Service,
19
24
  computer_app,
25
+ install,
20
26
  install_step,
27
+ linux,
21
28
  ready_check,
22
29
  )
23
30
  from .errors import (
@@ -97,8 +104,9 @@ def __getattr__(name: str) -> Any:
97
104
 
98
105
  __all__ = [
99
106
  "ComputerDriverEnvironment", "computer_driver", "DEFAULT_IDENTITY", "DriverDeclaration",
100
- "ComputerAppEnvironment", "computer_app", "install_step", "ready_check", "Linux", "Service", "Launch", "Ready",
101
- "AppDeclaration",
107
+ "ComputerAppEnvironment", "computer_app", "install", "linux", "install_step", "ready_check", "Linux", "Service",
108
+ "Launch", "Ready", "Packages", "AptSource", "Download", "RunScript",
109
+ "AppDeclaration", "AppOs",
102
110
  "APP_SETTINGS_ENV",
103
111
  "Display", "Image", "Effect", "ExecResult", "ReadyCheck", "Platform", "ComputerSettings", "SETTINGS_ENV",
104
112
  "PRINTABLE_KEYS",
@@ -98,7 +98,8 @@ def main(argv: list[str]) -> int:
98
98
  with contextlib.redirect_stdout(sys.stderr):
99
99
  declared = declare(Path(folder), file, name)
100
100
  except ValidationError as e:
101
- print("ValueError: " + "; ".join(error["msg"].removeprefix("Value error, ") for error in e.errors()),
101
+ print("ValueError: " + "; ".join(f"{'.'.join([e.title, *map(str, error['loc'])])}: "
102
+ f"{error['msg'].removeprefix('Value error, ')}" for error in e.errors()),
102
103
  file=sys.stderr)
103
104
  return 1
104
105
  except Exception as e: