feat: add proxyctl daemon manager, fix standalone LS cleanup
- Add proxyctl CLI script for systemd service management - Add systemd user service file for background operation - Fix standalone LS kill: properly track real LS PID via pgrep and use sudo kill for cross-user cleanup on shutdown - Remove deprecated scripts (dns-redirect, iptables-redirect, mitm-wrapper, standalone-ls, parse-snapshot) - Disable tool stripping in MITM for tool call investigation - Update GEMINI.md with CLI tools documentation
This commit is contained in:
@@ -9,7 +9,8 @@ use serde_json::Value;
|
||||
use tracing::info;
|
||||
|
||||
/// Strip ALL tool definitions.
|
||||
const STRIP_ALL_TOOLS: bool = true;
|
||||
/// Set to false to allow tools through (for tool call testing).
|
||||
const STRIP_ALL_TOOLS: bool = false;
|
||||
|
||||
/// Modify a streamGenerateContent request body in-place.
|
||||
/// Returns the modified JSON bytes, or None if modification wasn't possible.
|
||||
|
||||
@@ -29,6 +29,10 @@ const LS_USER: &str = "antigravity-ls";
|
||||
/// A running standalone LS process.
|
||||
pub struct StandaloneLS {
|
||||
child: Child,
|
||||
/// The actual LS process PID (may differ from child PID when spawned via sudo).
|
||||
ls_pid: Option<u32>,
|
||||
/// Whether the LS was spawned via sudo (needs sudo kill).
|
||||
use_sudo: bool,
|
||||
pub port: u16,
|
||||
pub csrf: String,
|
||||
}
|
||||
@@ -196,8 +200,25 @@ impl StandaloneLS {
|
||||
|
||||
info!(pid = child.id(), port, "Standalone LS spawned");
|
||||
|
||||
// When spawned via sudo, the child is the sudo process which exits after
|
||||
// launching the LS as the target user. We need the actual LS PID for cleanup.
|
||||
let ls_pid = if use_sudo {
|
||||
// Give sudo a moment to spawn the real process
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
// Find the LS process owned by antigravity-ls user
|
||||
find_ls_pid_for_user(LS_USER).ok()
|
||||
} else {
|
||||
Some(child.id())
|
||||
};
|
||||
|
||||
if let Some(pid) = ls_pid {
|
||||
info!(ls_pid = pid, sudo = use_sudo, "Discovered actual LS process");
|
||||
}
|
||||
|
||||
Ok(StandaloneLS {
|
||||
child,
|
||||
ls_pid,
|
||||
use_sudo,
|
||||
port,
|
||||
csrf: main_config.csrf.clone(),
|
||||
})
|
||||
@@ -239,8 +260,25 @@ impl StandaloneLS {
|
||||
/// Kill the standalone LS process.
|
||||
pub fn kill(&mut self) {
|
||||
info!("Killing standalone LS");
|
||||
let _ = self.child.kill();
|
||||
let _ = self.child.wait();
|
||||
|
||||
if self.use_sudo {
|
||||
// The child is sudo which already exited. Kill the actual LS via sudo.
|
||||
if let Some(pid) = self.ls_pid {
|
||||
info!(pid, "Killing LS process via sudo");
|
||||
let _ = std::process::Command::new("sudo")
|
||||
.args(["-n", "kill", "-TERM", &pid.to_string()])
|
||||
.status();
|
||||
// Give it a moment to exit gracefully
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
// Force kill if still alive
|
||||
let _ = std::process::Command::new("sudo")
|
||||
.args(["-n", "kill", "-KILL", &pid.to_string()])
|
||||
.status();
|
||||
}
|
||||
} else {
|
||||
let _ = self.child.kill();
|
||||
let _ = self.child.wait();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +404,23 @@ fn has_ls_user() -> bool {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Find the PID of a language_server process owned by a specific user.
|
||||
///
|
||||
/// Used to discover the actual LS process after sudo spawns it as a different user.
|
||||
fn find_ls_pid_for_user(user: &str) -> Result<u32, String> {
|
||||
let output = Command::new("pgrep")
|
||||
.args(["-u", user, "-f", "language_server_linux"])
|
||||
.output()
|
||||
.map_err(|e| format!("pgrep failed: {e}"))?;
|
||||
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
stdout
|
||||
.lines()
|
||||
.next()
|
||||
.and_then(|line| line.trim().parse::<u32>().ok())
|
||||
.ok_or_else(|| format!("No LS process found for user {user}"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user