Skip to content

fix(mcp): re-add image generation tool routing - #1091

Closed
TingtingZhou7 wants to merge 15 commits into
smg-project:mainfrom
TingtingZhou7:tingzhou/readd-imggen-tool
Closed

TingtingZhou7 wants to merge 15 commits into
smg-project:mainfrom
TingtingZhou7:tingzhou/readd-imggen-tool

Conversation

@TingtingZhou7

@TingtingZhou7 TingtingZhou7 commented Apr 10, 2026 •

Copy link
Copy Markdown
Contributor

Description

Problem

Remove gRPC from https://github.com/lightseekorg/smg/pull/1057/changes#diff-477dfd1a461c069d89a1fc610c9eb9e8d6f98fc6924ebc8de092a8ceca00d007

Solution

Disable image generation tool in gRPC.

Changes

Disable image generation tool in gRPC.

Test Plan

Tested with gRPC and image-generation-tool is disabled now.

Screenshot 2026-04-10 at 2 00 05 PM
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets --all-features -- -D warnings passes
  • (Optional) Documentation updated
  • (Optional) Please join us on Slack #sig-smg to discuss, review, and merge PRs

Summary by CodeRabbit

  • New Features

    • Added first-class image generation tool with configurable parameters (size, quality, background, format, compression, moderation, model).
    • Image generation calls stream progress events (in-progress, generating, partial image, completed).
  • Bug Fixes / Reliability

    • Improved error handling with fallback text extraction for failed image-generation responses.
  • Behavioral

    • gRPC Responses routes now explicitly reject image-generation tools (returns unsupported_tool).

@github-actions github-actions Bot added mcp MCP related changes protocols Protocols crate changes model-gateway Model gateway crate changes openai OpenAI router changes labels Apr 10, 2026
@coderabbitai

coderabbitai Bot commented Apr 10, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds image-generation as a built-in tool across MCP: new enums/types, transformer handling and helpers, protocol events, router integration, streaming/tool-loop changes, and compacted tool-output logic plus tests and a .gitignore entry for local MCP config.

Changes

Cohort / File(s) Summary
Ignore & Config
/.gitignore, crates/mcp/src/core/config.rs
Added .gitignore entry for mcp.local.yaml. Added BuiltinToolType::ImageGeneration and ResponseFormatConfig::ImageGenerationCall with serde mappings.
MCP Public API
crates/mcp/src/lib.rs, crates/mcp/src/transform/mod.rs
Re-exported extract_image_generation_fallback_text and is_image_generation_error from transform module.
Transform Types
crates/mcp/src/transform/types.rs
Added ResponseFormat::ImageGenerationCall and mapping from ResponseFormatConfig.
Transform Logic & Tests
crates/mcp/src/transform/transformer.rs
Implemented ImageGenerationCall handling producing ResponseOutputItem::ImageGenerationCall; added extract_image_generation_fallback_text, is_image_generation_error, internal JSON-RPC payload parsing, refactored Value type usage, and added unit tests.
Protocols: Events & Responses
crates/protocols/src/event_types.rs, crates/protocols/src/responses.rs
Added ImageGenerationCallEvent, extended ItemType for ImageGenerationCall, added ResponseTool::ImageGeneration, ImageGenerationTool struct, ResponseOutputItem::ImageGenerationCall, and ImageGenerationCallStatus.
Model Gateway: MCP Routing
model_gateway/src/routers/mcp_utils.rs, model_gateway/src/routers/mod.rs
Mapped ResponseTool::ImageGeneration to BuiltinToolType::ImageGeneration; added tool_output_context module declaration.
Tool Loop & Streaming
model_gateway/src/routers/openai/mcp/tool_loop.rs, model_gateway/src/routers/openai/responses/streaming.rs
Tool-loop now accepts full ResponsesRequest, applies per-request image-generation overrides, compacts per-tool outputs for model context, emits ImageGenerationCall streaming events (with ig_ id prefix) and injects IN_PROGRESS events.
Tool Output Serialization & Compacting
model_gateway/src/routers/openai/responses/utils.rs, model_gateway/src/routers/tool_output_context.rs
Serialize ResponseTool::ImageGeneration in restored tools; added compact_tool_output_for_model_context which produces compact JSON for image-generation outputs (success vs. error with extracted fallback note) and preserves behavior for other formats.
gRPC Streaming & Guards
model_gateway/src/routers/grpc/common/responses/streaming.rs, model_gateway/src/routers/grpc/common/responses/utils.rs, model_gateway/src/routers/grpc/harmony/builder.rs
Added streaming OutputItemType mapping for image generation, emit corresponding events, and added validation to reject image_generation in gRPC responses routes; extended tool-type allowlist mapping for Responses API message construction.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant ToolLoop as Tool Loop\n(model_gateway/src/.../tool_loop.rs)
    participant Model as External Model
    participant Transform as Transformer\n(crates/mcp/src/transformer.rs)
    participant OutputCtx as Output Context\n(model_gateway/src/routers/tool_output_context.rs)

    Client->>ToolLoop: execute_streaming_tool_calls(ResponsesRequest)
    ToolLoop->>ToolLoop: parse & apply request tool overrides
    ToolLoop->>Model: call image generation tool (args JSON)
    Model-->>ToolLoop: returns JSON result (wrapped result or error)
    ToolLoop->>Transform: is_image_generation_error(result)
    Transform-->>ToolLoop: error? and fallback text (if any)
    ToolLoop->>OutputCtx: compact_tool_output_for_model_context(format, result)
    OutputCtx-->>ToolLoop: compact JSON {tool,status,note}
    ToolLoop->>Client: emit ImageGenerationCall events (IN_PROGRESS / updates / COMPLETED)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • CatherineSue
  • key4ng
  • slin1237

Poem

🐰 I hopped in code to add a spark,
New image calls now leave their mark,
From transformer caves to gateway tracks,
ig_ events and compacted facts,
The rabbit paints with JSON art. 🎨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'fix(mcp): re-add image generation tool routing' accurately describes the main change: restoring image generation tool support across MCP routing with explicit gRPC disablement for safety.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@TingtingZhou7 TingtingZhou7 changed the title Tingzhou/readd imggen tool Open feat(imageopenaionly): add image generation tool support Apr 10, 2026
@mergify

mergify Bot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

⚠️ The sha of the head commit of this PR conflicts with #1089. Mergify cannot evaluate rules on this PR. Once #1089 is merged or closed, Mergify will resume processing this PR. ⚠️

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a built-in image generation tool for the MCP framework, including new protocol definitions, transformation logic, and streaming event support. It introduces a mechanism to override tool arguments from the request level and a utility to compact image generation outputs for model context to avoid large binary payloads. Review feedback identifies an opportunity to simplify repetitive result extraction logic in the transformer and recommends parameterizing a hardcoded tool name in the output compaction utility to improve robustness.

Comment thread crates/mcp/src/transform/transformer.rs Outdated
Comment thread model_gateway/src/routers/tool_output_context.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7ec7ac76c0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/mcp/src/transform/transformer.rs Outdated
Comment thread model_gateway/src/routers/tool_output_context.rs Outdated
@TingtingZhou7 TingtingZhou7 changed the title Open feat(imageopenaionly): add image generation tool support fix(mcp): re-add image generation tool routing Apr 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
model_gateway/src/routers/openai/responses/utils.rs (1)

206-233: 🧹 Nitpick | 🔵 Trivial

LGTM! Consider updating the docstring.

The ImageGeneration variant handling follows the same serialization pattern as WebSearchPreview and CodeInterpreter. The docstring at lines 207-209 lists "web_search_preview, and code_interpreter" but doesn't mention image_generation.

📝 Optional: Update docstring to include image_generation
 /// Convert a single ResponseTool back to its original JSON representation.
 ///
-/// Handles MCP tools (with server metadata), web_search_preview, and code_interpreter.
+/// Handles MCP tools (with server metadata), web_search_preview, code_interpreter, and image_generation.
 /// Returns None for function tools and other types that don't need restoration.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/openai/responses/utils.rs` around lines 206 - 233,
Update the function docstring for response_tool_to_value to list ImageGeneration
alongside WebSearchPreview and CodeInterpreter: modify the comment lines
describing handled variants (currently mentioning "web_search_preview, and
code_interpreter") to also include "image_generation" so the documentation
matches the match arms for ResponseTool::ImageGeneration and others in this
function.
model_gateway/src/routers/openai/mcp/tool_loop.rs (1)

689-702: ⚠️ Potential issue | 🟠 Major

Thread the builtin response_format through the max_tool_calls early-exit path.

Line 689 now resolves ResponseFormat::ImageGenerationCall, but build_incomplete_response() still reconstructs pending calls as generic mcp_call items. If the loop stops on max_tool_calls, an unexecuted image-generation call is returned with the wrong discriminator/id shape instead of image_generation_call/ig_*.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/openai/mcp/tool_loop.rs` around lines 689 - 702,
The early-exit on max_tool_calls currently computes response_format via
session.tool_response_format(&call.name) but then calls
build_incomplete_response(...) which reconstructs pending calls as generic
mcp_call items; thread the computed response_format into the early-exit call so
build_incomplete_response can produce the correct discriminator/ID shape (e.g.,
return image_generation_call / ig_* when response_format ==
ResponseFormat::ImageGenerationCall). Update the invocation of
build_incomplete_response to accept the response_format (or add an overload) and
ensure build_incomplete_response uses that value when reconstructing pending
calls for the max_tool_calls path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@model_gateway/src/routers/openai/mcp/tool_loop.rs`:
- Around line 279-295: The current tools.iter().find_map(...) in tool_loop.rs
silently picks the first ResponseTool::ImageGeneration config, making behavior
order-dependent; update validation to reject duplicate image-generation tool
definitions instead of allowing multiple or, alternatively, make merge semantics
deterministic. Concretely, add a uniqueness check in validate_response_tools()
to error when more than one ResponseTool::ImageGeneration is present (or, if you
prefer merging, implement a deterministic merge routine and replace the find_map
use with an explicit aggregate that sorts/merges deterministically). Reference
ResponseTool::ImageGeneration, tools.iter(), and validate_response_tools() when
making the change so the PR rejects duplicate image_generation configs during
validation or clearly implements deterministic merging.

---

Outside diff comments:
In `@model_gateway/src/routers/openai/mcp/tool_loop.rs`:
- Around line 689-702: The early-exit on max_tool_calls currently computes
response_format via session.tool_response_format(&call.name) but then calls
build_incomplete_response(...) which reconstructs pending calls as generic
mcp_call items; thread the computed response_format into the early-exit call so
build_incomplete_response can produce the correct discriminator/ID shape (e.g.,
return image_generation_call / ig_* when response_format ==
ResponseFormat::ImageGenerationCall). Update the invocation of
build_incomplete_response to accept the response_format (or add an overload) and
ensure build_incomplete_response uses that value when reconstructing pending
calls for the max_tool_calls path.

In `@model_gateway/src/routers/openai/responses/utils.rs`:
- Around line 206-233: Update the function docstring for response_tool_to_value
to list ImageGeneration alongside WebSearchPreview and CodeInterpreter: modify
the comment lines describing handled variants (currently mentioning
"web_search_preview, and code_interpreter") to also include "image_generation"
so the documentation matches the match arms for ResponseTool::ImageGeneration
and others in this function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 10da9d3b-f378-473a-bb85-fc965b2008b8

📥 Commits

Reviewing files that changed from the base of the PR and between 6c39621 and 7ec7ac7.

📒 Files selected for processing (14)
  • .gitignore
  • crates/mcp/src/core/config.rs
  • crates/mcp/src/lib.rs
  • crates/mcp/src/transform/mod.rs
  • crates/mcp/src/transform/transformer.rs
  • crates/mcp/src/transform/types.rs
  • crates/protocols/src/event_types.rs
  • crates/protocols/src/responses.rs
  • model_gateway/src/routers/mcp_utils.rs
  • model_gateway/src/routers/mod.rs
  • model_gateway/src/routers/openai/mcp/tool_loop.rs
  • model_gateway/src/routers/openai/responses/streaming.rs
  • model_gateway/src/routers/openai/responses/utils.rs
  • model_gateway/src/routers/tool_output_context.rs

Comment thread model_gateway/src/routers/openai/mcp/tool_loop.rs Outdated
@CatherineSue

Copy link
Copy Markdown
Member

Seems lint is failing. @TingtingZhou7 Can you take a look?

@github-actions github-actions Bot added the grpc gRPC client and router changes label Apr 10, 2026
@mergify

mergify Bot commented Apr 10, 2026

Copy link
Copy Markdown
Contributor

Hi @TingtingZhou7, the DCO sign-off check has failed. All commits must include a Signed-off-by line.

To fix existing commits:

# Sign off the last N commits (replace N with the number of unsigned commits)
git rebase HEAD~N --signoff
git push --force-with-lease

To sign off future commits automatically:

  • Use git commit -s every time, or
  • VSCode: enable Git: Always Sign Off in Settings
  • PyCharm: enable Sign-off commit in the Commit tool window

@github-actions github-actions Bot removed the grpc gRPC client and router changes label Apr 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@model_gateway/src/routers/tool_output_context.rs`:
- Around line 7-10: Update the doc comment in tool_output_context.rs to match
the implementation: state that ResponseFormat::ImageGenerationCall is compacted
into a minimal summary that DOES include a status field (mention the status
field explicitly), and clarify that other formats generally return
output.to_string() unchanged except that JSON strings are special-cased (they
are attempted to be parsed/deserialized and compacted). Reference
ResponseFormat::ImageGenerationCall, the status field, output.to_string(), and
the JSON special-case logic so the comment accurately describes current
behavior.
- Around line 23-25: Summary: The JSON uses an undefined identifier `tool_name`,
causing a compile error; replace it with the image generation tool identifier.
Locate the json! block that constructs `summary` in tool_output_context.rs (the
line creating {"tool": tool_name, ...}) and change `tool_name` to the correct
image-generation constant/variable used elsewhere in the module (e.g.,
IMAGE_GENERATION_TOOL_ID or the module's image tool identifier), ensuring the
identifier is in scope and imported if necessary so the JSON uses a defined
symbol.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 84c7479f-b9fa-4779-b1f1-078b257f47d7

📥 Commits

Reviewing files that changed from the base of the PR and between ae4e542 and b5f95de.

📒 Files selected for processing (1)
  • model_gateway/src/routers/tool_output_context.rs

Comment thread model_gateway/src/routers/tool_output_context.rs Outdated
Comment thread model_gateway/src/routers/tool_output_context.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
model_gateway/src/routers/tool_output_context.rs (2)

23-25: ⚠️ Potential issue | 🔴 Critical

tool_name is undefined and will fail lint/compile.

There is no in-scope binding for tool_name in this file. Use the concrete image-generation tool identifier or a shared constant instead.

Proposed fix
             let summary = json!({
-                "tool": tool_name,
+                "tool": "image_generation_call",
                 "status": if is_error { "failed" } else { "completed" },
                 "note": note
             });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/tool_output_context.rs` around lines 23 - 25, The
JSON construction for `summary` references an undefined variable `tool_name`,
which will fail compilation; replace `tool_name` with the correct concrete
identifier or shared constant for the image-generation tool (e.g., use the
existing image generator constant or literal name) wherever `summary` is built
in the function that contains the `let summary = json!({ ... })` expression so
the binding is in-scope and the code compiles.

7-10: ⚠️ Potential issue | 🟡 Minor

Update the doc comment to match the code.

The comment says the image summary has “no payload/status” and that other formats return output.to_string() unchanged, but the implementation includes a status field and special-cases Value::String by returning the raw string.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/tool_output_context.rs` around lines 7 - 10, Update
the doc comment above the compacting logic to accurately describe the current
behavior: state that ResponseFormat::ImageGenerationCall is compacted into a
minimal fixed summary that includes a status field (but omits the large binary
payload), and that other formats are not strictly no-ops — Value::String is
returned as the raw string instead of being wrapped, while other non-string
formats fall back to output.to_string(). Mention
ResponseFormat::ImageGenerationCall, the presence of the status field, and the
special-case handling of Value::String to make the comment match the
implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@model_gateway/src/routers/tool_output_context.rs`:
- Around line 23-25: The JSON construction for `summary` references an undefined
variable `tool_name`, which will fail compilation; replace `tool_name` with the
correct concrete identifier or shared constant for the image-generation tool
(e.g., use the existing image generator constant or literal name) wherever
`summary` is built in the function that contains the `let summary = json!({ ...
})` expression so the binding is in-scope and the code compiles.
- Around line 7-10: Update the doc comment above the compacting logic to
accurately describe the current behavior: state that
ResponseFormat::ImageGenerationCall is compacted into a minimal fixed summary
that includes a status field (but omits the large binary payload), and that
other formats are not strictly no-ops — Value::String is returned as the raw
string instead of being wrapped, while other non-string formats fall back to
output.to_string(). Mention ResponseFormat::ImageGenerationCall, the presence of
the status field, and the special-case handling of Value::String to make the
comment match the implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce38e72e-3421-49d0-a1a0-9828cbc0cab9

📥 Commits

Reviewing files that changed from the base of the PR and between b5f95de and e4f638a.

📒 Files selected for processing (1)
  • model_gateway/src/routers/tool_output_context.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e4f638a375

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/tool_output_context.rs Outdated
@github-actions github-actions Bot added the grpc gRPC client and router changes label Apr 10, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 329d2bfb2a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/grpc/common/responses/streaming.rs Outdated
Comment thread model_gateway/src/routers/openai/responses/streaming.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
model_gateway/src/routers/grpc/harmony/builder.rs (1)

418-435: ⚠️ Potential issue | 🟡 Minor

Keep image_generation classified consistently.

Adding ResponseTool::ImageGeneration(_) to tool_types without also updating BUILTIN_TOOLS makes has_custom_tools(&tool_types) return true for image-generation-only requests. That flips this path into the custom-tool flow and can emit an empty developer message for what should be a builtin tool. Either remove this mapping while gRPC rejects the tool, or add "image_generation" to the builtin classification used here.

🛠️ Minimal fix
-const BUILTIN_TOOLS: &[&str] = &["web_search_preview", "code_interpreter", "container"];
+const BUILTIN_TOOLS: &[&str] = &[
+    "web_search_preview",
+    "code_interpreter",
+    "image_generation",
+    "container",
+];
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/grpc/harmony/builder.rs` around lines 418 - 435,
The tool classification adds ResponseTool::ImageGeneration to the tool_types
vector which isn't listed in BUILTIN_TOOLS, causing
has_custom_tools(&tool_types) to treat image-generation-only requests as custom;
either remove the ResponseTool::ImageGeneration branch from the mapping in the
block that builds tool_types or add the string "image_generation" to the
BUILTIN_TOOLS set used by has_custom_tools so that image generation is treated
as a builtin; update the mapping or BUILTIN_TOOLS accordingly and keep the
references: tool_types, ResponseTool::ImageGeneration(_), has_custom_tools,
BUILTIN_TOOLS, and with_custom_tools.
♻️ Duplicate comments (1)
model_gateway/src/routers/tool_output_context.rs (1)

7-10: ⚠️ Potential issue | 🟡 Minor

Doc comment is still out of sync.

Lines 7-10 still say the compact summary has “no payload/status” and that other formats return output.to_string() unchanged, but Line 25 emits status and Lines 31-33 preserve raw strings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@model_gateway/src/routers/tool_output_context.rs` around lines 7 - 10, Update
the module doc comment to match the actual behavior: state that
ResponseFormat::ImageGenerationCall is compacted into a minimal summary that
includes status (not "no payload/status"), and clarify that other formats
preserve raw strings (not always returning output.to_string()). Reference the
ResponseFormat::ImageGenerationCall term and the compacting logic that emits
status and the branches that preserve raw strings so the comment accurately
reflects lines emitting status and the raw-string-preserving branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@model_gateway/src/routers/grpc/harmony/builder.rs`:
- Around line 418-435: The tool classification adds
ResponseTool::ImageGeneration to the tool_types vector which isn't listed in
BUILTIN_TOOLS, causing has_custom_tools(&tool_types) to treat
image-generation-only requests as custom; either remove the
ResponseTool::ImageGeneration branch from the mapping in the block that builds
tool_types or add the string "image_generation" to the BUILTIN_TOOLS set used by
has_custom_tools so that image generation is treated as a builtin; update the
mapping or BUILTIN_TOOLS accordingly and keep the references: tool_types,
ResponseTool::ImageGeneration(_), has_custom_tools, BUILTIN_TOOLS, and
with_custom_tools.

---

Duplicate comments:
In `@model_gateway/src/routers/tool_output_context.rs`:
- Around line 7-10: Update the module doc comment to match the actual behavior:
state that ResponseFormat::ImageGenerationCall is compacted into a minimal
summary that includes status (not "no payload/status"), and clarify that other
formats preserve raw strings (not always returning output.to_string()).
Reference the ResponseFormat::ImageGenerationCall term and the compacting logic
that emits status and the branches that preserve raw strings so the comment
accurately reflects lines emitting status and the raw-string-preserving
branches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 42911d29-bb39-4440-af62-a8b5896c1eea

📥 Commits

Reviewing files that changed from the base of the PR and between e4f638a and affd511.

📒 Files selected for processing (5)
  • crates/mcp/src/transform/transformer.rs
  • model_gateway/src/routers/grpc/common/responses/streaming.rs
  • model_gateway/src/routers/grpc/common/responses/utils.rs
  • model_gateway/src/routers/grpc/harmony/builder.rs
  • model_gateway/src/routers/tool_output_context.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: affd5110d5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/openai/mcp/tool_loop.rs
Comment thread model_gateway/src/routers/openai/responses/streaming.rs
@TingtingZhou7

Copy link
Copy Markdown
Contributor Author

Seems lint is failing. @TingtingZhou7 Can you take a look?
Fixed

Comment thread model_gateway/src/routers/openai/mcp/tool_loop.rs
ResponseTool::Function(_) => "function",
ResponseTool::WebSearchPreview(_) => "web_search_preview",
ResponseTool::CodeInterpreter(_) => "code_interpreter",
ResponseTool::ImageGeneration(_) => "image_generation",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following the design here. It seems Harmony still accepts the image generation tool call?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nvm. I saw this is just the builder

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Because harmony and openai share this ResponseTool file. And if i delete it, complition will fail. I have added it to make build succeed. But if you check the changes in "Utils", I have reject the request with image_generation_tool.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address this in a follow up PR. If Harmony should not support image generation, there are cleaner compile-safe options than “pretend it is a supported Harmony tool type here, then reject later in utils”.

For example,

ResponseTool::ImageGeneration(_) => continue

Or we could add a image generation mcp server, even a fake one so we can test this can work on harmony or other models.

@TingtingZhou7 TingtingZhou7 Apr 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use unreachable - 52cbda6

let event_type = match response_format {
ResponseFormat::WebSearchCall => WebSearchCallEvent::IN_PROGRESS,
ResponseFormat::CodeInterpreterCall => CodeInterpreterCallEvent::IN_PROGRESS,
ResponseFormat::ImageGenerationCall => ImageGenerationCallEvent::IN_PROGRESS,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory, the code path here won't be triggered, as we are disabling the image_generation_tool and returning a 400. Is that right?

@TingtingZhou7 TingtingZhou7 Apr 10, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. User request are gated before this.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. We can address this in a follow up PR.

@TingtingZhou7 TingtingZhou7 Apr 20, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard to remove it since we use an exhaustive match. If we remove exhaustive match, do you see any concern here?

@github-actions github-actions Bot removed mesh Mesh crate changes documentation Improvements or additions to documentation labels Apr 18, 2026
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: edd6146f66

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread crates/mcp/src/transform/transformer.rs
Comment thread crates/mcp/src/transform/types.rs Outdated
Comment on lines +29 to +30
let input = output.to_string();
let result = if matches!(self, ResponseFormat::ImageGenerationCall) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid unconditional output serialization in compaction

compact_tool_output_for_model_context serializes output to a string up front for debug logging, regardless of log level. This method is now called on every tool result, so large outputs (especially image/base64 payloads) incur extra CPU and allocation cost even when debug logs are disabled; for non-image formats it also ends up serializing the same value again for result in the else branch.

Useful? React with 👍 / 👎.

@mergify mergify Bot removed the needs-rebase PR has merge conflicts that need to be resolved label Apr 20, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 75c3606fd8

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}
};

apply_request_tool_overrides(&response_format, original_body, &mut arguments);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep streamed argument events aligned with executed overrides

Applying apply_request_tool_overrides here mutates the arguments right before tool execution, but in the OpenAI streaming path the earlier response.mcp_call_arguments.* events are still derived from the model’s original call.arguments_buffer. When clients request image options like size/quality in tools, the stream can report one argument payload while the server executes another, which breaks replay/audit assumptions for streaming consumers and makes debugging tool behavior difficult.

Useful? React with 👍 / 👎.

…iers

Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>
@mergify

mergify Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Hi @TingtingZhou7, the DCO sign-off check has failed. All commits must include a Signed-off-by line.

To fix existing commits:

# Sign off the last N commits (replace N with the number of unsigned commits)
git rebase HEAD~N --signoff
git push --force-with-lease

To sign off future commits automatically:

  • Use git commit -s every time, or
  • VSCode: enable Git: Always Sign Off in Settings
  • PyCharm: enable Sign-off commit in the Commit tool window

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 679d912119

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

}
};

apply_request_tool_overrides(&response_format, original_body, &mut arguments);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Build approval items from overridden tool arguments

execute_tool_loop now mutates tool arguments with apply_request_tool_overrides, but the PendingApproval path still calls build_mcp_approval_request_item with call.arguments (the pre-override JSON). In requests that set image-generation overrides and hit interactive MCP approval, the approval item can show stale parameters while the pending execution uses different arguments (pending.arguments_str), so users may approve a different call than what is displayed. The approval payload should be built from the effective overridden arguments.

Useful? React with 👍 / 👎.

Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9041e61002

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/openai/responses/streaming.rs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea31e32781

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +153 to +155
ResponseFormat::ImageGenerationCall => {
(ItemType::IMAGE_GENERATION_CALL, "ig_")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep image tool argument events on the ig_ item id*

Adding ImageGenerationCall to the output_item type rewrite here makes response.output_item.added/done use ig_* IDs, but the same stream still rewrites function_call.arguments.done to mcp_call.arguments.done with mcp_* item IDs in apply_event_transformations_inplace. In streaming image-tool calls (OpenAI Responses + MCP routing), clients that correlate by item_id will see argument events on a different logical item than the emitted image call, which breaks replay/audit pipelines and can drop argument metadata for that tool call.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9041e61002

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/grpc/common/responses/streaming.rs Outdated
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f6c25b6042

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/grpc/common/responses/utils.rs
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 52cbda6c1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/grpc/common/responses/streaming.rs
Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 561a40f176

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +37 to +43
content.iter().find_map(|item| {
item.as_object()
.filter(|o| o.get("type").and_then(|v| v.as_str()) == Some("text"))
.and_then(|o| o.get("text"))
.and_then(|v| v.as_str())
.filter(|text| !text.trim().is_empty())
.map(str::to_string)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer actual error text when image fallback has multiple blocks

extract_image_generation_fallback_text currently returns the first non-empty text entry, so when MCP returns multiple text blocks (for example a leading JSON metadata/progress block followed by a real failure string), the transformed image_generation_call.result captures the metadata instead of the actionable error. This misreports failures and can mislead retry/debug logic in clients that rely on the returned result text.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid point. I need to test case when mcp return multiple results. Noted down and will follow up on this. Should be good for this pr since it's a p2


const GRPC_RESPONSES_SUPPORTED_TOOL_KINDS: &[ResponseToolKind] = &[
ResponseToolKind::Function,
ResponseToolKind::WebSearchPreview,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should remove this also to make it exclusive match, so a new tool added later won't be missed here

Signed-off-by: TingtingZhou7 <zhoutt96@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 469d96cc15

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread model_gateway/src/routers/common/tool_overrides.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-approved grpc gRPC client and router changes mcp MCP related changes model-gateway Model gateway crate changes openai OpenAI router changes protocols Protocols crate changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants