codetether_agent/a2a/git_credentials/
helper.rs1use anyhow::{Result, anyhow};
13
14use super::gh_cli::{emit_credentials_via_gh_cli, should_delegate_to_gh_cli};
15use super::request_git_credentials;
16use super::stdin_query::read_git_credential_query_from_stdin;
17
18pub async fn run_git_credential_helper(args: &crate::cli::GitCredentialHelperArgs) -> Result<()> {
29 let operation = args.operation.as_deref().unwrap_or("get").trim();
30 if matches!(operation, "store" | "erase") {
31 return Ok(());
32 }
33 let query = read_git_credential_query_from_stdin()?;
34 let server = args
35 .server
36 .clone()
37 .or_else(|| std::env::var("CODETETHER_SERVER").ok())
38 .ok_or_else(|| anyhow!("CODETETHER_SERVER is not set for Git credential helper"))?;
39 let token = args
40 .token
41 .clone()
42 .or_else(|| std::env::var("CODETETHER_TOKEN").ok());
43 let worker_id = args
44 .worker_id
45 .clone()
46 .or_else(|| std::env::var("CODETETHER_WORKER_ID").ok());
47 let creds = request_git_credentials(
48 &server,
49 &token,
50 worker_id.as_deref(),
51 &args.workspace_id,
52 operation,
53 &query,
54 )
55 .await?;
56 if let Some(creds) = creds {
57 if should_delegate_to_gh_cli(&query, &creds) {
58 match emit_credentials_via_gh_cli(&query, &creds) {
59 Ok(()) => return Ok(()),
60 Err(e) => {
61 tracing::warn!(
62 error = %e,
63 "gh CLI delegation failed, falling back to direct credential output"
64 );
65 }
66 }
67 }
68 println!("username={}", creds.username);
69 println!("password={}", creds.password);
70 println!();
71 }
72 Ok(())
73}