Skip to content
Merged
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
30 changes: 20 additions & 10 deletions crates/adapter-antigravity/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
//! (antigravity currently nests under the gemini dir); override with
//! `AGENTD_ANTIGRAVITY_HOME`.
//!
//! Env overrides: `AGENTD_ANTIGRAVITY_BIN` (binary, default `agy`),
//! Env overrides: `AGENTD_ANTIGRAVITY_CMD` (full command prefix),
//! `AGENTD_ANTIGRAVITY_BIN` (binary, default `agy`),
//! `AGENTD_ANTIGRAVITY_MODE` (`interactive`|`headless`).

use agentd_protocol::adapter::pty::{run_session as run_pty, PtySpec};
Expand Down Expand Up @@ -106,8 +107,12 @@ fn resolve_mode(params: &SessionStartParams) -> Mode {
}
}

fn bin() -> String {
std::env::var("AGENTD_ANTIGRAVITY_BIN").unwrap_or_else(|_| "agy".into())
fn command_override() -> agentd_protocol::adapter::CommandOverride {
agentd_protocol::adapter::resolve_command_override(
"AGENTD_ANTIGRAVITY_CMD",
"AGENTD_ANTIGRAVITY_BIN",
"agy",
)
}

fn session_data_dir() -> Option<PathBuf> {
Expand Down Expand Up @@ -181,8 +186,9 @@ fn parse_conversation_id(log_text: &str) -> Option<String> {
}

async fn run_interactive(params: SessionStartParams, ctx: AdapterContext) {
let bin = bin();
let mut args = params.args.clone();
let command = command_override();
let mut args = command.args.clone();
args.extend(params.args.clone());

let resuming = std::env::var("AGENTD_RESUME").as_deref() == Ok("1");
let log_path = session_data_dir().map(|d| d.join("agy.log"));
Expand Down Expand Up @@ -226,7 +232,8 @@ async fn run_interactive(params: SessionStartParams, ctx: AdapterContext) {
.collect();
env.push(("AGENTD_SESSION_ID".into(), ctx.session_id.clone()));

let label = bin.clone();
let label = command.argv_preview();
let bin = command.bin;
let spec = PtySpec {
bin,
args,
Expand Down Expand Up @@ -262,7 +269,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
mut inbox,
} = ctx;

let bin = bin();
let command_override = command_override();
let cwd = PathBuf::from(&params.cwd);
let extra_args = params.args.clone();
let mut env: Vec<(String, String)> = params
Expand Down Expand Up @@ -325,7 +332,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
.map(|d| d.join("agy-headless.log"))
.unwrap_or_else(|| PathBuf::from("agy-headless.log"));

let mut child_args: Vec<String> = Vec::new();
let mut child_args: Vec<String> = command_override.args.clone();
child_args.push("-p".into());
child_args.push(user_text.clone());
child_args.push("--dangerously-skip-permissions".into());
Expand All @@ -339,7 +346,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
child_args.push(a.clone());
}

let mut command = Command::new(&bin);
let mut command = Command::new(&command_override.bin);
for a in &child_args {
command.arg(a);
}
Expand All @@ -357,7 +364,10 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
Ok(c) => c,
Err(e) => {
emit.emit(SessionEvent::Error {
message: agentd_protocol::adapter::missing_bin_hint(&bin, &e),
message: agentd_protocol::adapter::missing_bin_hint(
&command_override.argv_preview(),
&e,
),
});
break 127;
}
Expand Down
60 changes: 42 additions & 18 deletions crates/adapter-claude/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
//! `AGENTD_CLAUDE_MODE=interactive|headless`. Default is interactive when the
//! client supplies a PTY size (the TUI always does); otherwise headless.
//!
//! Honors `AGENTD_CLAUDE_BIN` for the binary path.
//! Honors `AGENTD_CLAUDE_CMD` for a full command prefix, falling back to
//! `AGENTD_CLAUDE_BIN` for a binary path.

use agentd_protocol::adapter::pty::{run_session as run_pty, PtySpec};
use agentd_protocol::adapter::{run, AdapterContext, AdapterInboxMsg, EventEmitter};
Expand Down Expand Up @@ -78,8 +79,13 @@ fn resolve_mode(params: &SessionStartParams) -> Mode {
}

async fn run_interactive(params: SessionStartParams, ctx: AdapterContext) {
let bin = std::env::var("AGENTD_CLAUDE_BIN").unwrap_or_else(|_| "claude".into());
let mut args = params.args.clone();
let command = agentd_protocol::adapter::resolve_command_override(
"AGENTD_CLAUDE_CMD",
"AGENTD_CLAUDE_BIN",
"claude",
);
let mut args = command.args.clone();
args.extend(params.args.clone());
if let Some(m) = params.model.as_ref() {
args.push("--model".into());
args.push(m.clone());
Expand All @@ -97,10 +103,9 @@ async fn run_interactive(params: SessionStartParams, ctx: AdapterContext) {
// daemon respawns us after a restart. claude's own session-persistence
// makes the conversation pick up where it left off.
let resuming = std::env::var("AGENTD_RESUME").as_deref() == Ok("1");
let sid_file =
std::env::var("AGENTD_SESSION_DATA_DIR").ok().map(|d| {
std::path::PathBuf::from(d).join("claude_session_id.txt")
});
let sid_file = std::env::var("AGENTD_SESSION_DATA_DIR")
.ok()
.map(|d| std::path::PathBuf::from(d).join("claude_session_id.txt"));
let claude_session_id = match (resuming, sid_file.as_ref()) {
(true, Some(p)) if p.exists() => std::fs::read_to_string(p)
.ok()
Expand Down Expand Up @@ -133,13 +138,17 @@ async fn run_interactive(params: SessionStartParams, ctx: AdapterContext) {
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
env.push(("AGENTD_SESSION_ID".into(), ctx.session_id.clone()));
let label = bin.clone();
let label = command.argv_preview();
let bin = command.bin;
let spec = PtySpec {
bin,
args,
cwd: std::path::PathBuf::from(&params.cwd),
env,
size: params.pty_size.unwrap_or(PtySize { cols: 100, rows: 30 }),
size: params.pty_size.unwrap_or(PtySize {
cols: 100,
rows: 30,
}),
status_detail: Some(format!("{label} (interactive)")),
};
let _ = run_pty(spec, ctx).await;
Expand All @@ -152,7 +161,11 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
mut inbox,
} = ctx;

let bin = std::env::var("AGENTD_CLAUDE_BIN").unwrap_or_else(|_| "claude".into());
let command_override = agentd_protocol::adapter::resolve_command_override(
"AGENTD_CLAUDE_CMD",
"AGENTD_CLAUDE_BIN",
"claude",
);
let cwd = PathBuf::from(&params.cwd);
let model = params.model.clone();
let extra_args = params.args.clone();
Expand Down Expand Up @@ -198,7 +211,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
});

// Build the per-turn child command args.
let mut child_args: Vec<String> = Vec::new();
let mut child_args: Vec<String> = command_override.args.clone();
child_args.push("-p".into());
child_args.push("--input-format".into());
child_args.push("stream-json".into());
Expand All @@ -220,7 +233,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
for a in &extra_args {
child_args.push(a.clone());
}
let mut command = Command::new(&bin);
let mut command = Command::new(&command_override.bin);
for a in &child_args {
command.arg(a);
}
Expand All @@ -239,7 +252,10 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
Ok(c) => c,
Err(e) => {
emit.emit(SessionEvent::Error {
message: agentd_protocol::adapter::missing_bin_hint(&bin, &e),
message: agentd_protocol::adapter::missing_bin_hint(
&command_override.argv_preview(),
&e,
),
});
break 127;
}
Expand All @@ -253,8 +269,7 @@ async fn run_session(params: SessionStartParams, ctx: AdapterContext) {
let writer_task = spawn_writer(child_stdin, user_text.clone());
let stderr_task = spawn_stderr_log(child_stderr, emit.clone());
let captured_sid = Arc::new(StdMutex::new(None::<String>));
let parser_task =
spawn_parser(child_stdout, emit.clone(), captured_sid.clone());
let parser_task = spawn_parser(child_stdout, emit.clone(), captured_sid.clone());

// Drive the child: queue mid-turn inputs, honor stop/interrupt.
let outcome = drive_turn(&mut child, &mut inbox, &emit, &mut pending).await;
Expand Down Expand Up @@ -333,7 +348,10 @@ async fn drive_turn(
}
}

fn spawn_writer(mut stdin: tokio::process::ChildStdin, user_text: String) -> tokio::task::JoinHandle<()> {
fn spawn_writer(
mut stdin: tokio::process::ChildStdin,
user_text: String,
) -> tokio::task::JoinHandle<()> {
let msg = serde_json::json!({
"type": "user",
"message": {
Expand Down Expand Up @@ -486,7 +504,10 @@ fn extract_message_text(msg: Option<&Value>) -> String {
}

fn forward_tool_uses(emit: &EventEmitter, msg: Option<&Value>) {
let Some(arr) = msg.and_then(|m| m.get("content")).and_then(|c| c.as_array()) else {
let Some(arr) = msg
.and_then(|m| m.get("content"))
.and_then(|c| c.as_array())
else {
return;
};
for block in arr {
Expand All @@ -506,7 +527,10 @@ fn forward_tool_uses(emit: &EventEmitter, msg: Option<&Value>) {
}

fn forward_tool_results(emit: &EventEmitter, msg: Option<&Value>) {
let Some(arr) = msg.and_then(|m| m.get("content")).and_then(|c| c.as_array()) else {
let Some(arr) = msg
.and_then(|m| m.get("content"))
.and_then(|c| c.as_array())
else {
return;
};
for block in arr {
Expand Down
Loading
Loading