Skip to content

fix(terminal): remap 'commands' alias to 'command' for google/gemma-4#3741

Draft
jeffmay wants to merge 1 commit into
OpenHands:mainfrom
jeffmay:fix/terminal-commands-alias-for-gemma4
Draft

fix(terminal): remap 'commands' alias to 'command' for google/gemma-4#3741
jeffmay wants to merge 1 commit into
OpenHands:mainfrom
jeffmay:fix/terminal-commands-alias-for-gemma4

Conversation

@jeffmay

@jeffmay jeffmay commented Jun 15, 2026

Copy link
Copy Markdown

Why

I was experiencing issues with Gemma 4 attempting to use the Bash tool with a commands input, when the tool expects command. At first, I solved this by just adding the note that the bash tool should use command instead, but this eats up tokens in the context and is not always followed by the AI. This solution is a potential fix that I am contributing back in case anyone else if having this issue, but I am unfamiliar with the work in this repo and whether this is the correct solution. On the surface, it doesn't seem to break anything and doesn't add to the cost, so it feels worth including, but if there is a cleaner way to achieve the same effect, I would be happy to review, test, and promote the changes.

Why a model_validator on TerminalAction and not fix_malformed_tool_arguments?

The existing fix_malformed_tool_arguments utility (and its recent additions for GLM 4.6 and minimax-m2.5) corrects wrong value types — JSON-encoded strings for list/dict fields, or lists of string chunks for str-only fields. The Gemma 4 issue is a different category: a wrong key name. Mixing key-name remapping into the value-coercion utility would blur that boundary.

A model_validator(mode="before") on the model is the idiomatic Pydantic solution for field-level aliasing and is co-located with the field it protects, making the intent obvious to future readers. It also composes correctly with the existing literal-argument detection logic that runs at validation time.

Summary

  • google/gemma-4 models consistently emit "commands" (plural) as the terminal tool's argument name instead of the correct "command" (singular), causing every shell invocation to fail with a Pydantic ValidationError before the command is ever executed.
  • Adds a mode='before' model_validator on TerminalAction that silently remaps the wrong key to the correct one so validation always succeeds for this known mismatch.
  • Adds three unit tests covering the alias path, the canonical path, and the precedence rule when both keys are present simultaneously.

Issue Number

How to Test

Automated Tests

  • tests/tools/terminal/test_terminal_tool.py::test_terminal_action_commands_alias_remapped — verifies "commands" is accepted and mapped
  • tests/tools/terminal/test_terminal_tool.py::test_terminal_action_command_canonical_unchanged — verifies "command" still works
  • tests/tools/terminal/test_terminal_tool.py::test_terminal_action_command_takes_precedence_over_commands — verifies no regression when both keys appear

Manual Test

  • Start OpenHands and use the openrouter/google/gemma-4-31b-it:free model to execute a bash command and verify that it uses the correct { "input_value" { "command": ... }, ...} field name.

Video/Screenshots

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

🤖 Generated with Claude Code

google/gemma-4 models consistently emit "commands" (plural) as the
terminal tool's argument name instead of the correct "command" (singular),
causing every shell invocation to fail with a Pydantic validation error.

A mode='before' model_validator on TerminalAction silently remaps the
wrong key before validation so the error path is never reached.

This is intentionally placed on the model rather than in
fix_malformed_tool_arguments because the two utilities address different
problems: fix_malformed_tool_arguments corrects wrong VALUE types (JSON-
encoded strings, chunked lists); a model_validator is the right layer for
wrong KEY names, keeping each concern co-located with what it describes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant