usdf 0.1.2__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.
- usdf/__init__.py +102 -0
- usdf/_http.py +91 -0
- usdf/accept.py +187 -0
- usdf/client.py +842 -0
- usdf/errors.py +56 -0
- usdf/estimate.py +123 -0
- usdf/langchain.py +142 -0
- usdf/sse.py +49 -0
- usdf/types.py +407 -0
- usdf/x402.py +555 -0
- usdf-0.1.2.dist-info/METADATA +124 -0
- usdf-0.1.2.dist-info/RECORD +14 -0
- usdf-0.1.2.dist-info/WHEEL +4 -0
- usdf-0.1.2.dist-info/licenses/LICENSE +21 -0
usdf/types.py
ADDED
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
"""Shapes of the gateway's responses, from the gateway's own handlers (gateway/src/proxy.ts, public.ts,
|
|
2
|
+
mcp.ts, account.ts, keys.ts, x402.ts). Each dataclass keeps the full response in ``raw`` so a field the
|
|
3
|
+
SDK does not model is still there. Money is carried as strings: ``units`` are whole base units
|
|
4
|
+
(1 unit = $0.000001 = 0.000001 USDF); ``usd`` and ``usdf`` are the same decimal figure."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class Amount:
|
|
14
|
+
units: str
|
|
15
|
+
usd: str
|
|
16
|
+
usdf: str
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def of(cls, d: Optional[Dict[str, Any]]) -> Optional["Amount"]:
|
|
20
|
+
if not isinstance(d, dict):
|
|
21
|
+
return None
|
|
22
|
+
return cls(str(d.get("units")), str(d.get("usd")), str(d.get("usdf")))
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def as_int(self) -> int:
|
|
26
|
+
return int(self.units)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class Usage:
|
|
31
|
+
prompt_tokens: int
|
|
32
|
+
completion_tokens: int
|
|
33
|
+
cached_tokens: int = 0
|
|
34
|
+
cache_write_tokens: int = 0
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def of(cls, d: Optional[Dict[str, Any]]) -> "Usage":
|
|
38
|
+
d = d or {}
|
|
39
|
+
return cls(int(d.get("prompt_tokens") or 0), int(d.get("completion_tokens") or 0), int(d.get("cached_tokens") or 0), int(d.get("cache_write_tokens") or 0))
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class Receipt:
|
|
44
|
+
"""The receipt attached to every keyed completion (JSON body, or the stream's last comment line)."""
|
|
45
|
+
|
|
46
|
+
request_id: str
|
|
47
|
+
model: str
|
|
48
|
+
provider: str
|
|
49
|
+
status: str # "ok" | "partial"
|
|
50
|
+
usage: Usage
|
|
51
|
+
price_version: str
|
|
52
|
+
cost: Amount
|
|
53
|
+
balance: Optional[Amount] # None when the ledger had not confirmed the charge when the response went out
|
|
54
|
+
settlement_status: str
|
|
55
|
+
note: Optional[str]
|
|
56
|
+
# What the serving route does with content and what the request asked for; on attested hardware it
|
|
57
|
+
# also carries ``attestation`` (pending, then verified or failed on the lookup) and ``attestation_lookup``.
|
|
58
|
+
data_policy: Optional[Dict[str, Any]] = None
|
|
59
|
+
# A request that failed after its hold was taken: status "failed_refunded", why, and what went back.
|
|
60
|
+
reason: Optional[str] = None
|
|
61
|
+
refunded: Optional[Amount] = None
|
|
62
|
+
batch: bool = False
|
|
63
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def attestation(self) -> Optional[str]:
|
|
67
|
+
return (self.data_policy or {}).get("attestation")
|
|
68
|
+
|
|
69
|
+
@classmethod
|
|
70
|
+
def of(cls, d: Dict[str, Any]) -> "Receipt":
|
|
71
|
+
price = d.get("price") or {}
|
|
72
|
+
return cls(
|
|
73
|
+
request_id=str(d.get("request_id")),
|
|
74
|
+
model=str(d.get("model")),
|
|
75
|
+
provider=str(d.get("provider")),
|
|
76
|
+
status=str(d.get("status")),
|
|
77
|
+
usage=Usage.of(d.get("usage")),
|
|
78
|
+
price_version=str(price.get("version")),
|
|
79
|
+
cost=Amount.of(d.get("cost")) or Amount("0", "0.000000", "0.000000"),
|
|
80
|
+
balance=Amount.of(d.get("balance")),
|
|
81
|
+
settlement_status=str((d.get("settlement") or {}).get("status")),
|
|
82
|
+
note=d.get("note"),
|
|
83
|
+
data_policy=d.get("data_policy"),
|
|
84
|
+
reason=d.get("reason"),
|
|
85
|
+
refunded=Amount.of(d.get("refunded")),
|
|
86
|
+
batch=d.get("batch") is True,
|
|
87
|
+
raw=d,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class X402Receipt:
|
|
93
|
+
"""An x402 receipt: ``paid`` is what the request was charged, its metered cost at the quoted price and
|
|
94
|
+
never more than the payment (``raw["payment"]["amount"]``); the rest of the payment is refunded to the
|
|
95
|
+
payer (``raw["refund"]``). ``usage_cost`` is what the usage came to at that price."""
|
|
96
|
+
|
|
97
|
+
request_id: str
|
|
98
|
+
model: str
|
|
99
|
+
provider: str
|
|
100
|
+
status: str
|
|
101
|
+
usage: Usage
|
|
102
|
+
price_version: str
|
|
103
|
+
paid: Amount
|
|
104
|
+
usage_cost: Amount
|
|
105
|
+
payment_tx: str
|
|
106
|
+
payer: str
|
|
107
|
+
asset: str # "USDF" | "USDG"
|
|
108
|
+
method: str # "permit2" | "eip3009"
|
|
109
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
110
|
+
|
|
111
|
+
@classmethod
|
|
112
|
+
def of(cls, d: Dict[str, Any]) -> "X402Receipt":
|
|
113
|
+
payment = d.get("payment") or {}
|
|
114
|
+
return cls(
|
|
115
|
+
request_id=str(d.get("request_id")),
|
|
116
|
+
model=str(d.get("model")),
|
|
117
|
+
provider=str(d.get("provider")),
|
|
118
|
+
status=str(d.get("status")),
|
|
119
|
+
usage=Usage.of(d.get("usage")),
|
|
120
|
+
price_version=str((d.get("price") or {}).get("version")),
|
|
121
|
+
paid=Amount.of(d.get("paid")) or Amount("0", "0.000000", "0.000000"),
|
|
122
|
+
usage_cost=Amount.of(d.get("usage_cost")) or Amount("0", "0.000000", "0.000000"),
|
|
123
|
+
payment_tx=str(payment.get("tx")),
|
|
124
|
+
payer=str(payment.get("payer")),
|
|
125
|
+
asset=str(payment.get("asset")),
|
|
126
|
+
method=str(payment.get("method")),
|
|
127
|
+
raw=d,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@dataclass
|
|
132
|
+
class ChatCompletion:
|
|
133
|
+
"""A completion in the OpenAI shape, with the gateway's receipt. ``raw`` is the whole body."""
|
|
134
|
+
|
|
135
|
+
id: str
|
|
136
|
+
model: str
|
|
137
|
+
content: Optional[str]
|
|
138
|
+
finish_reason: Optional[str]
|
|
139
|
+
tool_calls: Optional[List[Dict[str, Any]]]
|
|
140
|
+
usage: Optional[Dict[str, Any]]
|
|
141
|
+
receipt: Any # Receipt, or X402Receipt for an x402 completion
|
|
142
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
143
|
+
|
|
144
|
+
@classmethod
|
|
145
|
+
def of(cls, d: Dict[str, Any], x402: bool = False) -> "ChatCompletion":
|
|
146
|
+
choices = d.get("choices") or []
|
|
147
|
+
msg = (choices[0].get("message") if choices and isinstance(choices[0], dict) else None) or {}
|
|
148
|
+
receipt = d.get("receipt")
|
|
149
|
+
return cls(
|
|
150
|
+
id=str(d.get("id")),
|
|
151
|
+
model=str(d.get("model")),
|
|
152
|
+
content=msg.get("content"),
|
|
153
|
+
finish_reason=choices[0].get("finish_reason") if choices else None,
|
|
154
|
+
tool_calls=msg.get("tool_calls"),
|
|
155
|
+
usage=d.get("usage"),
|
|
156
|
+
receipt=(X402Receipt.of(receipt) if x402 else Receipt.of(receipt)) if isinstance(receipt, dict) else None,
|
|
157
|
+
raw=d,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@dataclass
|
|
162
|
+
class ReceiptLookup:
|
|
163
|
+
"""GET /v1/receipts/{id}: the charge and, once settled, the batch, its transaction and the rows URL."""
|
|
164
|
+
|
|
165
|
+
request_id: str
|
|
166
|
+
model: str
|
|
167
|
+
provider: str
|
|
168
|
+
status: str
|
|
169
|
+
created_at: str
|
|
170
|
+
usage: Usage
|
|
171
|
+
price_version: str
|
|
172
|
+
cost: Amount
|
|
173
|
+
settlement_status: str
|
|
174
|
+
settlement_batch: Optional[str]
|
|
175
|
+
settlement_tx: Optional[str]
|
|
176
|
+
settlement_explorer: Optional[str]
|
|
177
|
+
settlement_rows: Optional[str]
|
|
178
|
+
# The request's leaf in the usage log (status, leaf_index, tree_size, anchored_by, proof).
|
|
179
|
+
log: Optional[Dict[str, Any]] = None
|
|
180
|
+
# Served on attested hardware: pending, verified or failed, the provider's receipt id, where to read it.
|
|
181
|
+
attestation: Optional[str] = None
|
|
182
|
+
attestation_receipt: Optional[str] = None
|
|
183
|
+
attestation_lookup: Optional[str] = None
|
|
184
|
+
reason: Optional[str] = None
|
|
185
|
+
refunded: Optional[Amount] = None
|
|
186
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
187
|
+
|
|
188
|
+
@classmethod
|
|
189
|
+
def of(cls, d: Dict[str, Any]) -> "ReceiptLookup":
|
|
190
|
+
s = d.get("settlement") or {}
|
|
191
|
+
return cls(
|
|
192
|
+
request_id=str(d.get("request_id")),
|
|
193
|
+
model=str(d.get("model")),
|
|
194
|
+
provider=str(d.get("provider")),
|
|
195
|
+
status=str(d.get("status")),
|
|
196
|
+
created_at=str(d.get("created_at")),
|
|
197
|
+
usage=Usage.of(d.get("usage")),
|
|
198
|
+
price_version=str(d.get("price_version")),
|
|
199
|
+
cost=Amount.of(d.get("cost")) or Amount("0", "0.000000", "0.000000"),
|
|
200
|
+
settlement_status=str(s.get("status")),
|
|
201
|
+
settlement_batch=s.get("batch"),
|
|
202
|
+
settlement_tx=s.get("tx_hash"),
|
|
203
|
+
settlement_explorer=s.get("explorer"),
|
|
204
|
+
settlement_rows=s.get("rows"),
|
|
205
|
+
log=d.get("log"),
|
|
206
|
+
attestation=d.get("attestation"),
|
|
207
|
+
attestation_receipt=d.get("attestation_receipt"),
|
|
208
|
+
attestation_lookup=d.get("attestation_lookup"),
|
|
209
|
+
reason=d.get("reason"),
|
|
210
|
+
refunded=Amount.of(d.get("refunded")),
|
|
211
|
+
raw=d,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@dataclass
|
|
216
|
+
class Model:
|
|
217
|
+
id: str
|
|
218
|
+
name: str
|
|
219
|
+
owned_by: str
|
|
220
|
+
context_length: int
|
|
221
|
+
max_output_tokens: int
|
|
222
|
+
endpoints: List[str]
|
|
223
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
224
|
+
|
|
225
|
+
@classmethod
|
|
226
|
+
def of(cls, d: Dict[str, Any]) -> "Model":
|
|
227
|
+
return cls(str(d.get("id")), str(d.get("name")), str(d.get("owned_by")), int(d.get("context_length") or 0), int(d.get("max_output_tokens") or 0), list(d.get("endpoints") or []), d)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
@dataclass
|
|
231
|
+
class PricingModel:
|
|
232
|
+
id: str
|
|
233
|
+
name: str
|
|
234
|
+
owned_by: str
|
|
235
|
+
context: int
|
|
236
|
+
max_output: int
|
|
237
|
+
endpoints: List[str]
|
|
238
|
+
pricing: str # "list" | "passthrough": every model at a list price ("markup" only on sheets before 2026-10-10)
|
|
239
|
+
price: Dict[str, Any] # USD per 1M tokens: input, output, cached_input?, long_context?
|
|
240
|
+
available: bool
|
|
241
|
+
routes: List[Dict[str, Any]]
|
|
242
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
243
|
+
|
|
244
|
+
@classmethod
|
|
245
|
+
def of(cls, d: Dict[str, Any]) -> "PricingModel":
|
|
246
|
+
return cls(str(d.get("id")), str(d.get("name")), str(d.get("owned_by")), int(d.get("context") or 0), int(d.get("max_output") or 0), list(d.get("endpoints") or []), str(d.get("pricing")), dict(d.get("price") or {}), bool(d.get("available")), list(d.get("routes") or []), d)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@dataclass
|
|
250
|
+
class Pricing:
|
|
251
|
+
version: str
|
|
252
|
+
unit: str
|
|
253
|
+
markup: str
|
|
254
|
+
sheet_sha256: str
|
|
255
|
+
models: List[PricingModel]
|
|
256
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def of(cls, d: Dict[str, Any]) -> "Pricing":
|
|
260
|
+
return cls(str(d.get("version")), str(d.get("unit")), str(d.get("markup")), str(d.get("sheet_sha256")), [PricingModel.of(m) for m in d.get("models") or []], d)
|
|
261
|
+
|
|
262
|
+
def model(self, model_id: str) -> Optional[PricingModel]:
|
|
263
|
+
base = model_id.split(":")[0]
|
|
264
|
+
return next((m for m in self.models if m.id == base), None)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@dataclass
|
|
268
|
+
class Quote:
|
|
269
|
+
"""The hold the gateway places for a request (MCP ``quote``), and the x402 amount for the same request."""
|
|
270
|
+
|
|
271
|
+
model: str
|
|
272
|
+
price_version: str
|
|
273
|
+
max_tokens: int
|
|
274
|
+
prompt_tokens_held: int
|
|
275
|
+
max_cost: Amount
|
|
276
|
+
price: Dict[str, Any]
|
|
277
|
+
note: str
|
|
278
|
+
x402_amount: Optional[Amount]
|
|
279
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
280
|
+
|
|
281
|
+
@classmethod
|
|
282
|
+
def of(cls, d: Dict[str, Any]) -> "Quote":
|
|
283
|
+
x = d.get("x402") or {}
|
|
284
|
+
return cls(str(d.get("model")), str(d.get("price_version")), int(d.get("max_tokens") or 0), int(d.get("prompt_tokens_held") or 0), Amount.of(d.get("max_cost")) or Amount("0", "0.000000", "0.000000"), dict(d.get("price") or {}), str(d.get("note") or ""), Amount.of(x.get("amount")), d)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@dataclass
|
|
288
|
+
class Balance:
|
|
289
|
+
"""MCP ``balance``: what the key can spend, the account's balance and holds, the key's budget."""
|
|
290
|
+
|
|
291
|
+
available: Amount
|
|
292
|
+
balance: Optional[Amount]
|
|
293
|
+
held: Optional[Amount]
|
|
294
|
+
key_id: str
|
|
295
|
+
key_budget: Optional[Amount]
|
|
296
|
+
key_spent: Optional[Amount]
|
|
297
|
+
key_budget_left: Optional[Amount]
|
|
298
|
+
rate_limit_rpm: int
|
|
299
|
+
note: Optional[str]
|
|
300
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
301
|
+
|
|
302
|
+
@classmethod
|
|
303
|
+
def of(cls, d: Dict[str, Any]) -> "Balance":
|
|
304
|
+
k = d.get("key") or {}
|
|
305
|
+
return cls(Amount.of(d.get("available")) or Amount("0", "0.000000", "0.000000"), Amount.of(d.get("balance")), Amount.of(d.get("held")), str(k.get("id")), Amount.of(k.get("budget")), Amount.of(k.get("spent")), Amount.of(k.get("budget_left")), int(d.get("rate_limit_rpm") or 0), d.get("note"), d)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
@dataclass
|
|
309
|
+
class Account:
|
|
310
|
+
"""GET /v1/account: balance, held, linked wallet, pending withdrawals and the deposit address."""
|
|
311
|
+
|
|
312
|
+
id: str
|
|
313
|
+
wallet_address: Optional[str]
|
|
314
|
+
balance_units: int
|
|
315
|
+
held_units: int
|
|
316
|
+
pending_withdrawals: int
|
|
317
|
+
pending_withdrawal_units: int
|
|
318
|
+
deposit_to: str
|
|
319
|
+
deposit_token: str
|
|
320
|
+
chain_id: int
|
|
321
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def available_units(self) -> int:
|
|
325
|
+
return self.balance_units - self.held_units
|
|
326
|
+
|
|
327
|
+
@classmethod
|
|
328
|
+
def of(cls, d: Dict[str, Any]) -> "Account":
|
|
329
|
+
a = d.get("account") or {}
|
|
330
|
+
w = d.get("withdrawals") or {}
|
|
331
|
+
dep = d.get("deposit") or {}
|
|
332
|
+
return cls(str(a.get("id")), a.get("wallet_address"), int(a.get("balance_units") or 0), int(a.get("held_units") or 0), int(w.get("pending_count") or 0), int(w.get("pending_units") or 0), str(dep.get("to")), str(dep.get("token")), int(dep.get("chain_id") or 0), d)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@dataclass
|
|
336
|
+
class Session:
|
|
337
|
+
access_token: str
|
|
338
|
+
refresh_token: Optional[str]
|
|
339
|
+
expires_in: int
|
|
340
|
+
user_id: Optional[str]
|
|
341
|
+
email: Optional[str]
|
|
342
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
343
|
+
|
|
344
|
+
@classmethod
|
|
345
|
+
def of(cls, d: Dict[str, Any]) -> "Session":
|
|
346
|
+
u = d.get("user") or {}
|
|
347
|
+
return cls(str(d.get("access_token")), d.get("refresh_token"), int(d.get("expires_in") or 0), u.get("id"), u.get("email"), d)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@dataclass
|
|
351
|
+
class CreatedKey:
|
|
352
|
+
key_id: str
|
|
353
|
+
api_key: str # shown once; the ledger keeps only its hash
|
|
354
|
+
prefix: str
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
@dataclass
|
|
358
|
+
class ApiKey:
|
|
359
|
+
id: str
|
|
360
|
+
key_prefix: str
|
|
361
|
+
label: Optional[str]
|
|
362
|
+
budget_units: Optional[int]
|
|
363
|
+
spent_units: int
|
|
364
|
+
rate_limit_rpm: int
|
|
365
|
+
created_at: str
|
|
366
|
+
last_used_at: Optional[str]
|
|
367
|
+
revoked_at: Optional[str]
|
|
368
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
369
|
+
|
|
370
|
+
@classmethod
|
|
371
|
+
def of(cls, d: Dict[str, Any]) -> "ApiKey":
|
|
372
|
+
b = d.get("budget_units")
|
|
373
|
+
return cls(str(d.get("id")), str(d.get("key_prefix")), d.get("label"), None if b is None else int(b), int(d.get("spent_units") or 0), int(d.get("rate_limit_rpm") or 0), str(d.get("created_at")), d.get("last_used_at"), d.get("revoked_at"), d)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@dataclass
|
|
377
|
+
class KeyLimits:
|
|
378
|
+
"""GET /v1/keys/{id}/limits: trailing-window spend, caps, pause state, privacy flags, webhook."""
|
|
379
|
+
|
|
380
|
+
key_id: str
|
|
381
|
+
label: Optional[str]
|
|
382
|
+
hour_spent_units: int
|
|
383
|
+
hour_limit_units: Optional[int]
|
|
384
|
+
day_spent_units: int
|
|
385
|
+
day_limit_units: Optional[int]
|
|
386
|
+
month_spent_units: int
|
|
387
|
+
month_limit_units: Optional[int]
|
|
388
|
+
paused: bool
|
|
389
|
+
pause_reason: Optional[str]
|
|
390
|
+
auto_resume: Optional[bool]
|
|
391
|
+
no_logs: bool
|
|
392
|
+
private_tier: bool
|
|
393
|
+
webhook_url: Optional[str]
|
|
394
|
+
updated: List[str]
|
|
395
|
+
raw: Dict[str, Any] = field(repr=False, default_factory=dict)
|
|
396
|
+
|
|
397
|
+
@classmethod
|
|
398
|
+
def of(cls, d: Dict[str, Any]) -> "KeyLimits":
|
|
399
|
+
spend = d.get("spend") or {}
|
|
400
|
+
h = spend.get("hour") or {}
|
|
401
|
+
day = spend.get("day") or {}
|
|
402
|
+
# Pre-migration ledgers (gateway/src/keys.ts): the gateway sends spend.month as null.
|
|
403
|
+
month = spend.get("month") or {}
|
|
404
|
+
p = d.get("paused") or {}
|
|
405
|
+
priv = d.get("privacy") or {}
|
|
406
|
+
lim = lambda v: None if v is None else int(v) # noqa: E731
|
|
407
|
+
return cls(str(d.get("key_id")), d.get("label"), int(h.get("spent_units") or 0), lim(h.get("limit_units")), int(day.get("spent_units") or 0), lim(day.get("limit_units")), int(month.get("spent_units") or 0), lim(month.get("limit_units")), bool(p.get("state")), p.get("reason"), p.get("auto_resume"), bool(priv.get("no_logs")), bool(priv.get("private_tier")), (d.get("webhook") or {}).get("url"), list(d.get("updated") or []), d)
|