Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion desktop/src-tauri/src/managed_agents/restore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ pub async fn restore_managed_agents_on_launch(
spawn_agent_child(
app,
record,
&key.relay_url,
&relay_url,
true,
owner_hex_ref,
)
Expand Down
12 changes: 8 additions & 4 deletions desktop/src-tauri/src/managed_agents/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,9 +1673,13 @@ pub fn spawn_agent_child(
.map(|p| p.display().to_string())
.unwrap_or_else(|| effective_command.clone());

// The caller supplies the explicit canonical pair relay. This is the only
// relay this child may connect to, regardless of the record/workspace default.
let effective_relay_url = runtime_key.relay_url.clone();
// The caller supplies the explicit pair relay. This is the only relay this
// child may connect to, regardless of the record/workspace default. Dial it
// as configured, not via `runtime_key.relay_url`: the canonical form is
// identity-only, and its loopback folding (`localhost` -> `127.0.0.1`)
// changes the Host the relay derives the community boundary from, silently
// parking the child in a different (empty) community than the UI.
let effective_relay_url = relay_url.to_string();

// Augment PATH for DMG launches so child processes can find:
// - bundled CLI via ~/.local/bin symlink
Expand Down Expand Up @@ -2115,7 +2119,7 @@ pub fn start_managed_agent_process(
// Scalar PIDs are migration-only and never establish pair liveness.
record.runtime_pid = None;

let mut process = spawn_agent_child(app, record, &key.relay_url, false, owner_hex)?;
let mut process = spawn_agent_child(app, record, &relay_url, false, owner_hex)?;
let now = now_iso();
let receipt = super::ManagedAgentRuntimeReceipt {
key: key.clone(),
Expand Down
22 changes: 17 additions & 5 deletions desktop/src-tauri/src/managed_agents/runtime_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,13 @@ fn start_pair(
.get_mut(&key)
.is_some_and(|runtime| runtime.child.try_wait().ok().flatten().is_none())
{
let status = status_for(&app, record, &key, runtimes.get(&key), None);
let status = status_for(
&app,
record,
&key,
runtimes.get(&key),
Some(relay_url.clone()),
);
return Ok(status);
}
runtimes.remove(&key);
Expand All @@ -283,7 +289,7 @@ fn start_pair(
.lock()
.ok()
.map(|keys| keys.public_key().to_hex());
let mut process = spawn_agent_child(&app, record, &key.relay_url, lazy, owner.as_deref())?;
let mut process = spawn_agent_child(&app, record, &relay_url, lazy, owner.as_deref())?;
let now = crate::util::now_iso();
let receipt = ManagedAgentRuntimeReceipt {
key: key.clone(),
Expand All @@ -302,7 +308,13 @@ fn start_pair(
record.last_stopped_at = None;
record.last_error = None;
runtimes.insert(key.clone(), ManagedAgentPairRuntime::starting(process));
let status = status_for(&app, record, &key, runtimes.get(&key), None);
let status = status_for(
&app,
record,
&key,
runtimes.get(&key),
Some(relay_url.clone()),
);
drop(runtimes);
save_managed_agents(&app, &records)?;
emit_status(&app, &status);
Expand Down Expand Up @@ -403,7 +415,7 @@ async fn probe_agent_relay_access(
let key = ManagedAgentRuntimeKey::new(record.pubkey.clone(), &requested_relay_url)?;
let keys = nostr::Keys::parse(record.private_key_nsec.trim())
.map_err(|error| format!("invalid managed-agent key: {error}"))?;
let api_base = crate::relay::relay_http_base_url(&key.relay_url);
let api_base = crate::relay::relay_http_base_url(&requested_relay_url);
tokio::time::timeout(
std::time::Duration::from_secs(10),
crate::relay::query_relay_at_with_keys(
Expand Down Expand Up @@ -504,7 +516,7 @@ pub async fn reconcile_managed_agent_runtimes(
Ok((record, key, requested)) => {
match start_pair(
record.pubkey.clone(),
key.relay_url.clone(),
requested.clone(),
true,
Some(&record.updated_at),
app.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function ActiveAgentCommunitiesSettingsCard() {
? "start"
: "restart",
pubkey: runtime.pubkey,
relayUrl: runtime.relayUrl,
relayUrl: runtime.requestedRelayUrl ?? runtime.relayUrl,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Retain the requested relay URL across status refreshes

For a community configured as ws://localhost:3000, start_pair initially returns the raw URL, but the status event immediately invalidates the runtime query and list_managed_agent_runtimes returns only the canonical key (ws://127.0.0.1:3000). Once that refresh occurs, this fallback sends the canonical URL on a later Start/Restart (for example after a failed or stopped harness), so the child again dials Host 127.0.0.1 and is placed in the wrong community. Persist the configured URL with the runtime or recover it from the configured community before issuing lifecycle actions.

AGENTS.md reference: AGENTS.md:L120-L120

Useful? React with 👍 / 👎.

});
} finally {
setPendingRuntimeKey(null);
Expand Down