-
Notifications
You must be signed in to change notification settings - Fork 0
feat: remove stale claims, add streaming/tools/retries, compatibility table #26
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| """Async usage of the Ainfera SDK.""" | ||
|
|
||
| import asyncio | ||
|
|
||
| from ainfera import AsyncAinferaClient | ||
|
|
||
|
|
||
| async def main() -> None: | ||
| client = AsyncAinferaClient(api_key="ak_...") | ||
| agent = await client.agents.retrieve("ag_...") | ||
|
|
||
| response = await agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "Hello"}], | ||
| ) | ||
| print(response.text) | ||
|
|
||
| # Concurrent requests | ||
| tasks = [ | ||
| agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": f"Fact {i}"}], | ||
| ) | ||
| for i in range(3) | ||
| ] | ||
| results = await asyncio.gather(*tasks) | ||
| for r in results: | ||
| print(r.text) | ||
|
|
||
|
|
||
| asyncio.run(main()) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| """Production error handling with Ainfera SDK.""" | ||
|
|
||
| import logging | ||
|
|
||
| from ainfera import ( | ||
| AinferaClient, | ||
| AuthenticationError, | ||
| RateLimitError, | ||
| ServerError, | ||
| ) | ||
| from ainfera import ( | ||
| TimeoutError as APITimeoutError, | ||
| ) | ||
|
|
||
| logging.basicConfig(level=logging.INFO) | ||
| logger = logging.getLogger(__name__) | ||
|
|
||
| client = AinferaClient(api_key="ak_...", timeout=30.0) | ||
| agent = client.agents.retrieve("ag_...") | ||
|
|
||
| try: | ||
| response = agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "Hello"}], | ||
| ) | ||
| print(response.text) | ||
|
|
||
| except AuthenticationError: | ||
| logger.error("Invalid API key — check your credentials") | ||
|
|
||
| except RateLimitError as e: | ||
| logger.warning(f"Rate limited — retry after {e.retry_after}s") | ||
|
|
||
| except APITimeoutError: | ||
| logger.error("Request timed out — try a simpler prompt or increase timeout") | ||
|
|
||
| except ServerError as e: | ||
| logger.error(f"Server error {e.status_code}: {e.message}") | ||
|
|
||
| except Exception as e: | ||
| logger.exception(f"Unexpected error: {e}") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| """Verify an inference receipt locally.""" | ||
|
|
||
| from ainfera import AinferaClient | ||
| from ainfera.verify import verify_receipt | ||
|
|
||
| client = AinferaClient(api_key="ak_...") | ||
| agent = client.agents.retrieve("ag_...") | ||
|
|
||
| response = agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "Hello"}], | ||
| ) | ||
|
|
||
| # Verify the receipt locally — no API call needed | ||
| result = verify_receipt(response.receipt) | ||
|
|
||
| if result.valid: | ||
| print("Receipt is valid") | ||
| print(f" Sequence: {result.sequence}") | ||
| print(f" Previous hash: {result.previous_hash}") | ||
| print(f" Signature: {result.signature[:16]}...") | ||
| else: | ||
| print(f"Receipt INVALID: {result.error}") | ||
|
|
||
| # Local verification proves log integrity relative to the published signing key. | ||
| # It does not prevent tampering — it makes tamper-evidence verifiable. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| """Retry strategies for Ainfera inference.""" | ||
|
|
||
| from ainfera import AinferaClient | ||
|
|
||
| client = AinferaClient( | ||
| api_key="ak_...", | ||
| max_retries=3, | ||
| retry_delay=1.0, | ||
| retry_backoff=2.0, | ||
| retry_on_status=[429, 500, 502, 503], | ||
| ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Retries example invalid client kwargsMedium Severity
Reviewed by Cursor Bugbot for commit 1090b1a. Configure here. |
||
|
|
||
| agent = client.agents.retrieve("ag_...") | ||
|
|
||
| response = agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "Hello"}], | ||
| ) | ||
|
|
||
| print(response.text) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| """Streaming inference through Ainfera.""" | ||
|
|
||
| from ainfera import AinferaClient | ||
|
|
||
| client = AinferaClient(api_key="ak_...") | ||
| agent = client.agents.retrieve("ag_...") | ||
|
|
||
| stream = agent.inference_stream( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "Explain quantum computing in 3 sentences."}], | ||
| ) | ||
|
|
||
| for chunk in stream: | ||
| print(chunk.text, end="", flush=True) | ||
| print() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| """Tool use through Ainfera inference.""" | ||
|
|
||
| from ainfera import AinferaClient | ||
|
|
||
| client = AinferaClient(api_key="ak_...") | ||
| agent = client.agents.retrieve("ag_...") | ||
|
|
||
| tools = [ | ||
| { | ||
| "type": "function", | ||
| "function": { | ||
| "name": "get_weather", | ||
| "description": "Get current weather for a location", | ||
| "parameters": { | ||
| "type": "object", | ||
| "properties": { | ||
| "location": {"type": "string", "description": "City name"}, | ||
| }, | ||
| "required": ["location"], | ||
| }, | ||
| }, | ||
| } | ||
| ] | ||
|
|
||
| response = agent.inference( | ||
| model="ainfera-inference", | ||
| messages=[{"role": "user", "content": "What is the weather in Jakarta?"}], | ||
| tools=tools, | ||
| ) | ||
|
|
||
| print(response.text) | ||
| if response.tool_calls: | ||
| for call in response.tool_calls: | ||
| print(f"Tool: {call.function.name}({call.function.arguments})") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,21 +1,21 @@ | ||
| # sdk | ||
| # ainfera — Python SDK for Ainfera | ||
|
|
||
| Agent-native inference routing by Ainfera. Python SDK — signed AgentCards, routed inference, audit c | ||
| # Agent-native inference routing by Ainfera. Python SDK — signed AgentCards, routed inference, audit chains. | ||
|
|
||
| [build-system] | ||
| requires = ["setuptools>=68.0", "wheel"] | ||
| build-backend = "setuptools.build_meta" | ||
|
|
||
| [project] | ||
| name = "sdk" | ||
| version = "0.1.0" | ||
| description = "Agent-native inference routing by Ainfera. Python SDK — signed AgentCards, routed inference, audit c" | ||
| 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 :: 2 - Pre-Alpha", | ||
| "Development Status :: 4 - Beta", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
|
|
@@ -24,18 +24,26 @@ classifiers = [ | |
|
|
||
| [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", | ||
| ] | ||
|
Comment on lines
25
to
42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift Runtime dependencies belong in
Additionally, the 📦 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 |
||
|
|
||
| [tool.setuptools.packages.find] | ||
| where = ["src"] | ||
| include = ["sdk*"] | ||
| where = ["python"] | ||
| include = ["ainfera*"] | ||
|
|
||
| [tool.ruff] | ||
| target-version = "py310" | ||
|
|
@@ -45,5 +53,5 @@ line-length = 100 | |
| select = ["E", "F", "W", "I", "N", "B", "A", "C4", "SIM", "UP"] | ||
|
|
||
| [tool.pytest.ini_options] | ||
| testpaths = ["tests"] | ||
| testpaths = ["python/tests"] | ||
| addopts = "-v --tb=short" | ||


There was a problem hiding this comment.
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:
Repository: ainfera-ai/sdk-python
Length of output: 2207
🏁 Script executed:
Repository: ainfera-ai/sdk-python
Length of output: 2120
Use
AINFERA_API_KEYin this exampleapi_key="ak_..."teaches the wrong credential pattern in sample code. Useos.environ["AINFERA_API_KEY"](or omitapi_keyif the client already reads from env) so the example matches the SDK guidance.🤖 Prompt for AI Agents
Source: Coding guidelines