From 56d97f82a50843321ab68c6a0c1f83e977c984ff Mon Sep 17 00:00:00 2001 From: Dhillon Kannabhiran Date: Wed, 30 Sep 2026 06:44:27 +0800 Subject: [PATCH] fix(codex): set auto_review_model_override in the generated catalog Codex's automatic approval reviewer falls back to its built-in "codex-auto-review" id when the catalog does not override it. Moon Bridge does not route that id, so the reviewer fails closed and every escalated action is denied. Point each catalog entry at its own slug so review requests follow the same route as normal turns. --- internal/extension/codex/catalog.go | 64 +++++++++++++----------- internal/extension/codex/catalog_test.go | 13 +++++ 2 files changed, 48 insertions(+), 29 deletions(-) diff --git a/internal/extension/codex/catalog.go b/internal/extension/codex/catalog.go index 75ab8823..37704ae2 100644 --- a/internal/extension/codex/catalog.go +++ b/internal/extension/codex/catalog.go @@ -20,35 +20,40 @@ import ( // ModelInfo represents a model entry in the OpenAI /v1/models response. type ModelInfo struct { - Slug string `json:"slug"` - DisplayName string `json:"display_name"` - Description string `json:"description,omitempty"` - DefaultReasoningLevel string `json:"default_reasoning_level,omitempty"` - SupportedReasoningLevels []ReasoningLevelPresetDTO `json:"supported_reasoning_levels"` - ShellType string `json:"shell_type"` - Visibility string `json:"visibility"` - SupportedInAPI bool `json:"supported_in_api"` - Priority int `json:"priority"` - AdditionalSpeedTiers []string `json:"additional_speed_tiers"` - AvailabilityNux *ModelAvailabilityNux `json:"availability_nux"` - Upgrade *ModelInfoUpgrade `json:"upgrade"` - BaseInstructions string `json:"base_instructions"` - SupportsReasoningSummaries bool `json:"supports_reasoning_summaries"` - DefaultReasoningSummary string `json:"default_reasoning_summary"` - SupportVerbosity bool `json:"support_verbosity"` - DefaultVerbosity *string `json:"default_verbosity"` - ApplyPatchToolType *string `json:"apply_patch_tool_type"` - WebSearchToolType string `json:"web_search_tool_type"` - TruncationPolicy TruncationPolicyConfig `json:"truncation_policy"` - SupportsParallelToolCalls bool `json:"supports_parallel_tool_calls"` - SupportsImageDetailOriginal bool `json:"supports_image_detail_original"` - ContextWindow *int `json:"context_window,omitempty"` - MaxContextWindow *int `json:"max_context_window,omitempty"` - AutoCompactTokenLimit *int `json:"auto_compact_token_limit,omitempty"` - EffectiveContextWindowPct int `json:"effective_context_window_percent"` - ExperimentalSupportedTools []string `json:"experimental_supported_tools"` - InputModalities []string `json:"input_modalities"` - SupportsSearchTool bool `json:"supports_search_tool"` + Slug string `json:"slug"` + DisplayName string `json:"display_name"` + Description string `json:"description,omitempty"` + DefaultReasoningLevel string `json:"default_reasoning_level,omitempty"` + SupportedReasoningLevels []ReasoningLevelPresetDTO `json:"supported_reasoning_levels"` + ShellType string `json:"shell_type"` + Visibility string `json:"visibility"` + SupportedInAPI bool `json:"supported_in_api"` + Priority int `json:"priority"` + // AutoReviewModelOverride points Codex's automatic approval reviewer at a + // model the bridge actually serves. Without it Codex falls back to its + // built-in "codex-auto-review" id, which Moon Bridge does not route, so + // every approval review fails closed. + AutoReviewModelOverride string `json:"auto_review_model_override"` + AdditionalSpeedTiers []string `json:"additional_speed_tiers"` + AvailabilityNux *ModelAvailabilityNux `json:"availability_nux"` + Upgrade *ModelInfoUpgrade `json:"upgrade"` + BaseInstructions string `json:"base_instructions"` + SupportsReasoningSummaries bool `json:"supports_reasoning_summaries"` + DefaultReasoningSummary string `json:"default_reasoning_summary"` + SupportVerbosity bool `json:"support_verbosity"` + DefaultVerbosity *string `json:"default_verbosity"` + ApplyPatchToolType *string `json:"apply_patch_tool_type"` + WebSearchToolType string `json:"web_search_tool_type"` + TruncationPolicy TruncationPolicyConfig `json:"truncation_policy"` + SupportsParallelToolCalls bool `json:"supports_parallel_tool_calls"` + SupportsImageDetailOriginal bool `json:"supports_image_detail_original"` + ContextWindow *int `json:"context_window,omitempty"` + MaxContextWindow *int `json:"max_context_window,omitempty"` + AutoCompactTokenLimit *int `json:"auto_compact_token_limit,omitempty"` + EffectiveContextWindowPct int `json:"effective_context_window_percent"` + ExperimentalSupportedTools []string `json:"experimental_supported_tools"` + InputModalities []string `json:"input_modalities"` + SupportsSearchTool bool `json:"supports_search_tool"` } // ModelAvailabilityNux is a placeholder for Codex model availability nux. @@ -425,6 +430,7 @@ func newModelInfo( Visibility: "list", SupportedInAPI: true, Priority: 0, + AutoReviewModelOverride: slug, AdditionalSpeedTiers: []string{}, BaseInstructions: baseInstructions, SupportsReasoningSummaries: supportsReasoningSummaries, diff --git a/internal/extension/codex/catalog_test.go b/internal/extension/codex/catalog_test.go index f30e9509..27190578 100644 --- a/internal/extension/codex/catalog_test.go +++ b/internal/extension/codex/catalog_test.go @@ -25,6 +25,15 @@ func TestBuildModelInfoFromRouteEnablesApplyPatchFreeform(t *testing.T) { } } +func TestBuildModelInfoFromRouteSetsAutoReviewModelOverride(t *testing.T) { + info := codex.BuildModelInfoFromRoute("gpt-test", "default", config.RouteEntry{ + ContextWindow: 100000, + }) + if info.AutoReviewModelOverride != info.Slug { + t.Fatalf("auto_review_model_override = %q, want slug %q", info.AutoReviewModelOverride, info.Slug) + } +} + func TestBuildModelInfoFromRouteUsesTokenTruncationPolicy(t *testing.T) { info := codex.BuildModelInfoFromRoute("gpt-5.2", "default", config.RouteEntry{ ContextWindow: 200000, @@ -463,6 +472,10 @@ func TestWriteModelsCatalogProducesValidJSON(t *testing.T) { if len(result.Models) == 0 { t.Fatal("expected at least 1 model in catalog") } + if result.Models[0].AutoReviewModelOverride != result.Models[0].Slug { + t.Fatalf("auto_review_model_override = %q, want slug %q", + result.Models[0].AutoReviewModelOverride, result.Models[0].Slug) + } } func TestGenerateConfigTomlCatalogIncludesVisualInjectedImageModality(t *testing.T) {