Skip to content

fix(actions): Merge path-item parameters and flatten allOf in request bodies#12660

Open
CarterPape wants to merge 1 commit intodanny-avila:mainfrom
CarterPape:fix/actions-openapi-allof-and-pathitem-params
Open

fix(actions): Merge path-item parameters and flatten allOf in request bodies#12660
CarterPape wants to merge 1 commit intodanny-avila:mainfrom
CarterPape:fix/actions-openapi-allof-and-pathitem-params

Conversation

@CarterPape
Copy link
Copy Markdown

Fixes #12659

Summary

Two bugs in openapiToFunction (packages/data-provider/src/actions.ts) corrupt tool schemas when importing OpenAPI 3 specs that use path-item-level shared parameters or allOf in request bodies — both common, spec-compliant patterns.

Discovered while importing the FireCrawl v2 spec (30 operations), where they together broke 20 of 26 tools.


Bug 1 — Path-item parameters treated as a method (ghost tools + missing path params)

Object.entries(pathItem) iterated every key including non-method ones (parameters, summary, description, servers). The parameters key became a ghost tool, and the shared parameters were never merged into the real operations — so path params like {id} went missing.

Fix: restrict the inner loop to the 8 valid HTTP method names via an HTTP_METHODS set; extract path-item parameters and merge them into each operation (operation-level wins on (name, in) collision per OpenAPI 3.0 §4.8.9).

Before / After:

# Spec: /items/{id} with path-item parameters: [{name: id, in: path}] + GET + DELETE

Before: 3 signatures — "parameters_...", "getItem" (no id), "deleteItem" (no id)
After:  2 signatures — "getItem" (id required), "deleteItem" (id required)

Bug 2 — allOf in request body silently dropped

resolveRef only unwraps $ref; it doesn't expand allOf. A request body { allOf: [A, B] } left resolvedSchema.properties as undefined, so no body fields were added to the tool.

Fix: add flattenAllOf() — recursively resolves $ref and merges allOf member schemas (properties, required, type), with a cycle guard. Used in place of the bare resolveRef call on request body schemas.

Before / After:

# Spec: POST /scrape body = { allOf: [{url: string (required)}, {$ref: ScrapeOptions}] }

Before: scrape tool — properties: {}, required: []
After:  scrape tool — properties: {url, formats, onlyMainContent, ...}, required: [url]

Test plan

  • 8 new unit tests added in packages/data-provider/specs/actions.spec.ts
    • Shared path-item params merge into all operations
    • No ghost tool created for the parameters key
    • Operation-level param wins over path-item param on (name, in) collision
    • Non-method keys (summary, description, servers) are ignored
    • Inline allOf body is flattened
    • $ref inside allOf members resolves correctly
    • Nested allOf via $ref (component schema itself uses allOf) resolves fully
    • Properties alongside allOf on the same schema object are included
  • All 188 pre-existing tests in actions.spec.ts still pass (196 total)
  • tsc --noEmit clean

🤖 Generated with Claude Code

… bodies

Two bugs in openapiToFunction caused broken tool schemas when importing
OpenAPI specs that use path-item-level shared parameters or allOf in
request bodies (e.g. the FireCrawl v2 spec).

Bug 1 — path-item parameters:
Object.entries(pathItem) iterated ALL keys including non-method ones like
`parameters`, `summary`, `description`, and `servers`. This created ghost
tools (e.g. `parameters_/crawl/{id}`) and silently dropped the shared
path params from the real operations.

Fix: restrict the inner loop to the 8 valid HTTP method keys using a
`HTTP_METHODS` Set, then explicitly extract path-item-level `parameters`
and merge them into each operation's own parameter list, with operation-
level entries winning on (name, in) collision per OpenAPI 3.0 §4.8.9.

Bug 2 — allOf in request bodies:
resolveRef only unwraps $ref; it does not expand allOf. Request bodies
like `{ allOf: [ScrapeOptions, { properties: { url } }] }` resulted in
resolvedSchema.properties being undefined, so no body fields were added
to the tool.

Fix: add a flattenAllOf() helper that recursively resolves $ref and
merges allOf member schemas (properties, required, type), with a cycle
guard. Use it in place of the bare resolveRef call on request body schemas.

Adds 8 new unit tests covering: shared params merge, no ghost tools,
operation-level param wins on collision, non-method keys ignored,
inline allOf body, $ref-inside-allOf, nested allOf via $ref, and
properties alongside allOf.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@danny-avila
Copy link
Copy Markdown
Owner

/gitnexus index

@github-actions
Copy link
Copy Markdown
Contributor

GitNexus: ✅ indexed

PR #12660 was indexed with embeddings.
Index run

⏳ Waiting for deploy to serve the fresh index…

Copy link
Copy Markdown

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

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: fac124cc62

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

components,
seen,
);
merged.properties = { ...merged.properties, ...flat.properties };
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 Preserve intersected constraints when merging allOf properties

When allOf members define the same property name, merged.properties = { ...merged.properties, ...flat.properties } replaces the entire earlier property schema with the later one, which drops constraints instead of intersecting them. For example, a first member can declare id as type: string and a later member add minLength; after this merge, type is lost. This produces incorrect tool/zod schemas for composed request bodies and can allow invalid payloads or reject valid ones depending on member order.

Useful? React with 👍 / 👎.

Repository owner deleted a comment from github-actions Bot Apr 15, 2026
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.

[Bug]: Action OpenAPI converter drops shared path-item parameters and silently ignores allOf request bodies

2 participants