feat/file-transfer #5

Merged
troed merged 27 commits from feat/file-transfer into main 2026-10-14 16:08:27 +02:00
Owner

umwelt_copy_file to enable agents to transfer files between local and remote

umwelt_copy_file to enable agents to transfer files between local and remote
main() called ensure_sandbox() synchronously before reading stdin.
ensure_sandbox returns immediately when the control plane already
answers, but otherwise it launches run.py and waits up to 60s for a
socket that only appears after container creation. During that window
the MCP `initialize` handshake could not be answered, so a client that
evicts/reboots its MCP servers saw umwelt as unavailable for 5-22s
while every other server reconnected in under 1.5s, and a tool call in
flight across the window was orphaned.

Start with an empty ctx instead. `initialize`, `ping` and `tools/list`
need no control plane, and dispatch()'s tools/call branch already
attaches lazily through attach(), which stores a launched control plane
in ctx["proc"]. Teardown is untouched: main()'s finally block already
reads ctx["proc"], so a lazily launched control plane is still
SIGTERMed on exit and an attached one still is not. A failed lazy
attach keeps reporting through dispatch()'s existing ctx["error"] path,
with no new error shape.
Document umwelt_copy_file (Tasks 1-7), which moves one file byte-exactly
between any two sandboxes, local or remote, without the bytes entering
the model's context.

- CONFIGURATION.md: a tool-list bullet plus a new "Transfers" section -
  the endpoint/host shape, the result (including its optional `host`), the
  context-cap exemption, in-place overwrite with the partial-destination
  note (the error reports the offset reached and bytes written, not a
  destination digest), parent-dir creation, preserve_mode on a new
  destination only, the tar idiom, and the stale-agent remedy.
- README.md: the managed-policy sample gains the copy_file allow rule
  (it was out of sync with POLICY_ALLOW after Task 3).
- AGENTS.md, umwelt/plugin/AGENTS.md: one pointer each.
- umwelt/plugin/skills/umwelt/: SKILL.md gains a Where-to-start row and
  the CONFIGURATION.md#transfers anchor; references/remote.md spells out
  that copy_file takes `host` on each endpoint and has no top-level `host`.
- docs/specs: correct the streaming model's round-trip count (75 -> 76;
  the shipped loop makes one extra read for the stat probe).

The installed skill copy is STALE: `install.sh install` was deliberately
not run here (it mutates host state outside this worktree and is the
operator's step). The skill sources edited here are the deliverable;
re-render with `bash umwelt/install.sh install`.
Fix-round 1 for the file-transfer docs (78a146b).

- The stale-agent symptom is not always 'read_chunk': a copy whose remote
  endpoint is the destination fails first on its first write with
  'write_chunk' (the front door reads the local source, then writes to the
  remote). Both CONFIGURATION.md and the skill's references/remote.md now
  name both methods; the remedy and the no-PROTOCOL_VERSION-bump note are
  unchanged.
- Quote the tool's actual error line, with the prefix it prepends:
  `umwelt: copy_file: host '<name>' has an older umwelt agent; re-run
  umwelt-ctl remote-install <name>`.
- Retag the tree example fence from `sh` to `text`: it holds pseudo
  tool-call syntax, not shell, and a `sh` tag invites a bad paste.

The installed skill copy is still STALE (install.sh install is the
operator's step and was deliberately not run).
copy_between already had the destination digest in final_write["sha256"]
(the value verified is derived from); it was simply dropped from the
result. A mismatch now carries dst_sha256 and a loud warning, and the
umwelt-copy audit line records verified so a mismatch is not logged as
plain success. Also: the zero-byte progress note no longer claims the
destination was untouched (the first write truncates before it writes),
and the copy_file dispatch comment no longer claims the lazy local attach
is skipped (the local control plane is still needed to read [[remote]]).
- test_mcp: the mismatch test asserts dst_sha256 and the warning, plus a
  new test pinning the verified-copy shape (no dst_sha256, no warning) and
  one pinning the zero-byte progress note.
- test_run: the idempotency test recorded kw["input"] while the engine
  passes stdin, so the captured input was always None; record stdin.
- test_client: read_chunk/write_chunk join the timeout-default table.
- test_integration: register the agent container with env.names in both
  remote copy tests, make the and-back audit assertion exact, and fix the
  inverted peer labels (the relay leg is not "local").
troed merged commit 1f86c005fa into main 2026-10-14 16:08:27 +02:00
troed deleted branch feat/file-transfer 2026-10-14 16:08:27 +02:00
troed referenced this pull request from a commit 2026-10-14 16:08:27 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
troed/umwelt!5
No description provided.