mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-28 09:23:05 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8252b67567 | ||
|
|
207d3c5436 | ||
|
|
5fe8c24f55 |
@@ -169,6 +169,12 @@ func (f *execFakeRunner) Process() executor.ProcessHandle {
|
||||
return &execFakeProcess{pid: 1}
|
||||
}
|
||||
|
||||
func (f *execFakeRunner) UnsetEnv(keys ...string) {
|
||||
for _, k := range keys {
|
||||
delete(f.env, k)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecutorRunCodexTaskWithContext(t *testing.T) {
|
||||
defer resetTestHooks()
|
||||
|
||||
|
||||
@@ -274,6 +274,10 @@ func (d *drainBlockingCmd) Process() executor.ProcessHandle {
|
||||
return d.inner.Process()
|
||||
}
|
||||
|
||||
func (d *drainBlockingCmd) UnsetEnv(keys ...string) {
|
||||
d.inner.UnsetEnv(keys...)
|
||||
}
|
||||
|
||||
type bufferWriteCloser struct {
|
||||
buf bytes.Buffer
|
||||
mu sync.Mutex
|
||||
@@ -568,6 +572,14 @@ func (f *fakeCmd) Process() executor.ProcessHandle {
|
||||
return f.process
|
||||
}
|
||||
|
||||
func (f *fakeCmd) UnsetEnv(keys ...string) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
for _, k := range keys {
|
||||
delete(f.env, k)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *fakeCmd) runStdoutScript() {
|
||||
if len(f.stdoutPlan) == 0 {
|
||||
if !f.keepStdoutOpen {
|
||||
|
||||
@@ -41,6 +41,11 @@ func (f *fakeCmd) SetEnv(env map[string]string) {
|
||||
}
|
||||
}
|
||||
func (f *fakeCmd) Process() processHandle { return nil }
|
||||
func (f *fakeCmd) UnsetEnv(keys ...string) {
|
||||
for _, k := range keys {
|
||||
delete(f.env, k)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnvInjection_LogsToStderrAndMasksKey(t *testing.T) {
|
||||
// Arrange ~/.codeagent/models.json via HOME override.
|
||||
|
||||
@@ -113,6 +113,7 @@ type commandRunner interface {
|
||||
SetStderr(io.Writer)
|
||||
SetDir(string)
|
||||
SetEnv(env map[string]string)
|
||||
UnsetEnv(keys ...string)
|
||||
Process() processHandle
|
||||
}
|
||||
|
||||
@@ -221,6 +222,33 @@ func (r *realCmd) SetEnv(env map[string]string) {
|
||||
r.cmd.Env = out
|
||||
}
|
||||
|
||||
func (r *realCmd) UnsetEnv(keys ...string) {
|
||||
if r == nil || r.cmd == nil || len(keys) == 0 {
|
||||
return
|
||||
}
|
||||
// If cmd.Env is nil, Go inherits all parent env vars.
|
||||
// Populate explicitly so we can selectively remove keys.
|
||||
if r.cmd.Env == nil {
|
||||
r.cmd.Env = os.Environ()
|
||||
}
|
||||
drop := make(map[string]struct{}, len(keys))
|
||||
for _, k := range keys {
|
||||
drop[k] = struct{}{}
|
||||
}
|
||||
filtered := make([]string, 0, len(r.cmd.Env))
|
||||
for _, kv := range r.cmd.Env {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
name := kv
|
||||
if idx >= 0 {
|
||||
name = kv[:idx]
|
||||
}
|
||||
if _, ok := drop[name]; !ok {
|
||||
filtered = append(filtered, kv)
|
||||
}
|
||||
}
|
||||
r.cmd.Env = filtered
|
||||
}
|
||||
|
||||
func (r *realCmd) Process() processHandle {
|
||||
if r == nil || r.cmd == nil || r.cmd.Process == nil {
|
||||
return nil
|
||||
@@ -1126,6 +1154,13 @@ func RunCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
||||
|
||||
injectTempEnv(cmd)
|
||||
|
||||
// Claude Code sets CLAUDECODE=1 in its child processes. If we don't
|
||||
// remove it, the spawned `claude -p` detects the variable and refuses
|
||||
// to start ("cannot be launched inside another Claude Code session").
|
||||
if commandName == "claude" {
|
||||
cmd.UnsetEnv("CLAUDECODE")
|
||||
}
|
||||
|
||||
// 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 != "" {
|
||||
|
||||
@@ -20,8 +20,7 @@ var geminiNoisePatterns = []string{
|
||||
|
||||
// codexNoisePatterns contains stderr patterns to filter for codex backend
|
||||
var codexNoisePatterns = []string{
|
||||
"ERROR codex_core::codex: needs_follow_up:",
|
||||
"ERROR codex_core::skills::loader:",
|
||||
"ERROR codex_core::",
|
||||
}
|
||||
|
||||
// filteringWriter wraps an io.Writer and filters out lines matching patterns
|
||||
|
||||
@@ -71,3 +71,35 @@ func TestFilteringWriterPartialLines(t *testing.T) {
|
||||
t.Errorf("got %q, want %q", got, "Hello World\n")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilteringWriterCodexNoise(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "filter all codex_core errors",
|
||||
input: "ERROR codex_core::rollout::list: state db missing rollout path for thread 123\nERROR codex_core::skills::loader: missing skill\nVisible output\n",
|
||||
want: "Visible output\n",
|
||||
},
|
||||
{
|
||||
name: "keep non codex_core errors",
|
||||
input: "ERROR another_module::state: real failure\nERROR codex_core::codex: needs_follow_up: true\nDone\n",
|
||||
want: "ERROR another_module::state: real failure\nDone\n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
fw := newFilteringWriter(&buf, codexNoisePatterns)
|
||||
_, _ = fw.Write([]byte(tt.input))
|
||||
fw.Flush()
|
||||
|
||||
if got := buf.String(); got != tt.want {
|
||||
t.Errorf("got %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user