singularity-grid 0.1.0__tar.gz → 0.2.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.
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/PKG-INFO +1 -1
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/pyproject.toml +1 -1
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/singularity_grid/__init__.py +19 -2
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/singularity_grid/client.py +151 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/singularity_grid/models.py +90 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/.github/workflows/publish.yml +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/.gitignore +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/LICENSE +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/README.md +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/examples/check_capacity.py +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/examples/openai_compatible.py +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/examples/quickstart.py +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/singularity_grid/openai_compat.py +0 -0
- {singularity_grid-0.1.0 → singularity_grid-0.2.0}/singularity_grid/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: singularity-grid
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Python SDK for the SGL Network confidential compute grid
|
|
5
5
|
Project-URL: Homepage, https://singularitylayer.xyz
|
|
6
6
|
Project-URL: Repository, https://github.com/SingularityLayer/sgl-network-sdk
|
|
@@ -19,11 +19,19 @@ from .models import (
|
|
|
19
19
|
ModelsResponse,
|
|
20
20
|
PricingInfo,
|
|
21
21
|
PricingResponse,
|
|
22
|
+
ProcessorDeployResult,
|
|
23
|
+
ProcessorInfo,
|
|
24
|
+
ProcessorListResponse,
|
|
25
|
+
ProcessorLogEntry,
|
|
26
|
+
ProcessorLogsResponse,
|
|
27
|
+
ProcessorPayment,
|
|
28
|
+
ProcessorResult,
|
|
29
|
+
ProcessorTeeInfo,
|
|
22
30
|
TeeCapacity,
|
|
23
31
|
)
|
|
24
32
|
from .openai_compat import create_openai_client
|
|
25
33
|
|
|
26
|
-
__version__ = "0.
|
|
34
|
+
__version__ = "0.2.0"
|
|
27
35
|
|
|
28
36
|
__all__ = [
|
|
29
37
|
# Client
|
|
@@ -36,7 +44,7 @@ __all__ = [
|
|
|
36
44
|
"SGLAuthError",
|
|
37
45
|
"SGLConnectionError",
|
|
38
46
|
"SGLNotFoundError",
|
|
39
|
-
# Models
|
|
47
|
+
# Models — Grid
|
|
40
48
|
"AttestationProof",
|
|
41
49
|
"CapacityResponse",
|
|
42
50
|
"JobResponse",
|
|
@@ -47,4 +55,13 @@ __all__ = [
|
|
|
47
55
|
"PricingInfo",
|
|
48
56
|
"PricingResponse",
|
|
49
57
|
"TeeCapacity",
|
|
58
|
+
# Models — Processors
|
|
59
|
+
"ProcessorDeployResult",
|
|
60
|
+
"ProcessorInfo",
|
|
61
|
+
"ProcessorListResponse",
|
|
62
|
+
"ProcessorLogEntry",
|
|
63
|
+
"ProcessorLogsResponse",
|
|
64
|
+
"ProcessorPayment",
|
|
65
|
+
"ProcessorResult",
|
|
66
|
+
"ProcessorTeeInfo",
|
|
50
67
|
]
|
|
@@ -15,6 +15,12 @@ from .models import (
|
|
|
15
15
|
ModelsResponse,
|
|
16
16
|
PricingInfo,
|
|
17
17
|
PricingResponse,
|
|
18
|
+
ProcessorDeployResult,
|
|
19
|
+
ProcessorInfo,
|
|
20
|
+
ProcessorListResponse,
|
|
21
|
+
ProcessorLogEntry,
|
|
22
|
+
ProcessorLogsResponse,
|
|
23
|
+
ProcessorResult,
|
|
18
24
|
)
|
|
19
25
|
|
|
20
26
|
DEFAULT_BASE_URL = (
|
|
@@ -200,6 +206,151 @@ class GridClient:
|
|
|
200
206
|
data = self._request("GET", f"/grid/jobs/{job_id}/attestation")
|
|
201
207
|
return AttestationProof.model_validate(data)
|
|
202
208
|
|
|
209
|
+
# -- processor endpoints -----------------------------------------------
|
|
210
|
+
|
|
211
|
+
def deploy_processor(
|
|
212
|
+
self,
|
|
213
|
+
name: str,
|
|
214
|
+
code: str,
|
|
215
|
+
*,
|
|
216
|
+
wallet_address: str,
|
|
217
|
+
chain: str = "solana",
|
|
218
|
+
runtime: str = "deno",
|
|
219
|
+
memory_mb: int = 128,
|
|
220
|
+
timeout_seconds: int = 30,
|
|
221
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
222
|
+
) -> ProcessorDeployResult:
|
|
223
|
+
"""Deploy a serverless processor to the TEE grid.
|
|
224
|
+
|
|
225
|
+
Requires $SGL staking for higher tier limits.
|
|
226
|
+
|
|
227
|
+
Parameters
|
|
228
|
+
----------
|
|
229
|
+
name:
|
|
230
|
+
Processor name (lowercase alphanumeric + hyphens, 2-64 chars).
|
|
231
|
+
code:
|
|
232
|
+
JavaScript/TypeScript source code with a default export function.
|
|
233
|
+
wallet_address:
|
|
234
|
+
Owner wallet address (must have $SGL staked for higher tiers).
|
|
235
|
+
chain:
|
|
236
|
+
Chain the wallet is on (default ``"solana"``).
|
|
237
|
+
runtime:
|
|
238
|
+
Execution runtime (``"deno"`` or ``"wasm"``).
|
|
239
|
+
memory_mb:
|
|
240
|
+
Memory allocation in MB (64, 128, 256, 512, 1024).
|
|
241
|
+
timeout_seconds:
|
|
242
|
+
Max execution time (1-300s, tier-dependent).
|
|
243
|
+
metadata:
|
|
244
|
+
Optional metadata dict attached to the processor.
|
|
245
|
+
"""
|
|
246
|
+
body: Dict[str, Any] = {
|
|
247
|
+
"name": name,
|
|
248
|
+
"code": code,
|
|
249
|
+
"runtime": runtime,
|
|
250
|
+
"memory_mb": memory_mb,
|
|
251
|
+
"timeout_seconds": timeout_seconds,
|
|
252
|
+
}
|
|
253
|
+
if metadata:
|
|
254
|
+
body["metadata"] = metadata
|
|
255
|
+
|
|
256
|
+
# Set wallet auth headers
|
|
257
|
+
self._client.headers["X-Auth-Address"] = wallet_address
|
|
258
|
+
self._client.headers["X-Auth-Chain"] = chain
|
|
259
|
+
try:
|
|
260
|
+
data = self._request("POST", "/grid/processors", json=body)
|
|
261
|
+
finally:
|
|
262
|
+
self._client.headers.pop("X-Auth-Address", None)
|
|
263
|
+
self._client.headers.pop("X-Auth-Chain", None)
|
|
264
|
+
|
|
265
|
+
return ProcessorDeployResult.model_validate(data)
|
|
266
|
+
|
|
267
|
+
def invoke_processor(
|
|
268
|
+
self,
|
|
269
|
+
name: str,
|
|
270
|
+
input_data: Dict[str, Any],
|
|
271
|
+
*,
|
|
272
|
+
payment_header: str,
|
|
273
|
+
payment_token: str = "USDC",
|
|
274
|
+
) -> ProcessorResult:
|
|
275
|
+
"""Invoke a deployed processor with x402 payment.
|
|
276
|
+
|
|
277
|
+
Parameters
|
|
278
|
+
----------
|
|
279
|
+
name:
|
|
280
|
+
Processor name.
|
|
281
|
+
input_data:
|
|
282
|
+
Input object passed to the handler function.
|
|
283
|
+
payment_header:
|
|
284
|
+
x402 payment header (JSON-encoded).
|
|
285
|
+
payment_token:
|
|
286
|
+
Payment token type (``"USDC"`` or ``"SGL"``).
|
|
287
|
+
"""
|
|
288
|
+
body: Dict[str, Any] = {
|
|
289
|
+
"input": input_data,
|
|
290
|
+
"payment_token": payment_token,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
self._client.headers["X-Payment"] = payment_header
|
|
294
|
+
try:
|
|
295
|
+
data = self._request(
|
|
296
|
+
"POST", f"/grid/processors/{name}/invoke", json=body,
|
|
297
|
+
)
|
|
298
|
+
finally:
|
|
299
|
+
self._client.headers.pop("X-Payment", None)
|
|
300
|
+
|
|
301
|
+
return ProcessorResult.model_validate(data)
|
|
302
|
+
|
|
303
|
+
def list_processors(
|
|
304
|
+
self,
|
|
305
|
+
*,
|
|
306
|
+
owner: Optional[str] = None,
|
|
307
|
+
page: int = 0,
|
|
308
|
+
limit: int = 50,
|
|
309
|
+
) -> ProcessorListResponse:
|
|
310
|
+
"""List deployed processors."""
|
|
311
|
+
params: Dict[str, Any] = {"page": page, "limit": limit}
|
|
312
|
+
if owner:
|
|
313
|
+
params["owner"] = owner
|
|
314
|
+
data = self._request("GET", "/grid/processors", params=params)
|
|
315
|
+
return ProcessorListResponse.model_validate(data)
|
|
316
|
+
|
|
317
|
+
def get_processor(self, processor_id: str) -> ProcessorInfo:
|
|
318
|
+
"""Get details for a specific processor."""
|
|
319
|
+
data = self._request("GET", f"/grid/processors/{processor_id}")
|
|
320
|
+
return ProcessorInfo.model_validate(data)
|
|
321
|
+
|
|
322
|
+
def delete_processor(
|
|
323
|
+
self,
|
|
324
|
+
processor_id: str,
|
|
325
|
+
*,
|
|
326
|
+
wallet_address: str,
|
|
327
|
+
) -> Dict[str, Any]:
|
|
328
|
+
"""Delete a processor (must be the owner)."""
|
|
329
|
+
self._client.headers["X-Auth-Address"] = wallet_address
|
|
330
|
+
try:
|
|
331
|
+
data = self._request(
|
|
332
|
+
"DELETE", f"/grid/processors/{processor_id}",
|
|
333
|
+
)
|
|
334
|
+
finally:
|
|
335
|
+
self._client.headers.pop("X-Auth-Address", None)
|
|
336
|
+
return data
|
|
337
|
+
|
|
338
|
+
def get_processor_logs(
|
|
339
|
+
self,
|
|
340
|
+
processor_id: str,
|
|
341
|
+
*,
|
|
342
|
+
page: int = 0,
|
|
343
|
+
limit: int = 50,
|
|
344
|
+
) -> ProcessorLogsResponse:
|
|
345
|
+
"""Get invocation logs for a processor."""
|
|
346
|
+
params: Dict[str, Any] = {"page": page, "limit": limit}
|
|
347
|
+
data = self._request(
|
|
348
|
+
"GET",
|
|
349
|
+
f"/grid/processors/{processor_id}/logs",
|
|
350
|
+
params=params,
|
|
351
|
+
)
|
|
352
|
+
return ProcessorLogsResponse.model_validate(data)
|
|
353
|
+
|
|
203
354
|
# -- lifecycle ----------------------------------------------------------
|
|
204
355
|
|
|
205
356
|
def close(self) -> None:
|
|
@@ -108,3 +108,93 @@ class JobResult(BaseModel):
|
|
|
108
108
|
created_at: Optional[str] = None
|
|
109
109
|
completed_at: Optional[str] = None
|
|
110
110
|
error: Optional[str] = None
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# ---------------------------------------------------------------------------
|
|
114
|
+
# Processors
|
|
115
|
+
# ---------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
class ProcessorInfo(BaseModel):
|
|
118
|
+
"""Processor descriptor returned by list/get endpoints."""
|
|
119
|
+
id: str
|
|
120
|
+
name: str
|
|
121
|
+
owner_wallet: str = ""
|
|
122
|
+
owner_chain: str = "solana"
|
|
123
|
+
runtime: str = "deno"
|
|
124
|
+
memory_mb: int = 128
|
|
125
|
+
timeout_seconds: int = 30
|
|
126
|
+
invocation_count: int = 0
|
|
127
|
+
last_invoked_at: Optional[str] = None
|
|
128
|
+
status: str = "active"
|
|
129
|
+
deployment_stake_sgl: float = 0.0
|
|
130
|
+
invoke_url: Optional[str] = None
|
|
131
|
+
created_at: Optional[str] = None
|
|
132
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class ProcessorDeployResult(BaseModel):
|
|
136
|
+
"""Response from deploying a processor."""
|
|
137
|
+
id: str
|
|
138
|
+
name: str
|
|
139
|
+
runtime: str = "deno"
|
|
140
|
+
memory_mb: int = 128
|
|
141
|
+
timeout_seconds: int = 30
|
|
142
|
+
status: str = "active"
|
|
143
|
+
code_hash: str = ""
|
|
144
|
+
invoke_url: str = ""
|
|
145
|
+
tier: str = "free"
|
|
146
|
+
sgl_staked: float = 0.0
|
|
147
|
+
created_at: Optional[str] = None
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class ProcessorPayment(BaseModel):
|
|
151
|
+
"""Payment details from a processor invocation."""
|
|
152
|
+
amount_usd: str = "0"
|
|
153
|
+
token: str = "USDC"
|
|
154
|
+
discount_pct: float = 0.0
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ProcessorTeeInfo(BaseModel):
|
|
158
|
+
"""TEE details from a processor invocation."""
|
|
159
|
+
node_id: str = ""
|
|
160
|
+
tee_type: str = ""
|
|
161
|
+
attestation_verified: bool = False
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class ProcessorResult(BaseModel):
|
|
165
|
+
"""Response from invoking a processor."""
|
|
166
|
+
job_id: str
|
|
167
|
+
processor: str = ""
|
|
168
|
+
status: str = "pending"
|
|
169
|
+
output: Optional[Any] = None
|
|
170
|
+
duration_ms: Optional[int] = None
|
|
171
|
+
payment: Optional[ProcessorPayment] = None
|
|
172
|
+
tee: Optional[ProcessorTeeInfo] = None
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class ProcessorListResponse(BaseModel):
|
|
176
|
+
"""Paginated processor listing."""
|
|
177
|
+
processors: List[ProcessorInfo] = Field(default_factory=list)
|
|
178
|
+
total: int = 0
|
|
179
|
+
page: int = 0
|
|
180
|
+
limit: int = 50
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
class ProcessorLogEntry(BaseModel):
|
|
184
|
+
"""Single invocation log entry."""
|
|
185
|
+
id: str = ""
|
|
186
|
+
processor_id: str = ""
|
|
187
|
+
job_id: str = ""
|
|
188
|
+
node_id: Optional[str] = None
|
|
189
|
+
duration_ms: Optional[int] = None
|
|
190
|
+
status: str = ""
|
|
191
|
+
error_message: Optional[str] = None
|
|
192
|
+
created_at: Optional[str] = None
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class ProcessorLogsResponse(BaseModel):
|
|
196
|
+
"""Paginated processor logs."""
|
|
197
|
+
logs: List[ProcessorLogEntry] = Field(default_factory=list)
|
|
198
|
+
total: int = 0
|
|
199
|
+
page: int = 0
|
|
200
|
+
limit: int = 50
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|