fix(mcp): fallback déterministe du runtime dir socket
`unix_runtime_dir` essaie désormais les bases candidates dans l'ordre de priorité ($XDG_RUNTIME_DIR → $TMPDIR → /tmp) et retient la première dont le sous-dossier `idea-mcp` existe ou peut être créé. Un $XDG_RUNTIME_DIR positionné mais inutilisable (sandbox/CI pointant un chemin inexistant ou en lecture seule) ne doit plus dead-end le bind loopback : sans ce fallback le socket ne se liait jamais en silence et la délégation inter-agents mourait. Déterministe pour un environnement donné, donc le côté bind et tout lecteur de `socket_path()` s'accordent sur le même répertoire. Indépendant du Lot E1. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -87,13 +87,29 @@ impl McpEndpoint {
|
||||
/// per-user runtime dir (`$XDG_RUNTIME_DIR`, falling back to `$TMPDIR`, then
|
||||
/// `/tmp`). Kept short so the full socket path stays well under the ~108-byte
|
||||
/// `sockaddr_un` limit (`/run/user/<uid>/idea-mcp/<32 hex>.sock` ≈ 50 bytes).
|
||||
///
|
||||
/// The candidate bases are tried **in priority order**, returning the first whose
|
||||
/// `idea-mcp` subdir exists or can be created. A set-but-unusable `$XDG_RUNTIME_DIR`
|
||||
/// (e.g. a sandbox/CI where it points at a non-existent or read-only path) must not
|
||||
/// dead-end the loopback bind: without this fallback the socket silently never
|
||||
/// binds and inter-agent delegation dies. Deterministic for a given environment, so
|
||||
/// the bind side and any `socket_path()` reader always agree on the same directory.
|
||||
#[cfg(unix)]
|
||||
fn unix_runtime_dir() -> PathBuf {
|
||||
let base = std::env::var_os("XDG_RUNTIME_DIR")
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| std::env::var_os("TMPDIR").map(PathBuf::from))
|
||||
.unwrap_or_else(|| PathBuf::from("/tmp"));
|
||||
base.join("idea-mcp")
|
||||
let candidates = [
|
||||
std::env::var_os("XDG_RUNTIME_DIR").map(PathBuf::from),
|
||||
std::env::var_os("TMPDIR").map(PathBuf::from),
|
||||
Some(PathBuf::from("/tmp")),
|
||||
];
|
||||
for base in candidates.into_iter().flatten() {
|
||||
let dir = base.join("idea-mcp");
|
||||
if dir.is_dir() || std::fs::create_dir_all(&dir).is_ok() {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
// Last resort: keep the historical `/tmp` target even if creation just failed
|
||||
// (the bind will surface the real error rather than silently picking nowhere).
|
||||
PathBuf::from("/tmp").join("idea-mcp")
|
||||
}
|
||||
|
||||
/// **Single source of truth.** Computes the deterministic loopback endpoint of a
|
||||
|
||||
Reference in New Issue
Block a user