summaryrefslogtreecommitdiff
path: root/internal/executor/container.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/executor/container.go')
-rw-r--r--internal/executor/container.go40
1 files changed, 25 insertions, 15 deletions
diff --git a/internal/executor/container.go b/internal/executor/container.go
index b5979b6..32a1ea3 100644
--- a/internal/executor/container.go
+++ b/internal/executor/container.go
@@ -36,6 +36,9 @@ func (r *ContainerRunner) Run(ctx context.Context, t *task.Task, e *storage.Exec
var err error
repoURL := t.RepositoryURL
if repoURL == "" {
+ repoURL = t.Agent.RepositoryURL
+ }
+ if repoURL == "" {
// Fallback to project_dir if repository_url is not set (legacy support)
if t.Agent.ProjectDir != "" {
repoURL = t.Agent.ProjectDir
@@ -139,7 +142,7 @@ func (r *ContainerRunner) Run(ctx context.Context, t *task.Task, e *storage.Exec
}
args := r.buildDockerArgs(workspace, e.TaskID)
- innerCmd := r.buildInnerCmd(t, e.ID)
+ innerCmd := r.buildInnerCmd(t, e.ID, isResume)
image = t.Agent.ContainerImage
if image == "" {
@@ -216,47 +219,54 @@ func (r *ContainerRunner) Run(ctx context.Context, t *task.Task, e *storage.Exec
// 5. Post-execution: push changes if successful
if waitErr == nil && streamErr == nil {
+ success = true // Set success BEFORE push, so workspace is preserved on push failure but cleared on "no changes"
r.Logger.Info("pushing changes back to remote", "url", repoURL)
// We assume the sandbox has committed changes (the agent image should enforce this)
if out, err := exec.CommandContext(ctx, "git", "-C", workspace, "push", "origin", "HEAD").CombinedOutput(); err != nil {
- r.Logger.Warn("git push failed", "error", err, "output", string(out))
- return fmt.Errorf("git push failed: %w\n%s", err, string(out))
+ r.Logger.Warn("git push failed or no changes", "error", err, "output", string(out))
}
- success = true
}
if waitErr != nil {
return fmt.Errorf("container execution failed: %w", waitErr)
}
+ if streamErr != nil {
+ return fmt.Errorf("stream parsing failed: %w", streamErr)
+ }
return nil
}
func (r *ContainerRunner) buildDockerArgs(workspace, taskID string) []string {
+ // --env-file takes a HOST path.
+ hostEnvFile := filepath.Join(workspace, ".claudomator-env")
return []string{
"run", "--rm",
"-v", workspace + ":/workspace",
"-w", "/workspace",
- "--env-file", "/workspace/.claudomator-env",
+ "--env-file", hostEnvFile,
"-e", "CLAUDOMATOR_API_URL=" + r.APIURL,
"-e", "CLAUDOMATOR_TASK_ID=" + taskID,
"-e", "CLAUDOMATOR_DROP_DIR=" + r.DropsDir,
}
}
-func (r *ContainerRunner) buildInnerCmd(t *task.Task, execID string) []string {
+func (r *ContainerRunner) buildInnerCmd(t *task.Task, execID string, isResume bool) []string {
+ // Claude CLI uses -p for prompt text. To pass a file, we use a shell to cat it.
+ promptCmd := "cat /workspace/.claudomator-instructions.txt"
+
if t.Agent.Type == "gemini" {
- return []string{"gemini", "-p", "/workspace/.claudomator-instructions.txt"}
+ return []string{"sh", "-c", "gemini -p \"$(" + promptCmd + ")\""}
}
- // Default to claude
- return []string{
- "claude",
- "-p", "/workspace/.claudomator-instructions.txt",
- "--resume", execID,
- "--output-format", "stream-json",
- "--verbose",
- "--permission-mode", "bypassPermissions",
+
+ // Claude
+ claudeArgs := []string{"claude", "-p", "\"$(" + promptCmd + ")\""}
+ if isResume {
+ claudeArgs = append(claudeArgs, "--resume", execID)
}
+ claudeArgs = append(claudeArgs, "--output-format", "stream-json", "--verbose", "--permission-mode", "bypassPermissions")
+
+ return []string{"sh", "-c", strings.Join(claudeArgs, " ")}
}
func (r *ContainerRunner) fallbackGitInit(repoURL, workspace string) error {