store: expand ~ and env vars in cwd at session creation

When cwd was passed with ~ or $HOME (e.g. ~/src/myproj), it was used
unexpanded in BuildAgentEnv -> resolvePrompt, causing prompt commands
to fail silently (invalid cmd.Dir) and producing an empty system prompt.

Apply os.ExpandEnv + paths.ExpandHome before cwd is used anywhere.
This commit is contained in:
Levi Neely 2026-05-11 14:20:19 +02:00
parent b4237c326c
commit 73b166d276
2 changed files with 56 additions and 0 deletions

View File

@ -336,6 +336,7 @@ func (s *SessionStore) createSession(args []string) error {
}
}
cwd = paths.ExpandHome(os.ExpandEnv(cwd))
if cwd == "" {
return fmt.Errorf("cwd is required (e.g. new cwd=/path/to/project)")
}

View File

@ -1402,6 +1402,61 @@ func TestSessionStoreCreateSessionUnknownKey(t *testing.T) {
}
}
func TestSessionStoreCreateSessionEnvExpansion(t *testing.T) {
home, err := os.UserHomeDir()
if err != nil {
t.Skip("no home dir")
}
t.Setenv("HOME", home)
var gotCwd string
sink := testSink()
s := store.NewSessionStore(store.SessionStoreConfig{
Log: sink.NewLogger("test"),
Sink: sink,
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
MkdirAll: func(string, os.FileMode) error { return nil },
NewCore: func(sessionID, agentName, cwd string) (agent.Core, error) {
gotCwd = cwd
return &stubCore{state: "idle", backend: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
},
})
e, _ := s.Open("new")
if err := e.Write([]byte("name=envtest cwd=$HOME/")); err != nil {
t.Fatalf("Write(new): %v", err)
}
if gotCwd != home+"/" {
t.Errorf("cwd env not expanded: got %q, want %q", gotCwd, home+"/")
}
s.KillSession("envtest")
}
func TestSessionStoreCreateSessionTildeExpansion(t *testing.T) {
home, err := os.UserHomeDir()
if err != nil {
t.Skip("no home dir")
}
var gotCwd string
sink := testSink()
s := store.NewSessionStore(store.SessionStoreConfig{
Log: sink.NewLogger("test"),
Sink: sink,
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
MkdirAll: func(string, os.FileMode) error { return nil },
NewCore: func(sessionID, agentName, cwd string) (agent.Core, error) {
gotCwd = cwd
return &stubCore{state: "idle", backend: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
},
})
e, _ := s.Open("new")
if err := e.Write([]byte("name=tildetest cwd=~/")); err != nil {
t.Fatalf("Write(new): %v", err)
}
if gotCwd != home+"/" {
t.Errorf("cwd not expanded: got %q, want %q", gotCwd, home+"/")
}
s.KillSession("tildetest")
}
// ===== openEntry not-found =====
func TestSessionStoreOpenEntryNotFound(t *testing.T) {