mirror of
https://github.com/wirenboard/agent-vm.git
synced 2026-07-09 16:00:54 +00:00
run: add --auto-publish flag (vendored msb auto-publish)
Bumps vendor/microsandbox to pick up the runtime auto-publish
feature and exposes it as a CLI flag. When set:
- .network() builder enables auto_publish() so the runtime's
in-msb poll task spawns once the agent socket is ready.
- The host process subscribes to sandbox.port_events() and
prints each Added/Removed mapping to stderr as `==> auto-
publish: guest :PORT → host 127.0.0.1:PORT`.
All forwarding rides the native smoltcp PortPublisher; no
per-connection python3 tunnel like the previous exec-tunnel
prototype. Loopback-only guest binds are not auto-forwarded
(documented on the flag) because the smoltcp dial target is the
guest's VLAN IP, not loopback — use --publish or run the service
on 0.0.0.0 inside the guest.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca516fb807
commit
fd696a13ea
2 changed files with 54 additions and 2 deletions
|
|
@ -141,6 +141,19 @@ pub struct Args {
|
|||
#[arg(long = "publish", short = 'p')]
|
||||
publish: Vec<String>,
|
||||
|
||||
/// Lima-style host ← guest auto-port-forwarding. The runtime
|
||||
/// polls `/proc/net/tcp{,6}` inside the guest every ~2s and
|
||||
/// mirrors each detected wildcard (`0.0.0.0`/`[::]`) TCP LISTEN
|
||||
/// socket onto a host listener at `127.0.0.1:<same port>` (or
|
||||
/// an ephemeral host port if the preferred one is taken).
|
||||
/// Loopback-only guest binds are NOT forwarded — the smoltcp
|
||||
/// dial target is the guest's VLAN address, so a guest service
|
||||
/// bound to `127.0.0.1` only refuses the connection. agent-vm
|
||||
/// prints each new mapping to stderr as the runtime emits
|
||||
/// `PortEvent`s. Off by default.
|
||||
#[arg(long = "auto-publish", default_value_t = false)]
|
||||
auto_publish: bool,
|
||||
|
||||
/// Override the OCI image reference. Default:
|
||||
/// `ghcr.io/wirenboard/agent-vm-template:latest`. Use a timestamped tag
|
||||
/// (`...:YYYY-MM-DDTHH`) to pin a reproducible image.
|
||||
|
|
@ -468,7 +481,8 @@ pub async fn launch(agent: Agent, args: Args) -> Result<i32> {
|
|||
let has_creds = creds.anthropic_token_file.is_some()
|
||||
|| creds.openai_token_file.is_some()
|
||||
|| creds.gh_token_file.is_some();
|
||||
if has_creds || !publish_ports.is_empty() {
|
||||
let auto_publish = args.auto_publish;
|
||||
if has_creds || !publish_ports.is_empty() || auto_publish {
|
||||
use crate::secrets::*;
|
||||
let anthropic = creds.anthropic_token_file.clone();
|
||||
let openai = creds.openai_token_file.clone();
|
||||
|
|
@ -488,6 +502,9 @@ pub async fn launch(agent: Agent, args: Args) -> Result<i32> {
|
|||
PublishProto::Udp => n.port_udp_bind(host_bind, p.host_port, p.guest_port),
|
||||
};
|
||||
}
|
||||
if auto_publish {
|
||||
n = n.auto_publish();
|
||||
}
|
||||
if !has_creds {
|
||||
return n;
|
||||
}
|
||||
|
|
@ -669,6 +686,41 @@ pub async fn launch(agent: Agent, args: Args) -> Result<i32> {
|
|||
.await
|
||||
.context("verifying image-API contract version")?;
|
||||
|
||||
// Subscribe to the runtime's auto-publish event stream and
|
||||
// surface each mapping to the user. Spawned regardless of
|
||||
// whether auto-publish is enabled — when disabled the runtime
|
||||
// never emits events, so the subscriber just idles. Cheap.
|
||||
if args.auto_publish {
|
||||
eprintln!("==> auto-publish: watching guest LISTEN sockets via /proc/net/tcp{{,6}}");
|
||||
let sb_for_events = sandbox.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut events = sb_for_events.port_events().await;
|
||||
use microsandbox::protocol::network::PortEvent;
|
||||
while let Some(event) = events.recv().await {
|
||||
match event {
|
||||
PortEvent::Added {
|
||||
host_bind,
|
||||
host_port,
|
||||
guest_port,
|
||||
} => {
|
||||
eprintln!(
|
||||
"==> auto-publish: guest :{guest_port} → host {host_bind}:{host_port}"
|
||||
);
|
||||
}
|
||||
PortEvent::Removed {
|
||||
host_bind,
|
||||
host_port,
|
||||
guest_port,
|
||||
} => {
|
||||
eprintln!(
|
||||
"==> auto-publish: guest :{guest_port} closed (released {host_bind}:{host_port})"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let inner_cmd = agent.command();
|
||||
// Prepend agent-vm's default flags (e.g. --dangerously-skip-permissions
|
||||
// for Claude) unless the user already provided them.
|
||||
|
|
|
|||
2
vendor/microsandbox
vendored
2
vendor/microsandbox
vendored
|
|
@ -1 +1 @@
|
|||
Subproject commit 1e9864e0203fc03d2b91794990445649c69943d4
|
||||
Subproject commit 1d2c98425ae23efea047411e82c3ecb148f72782
|
||||
Loading…
Add table
Add a link
Reference in a new issue