Keep a typed path as typed, and expand ~ where it is used

A llama session's tools all answered "failed to spawn process
[exit code: -1]": `llama-server` takes the working directory as an
`x-tool-cwd` header and `chdir`s to it with no shell in the way, so a
`~/…` cwd named a directory of that name. `files::resolve_blocking`
asks the machine that will serve the session what the path is, and the
driver does that once at launch.

The other half is the storing. `~` and `/home/someone` are a path and a
snapshot of where it pointed, and it is the snapshot that breaks when an
account is renamed -- so `machines::tidy` no longer expands one and
`set_cwd` no longer contracts one (`shorten_home` is gone with it). The
identity file is expanded at the point `ssh` is invoked instead.

Spawn now asks the same question of a typed working directory that
`set_cwd` already did: absolute or home-relative, and actually there on
the machine that will run it. It accepted anything, so a typo became a
session whose process could not start, reported later and pointing at
nothing.

Also: a provider written before `mcp_servers` existed adopts the
defaults a probe would give it now, so a machine discovered before
2026-09-19 stops silently having no web search.

Exercised end to end against a real llama session spawned with
`cwd: "~/repos/ai-app/server"`: `exec_shell_command` with `pwd` answered
`/home/bob/repos/ai-app/server`, exit 0.
This commit is contained in:
iris-ai committed 2026-09-20 17:06:13 -04:00
1 parent bd9596d782
commit 3b309766d7
8 files changed
+201 -101

No files matched your search

+5 -1
View File
@@ -107,7 +107,11 @@ pub fn command(
command.args(["-p", &port.to_string()]);
}
if let Some(identity) = &ssh.identity_file {
command.arg("-i").arg(identity);
// Expanded here rather than when it was typed: this one *is* a path on
// this machine, but storing what `~` resolved to on the day it was
// entered is what breaks when the account is renamed. There is no shell
// between here and `ssh`, so nothing else would expand it.
command.arg("-i").arg(expand_home(identity));
// Without this, ssh may offer an agent key first and authenticate as
// somebody else entirely -- silently, and with different permissions.
command.args(["-o", "IdentitiesOnly=yes"]);