feat: add hypeman cp for file copy to/from running VMs#45
Conversation
✱ Stainless preview buildsThis PR will update the ✅ hypeman-typescript studio · code
✅ hypeman-go studio · code
⚡ hypeman-cli studio · conflict
This comment is auto-generated by GitHub Actions and is automatically kept up to date as you push. |
This commit renames the exec-agent to guest-agent to better reflect its expanding role as a general-purpose guest interaction service. Along with the rename, this adds gRPC support for file copy operations: - Rename lib/exec to lib/guest - Rename lib/system/exec_agent to lib/system/guest_agent - Add CopyToGuest and CopyFromGuest RPCs - Add StatPath RPC for querying guest filesystem metadata - Implement cp handlers with uid/gid preservation support - Update all imports and references The guest-agent continues to listen on vsock port 2222 and handle command execution, with new file copy capabilities.
Add /instances/{id}/cp WebSocket endpoint to enable file copy operations
between the local filesystem and running VM instances. Also adds
/instances/{id}/stat HTTP endpoint for querying guest path metadata.
Features:
- Copy files and directories to/from running instances
- Streaming file transfer with chunked data
- Support for symlinks and directory hierarchies
- UID/GID preservation for archive mode
- Follow symlinks option
Add a separate HTTP endpoint for querying filesystem path info in guests.
This replaces the overloaded 'direction: stat' option in the cp WebSocket
endpoint with a cleaner REST API.
- Add PathInfo schema with exists, is_dir, is_file, is_symlink, etc.
- Add GET /instances/{id}/stat endpoint with path and follow_links params
- Add stat method to stainless.yaml for SDK generation
The new endpoint:
- Uses simple HTTP GET instead of WebSocket overhead
- Enables autogenerated SDK methods (client.Instances.Stat())
- Mirrors the guest agent's separate StatPath RPC
- Is self-documenting via OpenAPI spec
Add comprehensive integration tests for file copy functionality: - Test copying single files to instance - Test copying directories recursively to instance - Test copying files from instance - Test copying directories from instance - Verify file content, permissions, and metadata preservation Also adds Reset() method to outputBuffer helper used in tests.
b35027f to
61f0469
Compare
The mtime was only being applied when currentFile != nil, which is only true for regular files. For directories, currentFile is never set since they are created with os.MkdirAll without opening a file handle. This fix moves the mtime logic outside of the currentFile != nil block so it applies to both files and directories.
|
Fixed in bdad985 - moved the mtime logic outside of the |
| @@ -0,0 +1,733 @@ | |||
| package main | |||
There was a problem hiding this comment.
accidentally committed the binary for this file to lib/system/guest_agent/guest_agent need adjust .gitignore file
| ) | ||
|
|
||
| // Metrics holds the metrics instruments for exec operations. | ||
| // Metrics holds the metrics instruments for guest operations. |
There was a problem hiding this comment.
I think we should add metrics for copy:
The exec path has metrics (hypeman_exec_sessions_total, _duration_seconds, bytes*), but cp has none.
Suggest adding similar counters in lib/guest/metrics.go, e.g.
hypeman_cp_sessions_total (labels: direction, status)
hypeman_cp_duration_seconds
hypeman_cp_bytes_total
but consider what other metrics might be good to include.
Also, WebSocket handlers bypass otelchi tracing—consider adding a manual span in CpHandler.
lib/system/guest_agent/main.go
Outdated
|
|
||
| log.Printf("[guest-agent] copy-from-guest complete: %d entries from %s", len(entries), rootPath) | ||
| return nil | ||
| } |
There was a problem hiding this comment.
is it worth making the guest agent more structured, similar to the lib/*/README.md pattern we have in the server? at this point 732 lines in a main.go is pretty big, might be worth doing since now it's 2 features instead of just 1
Updated .gitignore to cover both guest-agent and guest_agent naming patterns and removed the tracked binary from the repository.
Added metrics for copy operations following the exec metrics pattern: - hypeman_cp_sessions_total (labels: direction, status) - hypeman_cp_duration_seconds - hypeman_cp_bytes_total Also added OTEL span in CpHandler since WebSocket connections bypass the otelchi middleware for HTTP request tracing.
Reorganized the 732-line main.go into a cleaner structure: - main.go: Server setup, listener, gRPC registration (minimal) - exec.go: Exec-related methods (Exec, executeTTY, executeNoTTY, buildEnv) - cp.go: Copy methods (CopyToGuest, CopyFromGuest, helpers) - stat.go: StatPath method This matches the lib/*/README.md pattern used in the server codebase and makes the guest-agent more maintainable as it grows.

Summary
Add
hypeman cpfunctionality similar todocker cpfor copying files to/from running VM instances. This includes renaming the exec-agent to guest-agent to better reflect its expanding role.Changes
Guest Agent Refactor
lib/exectolib/guestandexec-agenttoguest-agentCopyToGuest,CopyFromGuest,StatPathAPI Server
/instances/{id}/cpfor streaming file transfers/instances/{id}/statfor guest path metadata queriesFeatures
/.suffix)-argument-a) for UID/GID preservation--follow-linksTesting
Note
Introduces streamed file transfer and consolidates guest operations under a new
guestpackage and agent.GET /instances/{id}/cpsupporting copy "to"/"from" with chunked binary streaming, headers, end markers, errors; OTEL tracing + metricsguest.protowithExec,CopyToGuest,CopyFromGuest,StatPath; client inlib/guest(vsock pooling); replaceslib/exec(removed)exec-agent→guest-agent; Makefile/build/test flow updated and.gitignoreentries addedStatInstancePathto query guest FS metadata; router wired; metrics migrated toguestpackageExecHandlernow usesguest.ExecIntoInstanceguestclientWritten by Cursor Bugbot for commit 8eea09f. This will update automatically on new commits. Configure here.