diff --git a/internal/profiles/clawhub/clawscan.yml b/internal/profiles/clawhub/clawscan.yml index 23f1d07..fec0244 100644 --- a/internal/profiles/clawhub/clawscan.yml +++ b/internal/profiles/clawhub/clawscan.yml @@ -12,6 +12,7 @@ profiles: - SKILLSPECTOR_PROVIDER judge: command: >- + [ -n "$CODEX_API_KEY" ] || export CODEX_API_KEY="$OPENAI_API_KEY"; codex exec --cd {{ workspace }} --model gpt-5.5 --sandbox {{ judge_sandbox }} @@ -39,6 +40,7 @@ profiles: - LLM_API_KEY judge: command: >- + [ -n "$CODEX_API_KEY" ] || export CODEX_API_KEY="$OPENAI_API_KEY"; codex exec --cd {{ workspace }} --model gpt-5.5 --sandbox {{ judge_sandbox }} diff --git a/internal/profiles/resolver_test.go b/internal/profiles/resolver_test.go index e8760eb..c6d8c05 100644 --- a/internal/profiles/resolver_test.go +++ b/internal/profiles/resolver_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "os" + "os/exec" "path/filepath" "reflect" "strings" @@ -41,6 +42,9 @@ func TestResolveArgsUsesEmbeddedClawHubProfile(t *testing.T) { if !strings.Contains(opts.Judge.Command, "codex exec") { t.Fatalf("judge command = %q", opts.Judge.Command) } + if !strings.Contains(opts.Judge.Command, `[ -n "$CODEX_API_KEY" ] || export CODEX_API_KEY="$OPENAI_API_KEY"; codex exec`) { + t.Fatalf("judge command does not alias OPENAI_API_KEY for codex exec: %q", opts.Judge.Command) + } if !strings.Contains(opts.Judge.Command, "--sandbox {{ judge_sandbox }}") { t.Fatalf("judge command missing runtime-aware sandbox placeholder: %q", opts.Judge.Command) } @@ -101,6 +105,47 @@ func TestResolveArgsUsesEmbeddedClawHubAIGCandidateProfile(t *testing.T) { } } +func TestClawHubProfilesAliasOpenAIKeyForCodex(t *testing.T) { + for _, profile := range []string{"clawhub", "clawhub-aig"} { + t.Run(profile, func(t *testing.T) { + opts, err := ResolveArgs([]string{"./skill", "--profile", profile}, t.TempDir()) + if err != nil { + t.Fatal(err) + } + prefix, _, ok := strings.Cut(opts.Judge.Command, "codex exec") + if !ok { + t.Fatalf("judge command missing codex exec: %q", opts.Judge.Command) + } + + for _, test := range []struct { + name string + openAI string + codex string + output string + }{ + {name: "openai fallback", openAI: "openai-marker", output: "openai-marker"}, + {name: "explicit codex key wins", openAI: "openai-marker", codex: "codex-marker", output: "codex-marker"}, + } { + t.Run(test.name, func(t *testing.T) { + cmd := exec.Command("sh", "-c", prefix+`sh -c 'printf %s "$CODEX_API_KEY"'`) + cmd.Env = append( + os.Environ(), + strings.Join([]string{"OPENAI_API_KEY", test.openAI}, "="), + strings.Join([]string{"CODEX_API_KEY", test.codex}, "="), + ) + output, err := cmd.Output() + if err != nil { + t.Fatal(err) + } + if got := string(output); got != test.output { + t.Fatalf("CODEX_API_KEY = %q, want %q", got, test.output) + } + }) + } + }) + } +} + func TestResolveArgsPassesExplicitRunContext(t *testing.T) { dir := t.TempDir() contextPath := filepath.Join(dir, "clawhub-context.json")