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}
|
return &execFakeProcess{pid: 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *execFakeRunner) UnsetEnv(keys ...string) {
|
||||||
|
for _, k := range keys {
|
||||||
|
delete(f.env, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestExecutorRunCodexTaskWithContext(t *testing.T) {
|
func TestExecutorRunCodexTaskWithContext(t *testing.T) {
|
||||||
defer resetTestHooks()
|
defer resetTestHooks()
|
||||||
|
|
||||||
|
|||||||
@@ -274,6 +274,10 @@ func (d *drainBlockingCmd) Process() executor.ProcessHandle {
|
|||||||
return d.inner.Process()
|
return d.inner.Process()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *drainBlockingCmd) UnsetEnv(keys ...string) {
|
||||||
|
d.inner.UnsetEnv(keys...)
|
||||||
|
}
|
||||||
|
|
||||||
type bufferWriteCloser struct {
|
type bufferWriteCloser struct {
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
@@ -568,6 +572,14 @@ func (f *fakeCmd) Process() executor.ProcessHandle {
|
|||||||
return f.process
|
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() {
|
func (f *fakeCmd) runStdoutScript() {
|
||||||
if len(f.stdoutPlan) == 0 {
|
if len(f.stdoutPlan) == 0 {
|
||||||
if !f.keepStdoutOpen {
|
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) Process() processHandle { return nil }
|
||||||
|
func (f *fakeCmd) UnsetEnv(keys ...string) {
|
||||||
|
for _, k := range keys {
|
||||||
|
delete(f.env, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestEnvInjection_LogsToStderrAndMasksKey(t *testing.T) {
|
func TestEnvInjection_LogsToStderrAndMasksKey(t *testing.T) {
|
||||||
// Arrange ~/.codeagent/models.json via HOME override.
|
// Arrange ~/.codeagent/models.json via HOME override.
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ type commandRunner interface {
|
|||||||
SetStderr(io.Writer)
|
SetStderr(io.Writer)
|
||||||
SetDir(string)
|
SetDir(string)
|
||||||
SetEnv(env map[string]string)
|
SetEnv(env map[string]string)
|
||||||
|
UnsetEnv(keys ...string)
|
||||||
Process() processHandle
|
Process() processHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +222,33 @@ func (r *realCmd) SetEnv(env map[string]string) {
|
|||||||
r.cmd.Env = out
|
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 {
|
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
|
||||||
@@ -1126,6 +1154,13 @@ func RunCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
|||||||
|
|
||||||
injectTempEnv(cmd)
|
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
|
// 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
|
// Codex passes workdir via -C flag, so we skip setting Dir for it to avoid conflicts
|
||||||
if cfg.Mode != "resume" && commandName != "codex" && cfg.WorkDir != "" {
|
if cfg.Mode != "resume" && commandName != "codex" && cfg.WorkDir != "" {
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ var geminiNoisePatterns = []string{
|
|||||||
|
|
||||||
// codexNoisePatterns contains stderr patterns to filter for codex backend
|
// codexNoisePatterns contains stderr patterns to filter for codex backend
|
||||||
var codexNoisePatterns = []string{
|
var codexNoisePatterns = []string{
|
||||||
"ERROR codex_core::codex: needs_follow_up:",
|
"ERROR codex_core::",
|
||||||
"ERROR codex_core::skills::loader:",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// filteringWriter wraps an io.Writer and filters out lines matching patterns
|
// 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")
|
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