feat: return worktree info in orchestrator.start response
- Add WorktreePath and WorktreeBranch to StartTaskResponse - Add those fields to TaskExecution and LaunchAgentResponse - Store worktree_path and worktree_branch in AgentInstance metadata - Update frontend to use worktree info from start response directly
This commit is contained in:
@@ -599,10 +599,23 @@ func (a *lifecycleAdapter) LaunchAgent(ctx context.Context, req *executor.Launch
|
||||
|
||||
// Streaming is now handled by the lifecycle manager
|
||||
|
||||
// Extract worktree info from metadata if available
|
||||
var worktreePath, worktreeBranch string
|
||||
if instance.Metadata != nil {
|
||||
if path, ok := instance.Metadata["worktree_path"].(string); ok {
|
||||
worktreePath = path
|
||||
}
|
||||
if branch, ok := instance.Metadata["worktree_branch"].(string); ok {
|
||||
worktreeBranch = branch
|
||||
}
|
||||
}
|
||||
|
||||
return &executor.LaunchAgentResponse{
|
||||
AgentInstanceID: instance.ID,
|
||||
ContainerID: instance.ContainerID,
|
||||
Status: instance.Status,
|
||||
WorktreePath: worktreePath,
|
||||
WorktreeBranch: worktreeBranch,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -304,6 +304,7 @@ func (m *Manager) Launch(ctx context.Context, req *LaunchRequest) (*AgentInstanc
|
||||
workspacePath := req.WorkspacePath
|
||||
var mainRepoGitDir string // Path to main repo's .git directory for container mount
|
||||
var worktreeID string // Store worktree ID for session resumption
|
||||
var worktreeBranch string // Store worktree branch for API responses
|
||||
if req.UseWorktree && m.worktreeMgr != nil && req.RepositoryPath != "" {
|
||||
wt, err := m.getOrCreateWorktree(ctx, req)
|
||||
if err != nil {
|
||||
@@ -314,6 +315,7 @@ func (m *Manager) Launch(ctx context.Context, req *LaunchRequest) (*AgentInstanc
|
||||
} else {
|
||||
workspacePath = wt.Path
|
||||
worktreeID = wt.ID
|
||||
worktreeBranch = wt.Branch
|
||||
// Git worktrees reference the main repo's .git directory via a .git file
|
||||
// The worktree metadata in .git/worktrees/{name} contains a 'commondir' file
|
||||
// that points back to the main .git directory (usually '../..')
|
||||
@@ -365,9 +367,11 @@ func (m *Manager) Launch(ctx context.Context, req *LaunchRequest) (*AgentInstanc
|
||||
if instanceMetadata == nil {
|
||||
instanceMetadata = make(map[string]interface{})
|
||||
}
|
||||
// Store worktree_id in metadata for session resumption
|
||||
// Store worktree info in metadata for session resumption and API responses
|
||||
if worktreeID != "" {
|
||||
instanceMetadata["worktree_id"] = worktreeID
|
||||
instanceMetadata["worktree_path"] = workspacePath
|
||||
instanceMetadata["worktree_branch"] = worktreeBranch
|
||||
}
|
||||
instance := &AgentInstance{
|
||||
ID: instanceID,
|
||||
|
||||
@@ -67,12 +67,22 @@ func (c *Controller) StartTask(ctx context.Context, req dto.StartTaskRequest) (d
|
||||
return dto.StartTaskResponse{}, err
|
||||
}
|
||||
|
||||
return dto.StartTaskResponse{
|
||||
resp := dto.StartTaskResponse{
|
||||
Success: true,
|
||||
TaskID: execution.TaskID,
|
||||
AgentInstanceID: execution.AgentInstanceID,
|
||||
Status: string(execution.Status),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Include worktree info if available
|
||||
if execution.WorktreePath != "" {
|
||||
resp.WorktreePath = &execution.WorktreePath
|
||||
}
|
||||
if execution.WorktreeBranch != "" {
|
||||
resp.WorktreeBranch = &execution.WorktreeBranch
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// StopTask stops task execution
|
||||
|
||||
@@ -51,10 +51,12 @@ type StartTaskRequest struct {
|
||||
|
||||
// StartTaskResponse is the response for orchestrator.start
|
||||
type StartTaskResponse struct {
|
||||
Success bool `json:"success"`
|
||||
TaskID string `json:"task_id"`
|
||||
AgentInstanceID string `json:"agent_instance_id"`
|
||||
Status string `json:"status"`
|
||||
Success bool `json:"success"`
|
||||
TaskID string `json:"task_id"`
|
||||
AgentInstanceID string `json:"agent_instance_id"`
|
||||
Status string `json:"status"`
|
||||
WorktreePath *string `json:"worktree_path,omitempty"`
|
||||
WorktreeBranch *string `json:"worktree_branch,omitempty"`
|
||||
}
|
||||
|
||||
// StopTaskRequest is the payload for orchestrator.stop
|
||||
|
||||
@@ -77,6 +77,8 @@ type LaunchAgentResponse struct {
|
||||
AgentInstanceID string
|
||||
ContainerID string
|
||||
Status v1.AgentStatus
|
||||
WorktreePath string
|
||||
WorktreeBranch string
|
||||
}
|
||||
|
||||
// TaskExecution tracks an active task execution (kept for API compatibility)
|
||||
@@ -90,6 +92,9 @@ type TaskExecution struct {
|
||||
LastUpdate time.Time
|
||||
// SessionID is the database ID of the agent session
|
||||
SessionID string
|
||||
// Worktree info for the agent
|
||||
WorktreePath string
|
||||
WorktreeBranch string
|
||||
}
|
||||
|
||||
// FromAgentSession converts a models.AgentSession to TaskExecution
|
||||
@@ -341,6 +346,8 @@ func (e *Executor) Execute(ctx context.Context, task *v1.Task) (*TaskExecution,
|
||||
Progress: 0,
|
||||
LastUpdate: now,
|
||||
SessionID: sessionID,
|
||||
WorktreePath: resp.WorktreePath,
|
||||
WorktreeBranch: resp.WorktreeBranch,
|
||||
}
|
||||
|
||||
e.mu.Lock()
|
||||
@@ -351,7 +358,9 @@ func (e *Executor) Execute(ctx context.Context, task *v1.Task) (*TaskExecution,
|
||||
zap.String("task_id", task.ID),
|
||||
zap.String("session_id", sessionID),
|
||||
zap.String("agent_instance_id", resp.AgentInstanceID),
|
||||
zap.String("container_id", resp.ContainerID))
|
||||
zap.String("container_id", resp.ContainerID),
|
||||
zap.String("worktree_path", resp.WorktreePath),
|
||||
zap.String("worktree_branch", resp.WorktreeBranch))
|
||||
|
||||
return execution, nil
|
||||
}
|
||||
|
||||
@@ -162,25 +162,25 @@ export default function TaskPage({ task: initialTask }: TaskPageClientProps) {
|
||||
try {
|
||||
// Use task's agent_type if set, otherwise default to 'augment-agent'
|
||||
const agentType = task.agent_type ?? 'augment-agent';
|
||||
await client.request('orchestrator.start', {
|
||||
interface StartResponse {
|
||||
success: boolean;
|
||||
task_id: string;
|
||||
agent_instance_id: string;
|
||||
status: string;
|
||||
worktree_path?: string;
|
||||
worktree_branch?: string;
|
||||
}
|
||||
const response = await client.request<StartResponse>('orchestrator.start', {
|
||||
task_id: task.id,
|
||||
agent_type: agentType,
|
||||
}, 15000);
|
||||
setIsAgentRunning(true);
|
||||
|
||||
// Fetch updated task info after agent starts (to get worktree path/branch)
|
||||
// Wait a bit for the worktree to be created
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
const updatedTask = await client.request<Task>('task.get', { id: task.id }, 5000);
|
||||
if (updatedTask?.worktree_path) {
|
||||
setWorktreePath(updatedTask.worktree_path);
|
||||
setWorktreeBranch(updatedTask.worktree_branch ?? null);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch updated task info:', err);
|
||||
}
|
||||
}, 1000);
|
||||
// Update worktree info from response
|
||||
if (response?.worktree_path) {
|
||||
setWorktreePath(response.worktree_path);
|
||||
setWorktreeBranch(response.worktree_branch ?? null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to start agent:', error);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user