fix(cli): absolute screenshot path (#16) + show relay in session list (#15)

#16: handle_screenshot now returns a canonicalized ABSOLUTE path, so the
`✓ Screenshot saved to …` line is the same regardless of process cwd and the
agent can read the file without guessing the cwd.

#15: `session list` now reflects the extension-relay connection — when the relay
is up it shows the active session as `(relay/extension → live Chrome)` instead
of "No active sessions", and the --json output gains a `relay` bool. Stops agents
misjudging a live relay connection as down.
This commit is contained in:
leeguooooo
2026-06-12 16:43:39 +09:00
parent b475038e25
commit db484f2ac9
2 changed files with 28 additions and 5 deletions
+17 -3
View File
@@ -269,13 +269,19 @@ fn run_session(args: &[String], session: &str, json_mode: bool) {
.into_iter() .into_iter()
.map(|s| s.name) .map(|s| s.name)
.collect(); .collect();
// The extension relay drives the user's live Chrome but isn't always
// registered as a launched daemon session — without surfacing it,
// `session list` says "No active sessions" while open/tab work fine,
// and agents misjudge the connection as down (issue #15).
let relay_up = connect::relay_url().is_some();
if json_mode { if json_mode {
println!( println!(
r#"{{"success":true,"data":{{"sessions":{}}}}}"#, r#"{{"success":true,"data":{{"sessions":{},"relay":{}}}}}"#,
serde_json::to_string(&sessions).unwrap_or_default() serde_json::to_string(&sessions).unwrap_or_default(),
relay_up
); );
} else if sessions.is_empty() { } else if sessions.is_empty() && !relay_up {
println!("No active sessions"); println!("No active sessions");
} else { } else {
println!("Active sessions:"); println!("Active sessions:");
@@ -287,6 +293,14 @@ fn run_session(args: &[String], session: &str, json_mode: bool) {
}; };
println!("{} {}", marker, s); println!("{} {}", marker, s);
} }
if relay_up && !sessions.iter().any(|s| s == session) {
println!(
"{} {} {}",
color::cyan(""),
session,
color::dim("(relay/extension → live Chrome)")
);
}
} }
} }
None | Some(_) => { None | Some(_) => {
+11 -2
View File
@@ -2877,6 +2877,15 @@ async fn handle_snapshot(cmd: &Value, state: &mut DaemonState) -> Result<Value,
Ok(json!({ "snapshot": tree, "origin": url, "refs": refs })) Ok(json!({ "snapshot": tree, "origin": url, "refs": refs }))
} }
/// Resolve a (possibly relative) saved-file path to an absolute one so the CLI
/// echoes a path the agent can read regardless of the process cwd (issue #16).
/// Falls back to the original string if the file can't be canonicalized.
fn absolutize_saved_path(p: &str) -> String {
std::fs::canonicalize(p)
.map(|c| c.to_string_lossy().into_owned())
.unwrap_or_else(|_| p.to_string())
}
async fn handle_screenshot(cmd: &Value, state: &mut DaemonState) -> Result<Value, String> { async fn handle_screenshot(cmd: &Value, state: &mut DaemonState) -> Result<Value, String> {
let annotate = cmd let annotate = cmd
.get("annotate") .get("annotate")
@@ -2902,7 +2911,7 @@ async fn handle_screenshot(cmd: &Value, state: &mut DaemonState) -> Result<Value
.map_err(|e| format!("Base64 decode error: {}", e))?; .map_err(|e| format!("Base64 decode error: {}", e))?;
std::fs::write(p, bytes) std::fs::write(p, bytes)
.map_err(|e| format!("Failed to write screenshot: {}", e))?; .map_err(|e| format!("Failed to write screenshot: {}", e))?;
return Ok(json!({ "path": p })); return Ok(json!({ "path": absolutize_saved_path(p) }));
} }
let tmp = format!( let tmp = format!(
"/tmp/screenshot-{}.png", "/tmp/screenshot-{}.png",
@@ -2976,7 +2985,7 @@ async fn handle_screenshot(cmd: &Value, state: &mut DaemonState) -> Result<Value
) )
.await?; .await?;
let mut response = json!({ "path": result.path }); let mut response = json!({ "path": absolutize_saved_path(&result.path) });
if !result.annotations.is_empty() { if !result.annotations.is_empty() {
response["annotations"] = serde_json::to_value(&result.annotations) response["annotations"] = serde_json::to_value(&result.annotations)
.map_err(|e| format!("Failed to serialize annotations: {}", e))?; .map_err(|e| format!("Failed to serialize annotations: {}", e))?;