merge: resolve conflicts with main (workdir reuse)
Main added execenv.Reuse() for workdir reuse across tasks on the same issue. Our branch removed Type/BranchName/gitRoot from Environment (repos are now checked out on demand). Resolution: keep Reuse() but simplify it to work with the new Environment struct (no workspace type tracking). Keep the "reused" log field from main, drop removed fields.
This commit is contained in:
commit
99ada27925
5 changed files with 49 additions and 15 deletions
|
|
@ -624,26 +624,33 @@ func (d *Daemon) runTask(ctx context.Context, task Task, provider string) (TaskR
|
|||
AgentSkills: convertSkillsForEnv(skills),
|
||||
Repos: convertReposForEnv(task.Repos),
|
||||
}
|
||||
env, err := execenv.Prepare(execenv.PrepareParams{
|
||||
WorkspacesRoot: d.cfg.WorkspacesRoot,
|
||||
TaskID: task.ID,
|
||||
AgentName: agentName,
|
||||
Provider: provider,
|
||||
Task: taskCtx,
|
||||
}, d.logger)
|
||||
if err != nil {
|
||||
return TaskResult{}, fmt.Errorf("prepare execution environment: %w", err)
|
||||
|
||||
// Try to reuse the workdir from a previous task on the same (agent, issue) pair.
|
||||
var env *execenv.Environment
|
||||
if task.PriorWorkDir != "" {
|
||||
env = execenv.Reuse(task.PriorWorkDir, provider, taskCtx, d.logger)
|
||||
}
|
||||
if env == nil {
|
||||
var err error
|
||||
env, err = execenv.Prepare(execenv.PrepareParams{
|
||||
WorkspacesRoot: d.cfg.WorkspacesRoot,
|
||||
TaskID: task.ID,
|
||||
AgentName: agentName,
|
||||
Provider: provider,
|
||||
Task: taskCtx,
|
||||
}, d.logger)
|
||||
if err != nil {
|
||||
return TaskResult{}, fmt.Errorf("prepare execution environment: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Inject runtime-specific config (meta skill) so the agent discovers .agent_context/.
|
||||
if err := execenv.InjectRuntimeConfig(env.WorkDir, provider, taskCtx); err != nil {
|
||||
d.logger.Warn("execenv: inject runtime config failed (non-fatal)", "error", err)
|
||||
}
|
||||
defer func() {
|
||||
if cleanupErr := env.Cleanup(!d.cfg.KeepEnvAfterTask); cleanupErr != nil {
|
||||
d.logger.Warn("cleanup env failed", "task_id", task.ID, "error", cleanupErr)
|
||||
}
|
||||
}()
|
||||
// NOTE: No cleanup — workdir is preserved for reuse by future tasks on
|
||||
// the same (agent, issue) pair. The work_dir path is stored in DB on
|
||||
// task completion and passed back via PriorWorkDir on the next claim.
|
||||
|
||||
prompt := BuildPrompt(task)
|
||||
|
||||
|
|
@ -671,7 +678,7 @@ func (d *Daemon) runTask(ctx context.Context, task Task, provider string) (TaskR
|
|||
return TaskResult{}, fmt.Errorf("create agent backend: %w", err)
|
||||
}
|
||||
|
||||
d.logger.Info("starting agent", "provider", provider, "task_id", task.ID, "workdir", env.WorkDir, "model", entry.Model, "timeout", d.cfg.AgentTimeout.String(), "resume_session", task.PriorSessionID)
|
||||
d.logger.Info("starting agent", "provider", provider, "task_id", task.ID, "workdir", env.WorkDir, "reused", task.PriorWorkDir != "" && env.WorkDir == task.PriorWorkDir, "model", entry.Model, "timeout", d.cfg.AgentTimeout.String(), "resume_session", task.PriorSessionID)
|
||||
|
||||
session, err := backend.Execute(ctx, prompt, agent.ExecOptions{
|
||||
Cwd: env.WorkDir,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,28 @@ func Prepare(params PrepareParams, logger *slog.Logger) (*Environment, error) {
|
|||
return env, nil
|
||||
}
|
||||
|
||||
// Reuse wraps an existing workdir into an Environment and refreshes context files.
|
||||
// Returns nil if the workdir does not exist (caller should fall back to Prepare).
|
||||
func Reuse(workDir, provider string, task TaskContextForEnv, logger *slog.Logger) *Environment {
|
||||
if _, err := os.Stat(workDir); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
env := &Environment{
|
||||
RootDir: filepath.Dir(workDir),
|
||||
WorkDir: workDir,
|
||||
logger: logger,
|
||||
}
|
||||
|
||||
// Refresh context files (issue_context.md, skills).
|
||||
if err := writeContextFiles(workDir, provider, task); err != nil {
|
||||
logger.Warn("execenv: refresh context files failed", "error", err)
|
||||
}
|
||||
|
||||
logger.Info("execenv: reusing env", "workdir", workDir)
|
||||
return env
|
||||
}
|
||||
|
||||
// Cleanup tears down the execution environment.
|
||||
// If removeAll is true, the entire env root is deleted. Otherwise, workdir is
|
||||
// removed but output/ and logs/ are preserved for debugging.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ type Task struct {
|
|||
Agent *AgentData `json:"agent,omitempty"`
|
||||
Repos []RepoData `json:"repos,omitempty"`
|
||||
PriorSessionID string `json:"prior_session_id,omitempty"` // Claude session ID from a previous task on this issue
|
||||
PriorWorkDir string `json:"prior_work_dir,omitempty"` // work_dir from a previous task on this issue
|
||||
}
|
||||
|
||||
// AgentData holds agent details returned by the claim endpoint.
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ type AgentTaskResponse struct {
|
|||
Repos []RepoData `json:"repos,omitempty"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
PriorSessionID string `json:"prior_session_id,omitempty"` // session ID from a previous task on same issue
|
||||
PriorWorkDir string `json:"prior_work_dir,omitempty"` // work_dir from a previous task on same issue
|
||||
}
|
||||
|
||||
// TaskAgentData holds agent info included in claim responses so the daemon
|
||||
|
|
|
|||
|
|
@ -244,6 +244,9 @@ func (h *Handler) ClaimTaskByRuntime(w http.ResponseWriter, r *http.Request) {
|
|||
IssueID: task.IssueID,
|
||||
}); err == nil && prior.SessionID.Valid {
|
||||
resp.PriorSessionID = prior.SessionID.String
|
||||
if prior.WorkDir.Valid {
|
||||
resp.PriorWorkDir = prior.WorkDir.String
|
||||
}
|
||||
}
|
||||
|
||||
slog.Info("task claimed by runtime", "task_id", uuidToString(task.ID), "runtime_id", runtimeID, "agent_id", uuidToString(task.AgentID), "prior_session", resp.PriorSessionID)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue