Compare commits

...

2 Commits

Author SHA1 Message Date
swe-agent[bot]
b227fee225 fix codeagent claude and gemini root dir 2025-12-13 16:56:53 +08:00
swe-agent[bot]
2b7569335b update readme 2025-12-13 15:29:12 +08:00
6 changed files with 29 additions and 19 deletions

View File

@@ -1,3 +1,5 @@
[中文](README_CN.md) [English](README.md)
# Claude Code Multi-Agent Workflow System # Claude Code Multi-Agent Workflow System
[![Run in Smithery](https://smithery.ai/badge/skills/cexll)](https://smithery.ai/skills?ns=cexll&utm_source=github&utm_medium=badge) [![Run in Smithery](https://smithery.ai/badge/skills/cexll)](https://smithery.ai/skills?ns=cexll&utm_source=github&utm_medium=badge)

View File

@@ -36,19 +36,13 @@ func (ClaudeBackend) BuildArgs(cfg *Config, targetArg string) []string {
args = append(args, "--dangerously-skip-permissions") args = append(args, "--dangerously-skip-permissions")
} }
workdir := cfg.WorkDir
if workdir == "" {
workdir = defaultWorkdir
}
if cfg.Mode == "resume" { if cfg.Mode == "resume" {
if cfg.SessionID != "" { if cfg.SessionID != "" {
// Claude CLI uses -r <session_id> for resume. // Claude CLI uses -r <session_id> for resume.
args = append(args, "-r", cfg.SessionID) args = append(args, "-r", cfg.SessionID)
} }
} else {
args = append(args, "-C", workdir)
} }
// Note: claude CLI doesn't support -C flag; workdir set via cmd.Dir
args = append(args, "--output-format", "stream-json", "--verbose", targetArg) args = append(args, "--output-format", "stream-json", "--verbose", targetArg)
@@ -67,18 +61,12 @@ func (GeminiBackend) BuildArgs(cfg *Config, targetArg string) []string {
} }
args := []string{"-o", "stream-json", "-y"} args := []string{"-o", "stream-json", "-y"}
workdir := cfg.WorkDir
if workdir == "" {
workdir = defaultWorkdir
}
if cfg.Mode == "resume" { if cfg.Mode == "resume" {
if cfg.SessionID != "" { if cfg.SessionID != "" {
args = append(args, "-r", cfg.SessionID) args = append(args, "-r", cfg.SessionID)
} }
} else {
args = append(args, "-C", workdir)
} }
// Note: gemini CLI doesn't support -C flag; workdir set via cmd.Dir
args = append(args, "-p", targetArg) args = append(args, "-p", targetArg)

View File

@@ -11,7 +11,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
t.Run("new mode uses workdir without skip by default", func(t *testing.T) { t.Run("new mode uses workdir without skip by default", func(t *testing.T) {
cfg := &Config{Mode: "new", WorkDir: "/repo"} cfg := &Config{Mode: "new", WorkDir: "/repo"}
got := backend.BuildArgs(cfg, "todo") got := backend.BuildArgs(cfg, "todo")
want := []string{"-p", "-C", "/repo", "--output-format", "stream-json", "--verbose", "todo"} want := []string{"-p", "--output-format", "stream-json", "--verbose", "todo"}
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want) t.Fatalf("got %v, want %v", got, want)
} }
@@ -20,7 +20,7 @@ func TestClaudeBuildArgs_ModesAndPermissions(t *testing.T) {
t.Run("new mode opt-in skip permissions with default workdir", func(t *testing.T) { t.Run("new mode opt-in skip permissions with default workdir", func(t *testing.T) {
cfg := &Config{Mode: "new", SkipPermissions: true} cfg := &Config{Mode: "new", SkipPermissions: true}
got := backend.BuildArgs(cfg, "-") got := backend.BuildArgs(cfg, "-")
want := []string{"-p", "--dangerously-skip-permissions", "-C", defaultWorkdir, "--output-format", "stream-json", "--verbose", "-"} want := []string{"-p", "--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "-"}
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want) t.Fatalf("got %v, want %v", got, want)
} }
@@ -56,7 +56,7 @@ func TestClaudeBuildArgs_GeminiAndCodexModes(t *testing.T) {
backend := GeminiBackend{} backend := GeminiBackend{}
cfg := &Config{Mode: "new", WorkDir: "/workspace"} cfg := &Config{Mode: "new", WorkDir: "/workspace"}
got := backend.BuildArgs(cfg, "task") got := backend.BuildArgs(cfg, "task")
want := []string{"-o", "stream-json", "-y", "-C", "/workspace", "-p", "task"} want := []string{"-o", "stream-json", "-y", "-p", "task"}
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Fatalf("got %v, want %v", got, want) t.Fatalf("got %v, want %v", got, want)
} }

View File

@@ -23,6 +23,7 @@ type commandRunner interface {
StdoutPipe() (io.ReadCloser, error) StdoutPipe() (io.ReadCloser, error)
StdinPipe() (io.WriteCloser, error) StdinPipe() (io.WriteCloser, error)
SetStderr(io.Writer) SetStderr(io.Writer)
SetDir(string)
Process() processHandle Process() processHandle
} }
@@ -72,6 +73,12 @@ func (r *realCmd) SetStderr(w io.Writer) {
} }
} }
func (r *realCmd) SetDir(dir string) {
if r.cmd != nil {
r.cmd.Dir = dir
}
}
func (r *realCmd) Process() processHandle { func (r *realCmd) Process() processHandle {
if r == nil || r.cmd == nil || r.cmd.Process == nil { if r == nil || r.cmd == nil || r.cmd.Process == nil {
return nil return nil
@@ -577,6 +584,12 @@ func runCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
cmd := newCommandRunner(ctx, commandName, codexArgs...) cmd := newCommandRunner(ctx, commandName, codexArgs...)
// For backends that don't support -C flag (claude, gemini), set working directory via cmd.Dir
// Codex passes workdir via -C flag, so we skip setting Dir for it to avoid conflicts
if cfg.Mode != "resume" && commandName != "codex" && cfg.WorkDir != "" {
cmd.SetDir(cfg.WorkDir)
}
stderrWriters := []io.Writer{stderrBuf} stderrWriters := []io.Writer{stderrBuf}
if stderrLogger != nil { if stderrLogger != nil {
stderrWriters = append(stderrWriters, stderrLogger) stderrWriters = append(stderrWriters, stderrLogger)

View File

@@ -117,6 +117,7 @@ func (f *execFakeRunner) StdinPipe() (io.WriteCloser, error) {
return &writeCloserStub{}, nil return &writeCloserStub{}, nil
} }
func (f *execFakeRunner) SetStderr(io.Writer) {} func (f *execFakeRunner) SetStderr(io.Writer) {}
func (f *execFakeRunner) SetDir(string) {}
func (f *execFakeRunner) Process() processHandle { func (f *execFakeRunner) Process() processHandle {
if f.process != nil { if f.process != nil {
return f.process return f.process

View File

@@ -250,6 +250,10 @@ func (d *drainBlockingCmd) SetStderr(w io.Writer) {
d.inner.SetStderr(w) d.inner.SetStderr(w)
} }
func (d *drainBlockingCmd) SetDir(dir string) {
d.inner.SetDir(dir)
}
func (d *drainBlockingCmd) Process() processHandle { func (d *drainBlockingCmd) Process() processHandle {
return d.inner.Process() return d.inner.Process()
} }
@@ -504,6 +508,8 @@ func (f *fakeCmd) SetStderr(w io.Writer) {
f.stderr = w f.stderr = w
} }
func (f *fakeCmd) SetDir(string) {}
func (f *fakeCmd) Process() processHandle { func (f *fakeCmd) Process() processHandle {
if f == nil { if f == nil {
return nil return nil
@@ -1371,7 +1377,7 @@ func TestBackendBuildArgs_ClaudeBackend(t *testing.T) {
backend := ClaudeBackend{} backend := ClaudeBackend{}
cfg := &Config{Mode: "new", WorkDir: defaultWorkdir} cfg := &Config{Mode: "new", WorkDir: defaultWorkdir}
got := backend.BuildArgs(cfg, "todo") got := backend.BuildArgs(cfg, "todo")
want := []string{"-p", "-C", defaultWorkdir, "--output-format", "stream-json", "--verbose", "todo"} want := []string{"-p", "--output-format", "stream-json", "--verbose", "todo"}
if len(got) != len(want) { if len(got) != len(want) {
t.Fatalf("length mismatch") t.Fatalf("length mismatch")
} }
@@ -1411,7 +1417,7 @@ func TestBackendBuildArgs_GeminiBackend(t *testing.T) {
backend := GeminiBackend{} backend := GeminiBackend{}
cfg := &Config{Mode: "new"} cfg := &Config{Mode: "new"}
got := backend.BuildArgs(cfg, "task") got := backend.BuildArgs(cfg, "task")
want := []string{"-o", "stream-json", "-y", "-C", defaultWorkdir, "-p", "task"} want := []string{"-o", "stream-json", "-y", "-p", "task"}
if len(got) != len(want) { if len(got) != len(want) {
t.Fatalf("length mismatch") t.Fatalf("length mismatch")
} }