silvanexum 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- silvanexum/__init__.py +40 -0
- silvanexum/_client.py +98 -0
- silvanexum/_errors.py +92 -0
- silvanexum/_generated/__init__.py +2 -0
- silvanexum/_generated/models.py +2512 -0
- silvanexum/_http.py +127 -0
- silvanexum/py.typed +0 -0
- silvanexum/resources.py +950 -0
- silvanexum-0.1.0.dist-info/METADATA +82 -0
- silvanexum-0.1.0.dist-info/RECORD +11 -0
- silvanexum-0.1.0.dist-info/WHEEL +4 -0
silvanexum/__init__.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Official Python SDK for Silvanexum — the proof-ranked agent platform.
|
|
2
|
+
|
|
3
|
+
All request/response models are GENERATED from the API's Zod contracts (see
|
|
4
|
+
packages/codegen) and exposed under ``silvanexum.models``, so they can never
|
|
5
|
+
drift from the live API.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from . import _generated as models
|
|
10
|
+
from ._client import Silvanexum
|
|
11
|
+
from ._errors import (
|
|
12
|
+
APIConnectionError,
|
|
13
|
+
APITimeoutError,
|
|
14
|
+
AuthenticationError,
|
|
15
|
+
InsufficientCreditsError,
|
|
16
|
+
InternalServerError,
|
|
17
|
+
NotFoundError,
|
|
18
|
+
PermissionError,
|
|
19
|
+
RateLimitError,
|
|
20
|
+
SilvanexumError,
|
|
21
|
+
ValidationError,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__version__ = "0.1.0"
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"Silvanexum",
|
|
28
|
+
"models",
|
|
29
|
+
"SilvanexumError",
|
|
30
|
+
"APIConnectionError",
|
|
31
|
+
"APITimeoutError",
|
|
32
|
+
"AuthenticationError",
|
|
33
|
+
"PermissionError",
|
|
34
|
+
"NotFoundError",
|
|
35
|
+
"ValidationError",
|
|
36
|
+
"RateLimitError",
|
|
37
|
+
"InsufficientCreditsError",
|
|
38
|
+
"InternalServerError",
|
|
39
|
+
"__version__",
|
|
40
|
+
]
|
silvanexum/_client.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""The Silvanexum client."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from ._http import HttpClient
|
|
9
|
+
from .resources import (
|
|
10
|
+
Agents,
|
|
11
|
+
Bounties,
|
|
12
|
+
Budgets,
|
|
13
|
+
Certification,
|
|
14
|
+
Connectors,
|
|
15
|
+
Enterprise,
|
|
16
|
+
Fleet,
|
|
17
|
+
Insurance,
|
|
18
|
+
Keys,
|
|
19
|
+
Marketplace,
|
|
20
|
+
Models,
|
|
21
|
+
Overview,
|
|
22
|
+
Proving,
|
|
23
|
+
Routing,
|
|
24
|
+
Runs,
|
|
25
|
+
Security,
|
|
26
|
+
Spending,
|
|
27
|
+
Studio,
|
|
28
|
+
Suites,
|
|
29
|
+
Team,
|
|
30
|
+
Templates,
|
|
31
|
+
Wallet,
|
|
32
|
+
Workforce,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Silvanexum:
|
|
37
|
+
"""Entry point for the Silvanexum API.
|
|
38
|
+
|
|
39
|
+
Example
|
|
40
|
+
-------
|
|
41
|
+
>>> from silvanexum import Silvanexum
|
|
42
|
+
>>> sx = Silvanexum(api_key="sx_live_...")
|
|
43
|
+
>>> run = sx.runs.create(agent_id=agent_id, prompt="Summarize this ticket.")
|
|
44
|
+
>>> print(run.output, sx.runs.share_url(run.id))
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
api_key: Optional[str] = None,
|
|
50
|
+
*,
|
|
51
|
+
base_url: Optional[str] = None,
|
|
52
|
+
timeout: float = 60.0,
|
|
53
|
+
max_retries: int = 2,
|
|
54
|
+
http_client: Optional[httpx.Client] = None,
|
|
55
|
+
) -> None:
|
|
56
|
+
self._http = HttpClient(
|
|
57
|
+
api_key=api_key,
|
|
58
|
+
base_url=base_url,
|
|
59
|
+
timeout=timeout,
|
|
60
|
+
max_retries=max_retries,
|
|
61
|
+
http_client=http_client,
|
|
62
|
+
)
|
|
63
|
+
self.agents = Agents(self._http)
|
|
64
|
+
self.runs = Runs(self._http)
|
|
65
|
+
self.templates = Templates(self._http)
|
|
66
|
+
self.connectors = Connectors(self._http)
|
|
67
|
+
self.marketplace = Marketplace(self._http)
|
|
68
|
+
self.wallet = Wallet(self._http)
|
|
69
|
+
self.suites = Suites(self._http)
|
|
70
|
+
self.keys = Keys(self._http)
|
|
71
|
+
self.models = Models(self._http)
|
|
72
|
+
self.team = Team(self._http)
|
|
73
|
+
self.overview = Overview(self._http)
|
|
74
|
+
self.security = Security(self._http)
|
|
75
|
+
self.proving = Proving(self._http)
|
|
76
|
+
self.fleet = Fleet(self._http)
|
|
77
|
+
self.routing = Routing(self._http)
|
|
78
|
+
self.studio = Studio(self._http)
|
|
79
|
+
self.workforce = Workforce(self._http)
|
|
80
|
+
self.certification = Certification(self._http)
|
|
81
|
+
self.enterprise = Enterprise(self._http)
|
|
82
|
+
self.insurance = Insurance(self._http)
|
|
83
|
+
self.bounties = Bounties(self._http)
|
|
84
|
+
self.budgets = Budgets(self._http)
|
|
85
|
+
self.spending = Spending(self._http)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def base_url(self) -> str:
|
|
89
|
+
return self._http.base_url
|
|
90
|
+
|
|
91
|
+
def close(self) -> None:
|
|
92
|
+
self._http.close()
|
|
93
|
+
|
|
94
|
+
def __enter__(self) -> "Silvanexum":
|
|
95
|
+
return self
|
|
96
|
+
|
|
97
|
+
def __exit__(self, *_exc: object) -> None:
|
|
98
|
+
self.close()
|
silvanexum/_errors.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Typed error hierarchy. Catch ``SilvanexumError`` for any API failure."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SilvanexumError(Exception):
|
|
8
|
+
"""Base error for all SDK failures."""
|
|
9
|
+
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
message: str,
|
|
13
|
+
*,
|
|
14
|
+
status: Optional[int] = None,
|
|
15
|
+
code: Optional[str] = None,
|
|
16
|
+
body: Optional[dict[str, Any]] = None,
|
|
17
|
+
request_id: Optional[str] = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
super().__init__(message)
|
|
20
|
+
self.message = message
|
|
21
|
+
self.status = status
|
|
22
|
+
self.code = code
|
|
23
|
+
self.body = body
|
|
24
|
+
self.request_id = request_id
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class APIConnectionError(SilvanexumError):
|
|
28
|
+
"""The request never reached the API (network/DNS/abort)."""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class APITimeoutError(APIConnectionError):
|
|
32
|
+
"""The request exceeded the configured timeout."""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class AuthenticationError(SilvanexumError):
|
|
36
|
+
"""401 — missing or invalid API key."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class PermissionError(SilvanexumError): # noqa: A001 - intentional API name
|
|
40
|
+
"""403 — the key lacks the required scope."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class NotFoundError(SilvanexumError):
|
|
44
|
+
"""404."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ValidationError(SilvanexumError):
|
|
48
|
+
"""400 / 422 — the request body or params failed validation."""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class RateLimitError(SilvanexumError):
|
|
52
|
+
"""429 — too many requests."""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class InsufficientCreditsError(SilvanexumError):
|
|
56
|
+
"""402 — not enough credits to settle the operation."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class InternalServerError(SilvanexumError):
|
|
60
|
+
"""5xx."""
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def error_from_response(
|
|
64
|
+
status: int, body: Optional[dict[str, Any]], request_id: Optional[str]
|
|
65
|
+
) -> SilvanexumError:
|
|
66
|
+
"""Map an HTTP status + body to the most specific error class."""
|
|
67
|
+
message = ""
|
|
68
|
+
if body:
|
|
69
|
+
message = body.get("message") or body.get("error") or ""
|
|
70
|
+
if not message:
|
|
71
|
+
message = f"Silvanexum API error (HTTP {status})"
|
|
72
|
+
kwargs = {
|
|
73
|
+
"status": status,
|
|
74
|
+
"code": (body or {}).get("code"),
|
|
75
|
+
"body": body,
|
|
76
|
+
"request_id": request_id,
|
|
77
|
+
}
|
|
78
|
+
if status in (400, 422):
|
|
79
|
+
return ValidationError(message, **kwargs)
|
|
80
|
+
if status == 401:
|
|
81
|
+
return AuthenticationError(message, **kwargs)
|
|
82
|
+
if status == 402:
|
|
83
|
+
return InsufficientCreditsError(message, **kwargs)
|
|
84
|
+
if status == 403:
|
|
85
|
+
return PermissionError(message, **kwargs)
|
|
86
|
+
if status == 404:
|
|
87
|
+
return NotFoundError(message, **kwargs)
|
|
88
|
+
if status == 429:
|
|
89
|
+
return RateLimitError(message, **kwargs)
|
|
90
|
+
if status >= 500:
|
|
91
|
+
return InternalServerError(message, **kwargs)
|
|
92
|
+
return SilvanexumError(message, **kwargs)
|