refactor(daemon): remove global ReposRoot, use per-task RepoPath from server
ReposRoot was a daemon-level config that locked all tasks to a single git repo. Replace with RepoPath in TaskContext so the server can specify the repo per task. When not provided, daemon falls back to directory mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aa3f927a37
commit
7b4a73c989
7 changed files with 15 additions and 36 deletions
|
|
@ -30,7 +30,6 @@ type Config struct {
|
|||
DeviceName string
|
||||
RuntimeName string
|
||||
Agents map[string]AgentEntry // "claude" -> entry, "codex" -> entry
|
||||
ReposRoot string // parent directory containing all repos
|
||||
WorkspacesRoot string // base path for execution envs (default: ~/multica_workspaces)
|
||||
KeepEnvAfterTask bool // preserve env after task for debugging
|
||||
PollInterval time.Duration
|
||||
|
|
@ -43,7 +42,6 @@ type Config struct {
|
|||
type Overrides struct {
|
||||
ServerURL string
|
||||
WorkspaceID string
|
||||
ReposRoot string
|
||||
WorkspacesRoot string
|
||||
ConfigPath string
|
||||
PollInterval time.Duration
|
||||
|
|
@ -118,22 +116,6 @@ func LoadConfig(overrides Overrides) (Config, error) {
|
|||
host = "local-machine"
|
||||
}
|
||||
|
||||
// Repos root: override > env > cwd
|
||||
reposRoot := strings.TrimSpace(os.Getenv("MULTICA_REPOS_ROOT"))
|
||||
if overrides.ReposRoot != "" {
|
||||
reposRoot = overrides.ReposRoot
|
||||
}
|
||||
if reposRoot == "" {
|
||||
reposRoot, err = os.Getwd()
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("resolve working directory: %w", err)
|
||||
}
|
||||
}
|
||||
reposRoot, err = filepath.Abs(reposRoot)
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("resolve absolute repos root: %w", err)
|
||||
}
|
||||
|
||||
// Durations: override > env > default
|
||||
pollInterval, err := durationFromEnv("MULTICA_DAEMON_POLL_INTERVAL", DefaultPollInterval)
|
||||
if err != nil {
|
||||
|
|
@ -181,12 +163,11 @@ func LoadConfig(overrides Overrides) (Config, error) {
|
|||
workspacesRoot = overrides.WorkspacesRoot
|
||||
}
|
||||
if workspacesRoot == "" {
|
||||
home, _ := os.UserHomeDir()
|
||||
if home != "" {
|
||||
workspacesRoot = filepath.Join(home, "multica_workspaces")
|
||||
} else {
|
||||
workspacesRoot = filepath.Join(reposRoot, "multica_workspaces")
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return Config{}, fmt.Errorf("resolve home directory: %w (set MULTICA_WORKSPACES_ROOT to override)", err)
|
||||
}
|
||||
workspacesRoot = filepath.Join(home, "multica_workspaces")
|
||||
}
|
||||
workspacesRoot, err = filepath.Abs(workspacesRoot)
|
||||
if err != nil {
|
||||
|
|
@ -204,7 +185,6 @@ func LoadConfig(overrides Overrides) (Config, error) {
|
|||
DeviceName: deviceName,
|
||||
RuntimeName: runtimeName,
|
||||
Agents: agents,
|
||||
ReposRoot: reposRoot,
|
||||
WorkspacesRoot: workspacesRoot,
|
||||
KeepEnvAfterTask: keepEnv,
|
||||
PollInterval: pollInterval,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ func (d *Daemon) Run(ctx context.Context) error {
|
|||
for name := range d.cfg.Agents {
|
||||
agentNames = append(agentNames, name)
|
||||
}
|
||||
d.logger.Info("starting daemon", "agents", agentNames, "workspace_id", d.cfg.WorkspaceID, "server", d.cfg.ServerBaseURL, "repos_root", d.cfg.ReposRoot)
|
||||
d.logger.Info("starting daemon", "agents", agentNames, "workspace_id", d.cfg.WorkspaceID, "server", d.cfg.ServerBaseURL)
|
||||
|
||||
if strings.TrimSpace(d.cfg.WorkspaceID) == "" {
|
||||
workspaceID, err := d.ensurePaired(ctx)
|
||||
|
|
@ -279,7 +279,7 @@ func (d *Daemon) runTask(ctx context.Context, task Task) (TaskResult, error) {
|
|||
}
|
||||
env, err := execenv.Prepare(execenv.PrepareParams{
|
||||
WorkspacesRoot: d.cfg.WorkspacesRoot,
|
||||
ReposRoot: d.cfg.ReposRoot,
|
||||
RepoPath: task.Context.RepoPath,
|
||||
TaskID: task.ID,
|
||||
AgentName: task.Context.Agent.Name,
|
||||
Task: taskCtx,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const (
|
|||
// PrepareParams holds all inputs needed to set up an execution environment.
|
||||
type PrepareParams struct {
|
||||
WorkspacesRoot string // base path for all envs (e.g., ~/multica_workspaces)
|
||||
ReposRoot string // source git repo (for worktree creation)
|
||||
RepoPath string // source git repo path (for worktree creation), provided per-task by server
|
||||
TaskID string // task UUID — used for directory name
|
||||
AgentName string // for git branch naming only
|
||||
Task TaskContextForEnv // context data for writing files
|
||||
|
|
@ -100,8 +100,8 @@ func Prepare(params PrepareParams, logger *slog.Logger) (*Environment, error) {
|
|||
}
|
||||
|
||||
// Detect git repo and set up worktree if available.
|
||||
if params.ReposRoot != "" {
|
||||
if gitRoot, ok := detectGitRepo(params.ReposRoot); ok {
|
||||
if params.RepoPath != "" {
|
||||
if gitRoot, ok := detectGitRepo(params.RepoPath); ok {
|
||||
branchName := fmt.Sprintf("agent/%s/%s", sanitizeName(params.AgentName), shortID(params.TaskID))
|
||||
|
||||
// Get the default branch as base ref.
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func TestPrepareDirectoryMode(t *testing.T) {
|
|||
|
||||
env, err := Prepare(PrepareParams{
|
||||
WorkspacesRoot: workspacesRoot,
|
||||
ReposRoot: reposRoot,
|
||||
RepoPath: reposRoot,
|
||||
TaskID: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
|
||||
AgentName: "Test Agent",
|
||||
Task: TaskContextForEnv{
|
||||
|
|
@ -176,7 +176,7 @@ func TestPrepareGitWorktreeMode(t *testing.T) {
|
|||
|
||||
env, err := Prepare(PrepareParams{
|
||||
WorkspacesRoot: workspacesRoot,
|
||||
ReposRoot: reposRoot,
|
||||
RepoPath: reposRoot,
|
||||
TaskID: "b2c3d4e5-f6a7-8901-bcde-f12345678901",
|
||||
AgentName: "Code Reviewer",
|
||||
Task: TaskContextForEnv{
|
||||
|
|
@ -334,7 +334,7 @@ func TestCleanupGitWorktree(t *testing.T) {
|
|||
|
||||
env, err := Prepare(PrepareParams{
|
||||
WorkspacesRoot: workspacesRoot,
|
||||
ReposRoot: reposRoot,
|
||||
RepoPath: reposRoot,
|
||||
TaskID: "c3d4e5f6-a7b8-9012-cdef-123456789012",
|
||||
AgentName: "Cleanup Test",
|
||||
Task: TaskContextForEnv{IssueTitle: "Cleanup test"},
|
||||
|
|
@ -477,7 +477,7 @@ func TestCleanupPreservesLogs(t *testing.T) {
|
|||
|
||||
env, err := Prepare(PrepareParams{
|
||||
WorkspacesRoot: workspacesRoot,
|
||||
ReposRoot: t.TempDir(), // not a git repo
|
||||
RepoPath: t.TempDir(), // not a git repo
|
||||
TaskID: "d4e5f6a7-b8c9-0123-defa-234567890123",
|
||||
AgentName: "Preserve Test",
|
||||
Task: TaskContextForEnv{IssueTitle: "Preserve test"},
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ type TaskContext struct {
|
|||
Agent AgentContext `json:"agent"`
|
||||
Runtime RuntimeContext `json:"runtime"`
|
||||
WorkspaceContext string `json:"workspace_context,omitempty"`
|
||||
RepoPath string `json:"repo_path,omitempty"`
|
||||
}
|
||||
|
||||
// IssueContext holds issue details for task execution.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue