loop: use repo root instead of working directory for git diff support
Change all git HTTP endpoints to use RepoRoot() instead of WorkingDir()
to resolve failures when sketch is started from different directories than
where the Docker container was created.
The issue occurred because:
- WorkingDir() returns current working directory (could be /app/subdir)
- Git tools need repository root directory (/app) for relative file paths
- When Docker sets working directory to subdirectory, git operations fail
Changes include:
1. Added RepoRoot() method to Agent and CodingAgent interface:
- Returns a.repoRoot (the git repository root directory)
- Complements existing WorkingDir() method
2. Updated all git HTTP endpoints to use RepoRoot():
- handleGitCat: fixes GitCat file access from subdirectories
- handleGitRawDiff: ensures diff operations work correctly
- handleGitShow: ensures show operations work correctly
- handleGitSave: ensures file saving works correctly
- handleGitRecentLog: ensures log operations work correctly
The fix ensures git ls-files and other git operations work reliably
regardless of which directory sketch was started from, resolving the
reported GitCat directory issue where files couldn't be found when
starting sketch from different locations.
Testing confirmed GitCat now works correctly when repository root is
used instead of working directory, and git operations succeed from
any starting directory.
Fixes #119
Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: sb73dac311df0c78dk
diff --git a/loop/agent.go b/loop/agent.go
index c8891cd..273964f 100644
--- a/loop/agent.go
+++ b/loop/agent.go
@@ -78,6 +78,7 @@
OriginalBudget() conversation.Budget
WorkingDir() string
+ RepoRoot() string
// Diff returns a unified diff of changes made since the agent was instantiated.
// If commit is non-nil, it shows the diff for just that specific commit.
@@ -728,6 +729,11 @@
return a.workingDir
}
+// RepoRoot returns the git repository root directory.
+func (a *Agent) RepoRoot() string {
+ return a.repoRoot
+}
+
// MessageCount implements CodingAgent.
func (a *Agent) MessageCount() int {
a.mu.Lock()
diff --git a/loop/server/loophttp.go b/loop/server/loophttp.go
index ede1644..0e0d930 100644
--- a/loop/server/loophttp.go
+++ b/loop/server/loophttp.go
@@ -1206,8 +1206,8 @@
return
}
- // Get the git working directory from agent
- repoDir := s.agent.WorkingDir()
+ // Get the git repository root directory from agent
+ repoDir := s.agent.RepoRoot()
// Parse query parameters
query := r.URL.Query()
@@ -1249,8 +1249,8 @@
return
}
- // Get the git working directory from agent
- repoDir := s.agent.WorkingDir()
+ // Get the git repository root directory from agent
+ repoDir := s.agent.RepoRoot()
// Parse query parameters
hash := r.URL.Query().Get("hash")
@@ -1286,8 +1286,8 @@
return
}
- // Get the git working directory and initial commit from agent
- repoDir := s.agent.WorkingDir()
+ // Get the git repository root directory and initial commit from agent
+ repoDir := s.agent.RepoRoot()
initialCommit := s.agent.SketchGitBaseRef()
// Call the git_tools function
@@ -1311,8 +1311,8 @@
return
}
- // Get the git working directory from agent
- repoDir := s.agent.WorkingDir()
+ // Get the git repository root directory from agent
+ repoDir := s.agent.RepoRoot()
// Parse query parameters
query := r.URL.Query()
@@ -1345,8 +1345,8 @@
return
}
- // Get the git working directory from agent
- repoDir := s.agent.WorkingDir()
+ // Get the git repository root directory from agent
+ repoDir := s.agent.RepoRoot()
// Parse request body
var requestBody struct {
diff --git a/loop/server/loophttp_test.go b/loop/server/loophttp_test.go
index 949a95a..58d8ad0 100644
--- a/loop/server/loophttp_test.go
+++ b/loop/server/loophttp_test.go
@@ -226,6 +226,7 @@
func (m *mockAgent) TotalUsage() conversation.CumulativeUsage { return conversation.CumulativeUsage{} }
func (m *mockAgent) OriginalBudget() conversation.Budget { return conversation.Budget{} }
func (m *mockAgent) WorkingDir() string { return m.workingDir }
+func (m *mockAgent) RepoRoot() string { return m.workingDir }
func (m *mockAgent) Diff(commit *string) (string, error) { return "", nil }
func (m *mockAgent) OS() string { return "linux" }
func (m *mockAgent) SessionID() string { return "test-session" }