pynukez 3.3.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.
pynukez/__init__.py ADDED
@@ -0,0 +1,1328 @@
1
+ """
2
+ Nukez - Agent-native Python SDK for Nukez storage.
3
+
4
+ Autonomous AI storage with cryptographic verification on Solana.
5
+
6
+ This SDK is designed for autonomous AI agents that need persistent storage with
7
+ cryptographic receipts. Every function is tool-shaped and stateless - perfect
8
+ for LLM tool-calling patterns.
9
+
10
+ Quick Start (sync):
11
+ from pynukez import Nukez
12
+
13
+ client = Nukez(keypair_path=KEYPAIR_PATH)
14
+ request = client.request_storage(units=1)
15
+ transfer = client.solana_transfer(request.pay_to_address, request.amount_sol)
16
+ receipt = client.confirm_storage(request.pay_req_id, transfer.signature)
17
+
18
+ Quick Start (async):
19
+ from pynukez import AsyncNukez
20
+
21
+ async with AsyncNukez(keypair_path=KEYPAIR_PATH) as client:
22
+ request = await client.request_storage(units=1)
23
+ transfer = await client.solana_transfer(request.pay_to_address, request.amount_sol)
24
+ receipt = await client.confirm_storage(request.pay_req_id, transfer.signature)
25
+ """
26
+
27
+ # Client classes
28
+ from .client import Nukez
29
+ from ._async_client import AsyncNukez
30
+
31
+ # Signer protocol and implementations
32
+ from .signer import Signer, EVMSigner
33
+
34
+ # Data models and types
35
+ from .types import (
36
+ # Payment flow types
37
+ StorageRequest,
38
+ TransferResult,
39
+ Receipt,
40
+ PaymentOption,
41
+
42
+ # File operation types
43
+ NukezManifest,
44
+ FileUrls,
45
+ FileInfo,
46
+ ViewerLink,
47
+ FileViewerInfo,
48
+ ViewerFileList,
49
+ ViewerContainer,
50
+ UploadResult,
51
+ DeleteResult,
52
+
53
+ # Utility types
54
+ VerificationResult,
55
+ WalletInfo,
56
+ PriceInfo,
57
+ DiscoveryDoc,
58
+
59
+ # Provider awareness
60
+ ProviderInfo,
61
+ PROVIDERS,
62
+
63
+ # Batch and Attest types
64
+ ConfirmResult,
65
+ BatchConfirmResult,
66
+ AttestResult,
67
+ BatchUploadResult,
68
+
69
+ # Operator delegation
70
+ OperatorResult,
71
+ )
72
+
73
+ # Error classes with agent-friendly messages
74
+ from .errors import (
75
+ NukezError, # Base exception
76
+ PaymentRequiredError, # HTTP 402 - contains payment instructions
77
+ TransactionNotFoundError, # Solana tx not yet confirmed (retryable)
78
+ AuthenticationError, # Signature verification failed
79
+ NukezFileNotFoundError, # File doesn't exist
80
+ FileNotFound, # Alias for NukezFileNotFoundError
81
+ URLExpiredError, # Signed URL has expired (retryable)
82
+ NukezNotProvisionedError, # Locker needs provisioning
83
+ InsufficientFundsError, # Wallet balance too low
84
+ RateLimitError, # API rate limit hit
85
+ # Operator delegation errors
86
+ OperatorError, # Base for all operator errors
87
+ InvalidOperatorPubkeyError, # 400 bad pubkey format
88
+ OperatorIsOwnerError, # 400 cannot delegate to self
89
+ OperatorNotAuthorizedError, # 403 signer not in operator list
90
+ OwnerOnlyError, # 403 owner-only action
91
+ OperatorNotFoundError, # 404 removing non-existent operator
92
+ OperatorConflictError, # 409 duplicate or max reached
93
+ )
94
+
95
+ # EVM payment support (optional — requires pip install pynukez[evm])
96
+ try:
97
+ from .evm_payment import EVMPayment, HAS_WEB3
98
+ except ImportError:
99
+ EVMPayment = None
100
+ HAS_WEB3 = False
101
+
102
+ # Authentication utilities
103
+ from .auth import (
104
+ Keypair,
105
+ build_signed_envelope,
106
+ build_unsigned_envelope,
107
+ attach_signature,
108
+ compute_locker_id,
109
+ SignedEnvelope,
110
+ UnsignedEnvelope,
111
+ )
112
+
113
+ # Discovery utilities
114
+ from .discovery import (
115
+ discover,
116
+ health_check,
117
+ get_current_price,
118
+ )
119
+
120
+ __version__ = "3.3.0"
121
+
122
+ __all__ = [
123
+ # Main client
124
+ "Nukez",
125
+
126
+ # Data types - Payment Flow
127
+ "StorageRequest",
128
+ "TransferResult",
129
+ "Receipt",
130
+ "PaymentOption",
131
+ "EVMPayment",
132
+
133
+ # Data types - File Operations
134
+ "SignedEnvelope",
135
+ "NukezManifest",
136
+ "FileUrls",
137
+ "FileInfo",
138
+ "ViewerLink",
139
+ "FileViewerInfo",
140
+ "ViewerFileList",
141
+ "ViewerContainer",
142
+ "UploadResult",
143
+ "DeleteResult",
144
+
145
+ # Data types - Utilities
146
+ "VerificationResult",
147
+ "WalletInfo",
148
+ "PriceInfo",
149
+ "DiscoveryDoc",
150
+
151
+ # Provider awareness
152
+ "ProviderInfo",
153
+ "PROVIDERS",
154
+
155
+ # Error classes
156
+ "NukezError",
157
+ "PaymentRequiredError",
158
+ "TransactionNotFoundError",
159
+ "AuthenticationError",
160
+ "NukezFileNotFoundError",
161
+ "FileNotFound",
162
+ "URLExpiredError",
163
+ "NukezNotProvisionedError",
164
+ "InsufficientFundsError",
165
+ "RateLimitError",
166
+
167
+ # Authentication utilities
168
+ "Keypair",
169
+ "build_signed_envelope",
170
+ "compute_locker_id",
171
+ "SignedEnvelope",
172
+
173
+ # Discovery utilities
174
+ "discover",
175
+ "health_check",
176
+ "get_current_price",
177
+
178
+ # Agent integration functions
179
+ "get_agent_instructions",
180
+ "get_tool_definitions",
181
+ ]
182
+
183
+
184
+ def get_agent_instructions() -> dict:
185
+ """
186
+ Get structured instructions for autonomous agents.
187
+
188
+ An agent that has installed this SDK can call this function
189
+ to understand how to use it without reading external documentation.
190
+
191
+ Returns:
192
+ dict: Structured instructions including quickstart, methods, and examples
193
+
194
+ Example:
195
+ >>> import pynukez
196
+ >>> instructions = pynukez.get_agent_instructions()
197
+ >>> print(instructions['quickstart_flow'])
198
+ """
199
+ return {
200
+ "package": "pynukez",
201
+ "version": __version__,
202
+ "description": "Agent-native storage with cryptographic verification on Solana",
203
+
204
+ "installation": {
205
+ "basic": "pip install pynukez",
206
+ "with_solana": "pip install pynukez[solana]",
207
+ "with_evm": "pip install pynukez[evm]",
208
+ "with_all": "pip install pynukez[all]",
209
+ "development": "pip install pynukez[dev]"
210
+ },
211
+
212
+ "quickstart_flow": [
213
+ "1. client = Nukez(keypair_path='~/.config/solana/id.json')",
214
+ "2. request = client.request_storage(units=1)",
215
+ "3. transfer = client.solana_transfer(request.pay_to_address, request.amount_sol)",
216
+ "4. receipt = client.confirm_storage(request.pay_req_id, transfer.signature)",
217
+ "5. manifest = client.provision_locker(receipt.id)",
218
+ "6. urls = client.create_file(receipt.id, 'data.txt')",
219
+ "7. client.upload_bytes(urls.upload_url, b'Hello!')",
220
+ "8. data = client.download_bytes(urls.download_url)"
221
+ ],
222
+
223
+ "payment_flow": {
224
+ "description": (
225
+ "After request_storage(), check the response to determine the payment chain. "
226
+ "The response includes payment_options listing ALL available chain/asset combinations."
227
+ ),
228
+ "solana": (
229
+ "If request.is_evm is False: call solana_transfer(request.pay_to_address, request.amount_sol)"
230
+ ),
231
+ "evm": (
232
+ "If request.is_evm is True: call evm_transfer(request.pay_to_address, request.amount_raw, "
233
+ "pay_asset=request.pay_asset, token_address=request.token_address, network=request.network)"
234
+ ),
235
+ "confirm": (
236
+ "Then call confirm_storage(request.pay_req_id, transfer.tx_hash). "
237
+ "For EVM payments, also pass payment_chain=request.network, payment_asset=request.pay_asset."
238
+ ),
239
+ },
240
+
241
+ "storage_providers": {
242
+ "note": "Available providers are determined by the gateway configuration. "
243
+ "Default is gcs. Use get_provider_info(provider) for capability details. "
244
+ "The gateway will reject providers that are not enabled.",
245
+ },
246
+
247
+ "important_note": (
248
+ "Most file operations require receipt_id (not locker_id) because "
249
+ "signed envelope authentication uses the receipt. Always track the "
250
+ "receipt_id returned from confirm_storage()."
251
+ ),
252
+ "sandbox_note": (
253
+ "In proxied app sandboxes where file-path uploads are blocked, use "
254
+ "sandbox_create_ingest_job -> sandbox_append_ingest_part -> "
255
+ "sandbox_complete_ingest_job. Reuse existing receipt_id; do not "
256
+ "purchase new storage unless explicitly requested."
257
+ ),
258
+
259
+ "core_operations": {
260
+ "discovery": {
261
+ "discover": "Get API capabilities and endpoints",
262
+ "get_current_price": "Check current storage pricing",
263
+ "health_check": "Verify API availability"
264
+ },
265
+ "payment": {
266
+ "request_storage": "Start x402 payment flow - returns payment instructions with payment_options",
267
+ "solana_transfer": "Execute SOL payment (Solana chain)",
268
+ "evm_transfer": "Execute EVM payment — MON/USDC/USDT/WETH (Monad, Ethereum, etc.)",
269
+ "confirm_storage": "Confirm payment and get receipt (SAVE receipt.id!)",
270
+ "get_provider_info": "Check provider capabilities and limits before selecting",
271
+ },
272
+ "storage": {
273
+ "provision_locker": "Create storage namespace (one-time per receipt)",
274
+ "create_file": "Get upload/download URLs for new file",
275
+ "create_files_batch": "Create multiple file URL pairs in one signed request",
276
+ "upload_bytes": "Upload data to signed URL (raw bytes interface)",
277
+ "upload_string": "Upload data to signed URL (agent-native, auto-sanitizes formatting; small payloads only)",
278
+ "upload_file_path": "Upload one local file by filesystem path (preferred for large files; no content in context)",
279
+ "bulk_upload_paths": "Upload many local files by path with parallelism and batch confirm (preferred for multi-file runs)",
280
+ "upload_directory": "Upload an entire directory (pattern/recursive aware)",
281
+ "start_bulk_upload_job": "Start non-blocking background bulk upload; returns job_id immediately (best for long-running uploads)",
282
+ "get_upload_job": "Poll background upload job state by job_id",
283
+ "sandbox_create_ingest_job": "Create sandbox chunk-ingest job (for app runtimes where file paths are blocked)",
284
+ "sandbox_append_ingest_part": "Append one base64 chunk to sandbox ingest job",
285
+ "sandbox_complete_ingest_job": "Finalize sandbox ingest job and commit files",
286
+ "sandbox_upload_bytes": "Chunked bytes convenience uploader for sandbox runtimes",
287
+ "sandbox_upload_base64": "Decode base64 then chunk-upload through sandbox ingest",
288
+ "sandbox_upload_file_path": "Read local file then upload through sandbox ingest flow",
289
+ "download_bytes": "Download data from signed URL",
290
+ "list_files": "List all files in locker",
291
+ "get_file_urls": "Get fresh URLs for existing file",
292
+ "delete_file": "Remove file from locker"
293
+ },
294
+ "viewer_portal": {
295
+ "get_viewer_container_handoff": "Build generic viewer_container payload (empty container by default)",
296
+ "make_*_renderable": "Build typed renderable objects (text/json/pdf/image/binary) for container payloads",
297
+ "get_locker_view_container": "Build locker view blocks (table + stats + links)",
298
+ "get_attestation_view_container": "Build attestation view blocks (kv + status + proofs + json)",
299
+ "get_file_view_container": "Build file view blocks (file_meta + file_preview)",
300
+ "get_owner_viewer_url": "Build stable portal URL for a locker (agent -> human handoff)",
301
+ "get_file_viewer_url": "Build file-scoped viewer URL (optionally embeds fresh download URL)",
302
+ "list_files_with_viewer_urls": "List files enriched with viewer URLs for human review",
303
+ "viewer_container_contract": "nukez.viewer_container@1.0.0 (container-first handoff)",
304
+ "renderer_contract": "nukez.mcp.viewer_link@1.0 with ui.variant='nukez-neon'"
305
+ },
306
+ "verification": {
307
+ "verify_storage": "Get cryptographic attestation — returns merkle_root, manifest_signature, att_code, per-file hashes",
308
+ "compute_hash": "Calculate SHA256 for local verification"
309
+ },
310
+ "utilities": {
311
+ "compute_locker_id": "Derive locker ID from receipt ID",
312
+ "build_signed_envelope": "Create authentication headers",
313
+ "get_wallet_info": "Get wallet balance and address"
314
+ }
315
+ },
316
+
317
+ "error_handling": {
318
+ "PaymentRequiredError": "Expected from request_storage() - contains payment instructions",
319
+ "TransactionNotFoundError": "Solana tx not visible yet - wait and retry confirm_storage()",
320
+ "AuthenticationError": "Check keypair and that envelope hasn't expired (5 min TTL)",
321
+ "NukezFileNotFoundError": "Use create_file() first or check list_files()",
322
+ "URLExpiredError": "Call get_file_urls() to get fresh URLs (30 min default TTL)"
323
+ },
324
+
325
+ "authentication_modes": [
326
+ "signed_envelope: Ed25519 signatures for API requests (automatic)",
327
+ "All signed operations require keypair_path in Nukez()"
328
+ ],
329
+
330
+ "networks": {
331
+ "solana": ["solana-devnet", "solana-mainnet-beta"],
332
+ "evm": ["monad-testnet", "monad-mainnet"],
333
+ },
334
+
335
+ "requirements": {
336
+ "python": ">=3.9",
337
+ "solana_keypair": "Required for Solana payments and signed requests",
338
+ "evm_private_key": "Required for EVM payments (hex string or raw 32 bytes)",
339
+ "dependencies": {
340
+ "core": ["requests", "pynacl", "base58"],
341
+ "solana_payments": ["solana", "solders"],
342
+ "evm_payments": ["web3", "eth-account"],
343
+ }
344
+ }
345
+ }
346
+
347
+
348
+ def get_tool_definitions() -> list:
349
+ """
350
+ Get OpenAI-compatible tool definitions for LLM function calling.
351
+
352
+ These definitions can be used directly with:
353
+ - OpenAI API (tools parameter)
354
+ - LangChain
355
+ - Any framework supporting OpenAI tool format
356
+
357
+ Returns:
358
+ list: Tool definitions ready for use with OpenAI, LangChain, etc.
359
+
360
+ Example:
361
+ >>> tools = pynukez.get_tool_definitions()
362
+ >>> # Use with OpenAI client
363
+ >>> response = openai.chat.completions.create(
364
+ ... model="gpt-4",
365
+ ... tools=tools,
366
+ ... messages=[...]
367
+ ... )
368
+ """
369
+ return [
370
+ {
371
+ "type": "function",
372
+ "function": {
373
+ "name": "nukez_request_storage",
374
+ "description": "Start x402 payment flow to purchase Nukez storage. Returns payment instructions including pay_req_id, pay_to_address, amount_sol, and payment_options listing all available chain/asset combinations.",
375
+ "parameters": {
376
+ "type": "object",
377
+ "properties": {
378
+ "units": {
379
+ "type": "integer",
380
+ "description": "Number of storage units to purchase",
381
+ "default": 1,
382
+ "minimum": 1
383
+ },
384
+ "provider": {
385
+ "type": "string",
386
+ "default": "gcs",
387
+ "description": "Storage backend (default: gcs). Available providers are "
388
+ "determined by the gateway. Common options: gcs, mongodb."
389
+ },
390
+ "pay_network": {
391
+ "type": "string",
392
+ "description": "Payment chain. Examples: solana-devnet, monad-testnet, monad-mainnet"
393
+ },
394
+ "pay_asset": {
395
+ "type": "string",
396
+ "description": "Token to pay with. SOL (Solana), USDC/USDT/MON/WETH (Monad)"
397
+ }
398
+ },
399
+ "required": []
400
+ }
401
+ }
402
+ },
403
+ {
404
+ "type": "function",
405
+ "function": {
406
+ "name": "nukez_solana_transfer",
407
+ "description": "Execute Solana SOL transfer to pay for storage. Use pay_to_address and amount_sol from request_storage() result.",
408
+ "parameters": {
409
+ "type": "object",
410
+ "properties": {
411
+ "to_address": {
412
+ "type": "string",
413
+ "description": "Destination Solana address (from request_storage().pay_to_address)"
414
+ },
415
+ "amount_sol": {
416
+ "type": "number",
417
+ "description": "Amount in SOL to transfer (from request_storage().amount_sol)"
418
+ }
419
+ },
420
+ "required": ["to_address", "amount_sol"]
421
+ }
422
+ }
423
+ },
424
+ {
425
+ "type": "function",
426
+ "function": {
427
+ "name": "nukez_evm_transfer",
428
+ "description": "Execute EVM token transfer for storage payment (Monad, Ethereum, etc.). Use when request_storage() returns an EVM network (is_evm=True). Requires pynukez[evm].",
429
+ "parameters": {
430
+ "type": "object",
431
+ "properties": {
432
+ "to_address": {
433
+ "type": "string",
434
+ "description": "Destination 0x address (from request_storage().pay_to_address)"
435
+ },
436
+ "amount_raw": {
437
+ "type": "integer",
438
+ "description": "Atomic units (from request_storage().amount_raw)"
439
+ },
440
+ "pay_asset": {
441
+ "type": "string",
442
+ "description": "Token symbol (from request_storage().pay_asset). e.g. MON, USDC, USDT, WETH"
443
+ },
444
+ "token_address": {
445
+ "type": "string",
446
+ "description": "ERC-20 contract address (from request_storage().token_address). Omit for native tokens."
447
+ },
448
+ "network": {
449
+ "type": "string",
450
+ "description": "EVM network (from request_storage().network). e.g. monad-testnet, monad-mainnet"
451
+ }
452
+ },
453
+ "required": ["to_address", "amount_raw"]
454
+ }
455
+ }
456
+ },
457
+ {
458
+ "type": "function",
459
+ "function": {
460
+ "name": "nukez_get_provider_info",
461
+ "description": "Get capabilities and limits for a storage provider. Use before selecting a provider for request_storage().",
462
+ "parameters": {
463
+ "type": "object",
464
+ "properties": {
465
+ "provider": {
466
+ "type": "string",
467
+ "description": "Provider ID to look up (e.g. gcs, mongodb). "
468
+ "See PROVIDERS dict for known provider capabilities."
469
+ }
470
+ },
471
+ "required": ["provider"]
472
+ }
473
+ }
474
+ },
475
+ {
476
+ "type": "function",
477
+ "function": {
478
+ "name": "nukez_confirm_storage",
479
+ "description": "Confirm payment and receive storage receipt. CRITICAL: The response contains receipt_id (aliased as 'id') — save it. Every subsequent operation (provision_locker, create_file, list_files, verify_storage) requires this receipt_id.",
480
+ "parameters": {
481
+ "type": "object",
482
+ "properties": {
483
+ "pay_req_id": {
484
+ "type": "string",
485
+ "description": "Payment request ID from request_storage()"
486
+ },
487
+ "tx_sig": {
488
+ "type": "string",
489
+ "description": "Transaction signature from solana_transfer()"
490
+ }
491
+ },
492
+ "required": ["pay_req_id", "tx_sig"]
493
+ }
494
+ }
495
+ },
496
+ {
497
+ "type": "function",
498
+ "function": {
499
+ "name": "nukez_provision_locker",
500
+ "description": "Create storage locker namespace. Call once per receipt before creating files.",
501
+ "parameters": {
502
+ "type": "object",
503
+ "properties": {
504
+ "receipt_id": {
505
+ "type": "string",
506
+ "description": "Receipt ID from confirm_storage()"
507
+ },
508
+ "tags": {
509
+ "type": "array",
510
+ "items": {"type": "string"},
511
+ "description": "Optional tags for the locker",
512
+ "default": []
513
+ }
514
+ },
515
+ "required": ["receipt_id"]
516
+ }
517
+ }
518
+ },
519
+ {
520
+ "type": "function",
521
+ "function": {
522
+ "name": "nukez_create_file",
523
+ "description": "Create file entry and get signed upload/download URLs. Requires receipt_id, not locker_id.",
524
+ "parameters": {
525
+ "type": "object",
526
+ "properties": {
527
+ "receipt_id": {
528
+ "type": "string",
529
+ "description": "Receipt ID from confirm_storage()"
530
+ },
531
+ "filename": {
532
+ "type": "string",
533
+ "description": "File name (auto-generated if not provided)"
534
+ },
535
+ "content_type": {
536
+ "type": "string",
537
+ "description": "MIME type",
538
+ "default": "application/octet-stream"
539
+ },
540
+ "ttl_min": {
541
+ "type": "integer",
542
+ "description": "URL expiration time in minutes",
543
+ "default": 30
544
+ }
545
+ },
546
+ "required": ["receipt_id"]
547
+ }
548
+ }
549
+ },
550
+ {
551
+ "type": "function",
552
+ "function": {
553
+ "name": "nukez_upload_bytes",
554
+ "description": "PUT raw bytes to the signed upload URL returned by create_file(). This executes an HTTP PUT directly to the signed URL — no additional auth headers needed. The SDK sanitizes the data parameter automatically (unwraps accidental JSON wrappers, strips markdown fencing).",
555
+ "parameters": {
556
+ "type": "object",
557
+ "properties": {
558
+ "upload_url": {
559
+ "type": "string",
560
+ "description": "The upload_url returned by create_file() — pass exactly as received"
561
+ },
562
+ "data": {
563
+ "type": "string",
564
+ "description": "The exact content to store as a plain string (e.g. 'Hello world'). This string becomes the raw HTTP PUT body. Do NOT wrap in JSON — pass the content directly."
565
+ },
566
+ "content_type": {
567
+ "type": "string",
568
+ "description": "Must match the content_type used in create_file() if one was specified"
569
+ }
570
+ },
571
+ "required": ["upload_url", "data"]
572
+ }
573
+ }
574
+ },
575
+ {
576
+ "type": "function",
577
+ "function": {
578
+ "name": "nukez_upload_file_path",
579
+ "description": "Upload one local file by filesystem path. The SDK reads file bytes directly from disk (no data-in-context), creates URLs, uploads, and optionally confirms.",
580
+ "parameters": {
581
+ "type": "object",
582
+ "properties": {
583
+ "receipt_id": {
584
+ "type": "string",
585
+ "description": "Receipt ID from confirm_storage()"
586
+ },
587
+ "filepath": {
588
+ "type": "string",
589
+ "description": "Absolute or relative filesystem path to a local file"
590
+ },
591
+ "filename": {
592
+ "type": "string",
593
+ "description": "Optional remote filename override (defaults to basename)"
594
+ },
595
+ "content_type": {
596
+ "type": "string",
597
+ "description": "Optional MIME type override"
598
+ },
599
+ "ttl_min": {
600
+ "type": "integer",
601
+ "description": "Signed URL lifetime in minutes",
602
+ "default": 30
603
+ },
604
+ "confirm": {
605
+ "type": "boolean",
606
+ "description": "If true, call server-side confirm after upload",
607
+ "default": True
608
+ }
609
+ },
610
+ "required": ["receipt_id", "filepath"]
611
+ }
612
+ }
613
+ },
614
+ {
615
+ "type": "function",
616
+ "function": {
617
+ "name": "nukez_bulk_upload_paths",
618
+ "description": "Upload multiple local files by path with batch URL creation, parallel uploads, optional batch confirm, and optional attestation.",
619
+ "parameters": {
620
+ "type": "object",
621
+ "properties": {
622
+ "receipt_id": {
623
+ "type": "string",
624
+ "description": "Receipt ID from confirm_storage()"
625
+ },
626
+ "sources": {
627
+ "type": "array",
628
+ "description": "List of file sources. Each item can be a string filepath or an object with filepath, filename, content_type.",
629
+ "items": {
630
+ "anyOf": [
631
+ {"type": "string"},
632
+ {"type": "object"}
633
+ ]
634
+ }
635
+ },
636
+ "workers": {
637
+ "type": "integer",
638
+ "description": "Concurrent upload workers",
639
+ "default": 6
640
+ },
641
+ "ttl_min": {
642
+ "type": "integer",
643
+ "description": "Signed URL lifetime in minutes",
644
+ "default": 30
645
+ },
646
+ "confirm": {
647
+ "type": "boolean",
648
+ "description": "If true, batch confirm uploaded files",
649
+ "default": True
650
+ },
651
+ "auto_attest": {
652
+ "type": "boolean",
653
+ "description": "If true, trigger attestation after upload batch",
654
+ "default": False
655
+ },
656
+ "attest_sync": {
657
+ "type": "boolean",
658
+ "description": "If auto_attest=true, wait for attest completion when true",
659
+ "default": False
660
+ }
661
+ },
662
+ "required": ["receipt_id", "sources"]
663
+ }
664
+ }
665
+ },
666
+ {
667
+ "type": "function",
668
+ "function": {
669
+ "name": "nukez_upload_directory",
670
+ "description": "Upload matching files from a directory with optional recursion/pattern filtering.",
671
+ "parameters": {
672
+ "type": "object",
673
+ "properties": {
674
+ "receipt_id": {
675
+ "type": "string",
676
+ "description": "Receipt ID from confirm_storage()"
677
+ },
678
+ "source_dir": {
679
+ "type": "string",
680
+ "description": "Directory path to scan for files"
681
+ },
682
+ "pattern": {
683
+ "type": "string",
684
+ "description": "Glob pattern (e.g. *.png, *.md)",
685
+ "default": "*"
686
+ },
687
+ "recursive": {
688
+ "type": "boolean",
689
+ "description": "If true, recurse into subdirectories",
690
+ "default": False
691
+ },
692
+ "exclude_pattern": {
693
+ "type": "string",
694
+ "description": "Optional glob exclusion pattern"
695
+ },
696
+ "preserve_structure": {
697
+ "type": "boolean",
698
+ "description": "If true, keep relative subpaths in remote filenames",
699
+ "default": False
700
+ },
701
+ "workers": {
702
+ "type": "integer",
703
+ "description": "Concurrent upload workers",
704
+ "default": 6
705
+ },
706
+ "confirm": {
707
+ "type": "boolean",
708
+ "description": "If true, batch confirm uploaded files",
709
+ "default": True
710
+ },
711
+ "auto_attest": {
712
+ "type": "boolean",
713
+ "description": "If true, trigger attestation after upload batch",
714
+ "default": False
715
+ }
716
+ },
717
+ "required": ["receipt_id", "source_dir"]
718
+ }
719
+ }
720
+ },
721
+ {
722
+ "type": "function",
723
+ "function": {
724
+ "name": "nukez_start_bulk_upload_job",
725
+ "description": "Start a non-blocking background bulk upload job. Returns immediately with job_id.",
726
+ "parameters": {
727
+ "type": "object",
728
+ "properties": {
729
+ "receipt_id": {
730
+ "type": "string",
731
+ "description": "Receipt ID from confirm_storage()"
732
+ },
733
+ "sources": {
734
+ "type": "array",
735
+ "description": "List of file sources (filepath strings or source objects).",
736
+ "items": {
737
+ "anyOf": [
738
+ {"type": "string"},
739
+ {"type": "object"}
740
+ ]
741
+ }
742
+ },
743
+ "workers": {
744
+ "type": "integer",
745
+ "description": "Concurrent upload workers",
746
+ "default": 6
747
+ },
748
+ "confirm": {
749
+ "type": "boolean",
750
+ "description": "If true, batch confirm uploaded files",
751
+ "default": True
752
+ },
753
+ "auto_attest": {
754
+ "type": "boolean",
755
+ "description": "If true, trigger attestation when uploads finish",
756
+ "default": False
757
+ }
758
+ },
759
+ "required": ["receipt_id", "sources"]
760
+ }
761
+ }
762
+ },
763
+ {
764
+ "type": "function",
765
+ "function": {
766
+ "name": "nukez_get_upload_job",
767
+ "description": "Get status/result for a previously started background upload job.",
768
+ "parameters": {
769
+ "type": "object",
770
+ "properties": {
771
+ "job_id": {
772
+ "type": "string",
773
+ "description": "Job identifier returned by nukez_start_bulk_upload_job"
774
+ }
775
+ },
776
+ "required": ["job_id"]
777
+ }
778
+ }
779
+ },
780
+ {
781
+ "type": "function",
782
+ "function": {
783
+ "name": "nukez_download_bytes",
784
+ "description": "GET data from the signed download URL returned by create_file() or get_file_urls(). If the URL has expired or fails, call list_files() or get_file_urls() for fresh URLs.",
785
+ "parameters": {
786
+ "type": "object",
787
+ "properties": {
788
+ "download_url": {
789
+ "type": "string",
790
+ "description": "The download_url returned by create_file() or get_file_urls() — pass exactly as received"
791
+ }
792
+ },
793
+ "required": ["download_url"]
794
+ }
795
+ }
796
+ },
797
+ {
798
+ "type": "function",
799
+ "function": {
800
+ "name": "nukez_list_files",
801
+ "description": "List all files in a locker",
802
+ "parameters": {
803
+ "type": "object",
804
+ "properties": {
805
+ "receipt_id": {
806
+ "type": "string",
807
+ "description": "Receipt ID from confirm_storage()"
808
+ }
809
+ },
810
+ "required": ["receipt_id"]
811
+ }
812
+ }
813
+ },
814
+ {
815
+ "type": "function",
816
+ "function": {
817
+ "name": "nukez_get_file_urls",
818
+ "description": "Get fresh upload/download URLs for an existing file (use if URLs expired)",
819
+ "parameters": {
820
+ "type": "object",
821
+ "properties": {
822
+ "receipt_id": {
823
+ "type": "string",
824
+ "description": "Receipt ID from confirm_storage()"
825
+ },
826
+ "filename": {
827
+ "type": "string",
828
+ "description": "Name of existing file"
829
+ },
830
+ "ttl_min": {
831
+ "type": "integer",
832
+ "description": "URL expiration time in minutes",
833
+ "default": 30
834
+ }
835
+ },
836
+ "required": ["receipt_id", "filename"]
837
+ }
838
+ }
839
+ },
840
+ {
841
+ "type": "function",
842
+ "function": {
843
+ "name": "nukez_get_viewer_container_contract",
844
+ "description": "Return the stable viewer-container contract descriptor used by generic container payloads.",
845
+ "parameters": {
846
+ "type": "object",
847
+ "properties": {},
848
+ "required": []
849
+ }
850
+ }
851
+ },
852
+ {
853
+ "type": "function",
854
+ "function": {
855
+ "name": "nukez_get_viewer_container",
856
+ "description": "Build a generic viewer_container payload for agent -> human handoff. This is container-first and render-agnostic.",
857
+ "parameters": {
858
+ "type": "object",
859
+ "properties": {
860
+ "viewer_base_url": {
861
+ "type": "string",
862
+ "description": "Viewer frontend origin",
863
+ "default": "https://nukez.xyz"
864
+ },
865
+ "request_type": {
866
+ "type": "string",
867
+ "description": "Container request mode",
868
+ "default": "container"
869
+ },
870
+ "view_kind": {
871
+ "type": "string",
872
+ "description": "High-level viewer mode: locker | attestation | file | custom",
873
+ "default": "custom"
874
+ },
875
+ "receipt_id": {
876
+ "type": "string",
877
+ "description": "Optional receipt ID if the container is locker-scoped"
878
+ },
879
+ "locker_id": {
880
+ "type": "string",
881
+ "description": "Optional locker ID override"
882
+ },
883
+ "filename": {
884
+ "type": "string",
885
+ "description": "Optional filename if this container is file-focused"
886
+ },
887
+ "renderables": {
888
+ "type": "array",
889
+ "description": "Optional renderable objects (text/json/pdf/image/binary) for in-container rendering",
890
+ "items": {
891
+ "type": "object"
892
+ }
893
+ },
894
+ "blocks": {
895
+ "type": "array",
896
+ "description": "Optional view blocks for structured container rendering (header/stats/links/table/kv/status/proofs/json/file_meta/file_preview)",
897
+ "items": {
898
+ "type": "object"
899
+ }
900
+ },
901
+ "embed_payload_in_url": {
902
+ "type": "boolean",
903
+ "description": "If true, embed container payload into viewer URL query for immediate rendering",
904
+ "default": True
905
+ },
906
+ "button_label": {
907
+ "type": "string",
908
+ "description": "Optional button label for UI renderers",
909
+ "default": "Open Nukez Viewer"
910
+ }
911
+ },
912
+ "required": []
913
+ }
914
+ }
915
+ },
916
+ {
917
+ "type": "function",
918
+ "function": {
919
+ "name": "nukez_get_locker_view",
920
+ "description": "Build a locker-focused viewer payload: table + stats + links.",
921
+ "parameters": {
922
+ "type": "object",
923
+ "properties": {
924
+ "receipt_id": {
925
+ "type": "string",
926
+ "description": "Receipt ID from confirm_storage()"
927
+ },
928
+ "viewer_base_url": {
929
+ "type": "string",
930
+ "description": "Viewer frontend origin",
931
+ "default": "https://nukez.xyz"
932
+ },
933
+ "include_download_urls": {
934
+ "type": "boolean",
935
+ "description": "If true, include per-file download links in table rows",
936
+ "default": False
937
+ },
938
+ "ttl_min": {
939
+ "type": "integer",
940
+ "description": "Download URL TTL when include_download_urls=true",
941
+ "default": 30
942
+ },
943
+ "embed_payload_in_url": {
944
+ "type": "boolean",
945
+ "description": "If true, embed block payload in viewer URL query",
946
+ "default": True
947
+ },
948
+ "button_label": {
949
+ "type": "string",
950
+ "description": "Optional button label for UI renderers",
951
+ "default": "Open Locker Viewer"
952
+ }
953
+ },
954
+ "required": ["receipt_id"]
955
+ }
956
+ }
957
+ },
958
+ {
959
+ "type": "function",
960
+ "function": {
961
+ "name": "nukez_get_attestation_view",
962
+ "description": "Build an attestation-focused viewer payload: kv + status + proofs + json.",
963
+ "parameters": {
964
+ "type": "object",
965
+ "properties": {
966
+ "receipt_id": {
967
+ "type": "string",
968
+ "description": "Receipt ID from confirm_storage()"
969
+ },
970
+ "viewer_base_url": {
971
+ "type": "string",
972
+ "description": "Viewer frontend origin",
973
+ "default": "https://nukez.xyz"
974
+ },
975
+ "embed_payload_in_url": {
976
+ "type": "boolean",
977
+ "description": "If true, embed block payload in viewer URL query",
978
+ "default": True
979
+ },
980
+ "button_label": {
981
+ "type": "string",
982
+ "description": "Optional button label for UI renderers",
983
+ "default": "Open Attestation Viewer"
984
+ }
985
+ },
986
+ "required": ["receipt_id"]
987
+ }
988
+ }
989
+ },
990
+ {
991
+ "type": "function",
992
+ "function": {
993
+ "name": "nukez_get_file_view",
994
+ "description": "Build a file-focused viewer payload: file_meta + file_preview (mime handling hidden in viewer).",
995
+ "parameters": {
996
+ "type": "object",
997
+ "properties": {
998
+ "receipt_id": {
999
+ "type": "string",
1000
+ "description": "Receipt ID from confirm_storage()"
1001
+ },
1002
+ "filename": {
1003
+ "type": "string",
1004
+ "description": "Target file name"
1005
+ },
1006
+ "viewer_base_url": {
1007
+ "type": "string",
1008
+ "description": "Viewer frontend origin",
1009
+ "default": "https://nukez.xyz"
1010
+ },
1011
+ "ttl_min": {
1012
+ "type": "integer",
1013
+ "description": "Download URL TTL in minutes",
1014
+ "default": 30
1015
+ },
1016
+ "include_download_url": {
1017
+ "type": "boolean",
1018
+ "description": "If true, include a signed download URL for preview fetching",
1019
+ "default": True
1020
+ },
1021
+ "embed_payload_in_url": {
1022
+ "type": "boolean",
1023
+ "description": "If true, embed block payload in viewer URL query",
1024
+ "default": True
1025
+ },
1026
+ "button_label": {
1027
+ "type": "string",
1028
+ "description": "Optional button label for UI renderers",
1029
+ "default": "Open File Viewer"
1030
+ }
1031
+ },
1032
+ "required": ["receipt_id", "filename"]
1033
+ }
1034
+ }
1035
+ },
1036
+ {
1037
+ "type": "function",
1038
+ "function": {
1039
+ "name": "nukez_get_viewer_renderer_contract",
1040
+ "description": "Return the stable renderer contract descriptor for viewer-link UI payloads.",
1041
+ "parameters": {
1042
+ "type": "object",
1043
+ "properties": {},
1044
+ "required": []
1045
+ }
1046
+ }
1047
+ },
1048
+ {
1049
+ "type": "function",
1050
+ "function": {
1051
+ "name": "nukez_get_owner_viewer_url",
1052
+ "description": "Build stable owner portal URL for human-in-the-loop review of a locker. Returns ui button metadata for Nukez-themed rendering.",
1053
+ "parameters": {
1054
+ "type": "object",
1055
+ "properties": {
1056
+ "receipt_id": {
1057
+ "type": "string",
1058
+ "description": "Receipt ID from confirm_storage()"
1059
+ },
1060
+ "viewer_base_url": {
1061
+ "type": "string",
1062
+ "description": "Viewer frontend origin",
1063
+ "default": "https://nukez.xyz"
1064
+ },
1065
+ "button_label": {
1066
+ "type": "string",
1067
+ "description": "Optional button label for UI renderers",
1068
+ "default": "Open Nukez Viewer"
1069
+ }
1070
+ },
1071
+ "required": ["receipt_id"]
1072
+ }
1073
+ }
1074
+ },
1075
+ {
1076
+ "type": "function",
1077
+ "function": {
1078
+ "name": "nukez_get_file_viewer_url",
1079
+ "description": "Build file-scoped viewer URL for a specific file. Optionally mints and embeds a fresh download_url for immediate viewing. Returns ui button metadata for Nukez-themed rendering.",
1080
+ "parameters": {
1081
+ "type": "object",
1082
+ "properties": {
1083
+ "receipt_id": {
1084
+ "type": "string",
1085
+ "description": "Receipt ID from confirm_storage()"
1086
+ },
1087
+ "filename": {
1088
+ "type": "string",
1089
+ "description": "Target file name"
1090
+ },
1091
+ "viewer_base_url": {
1092
+ "type": "string",
1093
+ "description": "Viewer frontend origin",
1094
+ "default": "https://nukez.xyz"
1095
+ },
1096
+ "ttl_min": {
1097
+ "type": "integer",
1098
+ "description": "Download URL TTL in minutes if include_download_url=true",
1099
+ "default": 30
1100
+ },
1101
+ "include_download_url": {
1102
+ "type": "boolean",
1103
+ "description": "If true, include a fresh signed download_url in the returned viewer link",
1104
+ "default": True
1105
+ },
1106
+ "button_label": {
1107
+ "type": "string",
1108
+ "description": "Optional button label for UI renderers",
1109
+ "default": "Open File Viewer"
1110
+ }
1111
+ },
1112
+ "required": ["receipt_id", "filename"]
1113
+ }
1114
+ }
1115
+ },
1116
+ {
1117
+ "type": "function",
1118
+ "function": {
1119
+ "name": "nukez_list_files_with_viewer_urls",
1120
+ "description": "List files and return portal viewer links per file plus owner portal URL. Includes ui button metadata for Nukez-themed rendering.",
1121
+ "parameters": {
1122
+ "type": "object",
1123
+ "properties": {
1124
+ "receipt_id": {
1125
+ "type": "string",
1126
+ "description": "Receipt ID from confirm_storage()"
1127
+ },
1128
+ "viewer_base_url": {
1129
+ "type": "string",
1130
+ "description": "Viewer frontend origin",
1131
+ "default": "https://nukez.xyz"
1132
+ },
1133
+ "include_download_urls": {
1134
+ "type": "boolean",
1135
+ "description": "If true, mint and embed download URLs per file (more expensive, expires)",
1136
+ "default": False
1137
+ },
1138
+ "ttl_min": {
1139
+ "type": "integer",
1140
+ "description": "Download URL TTL in minutes when include_download_urls=true",
1141
+ "default": 30
1142
+ }
1143
+ },
1144
+ "required": ["receipt_id"]
1145
+ }
1146
+ }
1147
+ },
1148
+ {
1149
+ "type": "function",
1150
+ "function": {
1151
+ "name": "nukez_delete_file",
1152
+ "description": "Delete a file from locker (permanent, cannot be undone)",
1153
+ "parameters": {
1154
+ "type": "object",
1155
+ "properties": {
1156
+ "receipt_id": {
1157
+ "type": "string",
1158
+ "description": "Receipt ID from confirm_storage()"
1159
+ },
1160
+ "filename": {
1161
+ "type": "string",
1162
+ "description": "Name of file to delete"
1163
+ }
1164
+ },
1165
+ "required": ["receipt_id", "filename"]
1166
+ }
1167
+ }
1168
+ },
1169
+ {
1170
+ "type": "function",
1171
+ "function": {
1172
+ "name": "nukez_verify_storage",
1173
+ "description": "Verify storage integrity and get cryptographic attestation. Returns merkle_root (hash of all files), manifest_signature (gateway's Ed25519 signature), att_code (on-chain attestation badge), file_count, and per-file content hashes. Call after uploading data to confirm integrity.",
1174
+ "parameters": {
1175
+ "type": "object",
1176
+ "properties": {
1177
+ "receipt_id": {
1178
+ "type": "string",
1179
+ "description": "Receipt ID from confirm_storage()"
1180
+ }
1181
+ },
1182
+ "required": ["receipt_id"]
1183
+ }
1184
+ }
1185
+ },
1186
+ # ── Attestation & Proof tools ────────────────────────────────
1187
+ {
1188
+ "type": "function",
1189
+ "function": {
1190
+ "name": "nukez_confirm_file",
1191
+ "description": "Confirm a file's content hash with the server. The server computes the SHA-256 hash of the uploaded file and stores it. This is step 1 of the attestation trust chain: confirm_file → attest → verify_storage → get_merkle_proof.",
1192
+ "parameters": {
1193
+ "type": "object",
1194
+ "properties": {
1195
+ "receipt_id": {
1196
+ "type": "string",
1197
+ "description": "Receipt ID from confirm_storage()"
1198
+ },
1199
+ "filename": {
1200
+ "type": "string",
1201
+ "description": "Name of the file to confirm"
1202
+ }
1203
+ },
1204
+ "required": ["receipt_id", "filename"]
1205
+ }
1206
+ }
1207
+ },
1208
+ {
1209
+ "type": "function",
1210
+ "function": {
1211
+ "name": "nukez_confirm_files",
1212
+ "description": "Confirm content hashes for multiple files in one call. Batch version of confirm_file.",
1213
+ "parameters": {
1214
+ "type": "object",
1215
+ "properties": {
1216
+ "receipt_id": {
1217
+ "type": "string",
1218
+ "description": "Receipt ID from confirm_storage()"
1219
+ },
1220
+ "filenames": {
1221
+ "type": "array",
1222
+ "items": {"type": "string"},
1223
+ "description": "List of filenames to confirm"
1224
+ }
1225
+ },
1226
+ "required": ["receipt_id", "filenames"]
1227
+ }
1228
+ }
1229
+ },
1230
+ {
1231
+ "type": "function",
1232
+ "function": {
1233
+ "name": "nukez_attest",
1234
+ "description": "Build a Merkle tree from confirmed file hashes and optionally push the root on-chain. This is step 2 of the attestation trust chain. Must call confirm_file for each file first. Returns tx_signature (on-chain attestation tx) and push_ok status.",
1235
+ "parameters": {
1236
+ "type": "object",
1237
+ "properties": {
1238
+ "receipt_id": {
1239
+ "type": "string",
1240
+ "description": "Receipt ID from confirm_storage()"
1241
+ },
1242
+ "sync": {
1243
+ "type": "boolean",
1244
+ "description": "If true (default), wait for attestation to complete. If false, return 202 and poll verify_storage for result.",
1245
+ "default": True
1246
+ }
1247
+ },
1248
+ "required": ["receipt_id"]
1249
+ }
1250
+ }
1251
+ },
1252
+ {
1253
+ "type": "function",
1254
+ "function": {
1255
+ "name": "nukez_get_merkle_proof",
1256
+ "description": "Get a per-file Merkle inclusion proof. Returns leaf_hash, proof path (sibling hashes), and merkle_root. This is step 4 of the trust chain: confirm_file → attest → verify_storage → get_merkle_proof. Must call attest first.",
1257
+ "parameters": {
1258
+ "type": "object",
1259
+ "properties": {
1260
+ "receipt_id": {
1261
+ "type": "string",
1262
+ "description": "Receipt ID from confirm_storage()"
1263
+ },
1264
+ "filename": {
1265
+ "type": "string",
1266
+ "description": "Name of the file to get proof for"
1267
+ }
1268
+ },
1269
+ "required": ["receipt_id", "filename"]
1270
+ }
1271
+ }
1272
+ },
1273
+ {
1274
+ "type": "function",
1275
+ "function": {
1276
+ "name": "nukez_get_wallet_info",
1277
+ "description": "Get wallet information for the current keypair. Returns pubkey, balance in SOL, and network.",
1278
+ "parameters": {
1279
+ "type": "object",
1280
+ "properties": {},
1281
+ "required": []
1282
+ }
1283
+ }
1284
+ },
1285
+ # ── Operator delegation tools ─────────────────────────────────
1286
+ {
1287
+ "type": "function",
1288
+ "function": {
1289
+ "name": "nukez_add_operator",
1290
+ "description": "Authorize an Ed25519 operator to perform file operations on this locker. Owner-only. Max 5 operators. The operator_pubkey must differ from your own wallet pubkey. Returns ok and updated operator_ids list.",
1291
+ "parameters": {
1292
+ "type": "object",
1293
+ "properties": {
1294
+ "receipt_id": {
1295
+ "type": "string",
1296
+ "description": "Receipt ID from confirm_storage()"
1297
+ },
1298
+ "operator_pubkey": {
1299
+ "type": "string",
1300
+ "description": "Base58-encoded Ed25519 public key to authorize (32-44 chars, must differ from your own wallet pubkey)"
1301
+ }
1302
+ },
1303
+ "required": ["receipt_id", "operator_pubkey"]
1304
+ }
1305
+ }
1306
+ },
1307
+ {
1308
+ "type": "function",
1309
+ "function": {
1310
+ "name": "nukez_remove_operator",
1311
+ "description": "Revoke an operator's access to this locker. Owner-only. Returns ok and updated operator_ids list.",
1312
+ "parameters": {
1313
+ "type": "object",
1314
+ "properties": {
1315
+ "receipt_id": {
1316
+ "type": "string",
1317
+ "description": "Receipt ID from confirm_storage()"
1318
+ },
1319
+ "operator_pubkey": {
1320
+ "type": "string",
1321
+ "description": "Base58-encoded Ed25519 public key to remove"
1322
+ }
1323
+ },
1324
+ "required": ["receipt_id", "operator_pubkey"]
1325
+ }
1326
+ }
1327
+ },
1328
+ ]