Skip to content

fix(openapi): let operation parameters override path-level ones - #7209

Open
1aifanatic wants to merge 2 commits into
google:mainfrom
1aifanatic:fix/openapi-operation-params-override-path-params
Open

1aifanatic wants to merge 2 commits into
google:mainfrom
1aifanatic:fix/openapi-operation-params-override-path-params

Conversation

@1aifanatic

Copy link
Copy Markdown

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:

OpenApiSpecParser._collect_operations() appended every path-level parameter to each operation's own parameters. Per the OpenAPI 3 Path Item Object, an operation-level parameter with the same name and in overrides the path-level one. Keeping both made the tool ask the model for the same path value twice (account_id and account_id_0, both required). Both map to the same {accountId} placeholder, and the path-level value won, so the operation's own, more specific parameter was dropped from the request.

Solution:

Skip path-level parameters whose (name, in) the operation already declares. Parameters with the same name but a different location are still merged. References are resolved before this step, so parameters are plain dicts here; anything without a name is left untouched.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

test_openapi_spec_parser.py::test_parse_spec_operation_parameter_overrides_path_level_parameter: the path accountId is overridden and keeps the operation's description, while a same-named header parameter is still merged. Fails on main.

$ pytest tests/unittests/tools/openapi_tool
342 passed

$ pytest tests/unittests -n 8   # Python 3.12, Windows 11
42 failed, 15146 passed, 102 skipped, 27 xfailed, 2 xpassed

Every failure outside the new tests also fails on an unmodified origin/main (3f4bb8f) on the same machine, where the same run gives 47 failed. Most are deterministic Windows-specific tests (cli/ deploy, conformance, scripts/check_new_py_files, path normalization, the unsafe local code executor, the import allowlist, yaml). The remainder differ between runs: telemetry functional/node-functional schema cases, and streaming/test_streaming_tool_events.py::test_delivered_event_carries_the_message_and_nothing_else, which failed 1/10 in isolation on clean main versus 2/10 on this branch. I ran on Python 3.12 only, not the full tox matrix.

Manual End-to-End (E2E) Tests:

An OpenAPIToolset whose /accounts/{accountId} path declares accountId and whose GET overrides it; HTTP goes to an httpx.MockTransport. The script is in #7205.

Before (main @ 3f4bb8f):

model is asked for: ['account_id', 'account_id_0']
args: {'account_id': 'ACC-123', 'account_id_0': 'ACC-999'} -> request: https://crm.example.com/accounts/ACC-999

After:

model is asked for: ['account_id']
args: {'account_id': 'ACC-123'} -> request: https://crm.example.com/accounts/ACC-123

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

🤖 Generated with Claude Code

https://claude.ai/code/session_013vXxD1ga1hnCq2uFRwNks7

_collect_operations() appended every path-level parameter to each
operation's parameters. An operation-level parameter with the same name
and location overrides the path-level one (OpenAPI Path Item Object), so
keeping both asked the model for the same path value twice, as
account_id and account_id_0. Both map to the same placeholder, and the
path-level value won, dropping the operation's more specific parameter.

Skip path-level parameters whose (name, in) the operation already
declares.

Fixes google#7205

Claude-Session: https://claude.ai/code/session_013vXxD1ga1hnCq2uFRwNks7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants