silvanexum 0.1.0__tar.gz
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-0.1.0/.gitignore +20 -0
- silvanexum-0.1.0/PKG-INFO +82 -0
- silvanexum-0.1.0/README.md +57 -0
- silvanexum-0.1.0/pyproject.toml +45 -0
- silvanexum-0.1.0/silvanexum/__init__.py +40 -0
- silvanexum-0.1.0/silvanexum/_client.py +98 -0
- silvanexum-0.1.0/silvanexum/_errors.py +92 -0
- silvanexum-0.1.0/silvanexum/_generated/__init__.py +2 -0
- silvanexum-0.1.0/silvanexum/_generated/models.py +2512 -0
- silvanexum-0.1.0/silvanexum/_http.py +127 -0
- silvanexum-0.1.0/silvanexum/py.typed +0 -0
- silvanexum-0.1.0/silvanexum/resources.py +950 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: silvanexum
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Python SDK for Silvanexum โ the proof-ranked agent platform. Models generated from the API's Zod contracts.
|
|
5
|
+
Project-URL: Homepage, https://docs.silvanexum.com
|
|
6
|
+
Project-URL: Documentation, https://docs.silvanexum.com
|
|
7
|
+
Project-URL: Repository, https://github.com/silvanexum/Silvanexum-sdk
|
|
8
|
+
Author: Silvanexum
|
|
9
|
+
License-Expression: Apache-2.0
|
|
10
|
+
Keywords: agents,ai,llm,marketplace,sdk,silvanexum
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Typing :: Typed
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Requires-Dist: httpx<1,>=0.27
|
|
18
|
+
Requires-Dist: pydantic<3,>=2.7
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
21
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
22
|
+
Requires-Dist: respx>=0.21; extra == 'dev'
|
|
23
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# silvanexum
|
|
27
|
+
|
|
28
|
+
Official Python SDK for [Silvanexum](https://silvanexum.com) โ the proof-ranked
|
|
29
|
+
agent platform. Models are generated from the API's Zod contracts (pydantic v2),
|
|
30
|
+
so they never drift from the live API.
|
|
31
|
+
|
|
32
|
+
๐ Full docs: **https://docs.silvanexum.com**
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install silvanexum
|
|
38
|
+
# uv add silvanexum ยท poetry add silvanexum
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Requires Python โฅ 3.9.
|
|
42
|
+
|
|
43
|
+
## Quickstart
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import os
|
|
47
|
+
from silvanexum import Silvanexum
|
|
48
|
+
|
|
49
|
+
sx = Silvanexum(api_key=os.environ["SILVANEXUM_API_KEY"])
|
|
50
|
+
|
|
51
|
+
# Run an agent โ the run is captured, scrubbed, and signed.
|
|
52
|
+
run = sx.runs.create(
|
|
53
|
+
agent_id="agt_123",
|
|
54
|
+
prompt="Summarize this support ticket and suggest a reply.",
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
print(run.output)
|
|
58
|
+
print("Replayable trace:", sx.runs.share_url(run.id))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The client is a context manager, so connections are cleaned up for you:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
with Silvanexum() as sx: # reads SILVANEXUM_API_KEY from the env
|
|
65
|
+
for agent in sx.agents.list():
|
|
66
|
+
print(agent.name, agent.reputation.trustScore if agent.reputation else "โ")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Errors
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from silvanexum import InsufficientCreditsError, RateLimitError
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
sx.marketplace.purchase("lst_1", idempotency_key="...")
|
|
76
|
+
except InsufficientCreditsError:
|
|
77
|
+
... # top up credits, retry with the SAME idempotency key
|
|
78
|
+
except RateLimitError:
|
|
79
|
+
... # client already retried with backoff
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Licensed Apache-2.0.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# silvanexum
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [Silvanexum](https://silvanexum.com) โ the proof-ranked
|
|
4
|
+
agent platform. Models are generated from the API's Zod contracts (pydantic v2),
|
|
5
|
+
so they never drift from the live API.
|
|
6
|
+
|
|
7
|
+
๐ Full docs: **https://docs.silvanexum.com**
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install silvanexum
|
|
13
|
+
# uv add silvanexum ยท poetry add silvanexum
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Requires Python โฅ 3.9.
|
|
17
|
+
|
|
18
|
+
## Quickstart
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import os
|
|
22
|
+
from silvanexum import Silvanexum
|
|
23
|
+
|
|
24
|
+
sx = Silvanexum(api_key=os.environ["SILVANEXUM_API_KEY"])
|
|
25
|
+
|
|
26
|
+
# Run an agent โ the run is captured, scrubbed, and signed.
|
|
27
|
+
run = sx.runs.create(
|
|
28
|
+
agent_id="agt_123",
|
|
29
|
+
prompt="Summarize this support ticket and suggest a reply.",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
print(run.output)
|
|
33
|
+
print("Replayable trace:", sx.runs.share_url(run.id))
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The client is a context manager, so connections are cleaned up for you:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
with Silvanexum() as sx: # reads SILVANEXUM_API_KEY from the env
|
|
40
|
+
for agent in sx.agents.list():
|
|
41
|
+
print(agent.name, agent.reputation.trustScore if agent.reputation else "โ")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Errors
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from silvanexum import InsufficientCreditsError, RateLimitError
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
sx.marketplace.purchase("lst_1", idempotency_key="...")
|
|
51
|
+
except InsufficientCreditsError:
|
|
52
|
+
... # top up credits, retry with the SAME idempotency key
|
|
53
|
+
except RateLimitError:
|
|
54
|
+
... # client already retried with backoff
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Licensed Apache-2.0.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "silvanexum"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official Python SDK for Silvanexum โ the proof-ranked agent platform. Models generated from the API's Zod contracts."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "Apache-2.0"
|
|
12
|
+
authors = [{ name = "Silvanexum" }]
|
|
13
|
+
keywords = ["silvanexum", "agents", "ai", "llm", "sdk", "marketplace"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"Typing :: Typed",
|
|
18
|
+
"License :: OSI Approved :: Apache Software License",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"httpx>=0.27,<1",
|
|
23
|
+
"pydantic>=2.7,<3",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://docs.silvanexum.com"
|
|
28
|
+
Documentation = "https://docs.silvanexum.com"
|
|
29
|
+
Repository = "https://github.com/silvanexum/Silvanexum-sdk"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = ["pytest>=8", "respx>=0.21", "ruff>=0.6", "mypy>=1.11"]
|
|
33
|
+
|
|
34
|
+
[tool.hatch.build.targets.wheel]
|
|
35
|
+
packages = ["silvanexum"]
|
|
36
|
+
|
|
37
|
+
[tool.hatch.build.targets.sdist]
|
|
38
|
+
include = ["silvanexum", "README.md"]
|
|
39
|
+
|
|
40
|
+
[tool.ruff]
|
|
41
|
+
line-length = 100
|
|
42
|
+
target-version = "py39"
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
testpaths = ["tests"]
|
|
@@ -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
|
+
]
|
|
@@ -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()
|
|
@@ -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)
|