feat(openapi): generated MCP/Python contract types + drift CI (#37 phase 2)#48
Merged
Conversation
…se 2) Implements phase 2 of #37 / closes #46. Generated artifacts are a contract reference; hand-written MCP/SDK public models are unchanged (no runtime or package behavior change — backward compatible). - MCP/TS: `openapi-typescript@7.4.4` (pinned devDep) -> checked-in packages/mcp/src/generated/openapi.d.ts; `npm run gen:openapi` regenerates. - Python SDK: `datamodel-code-generator==0.26.3` (pinned dev extra) -> checked-in packages/python-sdk/qveris/generated/openapi_models.py (pydantic v2, py3.8 target) + package __init__ documenting regeneration. - CI: .github/workflows/openapi-types.yml regenerates both with the pinned generators and fails on `git diff --exit-code`, path-scoped to docs/openapi/** + the generators (mirrors openapi-contract.yml from #44). Verified: artifacts are byte-reproducible from the checked-in spec (empty diff on regen), the .d.ts typechecks under tsc --strict, and the Python models pass py_compile.
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces automated generation of OpenAPI contract models for both the MCP package and the Python SDK. In the MCP package, a new gen:openapi script and the openapi-typescript dependency were added to generate TypeScript definitions. For the Python SDK, datamodel-code-generator was integrated to produce Pydantic models, accompanied by documentation on regeneration and CI drift prevention. Review feedback suggests appending a formatting step to the TypeScript generation script to ensure the output adheres to the project's 2-space indentation standard.
vxwork
approved these changes
May 18, 2026
* feat(contract): adopt generated OpenAPI types — CLI + Python guards (#37 phase 3) Implements phase 3 of #37 / closes #47. First low-risk adoption step; public MCP/CLI/Python SDK APIs unchanged (additive tests + CI only). - CLI (JS/MJS): packages/cli/test/openapi-contract.test.mjs asserts every endpoint+method the CLI calls (kept in sync with src/client/api.mjs: POST /search, /tools/by-ids, /tools/execute; GET /auth/credits, /auth/usage/history/v2, /auth/credits/ledger) exists in the mirrored public OpenAPI spec — the issue's "CLI contract tests before type gen". - Python SDK: tests/test_openapi_contract.py starts *consuming* the generated qveris.generated.openapi_models as a drift guard (core contract models present + pydantic + smoke roundtrip). Hand-written qveris.types stays the public surface; field alignment stays gradual by design. - CI: .github/workflows/contract-tests.yml runs both on PRs (the existing cli/python *-publish workflows only fire on release tags, so without this the guards would not gate PRs). Verified locally: CLI `node --test` 7/7 pass; Python pytest 11/11 pass. Builds on #46/#48 (needs the generated artifacts) — merge after #48. * fix(contract): load generated models standalone + robust shape check (#47) CI python-contract failed: importing qveris.generated.openapi_models pulled qveris/__init__.py (httpx not installed in the minimal contract job). Load the generated file by path so the guard only needs pydantic. Replace the instantiation smoke with a model_fields shape assertion (the generated file's __future__ annotations + constrained types need model_rebuild() to validate; the field map is the stable contract signal regardless).
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #46. Implements Phase 2 of #37 (follow-up to #44 / Phase 1).
What
Generate checked-in type artifacts from the website-mirrored
docs/openapi/qveris-public-api.openapi.json, as a contract reference — the hand-written public MCP/SDK models are untouched.openapi-typescript@7.4.4(pinned devDep) →packages/mcp/src/generated/openapi.d.ts. Regenerate withnpm --prefix packages/mcp run gen:openapi.datamodel-code-generator==0.26.3(pinneddevextra) →packages/python-sdk/qveris/generated/openapi_models.py(pydantic v2, py3.8 target) +generated/__init__.pydocumenting regeneration..github/workflows/openapi-types.ymlre-runs both pinned generators and fails ongit diff --exit-code, path-scoped todocs/openapi/**+ the generators (mirrorsopenapi-contract.ymlfrom ci: OpenAPI contract validation (#37 phase 1) #44).Non-goals (Phase 3 / #47)
No adoption of the generated types into runtime code. MCP, CLI, and Python SDK public APIs are unchanged and backward compatible.
Verification
git diff(so the drift gate is stable).packages/mcp/src/generated/openapi.d.tstypechecks undertsc --strict --skipLibCheck.openapi_models.pypassespy_compile.