Skip to content

feat(api): generate Projects REST bindings - #697

Merged
Abhijeet Prasad (AbhiPrasad) merged 1 commit into
mainfrom
abhi-openapi-projects
Aug 18, 2026
Merged

feat(api): generate Projects REST bindings#697
Abhijeet Prasad (AbhiPrasad) merged 1 commit into
mainfrom
abhi-openapi-projects

Conversation

@AbhiPrasad

@AbhiPrasad Abhijeet Prasad (AbhiPrasad) commented Aug 17, 2026

Copy link
Copy Markdown
Member

Implements step 2 of #683.

AI Summary

This adds the first public generated REST resource:

  • BraintrustOpenApiClient.projects: post_project, get_project, get_project_id, patch_project_id, and delete_project_id
  • braintrust.api.types: public CreateProject, PatchProject, Project, and GetProjectResponse types

The initial codegen surface is intentionally narrow: it selects one OpenAPI tag, slices the spec to that tag's transitive component closure, and emits one operation/resource module plus one model module:

    braintrust/api/_generated/
    ├── models/
    │   └── projects.py
    └── projects.py

The generated ProjectsAPI resource derives public method and inline response names mechanically from operation IDs, with normalized-name collisions rejected during generation. Generated methods forward request fields and parameters without implicit defaults. Unreachable models and unselected resource placeholders are omitted; selecting a second tag requires explicit cross-resource model partitioning.

Generated resources reuse the existing ResourceAPI transport, authentication, routing, retry, and error handling. BraintrustClient owns one transport and router shared by its handwritten auth service and non-owning openapi client; both client constructors remain network-free, while client.auth.login() explicitly performs organization discovery and configures routing. logger.py stores this shared client and returns its OpenAPI view from api_client(). Generation remains offline and deterministic, and codegen drift checks replace the generated tree atomically so stale files cannot survive a layout change.

Coverage includes deterministic codegen, exact wire behavior, additive responses, transparent request forwarding, typing, collision validation, and a cassette-backed end-to-end Projects flow.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1e29a894cd

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/projects.py Outdated
Comment thread py/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to main August 17, 2026 16:29

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6f1aa14a11

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 054a892cbb

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37ddc3da5b

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7f99719e2

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a8c2edf49

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/errors.py
Comment thread py/src/braintrust/api/_generated/models/projects.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) force-pushed the abhi-openapi-projects branch 2 times, most recently from 1122624 to a2a9583 Compare August 17, 2026 22:10

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2a9583788

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffa Compare August 17, 2026 22:44

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e84ffa12f

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/__init__.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d56125486

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/scripts/openapi_codegen.py Outdated
inline_models: Dict[str, Mapping[str, Any]] = {}
for method, path, operation_id, operation, path_item in _iter_operations(spec):
tags = operation.get("tags", [])
if method == "options" or not tags or tags[0] not in generated_tags:

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 Select operations by every declared tag

When an OpenAPI operation has a generated tag after another tag (for example, tags: ["Internal", "Projects"]), validation selects it because _selected_operations() checks every tag, but generation silently drops it here by checking only tags[0]. If another Projects operation exists, validation still succeeds and the resulting client is missing this operation; use the same any-tag membership predicate during collection.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81b40ed143

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/client.py

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0400981871

ℹ️ 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 (@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 (@codex) address that feedback".

Comment thread py/src/braintrust/api/auth.py Outdated
Comment on lines +99 to +100
resolved_api_url = api_url or self._router.api_url or BraintrustEnv.API_URL.get(organization.api_url)
resolved_proxy_url = proxy_url or self._router.proxy_url or BraintrustEnv.PROXY_URL.get(organization.proxy_url)

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 Refresh routing when selecting another organization

When the same client logs in again for a different organization, these fallbacks reuse the URLs written into the router by the first login. For example, after login(org_name="one"), login(org_name="two") can return organization two while leaving client.openapi routed to organization one's API and proxy hosts. Preserve constructor-level overrides separately, but otherwise resolve each login from the newly selected organization's URLs.

Useful? React with 👍 / 👎.

previous = generated_names.setdefault(generated_name, operation_id)
if previous != operation_id:
raise CodegenError(
f"Inline operation name collision: {previous!r} and {operation_id!r} both generate {generated_name!r}"

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 Validate collisions in emitted operation names

When two selected operation IDs differ only in acronym casing, such as getURL and getUrl, this check considers GetURL and GetUrl distinct even though _snake_case() emits get_url and GET_URL for both. The generated module then silently redefines the first operation and method, and both OPERATIONS entries reference the second operation's metadata; validate the actual method and constant identifier namespaces before generation.

Useful? React with 👍 / 👎.

Implements step 2 of #683 by adding synchronous project create, list, get,
update, and delete methods, along with their public TypedDict types.

Keep the initial codegen surface intentionally narrow: select one OpenAPI tag,
slice the spec to its transitive component closure, and emit one operation and
binding module plus one model module. Binding and inline response names are
derived mechanically from operation IDs, with normalized-name collisions
rejected during generation.

The generated bindings reuse the existing transport, authentication, routing,
retry, and error handling. Coverage includes deterministic codegen, exact wire
behavior, additive responses, typing, collision validation, and a cassette-backed
end-to-end Projects flow.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) merged commit fcb5dcc into main Aug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
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