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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); feat(api): generate Projects REST bindings by AbhiPrasad · Pull Request #697 · braintrustdata/braintrust-sdk-python · GitHub
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

@AbhiPrasadAbhijeet 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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated
Comment threadpy/src/braintrust/api/projects.py Outdated
Base automatically changed from abhi-openapi to mainAugust 17, 2026 16:29

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/projects.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/_adapter.py Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/errors.py
Comment threadpy/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 a2a9583CompareAugust 17, 2026 22:10

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the abhi-openapi-projects branch 2 times, most recently from 2c10610 to 6e84ffaCompareAugust 17, 2026 22:44

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/__init__.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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-connectorchatgpt-codex-connectorBot 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 threadpy/src/braintrust/api/client.py

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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 threadpy/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 mainAug 18, 2026
83 checks passed
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) deleted the abhi-openapi-projects branch August 18, 2026 00:55
Sign up for freeto 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

@AbhiPrasad