patchr 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.
- apps/__init__.py +2 -0
- apps/api/__init__.py +2 -0
- apps/api/main.py +652 -0
- apps/benchmarks/__init__.py +1 -0
- apps/benchmarks/main.py +20 -0
- apps/sandbox/__init__.py +1 -0
- apps/sandbox/main.py +20 -0
- apps/worker/__init__.py +2 -0
- apps/worker/main.py +15 -0
- apps/worker/verify.py +14 -0
- patchr/__init__.py +12 -0
- patchr/sdk/__init__.py +20 -0
- patchr/sdk/client.py +12 -0
- patchr-0.1.0.dist-info/METADATA +137 -0
- patchr-0.1.0.dist-info/RECORD +116 -0
- patchr-0.1.0.dist-info/WHEEL +5 -0
- patchr-0.1.0.dist-info/entry_points.txt +5 -0
- patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
- patchr-0.1.0.dist-info/top_level.txt +3 -0
- picux/__init__.py +6 -0
- picux/agents/__init__.py +5 -0
- picux/agents/registry.py +204 -0
- picux/api/__init__.py +5 -0
- picux/api/service.py +5075 -0
- picux/audit/__init__.py +31 -0
- picux/audit/activity.py +97 -0
- picux/audit/observability.py +55 -0
- picux/audit/verification/__init__.py +21 -0
- picux/audit/verification/ledger.py +633 -0
- picux/benchmarks/__init__.py +5 -0
- picux/benchmarks/local.py +286 -0
- picux/config.py +140 -0
- picux/contracts/__init__.py +22 -0
- picux/contracts/handshake.py +122 -0
- picux/contracts/integration.py +385 -0
- picux/contracts/openapi.py +187 -0
- picux/contracts/protocol_map.py +152 -0
- picux/contracts/routes.py +980 -0
- picux/contracts/schema_catalog.py +125 -0
- picux/core/__init__.py +17 -0
- picux/core/models.py +148 -0
- picux/core/router.py +131 -0
- picux/core/runtime.py +42 -0
- picux/core/state_machine.py +38 -0
- picux/domains/__init__.py +2 -0
- picux/domains/bridge/HostRun.py +1104 -0
- picux/domains/bridge/__init__.py +6 -0
- picux/domains/bridge/engine.py +345 -0
- picux/domains/hunt/__init__.py +6 -0
- picux/domains/hunt/engine.py +307 -0
- picux/domains/hunt/models.py +88 -0
- picux/domains/pay/__init__.py +16 -0
- picux/domains/pay/adapters.py +607 -0
- picux/domains/pay/engine.py +950 -0
- picux/domains/pay/models.py +95 -0
- picux/domains/proxy/__init__.py +5 -0
- picux/domains/proxy/engine.py +466 -0
- picux/domains/resolve/__init__.py +5 -0
- picux/domains/resolve/engine.py +546 -0
- picux/orchestrator/__init__.py +3 -0
- picux/orchestrator/engine.py +2840 -0
- picux/portals/__init__.py +17 -0
- picux/portals/templates.py +272 -0
- picux/protocols/__init__.py +1 -0
- picux/protocols/a2a/__init__.py +6 -0
- picux/protocols/a2a/client.py +51 -0
- picux/protocols/a2a/envelope.py +132 -0
- picux/protocols/mcp/__init__.py +7 -0
- picux/protocols/mcp/client.py +69 -0
- picux/protocols/mcp/contract.py +67 -0
- picux/protocols/mcp/server.py +76 -0
- picux/sandbox/__init__.py +6 -0
- picux/sandbox/midnight_arbitrage.py +215 -0
- picux/sandbox/models.py +90 -0
- picux/sdk/__init__.py +13 -0
- picux/sdk/client.py +768 -0
- picux/sdk/external.py +245 -0
- picux/security/__init__.py +18 -0
- picux/security/auth.py +86 -0
- picux/security/config_validator.py +58 -0
- picux/security/policy.py +158 -0
- picux/security/secrets.py +144 -0
- picux/signals/__init__.py +1 -0
- picux/signals/community/__init__.py +24 -0
- picux/signals/community/adapters/__init__.py +7 -0
- picux/signals/community/adapters/reddit.py +37 -0
- picux/signals/community/adapters/shopify.py +23 -0
- picux/signals/community/adapters/web.py +23 -0
- picux/signals/community/disambiguation.py +51 -0
- picux/signals/community/intake.py +227 -0
- picux/signals/community/models.py +102 -0
- picux/signals/community/rules.py +91 -0
- picux/signals/community/scoring.py +64 -0
- picux/storage/__init__.py +41 -0
- picux/storage/agents.py +50 -0
- picux/storage/cases.py +440 -0
- picux/storage/channels.py +476 -0
- picux/storage/connectors.py +411 -0
- picux/storage/envelopes.py +137 -0
- picux/storage/escrows.py +168 -0
- picux/storage/events.py +989 -0
- picux/storage/keyspace.py +60 -0
- picux/storage/mandates.py +107 -0
- picux/storage/portals.py +222 -0
- picux/storage/postgres.py +2049 -0
- picux/storage/providers.py +148 -0
- picux/storage/proxy.py +231 -0
- picux/storage/receipts.py +131 -0
- picux/storage/signals.py +147 -0
- picux/storage/tasks.py +179 -0
- picux/tools/__init__.py +11 -0
- picux/tools/shared.py +2048 -0
- picux/verification/__init__.py +5 -0
- picux/verification/rollout.py +183 -0
- picux/workflows/__init__.py +5 -0
- picux/workflows/templates.py +74 -0
picux/sdk/client.py
ADDED
|
@@ -0,0 +1,768 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import hashlib
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from typing import Any, Protocol
|
|
8
|
+
from urllib import error, request
|
|
9
|
+
from urllib.parse import urlencode
|
|
10
|
+
|
|
11
|
+
from picux.config import PicuxSettings
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Transport(Protocol):
|
|
15
|
+
def request(self, method: str, path: str, payload: dict[str, Any] | None = None, headers: dict[str, str] | None = None) -> tuple[int, dict[str, Any]]:
|
|
16
|
+
...
|
|
17
|
+
|
|
18
|
+
def stream(self, method: str, path: str, payload: dict[str, Any] | None = None, headers: dict[str, str] | None = None) -> Iterator[dict[str, Any]]:
|
|
19
|
+
...
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PicuxApiError(RuntimeError):
|
|
23
|
+
def __init__(self, status: int, payload: dict[str, Any]) -> None:
|
|
24
|
+
super().__init__(str(payload.get("error", f"picux_api_{status}")))
|
|
25
|
+
self.status = status
|
|
26
|
+
self.payload = payload
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class HttpTransport:
|
|
31
|
+
baseUrl: str
|
|
32
|
+
|
|
33
|
+
def request(
|
|
34
|
+
self,
|
|
35
|
+
method: str,
|
|
36
|
+
path: str,
|
|
37
|
+
payload: dict[str, Any] | None = None,
|
|
38
|
+
headers: dict[str, str] | None = None,
|
|
39
|
+
) -> tuple[int, dict[str, Any]]:
|
|
40
|
+
url = f"{self.baseUrl.rstrip('/')}/{path.lstrip('/')}"
|
|
41
|
+
body = None
|
|
42
|
+
reqHeaders = {"Accept": "application/json", **(headers or {})}
|
|
43
|
+
if payload is not None:
|
|
44
|
+
body = json.dumps(payload, ensure_ascii=True, sort_keys=True).encode("utf-8")
|
|
45
|
+
reqHeaders["Content-Type"] = "application/json"
|
|
46
|
+
req = request.Request(url, data=body, method=method.upper(), headers=reqHeaders)
|
|
47
|
+
try:
|
|
48
|
+
with request.urlopen(req, timeout=15) as response:
|
|
49
|
+
return int(response.status), self._decode(response.read())
|
|
50
|
+
except error.HTTPError as exc:
|
|
51
|
+
return int(exc.code), self._decode(exc.read())
|
|
52
|
+
|
|
53
|
+
def stream(
|
|
54
|
+
self,
|
|
55
|
+
method: str,
|
|
56
|
+
path: str,
|
|
57
|
+
payload: dict[str, Any] | None = None,
|
|
58
|
+
headers: dict[str, str] | None = None,
|
|
59
|
+
) -> Iterator[dict[str, Any]]:
|
|
60
|
+
url = f"{self.baseUrl.rstrip('/')}/{path.lstrip('/')}"
|
|
61
|
+
body = None
|
|
62
|
+
reqHeaders = {"Accept": "application/x-ndjson", **(headers or {})}
|
|
63
|
+
if payload is not None:
|
|
64
|
+
body = json.dumps(payload, ensure_ascii=True, sort_keys=True).encode("utf-8")
|
|
65
|
+
reqHeaders["Content-Type"] = "application/json"
|
|
66
|
+
req = request.Request(url, data=body, method=method.upper(), headers=reqHeaders)
|
|
67
|
+
try:
|
|
68
|
+
with request.urlopen(req, timeout=60) as response:
|
|
69
|
+
for rawLine in response:
|
|
70
|
+
event = self._decode(rawLine.strip())
|
|
71
|
+
if event:
|
|
72
|
+
yield event
|
|
73
|
+
except error.HTTPError as exc:
|
|
74
|
+
raise PicuxApiError(int(exc.code), self._decode(exc.read())) from exc
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def _decode(raw: bytes) -> dict[str, Any]:
|
|
78
|
+
try:
|
|
79
|
+
payload = json.loads(raw.decode("utf-8") or "{}")
|
|
80
|
+
except Exception:
|
|
81
|
+
return {}
|
|
82
|
+
return payload if isinstance(payload, dict) else {"data": payload}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class InProcessTransport:
|
|
86
|
+
"""Test/local migration transport that avoids network I/O."""
|
|
87
|
+
|
|
88
|
+
def __init__(self, service: Any | None = None) -> None:
|
|
89
|
+
if service is None:
|
|
90
|
+
from picux.api import PicuxApiService
|
|
91
|
+
|
|
92
|
+
service = PicuxApiService()
|
|
93
|
+
self.service = service
|
|
94
|
+
|
|
95
|
+
def request(
|
|
96
|
+
self,
|
|
97
|
+
method: str,
|
|
98
|
+
path: str,
|
|
99
|
+
payload: dict[str, Any] | None = None,
|
|
100
|
+
headers: dict[str, str] | None = None,
|
|
101
|
+
) -> tuple[int, dict[str, Any]]:
|
|
102
|
+
return self.service.handle(method, path, payload or {}, headers=headers or {})
|
|
103
|
+
|
|
104
|
+
def stream(
|
|
105
|
+
self,
|
|
106
|
+
method: str,
|
|
107
|
+
path: str,
|
|
108
|
+
payload: dict[str, Any] | None = None,
|
|
109
|
+
headers: dict[str, str] | None = None,
|
|
110
|
+
) -> Iterator[dict[str, Any]]:
|
|
111
|
+
body = payload or {}
|
|
112
|
+
if method.upper() == "POST" and path == "/v1/orchestrator/run":
|
|
113
|
+
events: list[dict[str, Any]] = []
|
|
114
|
+
result = self.service.runOrchestrator(body, onEvent=events.append)
|
|
115
|
+
yield from events
|
|
116
|
+
yield {"type": "final", "result": result}
|
|
117
|
+
return
|
|
118
|
+
status, result = self.service.handle(method, path, body, headers=headers or {})
|
|
119
|
+
if status >= 400:
|
|
120
|
+
raise PicuxApiError(status, result)
|
|
121
|
+
yield {"type": "final", "result": result}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class PicuxClient:
|
|
125
|
+
def __init__(self, *, baseUrl: str = "http://127.0.0.1:8088", token: str = "", transport: Transport | None = None) -> None:
|
|
126
|
+
self.baseUrl = baseUrl
|
|
127
|
+
self.token = token
|
|
128
|
+
self.transport = transport or HttpTransport(baseUrl)
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def fromEnv(cls, env: dict[str, str] | None = None) -> "PicuxClient":
|
|
132
|
+
settings = PicuxSettings.fromEnv(env)
|
|
133
|
+
return cls(baseUrl=settings.apiUrl, token=settings.apiToken)
|
|
134
|
+
|
|
135
|
+
def request(self, method: str, path: str, payload: dict[str, Any] | None = None, *, raiseForStatus: bool = True) -> dict[str, Any]:
|
|
136
|
+
if method.upper() == "GET" and payload:
|
|
137
|
+
path = _pathWithQuery(path, payload)
|
|
138
|
+
payload = None
|
|
139
|
+
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
140
|
+
status, result = self.transport.request(method, path, payload, headers)
|
|
141
|
+
if status >= 400 and raiseForStatus:
|
|
142
|
+
raise PicuxApiError(status, result)
|
|
143
|
+
return result
|
|
144
|
+
|
|
145
|
+
def requestRaw(self, method: str, path: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
146
|
+
if method.upper() == "GET" and payload:
|
|
147
|
+
path = _pathWithQuery(path, payload)
|
|
148
|
+
payload = None
|
|
149
|
+
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
150
|
+
status, result = self.transport.request(method, path, payload, headers)
|
|
151
|
+
return {"ok": status < 400, "status": status, "result": result}
|
|
152
|
+
|
|
153
|
+
def health(self) -> dict[str, Any]:
|
|
154
|
+
return self.request("GET", "/healthz")
|
|
155
|
+
|
|
156
|
+
def runtime(self) -> dict[str, Any]:
|
|
157
|
+
return self.request("GET", "/runtime")
|
|
158
|
+
|
|
159
|
+
def apiStatus(self) -> dict[str, Any]:
|
|
160
|
+
return self.request("GET", "/v1/status")
|
|
161
|
+
|
|
162
|
+
def manifest(self) -> dict[str, Any]:
|
|
163
|
+
return self.request("GET", "/v1/manifest")
|
|
164
|
+
|
|
165
|
+
def protocolMap(self) -> dict[str, Any]:
|
|
166
|
+
return self.request("GET", "/v1/protocol-map")
|
|
167
|
+
|
|
168
|
+
def handshake(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
169
|
+
return self.request("POST", "/v1/handshake", payload)
|
|
170
|
+
|
|
171
|
+
def a2aContract(self) -> dict[str, Any]:
|
|
172
|
+
return self.request("GET", "/v1/a2a/contract")
|
|
173
|
+
|
|
174
|
+
def evaluatePolicy(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
175
|
+
return self.request("POST", "/v1/security/policy/evaluate", payload)
|
|
176
|
+
|
|
177
|
+
def checkSecrets(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
178
|
+
return self.request("POST", "/v1/security/secrets/check", payload)
|
|
179
|
+
|
|
180
|
+
def nlpTool(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
181
|
+
return self.request("POST", "/v1/tools/nlp", payload)
|
|
182
|
+
|
|
183
|
+
def imageReader(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
184
|
+
return self.request("POST", "/v1/tools/imageReader", payload)
|
|
185
|
+
|
|
186
|
+
def browserReader(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
187
|
+
return self.request("POST", "/v1/tools/browserReader", payload)
|
|
188
|
+
|
|
189
|
+
def mapTool(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
190
|
+
return self.request("POST", "/v1/tools/map", payload)
|
|
191
|
+
|
|
192
|
+
def portalBrowser(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
193
|
+
return self.request("POST", "/v1/tools/portalBrowser", payload)
|
|
194
|
+
|
|
195
|
+
def runSandbox(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
196
|
+
return self.request("POST", "/v1/sandbox/midnight-arbitrage", payload or {})
|
|
197
|
+
|
|
198
|
+
def runOrchestrator(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
199
|
+
return self.request("POST", "/v1/orchestrator/run", payload)
|
|
200
|
+
|
|
201
|
+
def resumeOrchestrator(self, conversationId: str, itemId: str, action: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
202
|
+
return self.runOrchestrator({**(payload or {}), "conversationId": conversationId, "itemId": itemId, "action": action})
|
|
203
|
+
|
|
204
|
+
def streamOrchestrator(self, payload: dict[str, Any]) -> Iterator[dict[str, Any]]:
|
|
205
|
+
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
206
|
+
yield from self.transport.stream("POST", "/v1/orchestrator/run", {**payload, "stream": True}, headers)
|
|
207
|
+
|
|
208
|
+
def runBenchmark(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
209
|
+
return self.request("POST", "/v1/benchmarks/local", payload or {})
|
|
210
|
+
|
|
211
|
+
def listSchemas(self) -> dict[str, Any]:
|
|
212
|
+
return self.request("GET", "/v1/schemas")
|
|
213
|
+
|
|
214
|
+
def getSchema(self, schemaId: str) -> dict[str, Any]:
|
|
215
|
+
return self.request("GET", f"/v1/schemas/{schemaId}")
|
|
216
|
+
|
|
217
|
+
def createA2AEnvelope(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
218
|
+
return self.request("POST", "/v1/a2a/envelopes", payload)
|
|
219
|
+
|
|
220
|
+
def listA2AEnvelopes(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
221
|
+
return self.request("GET", "/v1/a2a/envelopes", filters)
|
|
222
|
+
|
|
223
|
+
def getA2AEnvelope(self, msgId: str) -> dict[str, Any]:
|
|
224
|
+
return self.request("GET", f"/v1/a2a/envelopes/{msgId}")
|
|
225
|
+
|
|
226
|
+
def updateA2AEnvelope(self, msgId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
227
|
+
return self.request("POST", f"/v1/a2a/envelopes/{msgId}/update", payload)
|
|
228
|
+
|
|
229
|
+
def recordEvent(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
230
|
+
return self.request("POST", "/v1/events", payload)
|
|
231
|
+
|
|
232
|
+
def listEvents(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
233
|
+
return self.request("GET", "/v1/events", filters)
|
|
234
|
+
|
|
235
|
+
def getEvent(self, eventId: str) -> dict[str, Any]:
|
|
236
|
+
return self.request("GET", f"/v1/events/{eventId}")
|
|
237
|
+
|
|
238
|
+
def ackEvent(self, eventId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
239
|
+
return self.request("POST", f"/v1/events/{eventId}/ack", payload or {})
|
|
240
|
+
|
|
241
|
+
def createEventSubscription(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
242
|
+
return self.request("POST", "/v1/event-subscriptions", payload)
|
|
243
|
+
|
|
244
|
+
def listEventSubscriptions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
245
|
+
return self.request("GET", "/v1/event-subscriptions", filters)
|
|
246
|
+
|
|
247
|
+
def getEventSubscription(self, subId: str) -> dict[str, Any]:
|
|
248
|
+
return self.request("GET", f"/v1/event-subscriptions/{subId}")
|
|
249
|
+
|
|
250
|
+
def updateEventSubscription(self, subId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
251
|
+
return self.request("POST", f"/v1/event-subscriptions/{subId}/update", payload)
|
|
252
|
+
|
|
253
|
+
def createEventDelivery(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
254
|
+
return self.request("POST", "/v1/event-deliveries", payload)
|
|
255
|
+
|
|
256
|
+
def listEventDeliveries(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
257
|
+
return self.request("GET", "/v1/event-deliveries", filters)
|
|
258
|
+
|
|
259
|
+
def eventDeliveryStats(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
260
|
+
return self.request("GET", "/v1/event-deliveries/stats", filters)
|
|
261
|
+
|
|
262
|
+
def eventDeliveryReady(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
263
|
+
return self.request("GET", "/v1/event-deliveries/ready", filters)
|
|
264
|
+
|
|
265
|
+
def getEventDelivery(self, deliveryId: str) -> dict[str, Any]:
|
|
266
|
+
return self.request("GET", f"/v1/event-deliveries/{deliveryId}")
|
|
267
|
+
|
|
268
|
+
def eventDeliveryChain(self, deliveryId: str, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
269
|
+
return self.request("GET", f"/v1/event-deliveries/{deliveryId}/chain", filters)
|
|
270
|
+
|
|
271
|
+
def claimEventDelivery(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
272
|
+
return self.request("POST", "/v1/event-deliveries/claim", payload or {})
|
|
273
|
+
|
|
274
|
+
def claimEventDeliveries(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
275
|
+
return self.request("POST", "/v1/event-deliveries/claimBatch", payload or {})
|
|
276
|
+
|
|
277
|
+
def sweepEventDeliveryLeases(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
278
|
+
return self.request("POST", "/v1/event-deliveries/sweep", payload or {})
|
|
279
|
+
|
|
280
|
+
def retryEventDelivery(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
281
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/retry", payload or {})
|
|
282
|
+
|
|
283
|
+
def failEventDelivery(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
284
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/fail", payload or {})
|
|
285
|
+
|
|
286
|
+
def completeEventDelivery(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
287
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/complete", payload or {})
|
|
288
|
+
|
|
289
|
+
def cancelEventDelivery(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
290
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/cancel", payload or {})
|
|
291
|
+
|
|
292
|
+
def renewEventDeliveryLease(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
293
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/lease", payload or {})
|
|
294
|
+
|
|
295
|
+
def releaseEventDelivery(self, deliveryId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
296
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/release", payload or {})
|
|
297
|
+
|
|
298
|
+
def updateEventDelivery(self, deliveryId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
299
|
+
return self.request("POST", f"/v1/event-deliveries/{deliveryId}/update", payload)
|
|
300
|
+
|
|
301
|
+
def createTask(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
302
|
+
return self.request("POST", "/v1/tasks", payload)
|
|
303
|
+
|
|
304
|
+
def listTasks(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
305
|
+
return self.request("GET", "/v1/tasks", filters)
|
|
306
|
+
|
|
307
|
+
def getTask(self, taskId: str) -> dict[str, Any]:
|
|
308
|
+
return self.request("GET", f"/v1/tasks/{taskId}")
|
|
309
|
+
|
|
310
|
+
def updateTask(self, taskId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
311
|
+
return self.request("POST", f"/v1/tasks/{taskId}/update", payload)
|
|
312
|
+
|
|
313
|
+
def createCase(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
314
|
+
return self.request("POST", "/v1/cases", payload)
|
|
315
|
+
|
|
316
|
+
def listCases(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
317
|
+
return self.request("GET", "/v1/cases", filters)
|
|
318
|
+
|
|
319
|
+
def getCase(self, caseId: str) -> dict[str, Any]:
|
|
320
|
+
return self.request("GET", f"/v1/cases/{caseId}")
|
|
321
|
+
|
|
322
|
+
def updateCase(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
323
|
+
return self.request("POST", f"/v1/cases/{caseId}/update", payload)
|
|
324
|
+
|
|
325
|
+
def addCaseStakeholder(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
326
|
+
return self.request("POST", f"/v1/cases/{caseId}/stakeholders", payload)
|
|
327
|
+
|
|
328
|
+
def addCaseDeadline(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
329
|
+
return self.request("POST", f"/v1/cases/{caseId}/deadlines", payload)
|
|
330
|
+
|
|
331
|
+
def reviewCaseDeadlines(self, caseId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
332
|
+
return self.request("POST", f"/v1/cases/{caseId}/deadlines/review", payload or {})
|
|
333
|
+
|
|
334
|
+
def addCaseAction(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
335
|
+
return self.request("POST", f"/v1/cases/{caseId}/actions", payload)
|
|
336
|
+
|
|
337
|
+
def listCaseActions(self, caseId: str, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
338
|
+
return self.request("GET", f"/v1/cases/{caseId}/actions", filters)
|
|
339
|
+
|
|
340
|
+
def updateCaseAction(self, caseId: str, actionId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
341
|
+
return self.request("POST", f"/v1/cases/{caseId}/actions/{actionId}/update", payload)
|
|
342
|
+
|
|
343
|
+
def addCaseEvent(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
344
|
+
return self.request("POST", f"/v1/cases/{caseId}/events", payload)
|
|
345
|
+
|
|
346
|
+
def caseTimeline(self, caseId: str, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
347
|
+
return self.request("GET", f"/v1/cases/{caseId}/timeline", filters)
|
|
348
|
+
|
|
349
|
+
def addCaseEvidence(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
350
|
+
return self.request("POST", f"/v1/cases/{caseId}/evidence", payload)
|
|
351
|
+
|
|
352
|
+
def addCaseNote(self, caseId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
353
|
+
return self.request("POST", f"/v1/cases/{caseId}/notes", payload)
|
|
354
|
+
|
|
355
|
+
def listCaseNotes(self, caseId: str, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
356
|
+
return self.request("GET", f"/v1/cases/{caseId}/notes", filters)
|
|
357
|
+
|
|
358
|
+
def exportCaseBundle(self, caseId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
359
|
+
return self.request("POST", f"/v1/cases/{caseId}/export", payload or {})
|
|
360
|
+
|
|
361
|
+
def listAgents(self) -> dict[str, Any]:
|
|
362
|
+
return self.request("GET", "/v1/agents")
|
|
363
|
+
|
|
364
|
+
def getAgent(self, agentId: str) -> dict[str, Any]:
|
|
365
|
+
return self.request("GET", f"/v1/agents/{agentId}")
|
|
366
|
+
|
|
367
|
+
def registerAgent(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
368
|
+
return self.request("POST", "/v1/agents", payload)
|
|
369
|
+
|
|
370
|
+
def matchAgents(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
371
|
+
return self.request("POST", "/v1/agents/match", payload)
|
|
372
|
+
|
|
373
|
+
def delegateAgent(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
374
|
+
return self.request("POST", "/v1/agents/delegate", payload)
|
|
375
|
+
|
|
376
|
+
def registerConnector(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
377
|
+
return self.request("POST", "/v1/bridge/connectors", payload)
|
|
378
|
+
|
|
379
|
+
def listReadyConnectors(self) -> dict[str, Any]:
|
|
380
|
+
return self.request("GET", "/v1/bridge/connectors/ready")
|
|
381
|
+
|
|
382
|
+
def installReadyConnectors(self, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
383
|
+
return self.request("POST", "/v1/bridge/connectors/ready/install", payload or {})
|
|
384
|
+
|
|
385
|
+
def createBridgeConnectionSession(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
386
|
+
return self.request("POST", "/v1/bridge/connection-sessions", payload)
|
|
387
|
+
|
|
388
|
+
def listBridgeConnectionSessions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
389
|
+
return self.request("GET", "/v1/bridge/connection-sessions", filters)
|
|
390
|
+
|
|
391
|
+
def getBridgeConnectionSession(self, sessionId: str) -> dict[str, Any]:
|
|
392
|
+
return self.request("GET", f"/v1/bridge/connection-sessions/{sessionId}")
|
|
393
|
+
|
|
394
|
+
def revokeBridgeConnectionSession(self, sessionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
395
|
+
return self.request("POST", f"/v1/bridge/connection-sessions/{sessionId}/revoke", payload or {})
|
|
396
|
+
|
|
397
|
+
def createBridgeAction(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
398
|
+
return self.request("POST", "/v1/bridge/actions", payload)
|
|
399
|
+
|
|
400
|
+
def listBridgeActions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
401
|
+
return self.request("GET", "/v1/bridge/actions", filters)
|
|
402
|
+
|
|
403
|
+
def getBridgeAction(self, actionId: str) -> dict[str, Any]:
|
|
404
|
+
return self.request("GET", f"/v1/bridge/actions/{actionId}")
|
|
405
|
+
|
|
406
|
+
def updateBridgeAction(self, actionId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
407
|
+
return self.request("POST", f"/v1/bridge/actions/{actionId}/update", payload)
|
|
408
|
+
|
|
409
|
+
def runBridgeAction(self, actionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
410
|
+
return self.request("POST", f"/v1/bridge/actions/{actionId}/run", payload or {})
|
|
411
|
+
|
|
412
|
+
def createPortalSession(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
413
|
+
return self.request("POST", "/v1/bridge/portal/sessions", payload)
|
|
414
|
+
|
|
415
|
+
def listPortalSessions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
416
|
+
return self.request("GET", "/v1/bridge/portal/sessions", filters)
|
|
417
|
+
|
|
418
|
+
def getPortalSession(self, portalSessionId: str) -> dict[str, Any]:
|
|
419
|
+
return self.request("GET", f"/v1/bridge/portal/sessions/{portalSessionId}")
|
|
420
|
+
|
|
421
|
+
def preflightPortalSession(self, portalSessionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
422
|
+
return self.request("POST", f"/v1/bridge/portal/sessions/{portalSessionId}/preflight", payload or {})
|
|
423
|
+
|
|
424
|
+
def createPortalAction(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
425
|
+
return self.request("POST", "/v1/bridge/portal/actions", payload)
|
|
426
|
+
|
|
427
|
+
def listPortalActions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
428
|
+
return self.request("GET", "/v1/bridge/portal/actions", filters)
|
|
429
|
+
|
|
430
|
+
def getPortalAction(self, portalActionId: str) -> dict[str, Any]:
|
|
431
|
+
return self.request("GET", f"/v1/bridge/portal/actions/{portalActionId}")
|
|
432
|
+
|
|
433
|
+
def listPortalActionTemplates(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
434
|
+
return self.request("GET", "/v1/bridge/portal/templates", filters)
|
|
435
|
+
|
|
436
|
+
def getPortalActionTemplate(self, templateId: str) -> dict[str, Any]:
|
|
437
|
+
return self.request("GET", f"/v1/bridge/portal/templates/{templateId}")
|
|
438
|
+
|
|
439
|
+
def listPortalPlaybooks(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
440
|
+
return self.request("GET", "/v1/bridge/portal/playbooks", filters)
|
|
441
|
+
|
|
442
|
+
def getPortalPlaybook(self, playbookId: str) -> dict[str, Any]:
|
|
443
|
+
return self.request("GET", f"/v1/bridge/portal/playbooks/{playbookId}")
|
|
444
|
+
|
|
445
|
+
def instantiatePortalPlaybook(self, playbookId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
446
|
+
return self.request("POST", f"/v1/bridge/portal/playbooks/{playbookId}/instantiate", payload)
|
|
447
|
+
|
|
448
|
+
def runPortalAction(self, portalActionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
449
|
+
return self.request("POST", f"/v1/bridge/portal/actions/{portalActionId}/run", payload or {})
|
|
450
|
+
|
|
451
|
+
def createChannelThread(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
452
|
+
return self.request("POST", "/v1/channels/threads", payload)
|
|
453
|
+
|
|
454
|
+
def listChannelThreads(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
455
|
+
return self.request("GET", "/v1/channels/threads", filters)
|
|
456
|
+
|
|
457
|
+
def getChannelThread(self, threadId: str) -> dict[str, Any]:
|
|
458
|
+
return self.request("GET", f"/v1/channels/threads/{threadId}")
|
|
459
|
+
|
|
460
|
+
def channelThreadTimeline(self, threadId: str, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
461
|
+
return self.request("GET", f"/v1/channels/threads/{threadId}/timeline", filters)
|
|
462
|
+
|
|
463
|
+
def recordTouchpoint(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
464
|
+
return self.request("POST", "/v1/channels/touchpoints", payload)
|
|
465
|
+
|
|
466
|
+
def listTouchpoints(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
467
|
+
return self.request("GET", "/v1/channels/touchpoints", filters)
|
|
468
|
+
|
|
469
|
+
def getTouchpoint(self, touchpointId: str) -> dict[str, Any]:
|
|
470
|
+
return self.request("GET", f"/v1/channels/touchpoints/{touchpointId}")
|
|
471
|
+
|
|
472
|
+
def ingestProviderCallback(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
473
|
+
return self.request("POST", "/v1/channels/callbacks", payload)
|
|
474
|
+
|
|
475
|
+
def listProviderCallbacks(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
476
|
+
return self.request("GET", "/v1/channels/callbacks", filters)
|
|
477
|
+
|
|
478
|
+
def listConnectors(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
479
|
+
return self.request("GET", "/v1/bridge/connectors", filters)
|
|
480
|
+
|
|
481
|
+
def getConnector(self, connectorId: str) -> dict[str, Any]:
|
|
482
|
+
return self.request("GET", f"/v1/bridge/connectors/{connectorId}")
|
|
483
|
+
|
|
484
|
+
def updateConnector(self, connectorId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
485
|
+
return self.request("POST", f"/v1/bridge/connectors/{connectorId}/update", payload)
|
|
486
|
+
|
|
487
|
+
def matchConnectors(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
488
|
+
return self.request("POST", "/v1/bridge/connectors/match", payload)
|
|
489
|
+
|
|
490
|
+
def preflightConnector(self, connectorId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
491
|
+
return self.request("POST", f"/v1/bridge/connectors/{connectorId}/preflight", payload)
|
|
492
|
+
|
|
493
|
+
def preflightConnectorPaid(
|
|
494
|
+
self,
|
|
495
|
+
connectorId: str,
|
|
496
|
+
payload: dict[str, Any],
|
|
497
|
+
*,
|
|
498
|
+
payer: dict[str, Any] | None = None,
|
|
499
|
+
) -> dict[str, Any]:
|
|
500
|
+
return self.payFetch("POST", f"/v1/bridge/connectors/{connectorId}/preflight", payload, payer=payer)
|
|
501
|
+
|
|
502
|
+
def createProxyMission(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
503
|
+
return self.request("POST", "/v1/proxy/missions", payload)
|
|
504
|
+
|
|
505
|
+
def listProxyMissions(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
506
|
+
return self.request("GET", "/v1/proxy/missions", filters)
|
|
507
|
+
|
|
508
|
+
def getProxyMission(self, proxyId: str) -> dict[str, Any]:
|
|
509
|
+
return self.request("GET", f"/v1/proxy/missions/{proxyId}")
|
|
510
|
+
|
|
511
|
+
def submitProxyOutcome(self, proxyId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
512
|
+
return self.request("POST", f"/v1/proxy/missions/{proxyId}/outcome", payload)
|
|
513
|
+
|
|
514
|
+
def submitProxyOutcomeByRef(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
515
|
+
return self.request("POST", "/v1/proxy/outcomes", payload)
|
|
516
|
+
|
|
517
|
+
def huntDiscover(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
518
|
+
return self.request("POST", "/v1/hunt/discover", payload)
|
|
519
|
+
|
|
520
|
+
def listWorkflowTemplates(self) -> dict[str, Any]:
|
|
521
|
+
return self.request("GET", "/v1/workflows/templates")
|
|
522
|
+
|
|
523
|
+
def getWorkflowTemplate(self, templateId: str) -> dict[str, Any]:
|
|
524
|
+
return self.request("GET", f"/v1/workflows/templates/{templateId}")
|
|
525
|
+
|
|
526
|
+
def runWorkflowTemplate(self, templateId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
527
|
+
return self.request("POST", f"/v1/workflows/templates/{templateId}/run", payload)
|
|
528
|
+
|
|
529
|
+
def resolveScamTriage(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
530
|
+
return self.request("POST", "/v1/resolve/scamTriage", payload)
|
|
531
|
+
|
|
532
|
+
def resolveRecovery(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
533
|
+
return self.request("POST", "/v1/resolve/recovery", payload)
|
|
534
|
+
|
|
535
|
+
def createMandate(self, mandate: dict[str, Any]) -> dict[str, Any]:
|
|
536
|
+
return self.request("POST", "/v1/mandates", mandate)
|
|
537
|
+
|
|
538
|
+
def listMandates(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
539
|
+
return self.request("GET", "/v1/mandates", filters)
|
|
540
|
+
|
|
541
|
+
def getMandate(self, mandateId: str) -> dict[str, Any]:
|
|
542
|
+
return self.request("GET", f"/v1/mandates/{mandateId}")
|
|
543
|
+
|
|
544
|
+
def verifyMandate(self, mandateId: str, mandate: dict[str, Any]) -> dict[str, Any]:
|
|
545
|
+
return self.request("POST", f"/v1/mandates/{mandateId}/verify", mandate)
|
|
546
|
+
|
|
547
|
+
def resolveTask(self, taskId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
548
|
+
return self.request("POST", f"/v1/tasks/{taskId}/resolve", payload)
|
|
549
|
+
|
|
550
|
+
def createEscrow(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
551
|
+
return self.request("POST", "/v1/pay/escrows", payload)
|
|
552
|
+
|
|
553
|
+
def listEscrows(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
554
|
+
return self.request("GET", "/v1/pay/escrows", filters)
|
|
555
|
+
|
|
556
|
+
def getEscrow(self, escrowId: str) -> dict[str, Any]:
|
|
557
|
+
return self.request("GET", f"/v1/pay/escrows/{escrowId}")
|
|
558
|
+
|
|
559
|
+
def updateEscrow(self, escrowId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
560
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/update", payload)
|
|
561
|
+
|
|
562
|
+
def fundEscrow(self, escrowId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
563
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/fund", payload or {})
|
|
564
|
+
|
|
565
|
+
def submitEscrowProof(self, escrowId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
566
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/proof", payload)
|
|
567
|
+
|
|
568
|
+
def settleEscrow(self, escrowId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
569
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/settle", payload or {})
|
|
570
|
+
|
|
571
|
+
def refundEscrow(self, escrowId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
572
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/refund", payload or {})
|
|
573
|
+
|
|
574
|
+
def disputeEscrow(self, escrowId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
575
|
+
return self.request("POST", f"/v1/pay/escrows/{escrowId}/dispute", payload)
|
|
576
|
+
|
|
577
|
+
def listPayRails(self) -> dict[str, Any]:
|
|
578
|
+
return self.request("GET", "/v1/pay/rails")
|
|
579
|
+
|
|
580
|
+
def getPayRail(self, railId: str) -> dict[str, Any]:
|
|
581
|
+
return self.request("GET", f"/v1/pay/rails/{railId}")
|
|
582
|
+
|
|
583
|
+
def listPayAdapters(self) -> dict[str, Any]:
|
|
584
|
+
return self.request("GET", "/v1/pay/adapters")
|
|
585
|
+
|
|
586
|
+
def getPayAdapter(self, adapterId: str) -> dict[str, Any]:
|
|
587
|
+
return self.request("GET", f"/v1/pay/adapters/{adapterId}")
|
|
588
|
+
|
|
589
|
+
def invokePayAdapter(self, adapterId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
590
|
+
return self.request("POST", f"/v1/pay/adapters/{adapterId}/invoke", payload)
|
|
591
|
+
|
|
592
|
+
def initEscrowMission(self, mission: dict[str, Any], *, adapterId: str = "solanaEscrowAdapter", live: bool = False, signedTransaction: str = "") -> dict[str, Any]:
|
|
593
|
+
payload: dict[str, Any] = {"mission": mission}
|
|
594
|
+
if live:
|
|
595
|
+
payload["live"] = True
|
|
596
|
+
if signedTransaction:
|
|
597
|
+
payload["signedTransaction"] = signedTransaction
|
|
598
|
+
return self.invokePayAdapter(adapterId, {"action": "mission.initialize", "payload": payload})
|
|
599
|
+
|
|
600
|
+
def settleEscrowMission(self, mission: dict[str, Any], *, adapterId: str = "solanaEscrowAdapter", live: bool = False, signedTransaction: str = "") -> dict[str, Any]:
|
|
601
|
+
payload: dict[str, Any] = {"mission": mission}
|
|
602
|
+
if live:
|
|
603
|
+
payload["live"] = True
|
|
604
|
+
if signedTransaction:
|
|
605
|
+
payload["signedTransaction"] = signedTransaction
|
|
606
|
+
return self.invokePayAdapter(adapterId, {"action": "mission.settle", "payload": payload})
|
|
607
|
+
|
|
608
|
+
def abortEscrowMission(self, mission: dict[str, Any], *, adapterId: str = "solanaEscrowAdapter", live: bool = False, signedTransaction: str = "") -> dict[str, Any]:
|
|
609
|
+
payload: dict[str, Any] = {"mission": mission}
|
|
610
|
+
if live:
|
|
611
|
+
payload["live"] = True
|
|
612
|
+
if signedTransaction:
|
|
613
|
+
payload["signedTransaction"] = signedTransaction
|
|
614
|
+
return self.invokePayAdapter(adapterId, {"action": "mission.abort", "payload": payload})
|
|
615
|
+
|
|
616
|
+
def listReputationCards(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
617
|
+
return self.request("GET", "/v1/pay/reputation", filters)
|
|
618
|
+
|
|
619
|
+
def getReputationCard(self, cardId: str) -> dict[str, Any]:
|
|
620
|
+
return self.request("GET", f"/v1/pay/reputation/{cardId}")
|
|
621
|
+
|
|
622
|
+
def updateReputationCard(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
623
|
+
return self.request("POST", "/v1/pay/reputation", payload)
|
|
624
|
+
|
|
625
|
+
def createPaymentChallenge(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
626
|
+
return self.request("POST", "/v1/pay/challenges", payload)
|
|
627
|
+
|
|
628
|
+
def verifyPaymentChallenge(self, challengeId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
629
|
+
return self.request("POST", f"/v1/pay/challenges/{challengeId}/verify", payload)
|
|
630
|
+
|
|
631
|
+
def createPaymentSession(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
632
|
+
return self.request("POST", "/v1/pay/sessions", payload)
|
|
633
|
+
|
|
634
|
+
def authorizePaymentSession(self, sessionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
635
|
+
return self.request("POST", f"/v1/pay/sessions/{sessionId}/authorize", payload or {})
|
|
636
|
+
|
|
637
|
+
def consumePaymentSession(self, sessionId: str, payload: dict[str, Any]) -> dict[str, Any]:
|
|
638
|
+
return self.request("POST", f"/v1/pay/sessions/{sessionId}/consume", payload)
|
|
639
|
+
|
|
640
|
+
def closePaymentSession(self, sessionId: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
641
|
+
return self.request("POST", f"/v1/pay/sessions/{sessionId}/close", payload or {})
|
|
642
|
+
|
|
643
|
+
def localPaymentCredential(self, challenge: dict[str, Any], payer: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
644
|
+
payerObj = payer if isinstance(payer, dict) else challenge.get("payer", {})
|
|
645
|
+
payerObj = payerObj if isinstance(payerObj, dict) else {}
|
|
646
|
+
challengeId = str(challenge.get("challengeId", "") or "")
|
|
647
|
+
railId = str(challenge.get("railId", "picuxLedger") or "picuxLedger")
|
|
648
|
+
credential = {
|
|
649
|
+
"credentialId": _stableId("paycred", {"challengeId": challengeId, "railId": railId, "payer": payerObj}),
|
|
650
|
+
"challengeId": challengeId,
|
|
651
|
+
"railId": railId,
|
|
652
|
+
"payer": payerObj,
|
|
653
|
+
"signature": _stableId("paysig", {"challengeId": challengeId, "railId": railId, "payer": payerObj}),
|
|
654
|
+
"paymentRef": _stableId("localpay", {"challengeId": challengeId, "payer": payerObj}),
|
|
655
|
+
"amount": challenge.get("amount", {}) if isinstance(challenge.get("amount"), dict) else {},
|
|
656
|
+
"createdAt": str(challenge.get("createdAt", "") or ""),
|
|
657
|
+
"meta": {"mode": "picuxLedgerLocal"},
|
|
658
|
+
}
|
|
659
|
+
return credential
|
|
660
|
+
|
|
661
|
+
def payFetch(
|
|
662
|
+
self,
|
|
663
|
+
method: str,
|
|
664
|
+
path: str,
|
|
665
|
+
payload: dict[str, Any] | None = None,
|
|
666
|
+
*,
|
|
667
|
+
payer: dict[str, Any] | None = None,
|
|
668
|
+
) -> dict[str, Any]:
|
|
669
|
+
headers = {"Authorization": f"Bearer {self.token}"} if self.token else {}
|
|
670
|
+
status, result = self.transport.request(method, path, payload, headers)
|
|
671
|
+
if status != 402:
|
|
672
|
+
if status >= 400:
|
|
673
|
+
raise PicuxApiError(status, result)
|
|
674
|
+
return result
|
|
675
|
+
challenge = result.get("challenge", {}) if isinstance(result.get("challenge"), dict) else {}
|
|
676
|
+
credential = self.localPaymentCredential(challenge, payer=payer)
|
|
677
|
+
verified = self.verifyPaymentChallenge(str(challenge.get("challengeId", "") or ""), {"credential": credential})
|
|
678
|
+
retryHeaders = {
|
|
679
|
+
**headers,
|
|
680
|
+
"X-Picux-Payment-Challenge": str(challenge.get("challengeId", "") or ""),
|
|
681
|
+
"X-Picux-Payment-Credential": credential["credentialId"],
|
|
682
|
+
"Payment-Signature": credential["signature"],
|
|
683
|
+
}
|
|
684
|
+
retryStatus, retryResult = self.transport.request(method, path, payload, retryHeaders)
|
|
685
|
+
if retryStatus >= 400:
|
|
686
|
+
raise PicuxApiError(retryStatus, retryResult)
|
|
687
|
+
return {**retryResult, "paymentReceipt": verified.get("receipt", {})}
|
|
688
|
+
|
|
689
|
+
def settlementAdapterContract(self) -> dict[str, Any]:
|
|
690
|
+
return self.request("GET", "/v1/pay/adapters/contract")
|
|
691
|
+
|
|
692
|
+
def prepareSettlement(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
693
|
+
return self.request("POST", "/v1/pay/prepare", payload)
|
|
694
|
+
|
|
695
|
+
def settle(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
696
|
+
return self.request("POST", "/v1/pay/settle", payload)
|
|
697
|
+
|
|
698
|
+
def listReceipts(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
699
|
+
return self.request("GET", "/v1/receipts", filters)
|
|
700
|
+
|
|
701
|
+
def getReceipt(self, receiptId: str) -> dict[str, Any]:
|
|
702
|
+
return self.request("GET", f"/v1/receipts/{receiptId}")
|
|
703
|
+
|
|
704
|
+
def getEvidence(self, artifactId: str) -> dict[str, Any]:
|
|
705
|
+
return self.request("GET", f"/v1/audit/evidence/{artifactId}")
|
|
706
|
+
|
|
707
|
+
def listEvidence(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
708
|
+
return self.request("GET", "/v1/audit/evidence", filters)
|
|
709
|
+
|
|
710
|
+
def recordEvidence(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
711
|
+
return self.request("POST", "/v1/audit/evidence", payload)
|
|
712
|
+
|
|
713
|
+
def createProofPack(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
714
|
+
return self.request("POST", "/v1/audit/proofPacks", payload)
|
|
715
|
+
|
|
716
|
+
def listProofPacks(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
717
|
+
return self.request("GET", "/v1/audit/proofPacks", filters)
|
|
718
|
+
|
|
719
|
+
def getProofPack(self, packId: str) -> dict[str, Any]:
|
|
720
|
+
return self.request("GET", f"/v1/audit/proofPacks/{packId}")
|
|
721
|
+
|
|
722
|
+
def getPov(self, povId: str) -> dict[str, Any]:
|
|
723
|
+
return self.request("GET", f"/v1/audit/pov/{povId}")
|
|
724
|
+
|
|
725
|
+
def listPov(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
726
|
+
return self.request("GET", "/v1/audit/pov", filters)
|
|
727
|
+
|
|
728
|
+
def recordPov(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
729
|
+
return self.request("POST", "/v1/audit/pov", payload)
|
|
730
|
+
|
|
731
|
+
def verifyReceipt(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
732
|
+
return self.request("POST", "/v1/audit/receipts/verify", payload)
|
|
733
|
+
|
|
734
|
+
def verifyChain(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
735
|
+
return self.request("POST", "/v1/audit/chain/verify", payload)
|
|
736
|
+
|
|
737
|
+
def communitySignal(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
738
|
+
return self.request("POST", "/v1/signals/community", payload)
|
|
739
|
+
|
|
740
|
+
def listCommunitySignals(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
741
|
+
return self.request("GET", "/v1/signals/community", filters)
|
|
742
|
+
|
|
743
|
+
def getCommunitySignal(self, signalId: str) -> dict[str, Any]:
|
|
744
|
+
return self.request("GET", f"/v1/signals/community/{signalId}")
|
|
745
|
+
|
|
746
|
+
def analyzeCommunitySignal(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
747
|
+
return self.request("POST", "/v1/signals/community/analyze", payload)
|
|
748
|
+
|
|
749
|
+
def launchCommunityTask(self, payload: dict[str, Any]) -> dict[str, Any]:
|
|
750
|
+
return self.request("POST", "/v1/signals/community/launch-task", payload)
|
|
751
|
+
|
|
752
|
+
def communityEntities(self) -> dict[str, Any]:
|
|
753
|
+
return self.request("GET", "/v1/signals/community/entities")
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def _pathWithQuery(path: str, payload: dict[str, Any]) -> str:
|
|
757
|
+
values = {key: value for key, value in payload.items() if value is not None and value != ""}
|
|
758
|
+
if not values:
|
|
759
|
+
return path
|
|
760
|
+
joiner = "&" if "?" in path else "?"
|
|
761
|
+
return f"{path}{joiner}{urlencode(values, doseq=True)}"
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
def _stableId(prefix: str, payload: dict[str, Any]) -> str:
|
|
765
|
+
digest = hashlib.sha256(
|
|
766
|
+
json.dumps(payload, ensure_ascii=True, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
|
767
|
+
).hexdigest()[:24]
|
|
768
|
+
return f"{prefix}_{digest}"
|