huskies: merge 563_story_build_agent_join_mechanism_agents_register_with_the_gateway_via_token

This commit is contained in:
dave
2026-04-14 12:02:17 +00:00
parent efe434ede3
commit d0d2b17484
6 changed files with 871 additions and 2 deletions
+43
View File
@@ -36,10 +36,15 @@ const SCAN_INTERVAL_SECS: u64 = 15;
///
/// This function never returns under normal operation — it runs until the
/// process is terminated (SIGINT/SIGTERM).
///
/// If `join_token` and `gateway_url` are both provided the agent will register
/// itself with the gateway on startup using the one-time token.
pub async fn run(
project_root: Option<PathBuf>,
rendezvous_url: String,
port: u16,
join_token: Option<String>,
gateway_url: Option<String>,
) -> Result<(), std::io::Error> {
let project_root = match project_root {
Some(r) => r,
@@ -127,6 +132,14 @@ pub async fn run(
// Write initial heartbeat.
write_heartbeat(&rendezvous_url, port);
// Register with gateway if a join token and gateway URL were provided.
if let (Some(token), Some(url)) = (join_token, gateway_url) {
let node_id = crdt_state::our_node_id().unwrap_or_else(|| "unknown".to_string());
let label = format!("build-agent-{}", &node_id[..node_id.len().min(8)]);
let address = format!("ws://0.0.0.0:{port}/crdt-sync");
register_with_gateway(&url, &token, &label, &address).await;
}
// Reconcile any committed work from a previous session.
{
let recon_agents = Arc::clone(&agents);
@@ -427,6 +440,36 @@ fn push_feature_branch(worktree_path: &str, story_id: &str) -> Result<(), String
}
}
// ── Gateway registration ──────────────────────────────────────────────────
/// Register this build agent with a gateway using a one-time join token.
///
/// POSTs `{ token, label, address }` to `{gateway_url}/gateway/register`. On
/// success the gateway stores the agent and it will appear in the gateway UI.
async fn register_with_gateway(gateway_url: &str, token: &str, label: &str, address: &str) {
let client = reqwest::Client::new();
let url = format!("{}/gateway/register", gateway_url.trim_end_matches('/'));
let body = serde_json::json!({
"token": token,
"label": label,
"address": address,
});
match client.post(&url).json(&body).send().await {
Ok(resp) if resp.status().is_success() => {
slog!("[agent-mode] Registered with gateway at {gateway_url}");
}
Ok(resp) => {
slog!(
"[agent-mode] Gateway registration failed: HTTP {}",
resp.status()
);
}
Err(e) => {
slog!("[agent-mode] Gateway registration error: {e}");
}
}
}
// ── Tests ────────────────────────────────────────────────────────────────
#[cfg(test)]