Skip to content

fix(sdk): preserve primitive JSON Schema semantics - #4316

Open
Alberto Schiabel (jkomyno) wants to merge 28 commits into
nextfrom
fix/cross-sdk-schema-primitives
Open

fix(sdk): preserve primitive JSON Schema semantics#4316
Alberto Schiabel (jkomyno) wants to merge 28 commits into
nextfrom
fix/cross-sdk-schema-primitives

Conversation

@jkomyno

@jkomyno Alberto Schiabel (jkomyno) commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • preserve boolean, empty, null, type-array, enum, const, and scalar-constraint semantics across every Python conversion entry point
  • intersect Zod enum and const values with declared types and constraints, including compound JSON values
  • default unversioned exact validation to Draft 7 and apply inclusive and numeric exclusive bounds independently
  • run one byte-identical corpus through Python, Zod, and Effect so accepted and rejected inputs stay aligned
  • keep exact JSON Schema acceptance separate from Pydantic default materialization

Review follow-up (second push)

  • Python: exact Draft 7 acceptance now wraps all three entry points (json_schema_to_pydantic_type, json_schema_to_model, pydantic_model_from_param_schema), so they can no longer disagree
  • Python: draft-4 boolean exclusiveMinimum/exclusiveMaximum (OpenAPI 3.0 style) no longer crash conversion — exact validation falls back to Draft 4, and the library input is translated to the numeric spelling
  • Python: ECMA-only regex patterns (look-around) no longer crash pydantic model builds — Rust-incompatible patterns fall back to Python re
  • Python: type arrays with sibling constraints no longer raise TypeError on valid input — constraints are scoped per member before the library sees them
  • Python: integral floats satisfy integer, const intersects enum, annotation-only schemas accept anything, and an optional property with an empty enum tolerates absence
  • Zod: typeless scalar constraints apply per instance type, and string lengths count Unicode code points instead of UTF-16 code units
  • Effect: draft-4 boolean exclusive bounds are enforced instead of silently ignored
  • multipleOf uses decimal scaling in all three converters (declared divergesFromJsonSchema on the corpus case)
  • shared corpus grows by 13 primitive cases; new property-based tests check acceptance against real Draft 7 oracles (hypothesis + jsonschema in Python, fast-check + Ajv in TypeScript)

Verification

  • Python make chk (ruff + mypy)
  • Python pytest: 1,572 passed (5 langchain-extra tests need an env this sandbox lacks; unchanged from base)
  • @composio/json-schema-to-zod: 187 passed incl. 300-run fast-check property test; typecheck + build
  • @composio/json-schema-to-effect-schema: 133 passed; typecheck
  • @composio/core corpus ingress tests: 61 passed
  • shared Python/TypeScript corpus files are byte-identical (shasum-verified)
  • git diff --check

Contributor context

This replaces four narrow proposals after independent local reproduction:

@vercel

vercel Bot commented Aug 31, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Sep 2, 2026 9:24pm UTC

Request Review

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

⚠️ Security Audit Warning

The pnpm audit --prod check found security vulnerabilities in production dependencies.

Please review and fix the vulnerabilities. You can try running:

pnpm audit --fix --prod
Audit output
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ extract-zip unvalidated symlink path traversal         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ extract-zip                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <=2.0.1                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=2.0.2                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__packages__cli>extract-zip                          │
│                     │                                                        │
│                     │ ts__packages__cli-local-tools>extract-zip              │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-jmr9-qjv8-65gv      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ fast-uri vulnerable to host confusion via skipped IDN  │
│                     │ canonicalization on scheme-relative references         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-uri                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=3.1.3 <3.1.6                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.1.6                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv>fast-uri             │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv-formats>ajv>fast-uri │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>ajv>fast-uri │
│                     │                                                        │
│                     │ ... Found 65 paths, run `pnpm why fast-uri` for more   │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-5jgf-p345-68v8      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ fast-uri vulnerable to server-side request forgery via │
│                     │ malformed IPv6 normalization                           │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-uri                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=3.0.0 <3.1.6                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.1.6                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv>fast-uri             │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv-formats>ajv>fast-uri │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>ajv>fast-uri │
│                     │                                                        │
│                     │ ... Found 65 paths, run `pnpm why fast-uri` for more   │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-f65p-4m7j-42xc      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ fast-uri vulnerable to server-side request forgery via │
│                     │ repeated hostname percent-decoding                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-uri                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=3.1.2 <3.1.6                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.1.6                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv>fast-uri             │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv-formats>ajv>fast-uri │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>ajv>fast-uri │
│                     │                                                        │
│                     │ ... Found 65 paths, run `pnpm why fast-uri` for more   │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-fph4-wmhf-6fwf      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ high                │ fast-uri vulnerable to host confusion via              │
│                     │ percent-encoded scheme normalization                   │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ fast-uri                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=3.0.0 <3.1.6                                         │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.1.6                                                │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv>fast-uri             │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>ajv-formats>ajv>fast-uri │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@modelcontextprotocol/sdk>ajv>fast-uri │
│                     │                                                        │
│                     │ ... Found 65 paths, run `pnpm why fast-uri` for more   │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-jqff-g426-hqxp      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ qs array-limit bypass via bracket-key comma parsing    │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ qs                                                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=6.14.2 <=6.15.3                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.15.4                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express>body-parser>qs   │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express>qs               │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express-rate-            │
│                     │ limit>express>body-parser>qs                           │
│                     │                                                        │
│                     │ ... Found 100 paths, run `pnpm why qs` for more        │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-x5fp-wj9c-mxmx      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ moderate            │ qs: Denial of Service via Attacker Controlled isBuffer │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ qs                                                     │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ >=2.2.5 <6.16.0                                        │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=6.16.0                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express>body-parser>qs   │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express>qs               │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__claude-agent-           │
│                     │ sdk>@anthropic-ai/claude-agent-                        │
│                     │ sdk>@modelcontextprotocol/sdk>express-rate-            │
│                     │ limit>express>body-parser>qs                           │
│                     │                                                        │
│                     │ ... Found 100 paths, run `pnpm why qs` for more        │
│                     │ information                                            │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-4mjr-xmp4-gh2g      │
└─────────────────────┴────────────────────────────────────────────────────────┘
┌─────────────────────┬────────────────────────────────────────────────────────┐
│ low                 │ @ai-sdk/provider-utils has an Uncontrolled Resource    │
│                     │ Consumption issue                                      │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Package             │ @ai-sdk/provider-utils                                 │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Vulnerable versions │ <=3.0.97                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Patched versions    │ >=3.0.98                                               │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ Paths               │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/core>@ai-sdk/provider-utils                 │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v3>@mastra/mcp>@mastra/core>@ai-sdk/provider-utils     │
│                     │                                                        │
│                     │ ts__e2e-tests__runtimes__node__mastra-tool-router-zod- │
│                     │ v4>@mastra/core>@ai-sdk/provider-utils                 │
│                     │                                                        │
│                     │ ... Found 14 paths, run `pnpm why                      │
│                     │ @ai-sdk/provider-utils` for more information           │
├─────────────────────┼────────────────────────────────────────────────────────┤
│ More info           │ https://github.com/advisories/GHSA-866g-f22w-33x8      │
└─────────────────────┴────────────────────────────────────────────────────────┘
8 vulnerabilities found
Severity: 1 low | 2 moderate | 5 high

Comment thread python/composio/utils/schema_converter.py
Comment thread python/composio/utils/schema_converter.py
Comment thread python/composio/utils/schema_converter.py
Comment thread python/composio/utils/schema_converter.py Outdated
Comment thread python/composio/utils/schema_converter.py Outdated
Comment thread python/composio/utils/schema_converter.py
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Preview this PR's installer

The hermetic install E2E suite passed for this commit. These commands run the PR's installer scripts against the latest published CLI release — they preview installer behavior, not unreleased binaries.

curl -fsSL "https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install.sh" | sh
curl -fsSL "https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install.sh" | COMPOSIO_INSTALL_SHELL=none sh

The first command is the default flow: it installs the CLI and configures your shell automatically. The second installs only, without touching shell startup files.

Shell-specific setup routes (the override points the variant at this PR's base installer):

curl -fsSL "https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install/bash.sh" | COMPOSIO_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install.sh" sh
curl -fsSL "https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install/zsh.sh" | COMPOSIO_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install.sh" sh
curl -fsSL "https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install/fish.sh" | COMPOSIO_INSTALL_SCRIPT_URL="https://raw.githubusercontent.com/ComposioHQ/composio/f354f6f51b7bda8b3701a04f5bd9b7b3ef49eca2/install.sh" sh

@socket-security

socket-security Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​hypothesis@​6.167.19810010010070
Addednpm/​fast-check@​4.9.010010010087100

View full report

Comment thread python/composio/utils/schema_converter.py
Comment thread python/composio/utils/schema_converter.py Outdated
@simpleqt

Copy link
Copy Markdown

Thanks for consolidating these — I went through the diff and it covers every shape my closed PRs (#4301/#4302/#4303/#4307) reported: draft-06 type-array folding, draft-04 tuple items, empty {} / bare "null" schemas, and the numeric/string constraint passthrough, plus the enum/const intersection and the TS-side parity work that mine didn't attempt. Happy to lend a review eye on the Python fixtures if useful.

Credit the schema conversion cases originally surfaced and implemented in #4301, #4302, #4303, and #4307.

Co-authored-by: simpleqt <89645338+simpleqt@users.noreply.github.com>
Comment thread python/composio/utils/schema_converter.py
Comment thread ts/packages/json-schema-to-zod/src/whole-schema-validation.ts
Comment thread ts/packages/json-schema-to-zod/src/whole-schema-validation.ts Outdated
…eep literal checks

- thread the document root through Refs so shape properties and nested
  refs resolve #/$defs pointers
- widen only the permissive node so enclosing defaults survive
- dispatch enum/const before object and array parsers
- materialize closed allOf branches open and re-apply strictness once
- normalize draft-4 boolean bounds before whole-schema validation
- refuse non-local $ref at conversion time and build the validator with a
  local-only registry so remote references never trigger network I/O
- match pattern through pydantic's linear-time regex, falling back to re
  only for ECMA-only constructs, so backtracking patterns cannot stall
  argument validation
- run every anyOf/oneOf through exact validation so unions stop coercing
  booleans into integers
- apply the omitted-additionalProperties strictness rule once per allOf
  over the union of closed branch keys
handle_response now reuses the normalize, validate, serialize, and alias
restoration sequence of the wrapped callable instead of executing raw
arguments.
…t draft 4

- skip the boolean-to-numeric bound rewrite when the caller selects draft 4
- open closed allOf object branches and apply strictness once over the
  union of declared keys, matching the Zod and Python converters
- add the shared corpus case that pins the merged allOf contract
Comment thread python/composio/utils/schema_converter.py
Comment thread python/composio/utils/shared.py
…pers

- descend through Annotated exact-validation wrappers when marking
  explicit default fields, so array items with union properties keep their
  materialized defaults
- wrap library models produced for top-level anyOf/oneOf so sibling
  assertions such as required are not dropped
- keep exact validation on property-less param schemas instead of
  returning a bare dict

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 488ff1a. Configure here.

Comment thread python/composio/utils/shared.py Outdated
…tation

Wrapping a bare dict forced object coercion on schemas that admit other
JSON types. Delegating to json_schema_to_pydantic_type keeps exact
validation and permissive materialization identical across entry points.
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.

2 participants