ref:36d8d5a8a89007026d69dca6a916e51efc100c3b

feat(cli): --json on issue comments/links and the agent read family (#329 B)

Rounds out the machine-readable surface: `issue comments`, `issue links`, `agent list/view/sessions/session` now echo the server payload under --json instead of rendering tables only. Part of epic fangorn/anvil#329 (Workstream B). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SHA: 36d8d5a8a89007026d69dca6a916e51efc100c3b
Author: CI <ci@anvil.test>
Date: 2026-07-07 04:15
Parents: 061c436
2 files changed +33 -0
Type
src/commands/agent.rs +20 −0
@@ -89,6 +89,11 @@
let resp: serde_json::Value = client.get(&format!("/{org}/{name}/agents")).await?;
if output::is_json() {
output::print_json(&resp);
return Ok(());
}
let agents: Vec<serde_json::Value> = if let Some(arr) = resp.get("agents") {
serde_json::from_value(arr.clone()).unwrap_or_default()
} else if let Some(arr) = resp.get("data") {
@@ -131,6 +136,11 @@
let resp: serde_json::Value = client
.get(&format!("/{org}/{name}/agents/{agent_name}"))
.await?;
if output::is_json() {
output::print_json(&resp);
return Ok(());
}
let agent = resp
.get("agent")
@@ -196,6 +206,11 @@
.get(&format!("/{org}/{name}/agents/{agent_name}/sessions"))
.await?;
if output::is_json() {
output::print_json(&resp);
return Ok(());
}
let sessions: Vec<serde_json::Value> = if let Some(arr) = resp.get("sessions") {
serde_json::from_value(arr.clone()).unwrap_or_default()
} else if let Some(arr) = resp.get("data") {
@@ -237,6 +252,11 @@
let resp: serde_json::Value = client
.get(&format!("/{org}/{name}/agents/sessions/{id}"))
.await?;
if output::is_json() {
output::print_json(&resp);
return Ok(());
}
let session = resp
.get("session")
src/commands/issue.rs +13 −0
@@ -591,6 +591,11 @@
.get(&format!("/{org}/{name}/issues/{number}/comments"))
.await?;
if output::is_json() {
output::print_json(&resp);
return Ok(());
}
let comments: Vec<serde_json::Value> = resp
.get("comments")
.and_then(|v| serde_json::from_value(v.clone()).ok())
@@ -756,6 +761,14 @@
async fn list_links(repo: Option<&str>, number: u32) -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_config()?;
let (org, name) = config::resolve_repo(repo)?;
if output::is_json() {
let raw: serde_json::Value = client
.get(&format!("/{org}/{name}/issues/{number}/links"))
.await?;
output::print_json(&raw);
return Ok(());
}
let resp: LinksResponse = client
.get(&format!("/{org}/{name}/issues/{number}/links"))