Repository navigation
feat(computer): the computer env type and the composer (container forms) - #358
earakely-scale wants to merge 15 commits into
Conversation
77a90dc to
3e2870d
Compare
f530255 to
1f2feea
Compare
1f2feea to
a1ad43a
Compare
15457ac to
144a07a
Compare
| def _resolve_aliases(self) -> None: | ||
| """Point each task's reference to an agent, env or artifact by an alias an installed bundle gives it, and the | ||
| configured default agent when it's one, at what it names, pulled into the plan, unless the store has one of the | ||
| alias's id, which the reference keeps naming. A field naming the alias is rewritten to the id. A reference that | ||
| can't be pointed at the alias's entity is left with the problem the store ref check reports; ``alias_uses`` | ||
| holds the aliases the plan names.""" | ||
| """Point each entry's reference to an agent, env or artifact by an alias an installed bundle gives it, and each | ||
| task's to the configured default agent when it's one, at what it names, pulled into the plan, unless the store | ||
| has one of the alias's id, which the reference keeps naming. A field naming the alias is rewritten to the id. A | ||
| reference that can't be pointed at the alias's entity is left with the problem the store ref check reports; | ||
| ``alias_uses`` holds the aliases the plan names.""" |
There was a problem hiding this comment.
Installed computer writes fail
write_installed uses plan_entities, which never calls _resolve_aliases. References such as computer = "ubuntu-24.04" and driver = "reference" therefore stay bare store references. On a fresh store, writing the env fails instead of pulling in its base and driver, even though a bundle run resolves them correctly.
Run alias resolution before checking and ordering entity-only plans too.
Knowledge Base Used: Bundle authoring, installation, and execution
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent_env/bundle/plan.py
Line: 305-310
Comment:
**Installed computer writes fail**
`write_installed` uses `plan_entities`, which never calls `_resolve_aliases`. References such as `computer = "ubuntu-24.04"` and `driver = "reference"` therefore stay bare store references. On a fresh store, writing the env fails instead of pulling in its base and driver, even though a bundle run resolves them correctly.
Run alias resolution before checking and ordering entity-only plans too.
**Knowledge Base Used:** [Bundle authoring, installation, and execution](https://app.greptile.com/scale-ai/-/custom-context/knowledge-base/scaleapi/agentenv-framework/-/docs/bundle-authoring-and-execution.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| problems += [f"forms: the {form} form isn't supported yet; a computer env composes {', '.join(FORMS)}" | ||
| for form in forms if form not in FORMS] |
There was a problem hiding this comment.
forms = [] passes the gate and saves an env that can never produce a computer. Composition has no pairs to build, so _computer writes nothing. Later, env build also has no pairs and exits successfully without repairing the env.
Reject an empty forms list before saving it.
| problems += [f"forms: the {form} form isn't supported yet; a computer env composes {', '.join(FORMS)}" | |
| for form in forms if form not in FORMS] | |
| if not forms: | |
| problems.append("forms: name at least one form to compose") | |
| problems += [f"forms: the {form} form isn't supported yet; a computer env composes {', '.join(FORMS)}" | |
| for form in forms if form not in FORMS] |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent_env/env/envs/computer/gate.py
Line: 29-30
Comment:
**Empty forms create nothing**
`forms = []` passes the gate and saves an env that can never produce a computer. Composition has no pairs to build, so `_computer` writes nothing. Later, `env build` also has no pairs and exits successfully without repairing the env.
Reject an empty forms list before saving it.
```suggestion
if not forms:
problems.append("forms: name at least one form to compose")
problems += [f"forms: the {form} form isn't supported yet; a computer env composes {', '.join(FORMS)}"
for form in forms if form not in FORMS]
```
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.ce61b31 to
a41b625
Compare
…not only a task's An env, an agent or an artifact naming another bundle's alias is pointed at what the alias names and pulled in, as a task's step is, with the field rewritten to its id: a computer env names its base and driver as ubuntu-24.04 and reference. Entries pulled in before the aliases are read are pointed too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rotocol.computer.serve Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…port it serves on A computer_driver env.toml gains port and [install.<os>]: the folder's files copied under the driver's prefix, a requirements file installed into a venv beside them, and the services the base's init runs. The reference driver declares a session service serving its class from a venv of its requirements.txt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…per form and arch A computer env names a base computer and a driver, with its display, network, hidden tools, settings and data paths. Gate 1 matches them before anything is stored and refuses every mismatch at once. The composer then builds each form and arch with this machine's Docker, the other arch through its emulation: the base, built here from its context when no registry has it, with the driver's files, venv and supervisord programs on top. Each image is tagged in the image store by a key of its Dockerfile and build context, so any env with the same inputs reuses it. Statuses go into the env's metadata as each pair finishes, the built arches are written as the env's computer over one index, and agent-env env build resumes what a put left. Builds end unverified; M0.7 boots and probes them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…be the image at full The integration tier composes a bundle's computer env naming ubuntu-24.04 and reference, boots this machine's arch and runs the conformance probe at full three times, and checks an env differing only in display reuses the image. The packages a build installs are read from pip list, so the protocol, when installed from a checkout's source, shows its version. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…es in every entry Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y, and keep what reuse and retries need - A base stored as its build context is built FROM a tag fixed by its arch, so the key is found and an image reused before the base is built. - The image store's credentials sign Docker in to a registry base before a build pulls it. - Scripts and ELF binaries in a driver's files stay executable in the image; the store keeps no file modes. - Each build labels its image with what it installed and whether it was emulated, read back from its arch's config when another env reuses it. - The env's computer records the images it was written over, and env build writes it again when they aren't every pair built. - The port limit is named. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…as no emulation for it Docker can still list a platform after its emulation is removed, until it restarts, so the check before a build passes and the build fails running a program. That failure's log names it, and the pair now says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and sign in before joining them An @Local env's images and index go to the local registry under namespace routing, as a docker_image's do. Docker is signed in to the store before the index is joined, so reusing every image, or an env build that only writes the computer again, can join images in a private registry. The executable mode gets a name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… into the stored record An env got through an installed alias composes into the store and under the ids of the env the alias names. Each pair's result is merged into the stored composed table, read again when another build wrote it first, so two builds of one version keep each other's pairs, and a built pair isn't replaced by another build's building or failed. data_paths is read once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…low-tier shards Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n tools every computer offers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… dicts of their ids
As an MCP server env holds its image and a multi env its children: from_dict
loads them, to_dict writes the same {id, version} as before. The composer takes
them from the env.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What a computer's data/get returns is the reader's to name, not the env's: the env drops data_paths, and an env.toml naming it is refused as an unknown key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e532a49 to
ec1ef0a
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
M0.6 of the CUA env epic (FD-4345): the
computerenv type and the composer for container forms, FD-4356. It follows the reviewed design, CUA Env M0.6: Computer Env Type and the Composer, with its 14 choices confirmed. It builds on #354 (M0.1), merged in v0.9.1369.What's in it
The
computerenv type (ComputerEnv,env/envs/computer/). An env.toml names a base computer and a driver, and declares what makes the env itself:forms,display,network,[tools] hideand[settings.<layer>];appsis accepted only empty until computer app envs arrive (M1.1, M1.3).Gate 1 at put. The base, the driver and the declaration are matched before anything is stored, and every mismatch is refused at once:
supportsagainst the base's OS, and the arches the two share;container;systemservice on a base whose supervisord runs as the session user;displayoutside 1 to 32767 per side, or beside aresolutionsetting;network, atools.hidepattern matching no tool or hiding one of the seven every computer offers;The composer (
composer.py) builds one OCI image per form and arch with this machine's Docker.requirements.txt, and its supervisord programs go on top.emulated. Without emulation that pair fails alone.agentenv-computers:<key>in the image store. The key hashes its Dockerfile, its whole build context, the base, the form, the arch and the composer's source, so any env with the same inputs reuses the image without building it.What a build records. Each pair's status goes into the env's metadata,
composed, as it finishes:unverifiedwith its key, image, packages installed (frompip list) and whether it was emulated, orfailedwith its stage, reason and a FileArtifact of the build log. The arches built are written as the env's computer,<env id>__computer, acomputerartifact over one index of their images. It is written throughComputerArtifact.put, so M0.1's inspection reads each arch back.agent-env env build --id <id> [--version <n>]builds what a put left: failed pairs, and pairs a put that stopped leftbuilding. It reuses any image of the same key, prints each pair, and exits 1 if one failed. Builds endunverified; booting and probing them is M0.7, and until then a computer env's deploy is refused, naming its statuses.A driver declares its install (
computer_driverenv.toml):port, and[install.<os>]withfiles,python(a requirements file) andservices. The reference driver gains arequirements.txt(protocol, mss, python-xlib) and a session service run bypython -m agentenv_protocol.computer.serve driver.py:ReferenceDriver, a new SDK entry point that serves a driver class from its file.Aliases in every entry's references. As decided while building this, the planner resolves an installed bundle's alias in an env's, an agent's or an artifact's references as it does in a task's steps. It rewrites the field to the target's id and pulls the target in, for entries pulled from other bundles too. The rule that an entry's reference to an alias is refused goes away. This is what lets a computer env write
computer = "ubuntu-24.04"anddriver = "reference".A bundle run says it's building. It prints its "building with docker" line before writing an env whose type builds at put (
Env.builds_at_put). Each pair's result is logged, and a failed pair is a warning.Where this differs from the design
computer = "ubuntu-24.04"to the base's full id, so[settings."ubuntu-24.04"]must still find it.<env id>__computer, afterderive_id, not<env id>-computer. Its settings' defaults carry the env's values and its display.data_pathson the env (decided in review). What a computer'sdata/getreturns is the reader's choice: it names the paths it reads (data/gettakespaths, M0.7), and with none, the driver returns its OS's standard user folders and declares them on its card.snapshot_envtakescomputer_file_pathswith M1.8.Testing
Unit. 75 tests cover:
serveentry point;Line coverage of that code is 96% (composer 95%). The whole tier passes (11,157 tests) except
parse_test.py::TestFiles::test_deep_nesting[json], which also fails onmainunder Python 3.14; CI runs 3.12.Integration (
tst/integration/computer, real Docker):Chaos on the laptop (arm64, with amd64 emulated): 16/16 at f530255.
full(51 checks, three times), and the computer boots to ready in 1.6 s.building, andenv buildfinishes them.Chaos on EC2 (amd64, with arm64 emulated).
full×3 and boot takes 1.8 s.exec format erroris reported as "this machine can't run linux/arm64 programs: its Docker has no emulation for it", with the log stored. The f530255 run had reported only "the build failed", which is why 1f2feea maps it.env buildbuilds both,unverified.An agent on the composed computer (laptop, at f530255): claude-code drove the env's composed arm64 computer and created a folder through the desktop's file manager. The task's outcome check passed in 30.7 s, and its recording had no missing segments.
Greptile: 12 findings over four reviews, all fixed and answered on their threads:
current(),images);MAX_PORT;data_pathsonce, a field since removed (see below).Each finding from the last two rounds has a unit test that fails against the code before its fix.
🤖 Generated with Claude Code
The installed-entity alias failure still blocks merging; empty forms also remain accepted.
Fix with agent prompt
Summary
Adds computer environments that combine a base computer and a driver into container images.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Computer environment declaration] --> B[Resolve base and driver] B --> C[Check compatibility] C --> D[Save environment] D --> E[Compose each architecture] E --> F{Matching image exists?} F -->|Yes| G[Reuse image] F -->|No| H[Build and push image] G --> I[Record result] H --> I I --> J[Join completed images] J --> K[Save computer artifact] L[env build] --> EReviews (12) · Last reviewed commit: "refactor(computer): a computer env names..." · Reviewed by Greptile