Skip to content

feat: remove stale claims, add streaming/tools/retries, compatibility table#26

Merged
hizrianraz merged 1 commit into
mainfrom
feat/sdk-python-cleanup-expand
Jul 11, 2026
Merged

feat: remove stale claims, add streaming/tools/retries, compatibility table#26
hizrianraz merged 1 commit into
mainfrom
feat/sdk-python-cleanup-expand

Conversation

@hizrianraz

@hizrianraz hizrianraz commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

What shipped

Stale claims removed

  • Removed '57 models' from README (2 places) — all model counts now derive from API

Examples added

  • examples/streaming.py — streaming inference
  • examples/tools.py — tool use
  • examples/retries.py — retry strategies
  • examples/async_usage.py — async usage
  • examples/receipt_verification.py — local receipt verification
  • examples/error_handling.py — production error handling

pyproject.toml fixed

  • Package name: sdk → ainfera
  • Version: 0.1.0 → 1.1.0
  • Packages: src → python, sdk* → ainfera*
  • Testpaths: tests → python/tests
  • Added missing dev deps: httpx, pydantic, joserfc, respx, pytest-asyncio, pyright, click, pyyaml
  • Fixed broken prose line 3 (was causing TOML parse error)

Other

  • Compatibility table (ainfera vs openai vs anthropic SDK)
  • Semantic-release config (releaserc.toml)
  • Concept page links fixed (/concepts/ → /docs#)
  • 04_inference.py: model→ainfera-inference, fixed broken receipt.audit_url
  • ruff format applied to pre-existing files

Test results

  • 66 tests pass
  • ruff check: clean (6 pre-existing N818 errors in exceptions.py, not from this PR)
  • ruff format: 42 files clean

Co-authored-by: Aulë aule@ainfera.ai


Note

Medium Risk
Packaging rename (sdkainfera, package path srcpython) can break installs, CI, and imports if downstream still expect the old layout; version jump to 1.1.0 is a release-facing change.

Overview
Repositions the repo as the ainfera PyPI package at 1.1.0: pyproject.toml renames the project from sdk, points setuptools at python/ainfera*, moves tests to python/tests, bumps status to Beta, and expands dev optional deps (httpx, pydantic, joserfc, respx, etc.). Adds releaserc.toml for semantic-release off pyproject.toml:version.

README gains a compatibility table (ainfera vs OpenAI/Anthropic SDKs), API v1 versioning note, generic “all routed models” wording (drops hard-coded “57 models”), and concept links updated to ainfera.ai/docs#….

New examples/ scripts document async usage, streaming, tools, retries, receipt verification, and typed error handling; existing quickstart and python/examples/04_inference.py default to ainfera-inference and fix audit URL access (response.audit_url).

Library code changes are mostly ruff format (line wraps); no functional API changes in the diff hunks.

Reviewed by Cursor Bugbot for commit 1090b1a. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Added examples for asynchronous inference, streaming, tool use, retries, error handling, and receipt verification.
    • Updated inference examples to use the Ainfera inference model and expose audit information.
  • Documentation
    • Added SDK compatibility comparisons, API versioning guidance, and updated documentation links.
  • Release Updates
    • Updated package identity and version to 1.1.0.
    • Added semantic-release configuration for automated version management.

…ompatibility table

- Remove '57 models' references from README (2 places)
- Fix pyproject.toml: name sdk→ainfera, version 0.1.0→1.1.0, packages src→python,
  testpaths tests→python/tests, add missing dev deps (httpx, pydantic, joserfc, respx,
  pytest-asyncio, pyright, click, pyyaml), fix broken prose line 3
- Add examples: streaming, tools, retries, async_usage, receipt_verification, error_handling
- Add compatibility table (ainfera vs openai vs anthropic SDK)
- Add semantic-release config (releaserc.toml)
- Fix concept page links (/concepts/ → /docs#)
- Fix 04_inference.py: model→ainfera-inference, remove broken receipt.audit_url
- Fix quickstart.py: model→ainfera-inference
- ruff format applied to pre-existing files

Co-authored-by: Aulë <aule@ainfera.ai>
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The SDK package identity and release configuration are updated, README documentation adds compatibility and versioning details, new usage examples are introduced, existing examples are adjusted, and formatting-only changes are applied across implementation and test files.

Changes

SDK release and examples

Layer / File(s) Summary
Package identity and release configuration
pyproject.toml, releaserc.toml
Package metadata, dependency groups, package discovery, test discovery, and semantic-release settings are updated for the ainfera package.
Compatibility documentation and usage examples
README.md, examples/*, python/examples/04_inference.py
README compatibility and API-versioning content is added, and examples cover async inference, error handling, receipts, retries, streaming, tools, and updated model and audit access.
SDK source formatting cleanup
python/ainfera/...
Existing HTTP, JWS, agent, audit, CLI, client, and wallet code is reformatted without behavior changes.
Test fixture and assertion formatting
python/tests/..., tests/test_smoke.py
Test mocks, helper signatures, function definitions, and one verification call are reformatted while preserving test behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers what changed and testing, but it omits the required Why, How, Vocabulary check, and Linked sections from the template. Add the missing Why, How, Vocabulary check, Testing checkboxes, and Linked sections so the description matches the repository template.
Docstring Coverage ⚠️ Warning Docstring coverage is 28.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: stale-claim cleanup plus new streaming, tools, retries, and compatibility documentation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sdk-python-cleanup-expand

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hizrianraz
hizrianraz merged commit 37816d0 into main Jul 11, 2026
5 of 7 checks passed

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Fix All in Cursor

Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.

Reviewed by Cursor Bugbot for commit 1090b1a. Configure here.

Comment thread examples/retries.py
retry_delay=1.0,
retry_backoff=2.0,
retry_on_status=[429, 500, 502, 503],
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retries example invalid client kwargs

Medium Severity

examples/retries.py constructs AinferaClient with max_retries, retry_delay, retry_backoff, and retry_on_status, but AinferaClient.__init__ only accepts api_key, base_url, and timeout, so the example fails immediately with unexpected keyword arguments.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 1090b1a. Configure here.

@hizrianraz
hizrianraz deleted the feat/sdk-python-cleanup-expand branch July 11, 2026 06:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
releaserc.toml (1)

6-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider whether docs commits should trigger patch releases.

docs is listed in patch_tags, meaning documentation-only changes (e.g., README updates) will produce a new patch version. This may be intentional, but if you'd prefer docs changes to not trigger releases, remove "docs" from patch_tags and allowed_tags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@releaserc.toml` around lines 6 - 9, Review the semantic-release tag
configuration in [semantic_release.commit_parser] and decide whether
documentation-only commits should create patch releases; if not, remove "docs"
from both patch_tags and allowed_tags, ensuring the remaining tag configuration
reflects the intended release policy.
examples/async_usage.py (1)

16-16: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use response.content instead of deprecated response.text in new examples.

response.text is a deprecated 1.0.x alias (per inference.py:45-51 and README line 59). New example files should showcase the current recommended API (response.content) rather than the deprecated alias that will be removed in 2.0.

♻️ Proposed fix
     print(response.text)
+    print(response.content)

And on line 28:

     for r in results:
-        print(r.text)
+        print(r.content)

Also applies to: 28-28

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/async_usage.py` at line 16, Replace all uses of the deprecated
response.text alias in the async example, including both referenced lines, with
response.content so the example demonstrates the current API.
python/examples/04_inference.py (1)

11-11: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use response.content instead of deprecated response.text.

response.text is a deprecated 1.0.x alias (per inference.py:45-51). Since this line was modified in this PR, consider updating to response.content to align with the current API.

♻️ Proposed fix
-print(response.text)
+print(response.content)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/examples/04_inference.py` at line 11, Replace the deprecated
response.text access in the example with response.content, preserving the
existing output behavior.
examples/error_handling.py (1)

26-26: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use response.content instead of deprecated response.text in new examples.

response.text is a deprecated 1.0.x alias (per inference.py:45-51). New example files should use response.content to showcase the current API.

♻️ Proposed fix
-    print(response.text)
+    print(response.content)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/error_handling.py` at line 26, Replace the deprecated response.text
access with response.content in the example’s response-printing logic, using the
response variable at the affected statement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/receipt_verification.py`:
- Line 6: Update the AinferaClient initialization in the receipt verification
example to use the AINFERA_API_KEY environment variable via os.environ, or omit
the api_key argument if the client automatically reads it; add the required os
import if needed.

In `@pyproject.toml`:
- Around line 25-42: Move the runtime packages httpx, pydantic, joserfc, click,
and pyyaml from [project.optional-dependencies].dev into [project.dependencies]
so plain installations include SDK imports. Update the test extra to include
pytest-asyncio and respx alongside pytest and pytest-cov, while keeping only
development tooling and test-related packages in the dev group.

In `@python/examples/04_inference.py`:
- Line 12: Remove the invalid response.audit_url access from the example because
InferenceResponse does not define that field. Use the audit_url from the
returned Receipt instead, if the example needs to display it, by locating the
Receipt object produced by the inference flow.

In `@releaserc.toml`:
- Around line 1-4: Add python/ainfera/_version.py:__version__ to the
semantic_release version_variable configuration alongside
pyproject.toml:version, ensuring both package metadata and the runtime
ainfera.__version__ are updated during releases.

---

Nitpick comments:
In `@examples/async_usage.py`:
- Line 16: Replace all uses of the deprecated response.text alias in the async
example, including both referenced lines, with response.content so the example
demonstrates the current API.

In `@examples/error_handling.py`:
- Line 26: Replace the deprecated response.text access with response.content in
the example’s response-printing logic, using the response variable at the
affected statement.

In `@python/examples/04_inference.py`:
- Line 11: Replace the deprecated response.text access in the example with
response.content, preserving the existing output behavior.

In `@releaserc.toml`:
- Around line 6-9: Review the semantic-release tag configuration in
[semantic_release.commit_parser] and decide whether documentation-only commits
should create patch releases; if not, remove "docs" from both patch_tags and
allowed_tags, ensuring the remaining tag configuration reflects the intended
release policy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 401d8cf7-c5e0-43bc-8e9e-0e4a8646e6a7

📥 Commits

Reviewing files that changed from the base of the PR and between 5802df6 and 1090b1a.

📒 Files selected for processing (24)
  • README.md
  • examples/async_usage.py
  • examples/error_handling.py
  • examples/quickstart.py
  • examples/receipt_verification.py
  • examples/retries.py
  • examples/streaming.py
  • examples/tools.py
  • pyproject.toml
  • python/ainfera/_internal/http.py
  • python/ainfera/_internal/jws.py
  • python/ainfera/agents.py
  • python/ainfera/audit.py
  • python/ainfera/cli.py
  • python/ainfera/client.py
  • python/ainfera/wallet.py
  • python/examples/04_inference.py
  • python/tests/test_async_resources.py
  • python/tests/test_cli_install.py
  • python/tests/test_http.py
  • python/tests/test_resources.py
  • python/tests/test_verify.py
  • releaserc.toml
  • tests/test_smoke.py

from ainfera import AinferaClient
from ainfera.verify import verify_receipt

client = AinferaClient(api_key="ak_...")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether AinferaClient auto-reads AINFERA_API_KEY from env,
# and whether verify_receipt exists in ainfera.verify.

# Check AinferaClient constructor signature
ast-grep outline python/ainfera/client.py --match 'AinferaClient' --view expanded

# Check for env var reading in client constructor
rg -n -C3 'AINFERA_API_KEY|os.environ|getenv' python/ainfera/client.py

# Check verify_receipt exists in ainfera.verify
rg -n 'def verify_receipt' python/ainfera/verify.py

Repository: ainfera-ai/sdk-python

Length of output: 2207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the receipt verification example and related example files that may use the same pattern.
git ls-files 'examples/*.py'

printf '\n--- examples/receipt_verification.py ---\n'
cat -n examples/receipt_verification.py

printf '\n--- api_key literals in examples ---\n'
rg -n 'api_key\s*=\s*"' examples/*.py

printf '\n--- AINFERA_API_KEY usage in examples ---\n'
rg -n 'AINFERA_API_KEY|os\.environ|getenv' examples/*.py

Repository: ainfera-ai/sdk-python

Length of output: 2120


Use AINFERA_API_KEY in this example
api_key="ak_..." teaches the wrong credential pattern in sample code. Use os.environ["AINFERA_API_KEY"] (or omit api_key if the client already reads from env) so the example matches the SDK guidance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/receipt_verification.py` at line 6, Update the AinferaClient
initialization in the receipt verification example to use the AINFERA_API_KEY
environment variable via os.environ, or omit the api_key argument if the client
automatically reads it; add the required os import if needed.

Source: Coding guidelines

Comment thread pyproject.toml
Comment on lines 25 to 42
[project.optional-dependencies]
dev = [
"httpx>=0.27",
"pydantic>=2.0",
"joserfc>=0.9",
"pytest>=7.0",
"pytest-cov>=4.0",
"ruff>=0.4.0",
"pytest-asyncio>=0.23",
"pyright>=1.1",
"click>=8.0",
"pyyaml>=6.0",
"respx>=0.21",
]
test = [
"pytest>=7.0",
"pytest-cov>=4.0",
]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Runtime dependencies belong in [project.dependencies], not dev extras.

httpx, pydantic, joserfc, click, and pyyaml are imported by core SDK modules (http.py, jws.py, cli.py, etc.) but are only available via pip install ainfera[dev]. A plain pip install ainfera or pip install -e . will fail at import time. These should be declared under [project.dependencies].

Additionally, the test extras group is incomplete — it includes only pytest and pytest-cov but omits pytest-asyncio and respx, both of which are required by the test suite (e.g., test_async_resources.py, test_http.py). Anyone running pip install ainfera[test] followed by pytest will hit ImportError.

📦 Proposed fix for dependency grouping
 [project]
 name = "ainfera"
 version = "1.1.0"
 description = "Agent-native inference routing by Ainfera. Python SDK — signed AgentCards, routed inference, audit chains."
 readme = "README.md"
 requires-python = ">=3.10"
 license = {text = "Apache-2.0"}
 authors = [{name = "Ainfera Inc"}]
 classifiers = [
     "Development Status :: 4 - Beta",
     "Programming Language :: Python :: 3",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
 ]
+dependencies = [
+    "httpx>=0.27",
+    "pydantic>=2.0",
+    "joserfc>=0.9",
+    "click>=8.0",
+    "pyyaml>=6.0",
+]
 
 [project.optional-dependencies]
 dev = [
-    "httpx>=0.27",
-    "pydantic>=2.0",
-    "joserfc>=0.9",
     "pytest>=7.0",
     "pytest-cov>=4.0",
     "ruff>=0.4.0",
     "pytest-asyncio>=0.23",
     "pyright>=1.1",
-    "click>=8.0",
-    "pyyaml>=6.0",
     "respx>=0.21",
 ]
 test = [
     "pytest>=7.0",
     "pytest-cov>=4.0",
+    "pytest-asyncio>=0.23",
+    "respx>=0.21",
 ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyproject.toml` around lines 25 - 42, Move the runtime packages httpx,
pydantic, joserfc, click, and pyyaml from [project.optional-dependencies].dev
into [project.dependencies] so plain installations include SDK imports. Update
the test extra to include pytest-asyncio and respx alongside pytest and
pytest-cov, while keeping only development tooling and test-related packages in
the dev group.

)
print(response.text)
print(response.receipt.audit_url)
print(response.audit_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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify InferenceResponse has an `audit_url` attribute.

# Find the InferenceResponse model definition
rg -n "class InferenceResponse" --type py python/
# Then inspect the model fields for audit_url
rg -n "audit_url" --type py python/ainfera/

Repository: ainfera-ai/sdk-python

Length of output: 274


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the InferenceResponse model and nearby definitions.
sed -n '1,220p' python/ainfera/inference.py

printf '\n--- receipt.py ---\n'
sed -n '1,220p' python/ainfera/receipt.py

printf '\n--- search for audit_url access on InferenceResponse ---\n'
rg -n "response\.audit_url|receipt\.audit_url|audit_url" python/examples python/ainfera -g '*.py'

Repository: ainfera-ai/sdk-python

Length of output: 2496


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the example around the flagged line to preserve the correct guidance.
sed -n '1,80p' python/examples/04_inference.py

Repository: ainfera-ai/sdk-python

Length of output: 491


response.audit_url is not available here InferenceResponse doesn’t define audit_url; the only audit_url field in the SDK is on Receipt, so this example will raise AttributeError.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/examples/04_inference.py` at line 12, Remove the invalid
response.audit_url access from the example because InferenceResponse does not
define that field. Use the audit_url from the returned Receipt instead, if the
example needs to display it, by locating the Receipt object produced by the
inference flow.

Comment thread releaserc.toml
Comment on lines +1 to +4
[semantic_release]
version_variable = ["pyproject.toml:version"]
branch = "main"
upload_to_pypi = false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf 'FILES:\n'
git ls-files releaserc.toml pyproject.toml python/ainfera/_version.py python/ainfera/__init__.py || true

printf '\nRELEASE CONFIG:\n'
cat -n releaserc.toml

printf '\nVERSION FILES / IMPORTS:\n'
for f in python/ainfera/_version.py python/ainfera/__init__.py pyproject.toml; do
  if [ -f "$f" ]; then
    printf '\n== %s ==\n' "$f"
    cat -n "$f"
  fi
done

printf '\nSEARCHES:\n'
rg -n "__version__|version_variable|semantic_release" . --glob '!**/.git/**'

Repository: ainfera-ai/sdk-python

Length of output: 5303


version_variable also needs python/ainfera/_version.py:__version__. ainfera.__version__ is imported from that file, so leaving it out will make the runtime version drift from pyproject.toml after a release.

🔧 Proposed fix
 [semantic_release]
-version_variable = ["pyproject.toml:version"]
+version_variable = ["pyproject.toml:version", "python/ainfera/_version.py:__version__"]
 branch = "main"
 upload_to_pypi = false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[semantic_release]
version_variable = ["pyproject.toml:version"]
branch = "main"
upload_to_pypi = false
[semantic_release]
version_variable = ["pyproject.toml:version", "python/ainfera/_version.py:__version__"]
branch = "main"
upload_to_pypi = false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@releaserc.toml` around lines 1 - 4, Add
python/ainfera/_version.py:__version__ to the semantic_release version_variable
configuration alongside pyproject.toml:version, ensuring both package metadata
and the runtime ainfera.__version__ are updated during releases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant