Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ description = "Amigo AI Python SDK"
readme = "README.md"
requires-python = ">= 3.11"
authors=[{name="Amigo AI"}]
license = "MIT"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
Expand All @@ -24,6 +25,13 @@ dependencies = [
"email-validator>=2.0,<3.0",
]

[project.urls]
Homepage = "https://github.com/amigo-ai/amigo-python-sdk"
Documentation = "https://docs.amigo.ai"
Repository = "https://github.com/amigo-ai/amigo-python-sdk"
Issues = "https://github.com/amigo-ai/amigo-python-sdk/issues"
Changelog = "https://github.com/amigo-ai/amigo-python-sdk/blob/main/CHANGELOG.md"

[project.scripts]
gen-models = "scripts.gen_models:main"
check = "scripts.check:main"
Expand All @@ -36,6 +44,7 @@ dev = [
"pytest-httpx>=0.30,<1.0",
"python-dotenv>=1.0,<2.0",
"ruff>=0.1,<1.0",
"mypy>=1.0",
"datamodel-code-generator[http]>=0.21,<1.0",
]
docs = [
Expand All @@ -50,7 +59,6 @@ path = "src/amigo_sdk/__init__.py"
[tool.hatch.build.targets.wheel]
packages = [
"src/amigo_sdk",
"scripts",
]

[tool.hatch.build.targets.sdist]
Expand Down
26 changes: 26 additions & 0 deletions src/amigo_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
__version__ = "0.137.1"
from .config import AmigoConfig
from .errors import (
AmigoError,
AuthenticationError,
BadRequestError,
ConflictError,
ForbiddenError,
NotFoundError,
RateLimitError,
SDKInternalError,
ServerError,
ServiceUnavailableError,
ValidationError,
)
from .rate_limits import RateLimitInfo, parse_rate_limit_headers
from .sdk_client import AmigoClient, AsyncAmigoClient
from .webhooks import (
Expand All @@ -12,9 +26,21 @@
__all__ = [
"__version__",
"AmigoClient",
"AmigoConfig",
"AmigoError",
"AsyncAmigoClient",
"AuthenticationError",
"BadRequestError",
"ConflictError",
"ConversationPostProcessingCompleteEvent",
"ForbiddenError",
"NotFoundError",
"RateLimitError",
"RateLimitInfo",
"SDKInternalError",
"ServerError",
"ServiceUnavailableError",
"ValidationError",
"WebhookEvent",
"WebhookVerificationError",
"parse_rate_limit_headers",
Expand Down
4 changes: 2 additions & 2 deletions src/amigo_sdk/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class AuthenticationError(AmigoError): # 401
pass


class PermissionError(AmigoError): # 403
class ForbiddenError(AmigoError): # 403
pass


Expand Down Expand Up @@ -118,7 +118,7 @@ def get_error_class_for_status_code(status_code: int) -> type[AmigoError]:
error_map = {
400: BadRequestError,
401: AuthenticationError,
403: PermissionError,
403: ForbiddenError,
404: NotFoundError,
409: ConflictError,
422: ValidationError,
Expand Down
4 changes: 2 additions & 2 deletions src/amigo_sdk/http_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,12 @@ def _yield_from_response(resp: httpx.Response) -> Iterator[str]:
for ln in _yield_from_response(resp):
yield ln

def aclose(self) -> None:
def close(self) -> None:
"""Close the underlying httpx client."""
self._client.close()

def __enter__(self):
return self

def __exit__(self, *_):
self.aclose()
self.close()
190 changes: 190 additions & 0 deletions src/amigo_sdk/resources/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
from amigo_sdk.generated.model import (
CreateAgentVersionParametersQuery,
GetAgentsParametersQuery,
GetAgentVersionsParametersQuery,
OrganizationCreateAgentRequest,
OrganizationCreateAgentResponse,
OrganizationCreateAgentVersionRequest,
OrganizationCreateAgentVersionResponse,
OrganizationGetAgentsResponse,
OrganizationGetAgentVersionsResponse,
)
from amigo_sdk.http_client import AmigoAsyncHttpClient, AmigoHttpClient


class AsyncAgentResource:
"""Agent resource for Amigo API operations."""

def __init__(self, http_client: AmigoAsyncHttpClient, organization_id: str) -> None:
self._http = http_client
self._organization_id = organization_id

async def create_agent(
self, body: OrganizationCreateAgentRequest
) -> OrganizationCreateAgentResponse:
"""Create a new agent in the organization."""
response = await self._http.request(
"POST",
f"/v1/{self._organization_id}/organization/agent",
json=body.model_dump(mode="json", exclude_none=True),
)
return OrganizationCreateAgentResponse.model_validate_json(response.text)

async def get_agents(
self, params: GetAgentsParametersQuery | None = None
) -> OrganizationGetAgentsResponse:
"""Get a list of agents in the organization."""
response = await self._http.request(
"GET",
f"/v1/{self._organization_id}/organization/agent",
params=params.model_dump(mode="json", exclude_none=True)
if params
else None,
)
return OrganizationGetAgentsResponse.model_validate_json(response.text)

async def delete_agent(self, agent_id: str) -> None:
"""Delete an agent by ID. Returns None on success (e.g., 204)."""
await self._http.request(
"DELETE",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/",
)

async def create_agent_version(
self,
agent_id: str,
body: OrganizationCreateAgentVersionRequest,
version: int | None = None,
) -> OrganizationCreateAgentVersionResponse:
"""Create a new version for an agent."""
params = None
if version is not None:
query = CreateAgentVersionParametersQuery(version=version)
params = query.model_dump(mode="json", exclude_none=True)
response = await self._http.request(
"POST",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/",
json=body.model_dump(mode="json", exclude_none=True),
params=params,
)
return OrganizationCreateAgentVersionResponse.model_validate_json(response.text)

async def get_agent_versions(
self, agent_id: str, params: GetAgentVersionsParametersQuery | None = None
) -> OrganizationGetAgentVersionsResponse:
"""Get versions for a specific agent."""
response = await self._http.request(
"GET",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/version",
params=params.model_dump(mode="json", exclude_none=True)
if params
else None,
)
return OrganizationGetAgentVersionsResponse.model_validate_json(response.text)

# --- Convenience aliases ---

async def list(
self, params: GetAgentsParametersQuery | None = None
) -> OrganizationGetAgentsResponse:
"""Alias for get_agents."""
return await self.get_agents(params)

async def create(
self, body: OrganizationCreateAgentRequest
) -> OrganizationCreateAgentResponse:
"""Alias for create_agent."""
return await self.create_agent(body)

async def delete(self, agent_id: str) -> None:
"""Alias for delete_agent."""
return await self.delete_agent(agent_id)


class AgentResource:
"""Agent resource (synchronous)."""

def __init__(self, http_client: AmigoHttpClient, organization_id: str) -> None:
self._http = http_client
self._organization_id = organization_id

def create_agent(
self, body: OrganizationCreateAgentRequest
) -> OrganizationCreateAgentResponse:
"""Create a new agent in the organization."""
response = self._http.request(
"POST",
f"/v1/{self._organization_id}/organization/agent",
json=body.model_dump(mode="json", exclude_none=True),
)
return OrganizationCreateAgentResponse.model_validate_json(response.text)

def get_agents(
self, params: GetAgentsParametersQuery | None = None
) -> OrganizationGetAgentsResponse:
"""Get a list of agents in the organization."""
response = self._http.request(
"GET",
f"/v1/{self._organization_id}/organization/agent",
params=params.model_dump(mode="json", exclude_none=True)
if params
else None,
)
return OrganizationGetAgentsResponse.model_validate_json(response.text)

def delete_agent(self, agent_id: str) -> None:
"""Delete an agent by ID."""
self._http.request(
"DELETE",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/",
)

def create_agent_version(
self,
agent_id: str,
body: OrganizationCreateAgentVersionRequest,
version: int | None = None,
) -> OrganizationCreateAgentVersionResponse:
"""Create a new version for an agent."""
params = None
if version is not None:
query = CreateAgentVersionParametersQuery(version=version)
params = query.model_dump(mode="json", exclude_none=True)
response = self._http.request(
"POST",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/",
json=body.model_dump(mode="json", exclude_none=True),
params=params,
)
return OrganizationCreateAgentVersionResponse.model_validate_json(response.text)

def get_agent_versions(
self, agent_id: str, params: GetAgentVersionsParametersQuery | None = None
) -> OrganizationGetAgentVersionsResponse:
"""Get versions for a specific agent."""
response = self._http.request(
"GET",
f"/v1/{self._organization_id}/organization/agent/{agent_id}/version",
params=params.model_dump(mode="json", exclude_none=True)
if params
else None,
)
return OrganizationGetAgentVersionsResponse.model_validate_json(response.text)

# --- Convenience aliases ---

def list(
self, params: GetAgentsParametersQuery | None = None
) -> OrganizationGetAgentsResponse:
"""Alias for get_agents."""
return self.get_agents(params)

def create(
self, body: OrganizationCreateAgentRequest
) -> OrganizationCreateAgentResponse:
"""Alias for create_agent."""
return self.create_agent(body)

def delete(self, agent_id: str) -> None:
"""Alias for delete_agent."""
return self.delete_agent(agent_id)
Loading
Loading