agirails 2.2.0__tar.gz → 2.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. {agirails-2.2.0 → agirails-2.3.1}/.gitignore +1 -0
  2. agirails-2.3.1/PKG-INFO +226 -0
  3. agirails-2.3.1/README.md +170 -0
  4. {agirails-2.2.0 → agirails-2.3.1}/pyproject.toml +1 -1
  5. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/adapters/__init__.py +41 -0
  6. agirails-2.3.1/src/agirails/adapters/adapter_registry.py +150 -0
  7. agirails-2.3.1/src/agirails/adapters/adapter_router.py +428 -0
  8. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/adapters/basic.py +35 -3
  9. agirails-2.3.1/src/agirails/adapters/i_adapter.py +106 -0
  10. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/adapters/standard.py +63 -1
  11. agirails-2.3.1/src/agirails/adapters/types.py +146 -0
  12. agirails-2.3.1/src/agirails/adapters/x402_adapter.py +788 -0
  13. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/__init__.py +6 -0
  14. agirails-2.3.1/src/agirails/cli/commands/deploy_check.py +354 -0
  15. agirails-2.3.1/src/agirails/cli/commands/deploy_env.py +129 -0
  16. agirails-2.3.1/src/agirails/cli/commands/diff.py +213 -0
  17. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/pay.py +34 -19
  18. agirails-2.3.1/src/agirails/cli/commands/publish.py +187 -0
  19. agirails-2.3.1/src/agirails/cli/commands/pull.py +202 -0
  20. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/main.py +23 -0
  21. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/client.py +92 -1
  22. agirails-2.3.1/src/agirails/config/__init__.py +106 -0
  23. agirails-2.3.1/src/agirails/config/agirailsmd.py +351 -0
  24. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/config/networks.py +9 -12
  25. agirails-2.3.1/src/agirails/config/pending_publish.py +345 -0
  26. agirails-2.3.1/src/agirails/config/publish_pipeline.py +374 -0
  27. agirails-2.3.1/src/agirails/config/sync_operations.py +319 -0
  28. agirails-2.3.1/src/agirails/erc8004/__init__.py +23 -0
  29. agirails-2.3.1/src/agirails/erc8004/bridge.py +311 -0
  30. agirails-2.3.1/src/agirails/erc8004/reputation_reporter.py +275 -0
  31. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/__init__.py +2 -0
  32. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/network.py +33 -0
  33. agirails-2.3.1/src/agirails/protocol/base.py +171 -0
  34. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/escrow.py +14 -111
  35. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/kernel.py +11 -107
  36. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/nonce.py +16 -7
  37. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/blockchain_runtime.py +50 -13
  38. agirails-2.3.1/src/agirails/types/erc8004.py +287 -0
  39. agirails-2.3.1/src/agirails/types/x402.py +200 -0
  40. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/__init__.py +0 -5
  41. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/circuit_breaker.py +10 -4
  42. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/security.py +3 -1
  43. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/semaphore.py +14 -5
  44. agirails-2.3.1/src/agirails/version.py +4 -0
  45. agirails-2.3.1/src/agirails/wallet/__init__.py +50 -0
  46. agirails-2.3.1/src/agirails/wallet/aa/__init__.py +90 -0
  47. agirails-2.3.1/src/agirails/wallet/aa/bundler_client.py +303 -0
  48. agirails-2.3.1/src/agirails/wallet/aa/constants.py +67 -0
  49. agirails-2.3.1/src/agirails/wallet/aa/dual_nonce_manager.py +202 -0
  50. agirails-2.3.1/src/agirails/wallet/aa/paymaster_client.py +194 -0
  51. agirails-2.3.1/src/agirails/wallet/aa/transaction_batcher.py +447 -0
  52. agirails-2.3.1/src/agirails/wallet/aa/user_op_builder.py +339 -0
  53. agirails-2.3.1/src/agirails/wallet/auto_wallet_provider.py +452 -0
  54. agirails-2.3.1/src/agirails/wallet/eoa_wallet_provider.py +125 -0
  55. agirails-2.3.1/src/agirails/wallet/keystore.py +372 -0
  56. {agirails-2.2.0 → agirails-2.3.1}/tests/benchmarks/test_performance.py +44 -34
  57. agirails-2.3.1/tests/test_adapters/test_adapter_router.py +570 -0
  58. agirails-2.3.1/tests/test_adapters/test_x402_adapter.py +785 -0
  59. agirails-2.3.1/tests/test_cli/test_publish.py +501 -0
  60. agirails-2.3.1/tests/test_cli_deploy/__init__.py +1 -0
  61. agirails-2.3.1/tests/test_cli_deploy/test_deploy.py +336 -0
  62. agirails-2.3.1/tests/test_config/test_agirailsmd.py +561 -0
  63. agirails-2.3.1/tests/test_config/test_pending_publish.py +363 -0
  64. agirails-2.3.1/tests/test_erc8004/__init__.py +1 -0
  65. agirails-2.3.1/tests/test_erc8004/test_bridge.py +372 -0
  66. agirails-2.3.1/tests/test_erc8004/test_reputation_reporter.py +295 -0
  67. agirails-2.3.1/tests/test_errors/test_transient_rpc.py +35 -0
  68. agirails-2.3.1/tests/test_protocol/test_contract_base.py +223 -0
  69. {agirails-2.2.0 → agirails-2.3.1}/tests/test_protocol/test_networks.py +14 -15
  70. agirails-2.3.1/tests/test_runtime/__init__.py +0 -0
  71. agirails-2.3.1/tests/test_utils/__init__.py +0 -0
  72. agirails-2.3.1/tests/test_wallet/__init__.py +1 -0
  73. agirails-2.3.1/tests/test_wallet/test_auto_wallet_provider.py +312 -0
  74. agirails-2.3.1/tests/test_wallet/test_bundler_client.py +304 -0
  75. agirails-2.3.1/tests/test_wallet/test_dual_nonce_manager.py +233 -0
  76. agirails-2.3.1/tests/test_wallet/test_keystore.py +555 -0
  77. agirails-2.3.1/tests/test_wallet/test_transaction_batcher.py +370 -0
  78. agirails-2.3.1/tests/test_wallet/test_user_op_builder.py +389 -0
  79. agirails-2.2.0/PKG-INFO +0 -675
  80. agirails-2.2.0/README.md +0 -619
  81. agirails-2.2.0/src/agirails/config/__init__.py +0 -27
  82. agirails-2.2.0/src/agirails/version.py +0 -4
  83. {agirails-2.2.0 → agirails-2.3.1}/.env.example +0 -0
  84. {agirails-2.2.0 → agirails-2.3.1}/.github/workflows/test.yml +0 -0
  85. {agirails-2.2.0 → agirails-2.3.1}/CHANGELOG.md +0 -0
  86. {agirails-2.2.0 → agirails-2.3.1}/LICENSE +0 -0
  87. {agirails-2.2.0 → agirails-2.3.1}/MIGRATION.md +0 -0
  88. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/__init__.py +0 -0
  89. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abi/ACTPKernel.json +0 -0
  90. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abi/ERC20.json +0 -0
  91. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abi/EscrowVault.json +0 -0
  92. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abis/actp_kernel.json +0 -0
  93. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abis/agent_registry.json +0 -0
  94. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abis/eas.json +0 -0
  95. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abis/escrow_vault.json +0 -0
  96. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/abis/usdc.json +0 -0
  97. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/adapters/base.py +0 -0
  98. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/builders/__init__.py +0 -0
  99. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/builders/delivery_proof.py +0 -0
  100. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/builders/quote.py +0 -0
  101. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/__init__.py +0 -0
  102. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/balance.py +0 -0
  103. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/batch.py +0 -0
  104. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/config.py +0 -0
  105. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/init.py +0 -0
  106. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/mint.py +0 -0
  107. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/simulate.py +0 -0
  108. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/time.py +0 -0
  109. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/tx.py +0 -0
  110. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/commands/watch.py +0 -0
  111. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/utils/__init__.py +0 -0
  112. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/utils/client.py +0 -0
  113. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/utils/output.py +0 -0
  114. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/cli/utils/validation.py +0 -0
  115. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/config/abis/AgentRegistry.json +0 -0
  116. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/agent.py +0 -0
  117. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/base.py +0 -0
  118. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/mock.py +0 -0
  119. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/storage.py +0 -0
  120. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/transaction.py +0 -0
  121. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/errors/validation.py +0 -0
  122. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level0/__init__.py +0 -0
  123. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level0/directory.py +0 -0
  124. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level0/provide.py +0 -0
  125. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level0/provider.py +0 -0
  126. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level0/request.py +0 -0
  127. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level1/__init__.py +0 -0
  128. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level1/agent.py +0 -0
  129. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level1/config.py +0 -0
  130. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level1/job.py +0 -0
  131. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/level1/pricing.py +0 -0
  132. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/__init__.py +0 -0
  133. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/agent_registry.py +0 -0
  134. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/did.py +0 -0
  135. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/eas.py +0 -0
  136. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/events.py +0 -0
  137. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/messages.py +0 -0
  138. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/protocol/proofs.py +0 -0
  139. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/py.typed +0 -0
  140. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/__init__.py +0 -0
  141. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/base.py +0 -0
  142. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/mock_runtime.py +0 -0
  143. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/mock_state_manager.py +0 -0
  144. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/runtime/types.py +0 -0
  145. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/storage/__init__.py +0 -0
  146. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/storage/archive_bundle_builder.py +0 -0
  147. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/storage/arweave_client.py +0 -0
  148. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/storage/filebase_client.py +0 -0
  149. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/storage/types.py +0 -0
  150. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/types/__init__.py +0 -0
  151. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/types/did.py +0 -0
  152. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/types/message.py +0 -0
  153. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/types/transaction.py +0 -0
  154. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/canonical_json.py +0 -0
  155. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/helpers.py +0 -0
  156. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/logger.py +0 -0
  157. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/logging.py +0 -0
  158. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/nonce_tracker.py +0 -0
  159. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/received_nonce_tracker.py +0 -0
  160. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/retry.py +0 -0
  161. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/secure_nonce.py +0 -0
  162. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/used_attestation_tracker.py +0 -0
  163. {agirails-2.2.0 → agirails-2.3.1}/src/agirails/utils/validation.py +0 -0
  164. {agirails-2.2.0 → agirails-2.3.1}/tests/__init__.py +0 -0
  165. {agirails-2.2.0 → agirails-2.3.1}/tests/benchmarks/__init__.py +0 -0
  166. {agirails-2.2.0 → agirails-2.3.1}/tests/conftest.py +0 -0
  167. {agirails-2.2.0 → agirails-2.3.1}/tests/fixtures/parity/canonical_json.json +0 -0
  168. {agirails-2.2.0 → agirails-2.3.1}/tests/fixtures/parity/delivery_proof.json +0 -0
  169. {agirails-2.2.0 → agirails-2.3.1}/tests/fixtures/parity/eip712.json +0 -0
  170. {agirails-2.2.0 → agirails-2.3.1}/tests/fixtures/parity/service_hash.json +0 -0
  171. {agirails-2.2.0 → agirails-2.3.1}/tests/integration/__init__.py +0 -0
  172. {agirails-2.2.0 → agirails-2.3.1}/tests/integration/test_blockchain_runtime.py +0 -0
  173. {agirails-2.2.0 → agirails-2.3.1}/tests/integration/test_eas.py +0 -0
  174. {agirails-2.2.0 → agirails-2.3.1}/tests/test_adapters/__init__.py +0 -0
  175. {agirails-2.2.0 → agirails-2.3.1}/tests/test_adapters/test_basic.py +0 -0
  176. {agirails-2.2.0 → agirails-2.3.1}/tests/test_adapters/test_standard.py +0 -0
  177. {agirails-2.2.0 → agirails-2.3.1}/tests/test_builders/__init__.py +0 -0
  178. {agirails-2.2.0 → agirails-2.3.1}/tests/test_builders/test_delivery_proof.py +0 -0
  179. {agirails-2.2.0 → agirails-2.3.1}/tests/test_builders/test_quote.py +0 -0
  180. {agirails-2.2.0/tests/test_runtime → agirails-2.3.1/tests/test_cli}/__init__.py +0 -0
  181. /agirails-2.2.0/tests/test_cli.py → /agirails-2.3.1/tests/test_cli/test_cli_original.py +0 -0
  182. {agirails-2.2.0 → agirails-2.3.1}/tests/test_client.py +0 -0
  183. {agirails-2.2.0/tests/test_utils → agirails-2.3.1/tests/test_config}/__init__.py +0 -0
  184. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/__init__.py +0 -0
  185. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/test_agent.py +0 -0
  186. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/test_base.py +0 -0
  187. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/test_network.py +0 -0
  188. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/test_transaction.py +0 -0
  189. {agirails-2.2.0 → agirails-2.3.1}/tests/test_errors/test_validation.py +0 -0
  190. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level0/__init__.py +0 -0
  191. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level0/test_directory.py +0 -0
  192. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level0/test_provider.py +0 -0
  193. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level0/test_request.py +0 -0
  194. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level1/__init__.py +0 -0
  195. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level1/test_agent_lifecycle.py +0 -0
  196. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level1/test_config.py +0 -0
  197. {agirails-2.2.0 → agirails-2.3.1}/tests/test_level1/test_pricing.py +0 -0
  198. {agirails-2.2.0 → agirails-2.3.1}/tests/test_packaging/__init__.py +0 -0
  199. {agirails-2.2.0 → agirails-2.3.1}/tests/test_packaging/test_smoke.py +0 -0
  200. {agirails-2.2.0 → agirails-2.3.1}/tests/test_parity.py +0 -0
  201. {agirails-2.2.0 → agirails-2.3.1}/tests/test_properties/__init__.py +0 -0
  202. {agirails-2.2.0 → agirails-2.3.1}/tests/test_properties/test_state_machine.py +0 -0
  203. {agirails-2.2.0 → agirails-2.3.1}/tests/test_protocol/__init__.py +0 -0
  204. {agirails-2.2.0 → agirails-2.3.1}/tests/test_protocol/test_did.py +0 -0
  205. {agirails-2.2.0 → agirails-2.3.1}/tests/test_protocol/test_eas_verification.py +0 -0
  206. {agirails-2.2.0 → agirails-2.3.1}/tests/test_protocol/test_proofs.py +0 -0
  207. {agirails-2.2.0 → agirails-2.3.1}/tests/test_runtime/test_concurrent_file_locking.py +0 -0
  208. {agirails-2.2.0 → agirails-2.3.1}/tests/test_runtime/test_mock_runtime.py +0 -0
  209. {agirails-2.2.0 → agirails-2.3.1}/tests/test_runtime/test_mock_state_manager.py +0 -0
  210. {agirails-2.2.0 → agirails-2.3.1}/tests/test_security/__init__.py +0 -0
  211. {agirails-2.2.0 → agirails-2.3.1}/tests/test_security/test_security_audit.py +0 -0
  212. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/__init__.py +0 -0
  213. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/conftest.py +0 -0
  214. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/test_archive_bundle_builder.py +0 -0
  215. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/test_arweave_client.py +0 -0
  216. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/test_filebase_client.py +0 -0
  217. {agirails-2.2.0 → agirails-2.3.1}/tests/test_storage/test_types.py +0 -0
  218. {agirails-2.2.0 → agirails-2.3.1}/tests/test_types/__init__.py +0 -0
  219. {agirails-2.2.0 → agirails-2.3.1}/tests/test_types/test_message.py +0 -0
  220. {agirails-2.2.0 → agirails-2.3.1}/tests/test_types/test_transaction.py +0 -0
  221. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_attestation_replay.py +0 -0
  222. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_circuit_breaker.py +0 -0
  223. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_helpers.py +0 -0
  224. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_helpers_extended.py +0 -0
  225. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_nonce_tracker.py +0 -0
  226. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_nonce_tracker_extended.py +0 -0
  227. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_received_nonce_tracker_extended.py +0 -0
  228. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_retry.py +0 -0
  229. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_secure_nonce_concurrency.py +0 -0
  230. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_security.py +0 -0
  231. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_security_extended.py +0 -0
  232. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_validation.py +0 -0
  233. {agirails-2.2.0 → agirails-2.3.1}/tests/test_utils/test_validation_extended.py +0 -0
@@ -92,4 +92,5 @@ secrets.json
92
92
  .ralph/
93
93
  .serena/
94
94
  CLAUDE.md
95
+ SCRATCHPAD.md
95
96
  uv.lock
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: agirails
3
+ Version: 2.3.1
4
+ Summary: AGIRAILS Python SDK - Agent Commerce Transaction Protocol
5
+ Project-URL: Homepage, https://agirails.io
6
+ Project-URL: Documentation, https://docs.agirails.io
7
+ Project-URL: Repository, https://github.com/agirails/sdk-python
8
+ Project-URL: Issues, https://github.com/agirails/sdk-python/issues
9
+ Author-email: AGIRAILS Team <developers@agirails.io>
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ Keywords: actp,ai-agents,base,blockchain,escrow,ethereum,payments,web3
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: Apache Software License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.9
25
+ Requires-Dist: aiofiles<25.0.0,>=24.0.0
26
+ Requires-Dist: eth-abi<6.0.0,>=5.0.0
27
+ Requires-Dist: eth-account<0.14.0,>=0.13.0
28
+ Requires-Dist: eth-utils<6.0.0,>=5.0.0
29
+ Requires-Dist: httpx<1.0.0,>=0.27.0
30
+ Requires-Dist: pydantic<3.0.0,>=2.6.0
31
+ Requires-Dist: python-dateutil<3.0.0,>=2.8.0
32
+ Requires-Dist: rich<14.0.0,>=13.0.0
33
+ Requires-Dist: typer<1.0.0,>=0.12.0
34
+ Requires-Dist: typing-extensions<5.0.0,>=4.0.0; python_version < '3.10'
35
+ Requires-Dist: web3<8.0.0,>=7.0.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: black>=24.0.0; extra == 'dev'
38
+ Requires-Dist: hypothesis>=6.100.0; extra == 'dev'
39
+ Requires-Dist: mypy>=1.11.0; extra == 'dev'
40
+ Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
41
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == 'dev'
42
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
43
+ Requires-Dist: pytest-timeout>=2.3.0; extra == 'dev'
44
+ Requires-Dist: pytest-xdist>=3.5.0; extra == 'dev'
45
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
46
+ Requires-Dist: ruff>=0.6.0; extra == 'dev'
47
+ Requires-Dist: types-aiofiles>=24.0.0; extra == 'dev'
48
+ Requires-Dist: types-python-dateutil>=2.8.0; extra == 'dev'
49
+ Provides-Extra: mutation
50
+ Requires-Dist: mutmut>=2.4.0; extra == 'mutation'
51
+ Provides-Extra: security
52
+ Requires-Dist: bandit>=1.7.0; extra == 'security'
53
+ Requires-Dist: pip-audit>=2.7.0; extra == 'security'
54
+ Requires-Dist: safety>=3.0.0; extra == 'security'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # AGIRAILS Python SDK
58
+
59
+ [![PyPI](https://img.shields.io/pypi/v/agirails.svg)](https://pypi.org/project/agirails/)
60
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
61
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
62
+ [![Tests](https://img.shields.io/badge/tests-1738%20passed-brightgreen.svg)]()
63
+
64
+ The official Python SDK for the **Agent Commerce Transaction Protocol (ACTP)** — enabling AI agents to transact with each other through blockchain-based escrow on Base L2.
65
+
66
+ **Full 1:1 parity with TypeScript SDK v2.5.0.**
67
+
68
+ ## Install
69
+
70
+ ```bash
71
+ pip install agirails==2.3.0
72
+ ```
73
+
74
+ ## Features
75
+
76
+ - **Adapter Routing** — priority-based adapter selection (Standard, Basic, X402)
77
+ - **x402 Payments** — HTTP-based instant payments with relay fee splitting
78
+ - **ERC-8004 Identity** — on-chain agent identity resolution and reputation
79
+ - **Keystore Security (AIP-13)** — fail-closed private key policy, `ACTP_KEYSTORE_BASE64` for CI/CD
80
+ - **AGIRAILS.md Source of Truth** — parse, hash, publish, pull, diff agent configs
81
+ - **Smart Wallet (ERC-4337)** — batched transactions with paymaster gas sponsorship
82
+ - **Lazy Publish** — mainnet activation deferred to first real transaction
83
+ - **Three-tier API** — Basic, Standard, and Advanced levels
84
+ - **Mock Runtime** — full local testing without blockchain
85
+ - **CLI** — `actp pay`, `publish`, `pull`, `diff`, `deploy:env`, `deploy:check`
86
+ - **Async-first** — built on asyncio
87
+ - **1,738 tests passing**
88
+
89
+ ## Quick Start
90
+
91
+ ```python
92
+ import asyncio
93
+ from agirails import ACTPClient
94
+
95
+ async def main():
96
+ client = await ACTPClient.create(mode="mock", requester_address="0x1234...")
97
+
98
+ # Adapter router auto-selects the best path
99
+ # EVM address → ACTP (StandardAdapter)
100
+ result = await client.pay({"to": "0xProvider...", "amount": "10.00"})
101
+
102
+ # HTTP URL → x402 instant payment
103
+ result = await client.pay({"to": "https://api.example.com/pay", "amount": "5.00"})
104
+
105
+ # Agent ID → ERC-8004 resolve → ACTP
106
+ result = await client.pay({"to": "12345", "amount": "10.00"})
107
+
108
+ print(f"Transaction: {result.tx_id}, State: {result.state}")
109
+
110
+ asyncio.run(main())
111
+ ```
112
+
113
+ ## Adapter Routing
114
+
115
+ Priority-based adapter selection matching TypeScript `AdapterRouter`:
116
+
117
+ | Adapter | Priority | Target | Use Case |
118
+ |---------|----------|--------|----------|
119
+ | **X402Adapter** | 70 | `https://...` URLs | Instant HTTP payments with relay fee splitting |
120
+ | **StandardAdapter** | 60 | `0x...` addresses | Full ACTP lifecycle with escrow |
121
+ | **BasicAdapter** | 50 | `0x...` addresses | Simple pay-and-forget (Smart Wallet batched) |
122
+
123
+ ## Keystore & Deployment Security (AIP-13)
124
+
125
+ Fail-closed private key policy with network-aware enforcement:
126
+
127
+ | Network | `ACTP_PRIVATE_KEY` | Behavior |
128
+ |---------|-------------------|----------|
129
+ | mock | Allowed | Silent |
130
+ | testnet (base-sepolia) | Allowed | Warn once |
131
+ | mainnet (base-mainnet) | Blocked | Hard fail |
132
+
133
+ **Resolution order:** `ACTP_PRIVATE_KEY` → `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD` → `.actp/keystore.json` → `None`
134
+
135
+ ```bash
136
+ # Generate base64 keystore for CI/CD
137
+ actp deploy:env
138
+
139
+ # Scan repo for exposed secrets
140
+ actp deploy:check
141
+ ```
142
+
143
+ ## AGIRAILS.md Config Management
144
+
145
+ ```bash
146
+ actp publish --network base-sepolia # Hash + upload to IPFS + register on-chain
147
+ actp pull --network base-sepolia # Fetch config from chain
148
+ actp diff --network base-sepolia # Compare local vs on-chain
149
+ ```
150
+
151
+ ## Transaction Lifecycle
152
+
153
+ ```
154
+ INITIATED → QUOTED → COMMITTED → IN_PROGRESS → DELIVERED → SETTLED
155
+ ↘ ↘ ↘
156
+ CANCELLED CANCELLED DISPUTED → SETTLED
157
+ ```
158
+
159
+ ## CLI
160
+
161
+ ```bash
162
+ # Payments
163
+ actp pay <to> <amount> [--deadline TIME]
164
+ actp balance [ADDRESS]
165
+
166
+ # Transaction management
167
+ actp tx list [--state STATE]
168
+ actp tx status <tx_id>
169
+ actp tx deliver <tx_id>
170
+ actp tx settle <tx_id>
171
+
172
+ # Config sync
173
+ actp publish [path]
174
+ actp pull [path] [--network NETWORK]
175
+ actp diff [path] [--network NETWORK]
176
+
177
+ # Deployment security
178
+ actp deploy:env
179
+ actp deploy:check [path] [--fix]
180
+
181
+ # Mock mode
182
+ actp mint <address> <amount>
183
+ actp time advance <duration>
184
+ ```
185
+
186
+ ## SDK Parity
187
+
188
+ Full 1:1 parity with TypeScript SDK v2.5.0:
189
+
190
+ | Feature | Python | TypeScript |
191
+ |---------|--------|------------|
192
+ | Adapter Routing | AdapterRouter + 3 adapters | AdapterRouter + 3 adapters |
193
+ | x402 Payments | X402Adapter with relay | X402Adapter with relay |
194
+ | ERC-8004 Identity | ERC8004Bridge + ReputationReporter | ERC8004Bridge + ReputationReporter |
195
+ | Keystore AIP-13 | Full (30-min TTL cache) | Full (30-min TTL cache) |
196
+ | AGIRAILS.md SOT | parse, hash, publish, pull, diff | parse, hash, publish, pull, diff |
197
+ | Smart Wallet | ERC-4337 scaffolding | ERC-4337 full |
198
+ | Lazy Publish | pending-publish lifecycle | pending-publish lifecycle |
199
+ | CLI Commands | pay, publish, pull, diff, deploy:* | pay, publish, pull, diff, deploy:* |
200
+ | State Machine | 8 states, all transitions | 8 states, all transitions |
201
+ | Cross-SDK Tests | Shared test vectors | Shared test vectors |
202
+
203
+ ## Testing
204
+
205
+ ```bash
206
+ pytest # Run all 1,738 tests
207
+ pytest -v # Verbose output
208
+ pytest tests/test_adapters/ # Adapter tests only
209
+ pytest -k "test_pay" # Pattern match
210
+ ```
211
+
212
+ ## Requirements
213
+
214
+ - Python 3.9+
215
+ - Dependencies: web3, eth-account, pydantic, aiofiles, httpx, typer, rich
216
+
217
+ ## Links
218
+
219
+ - [PyPI](https://pypi.org/project/agirails/)
220
+ - [Documentation](https://docs.agirails.io)
221
+ - [GitHub](https://github.com/agirails/sdk-python)
222
+ - [Discord](https://discord.gg/nuhCt75qe4)
223
+
224
+ ## License
225
+
226
+ Apache 2.0 — see [LICENSE](LICENSE) for details.
@@ -0,0 +1,170 @@
1
+ # AGIRAILS Python SDK
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/agirails.svg)](https://pypi.org/project/agirails/)
4
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
6
+ [![Tests](https://img.shields.io/badge/tests-1738%20passed-brightgreen.svg)]()
7
+
8
+ The official Python SDK for the **Agent Commerce Transaction Protocol (ACTP)** — enabling AI agents to transact with each other through blockchain-based escrow on Base L2.
9
+
10
+ **Full 1:1 parity with TypeScript SDK v2.5.0.**
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ pip install agirails==2.3.0
16
+ ```
17
+
18
+ ## Features
19
+
20
+ - **Adapter Routing** — priority-based adapter selection (Standard, Basic, X402)
21
+ - **x402 Payments** — HTTP-based instant payments with relay fee splitting
22
+ - **ERC-8004 Identity** — on-chain agent identity resolution and reputation
23
+ - **Keystore Security (AIP-13)** — fail-closed private key policy, `ACTP_KEYSTORE_BASE64` for CI/CD
24
+ - **AGIRAILS.md Source of Truth** — parse, hash, publish, pull, diff agent configs
25
+ - **Smart Wallet (ERC-4337)** — batched transactions with paymaster gas sponsorship
26
+ - **Lazy Publish** — mainnet activation deferred to first real transaction
27
+ - **Three-tier API** — Basic, Standard, and Advanced levels
28
+ - **Mock Runtime** — full local testing without blockchain
29
+ - **CLI** — `actp pay`, `publish`, `pull`, `diff`, `deploy:env`, `deploy:check`
30
+ - **Async-first** — built on asyncio
31
+ - **1,738 tests passing**
32
+
33
+ ## Quick Start
34
+
35
+ ```python
36
+ import asyncio
37
+ from agirails import ACTPClient
38
+
39
+ async def main():
40
+ client = await ACTPClient.create(mode="mock", requester_address="0x1234...")
41
+
42
+ # Adapter router auto-selects the best path
43
+ # EVM address → ACTP (StandardAdapter)
44
+ result = await client.pay({"to": "0xProvider...", "amount": "10.00"})
45
+
46
+ # HTTP URL → x402 instant payment
47
+ result = await client.pay({"to": "https://api.example.com/pay", "amount": "5.00"})
48
+
49
+ # Agent ID → ERC-8004 resolve → ACTP
50
+ result = await client.pay({"to": "12345", "amount": "10.00"})
51
+
52
+ print(f"Transaction: {result.tx_id}, State: {result.state}")
53
+
54
+ asyncio.run(main())
55
+ ```
56
+
57
+ ## Adapter Routing
58
+
59
+ Priority-based adapter selection matching TypeScript `AdapterRouter`:
60
+
61
+ | Adapter | Priority | Target | Use Case |
62
+ |---------|----------|--------|----------|
63
+ | **X402Adapter** | 70 | `https://...` URLs | Instant HTTP payments with relay fee splitting |
64
+ | **StandardAdapter** | 60 | `0x...` addresses | Full ACTP lifecycle with escrow |
65
+ | **BasicAdapter** | 50 | `0x...` addresses | Simple pay-and-forget (Smart Wallet batched) |
66
+
67
+ ## Keystore & Deployment Security (AIP-13)
68
+
69
+ Fail-closed private key policy with network-aware enforcement:
70
+
71
+ | Network | `ACTP_PRIVATE_KEY` | Behavior |
72
+ |---------|-------------------|----------|
73
+ | mock | Allowed | Silent |
74
+ | testnet (base-sepolia) | Allowed | Warn once |
75
+ | mainnet (base-mainnet) | Blocked | Hard fail |
76
+
77
+ **Resolution order:** `ACTP_PRIVATE_KEY` → `ACTP_KEYSTORE_BASE64` + `ACTP_KEY_PASSWORD` → `.actp/keystore.json` → `None`
78
+
79
+ ```bash
80
+ # Generate base64 keystore for CI/CD
81
+ actp deploy:env
82
+
83
+ # Scan repo for exposed secrets
84
+ actp deploy:check
85
+ ```
86
+
87
+ ## AGIRAILS.md Config Management
88
+
89
+ ```bash
90
+ actp publish --network base-sepolia # Hash + upload to IPFS + register on-chain
91
+ actp pull --network base-sepolia # Fetch config from chain
92
+ actp diff --network base-sepolia # Compare local vs on-chain
93
+ ```
94
+
95
+ ## Transaction Lifecycle
96
+
97
+ ```
98
+ INITIATED → QUOTED → COMMITTED → IN_PROGRESS → DELIVERED → SETTLED
99
+ ↘ ↘ ↘
100
+ CANCELLED CANCELLED DISPUTED → SETTLED
101
+ ```
102
+
103
+ ## CLI
104
+
105
+ ```bash
106
+ # Payments
107
+ actp pay <to> <amount> [--deadline TIME]
108
+ actp balance [ADDRESS]
109
+
110
+ # Transaction management
111
+ actp tx list [--state STATE]
112
+ actp tx status <tx_id>
113
+ actp tx deliver <tx_id>
114
+ actp tx settle <tx_id>
115
+
116
+ # Config sync
117
+ actp publish [path]
118
+ actp pull [path] [--network NETWORK]
119
+ actp diff [path] [--network NETWORK]
120
+
121
+ # Deployment security
122
+ actp deploy:env
123
+ actp deploy:check [path] [--fix]
124
+
125
+ # Mock mode
126
+ actp mint <address> <amount>
127
+ actp time advance <duration>
128
+ ```
129
+
130
+ ## SDK Parity
131
+
132
+ Full 1:1 parity with TypeScript SDK v2.5.0:
133
+
134
+ | Feature | Python | TypeScript |
135
+ |---------|--------|------------|
136
+ | Adapter Routing | AdapterRouter + 3 adapters | AdapterRouter + 3 adapters |
137
+ | x402 Payments | X402Adapter with relay | X402Adapter with relay |
138
+ | ERC-8004 Identity | ERC8004Bridge + ReputationReporter | ERC8004Bridge + ReputationReporter |
139
+ | Keystore AIP-13 | Full (30-min TTL cache) | Full (30-min TTL cache) |
140
+ | AGIRAILS.md SOT | parse, hash, publish, pull, diff | parse, hash, publish, pull, diff |
141
+ | Smart Wallet | ERC-4337 scaffolding | ERC-4337 full |
142
+ | Lazy Publish | pending-publish lifecycle | pending-publish lifecycle |
143
+ | CLI Commands | pay, publish, pull, diff, deploy:* | pay, publish, pull, diff, deploy:* |
144
+ | State Machine | 8 states, all transitions | 8 states, all transitions |
145
+ | Cross-SDK Tests | Shared test vectors | Shared test vectors |
146
+
147
+ ## Testing
148
+
149
+ ```bash
150
+ pytest # Run all 1,738 tests
151
+ pytest -v # Verbose output
152
+ pytest tests/test_adapters/ # Adapter tests only
153
+ pytest -k "test_pay" # Pattern match
154
+ ```
155
+
156
+ ## Requirements
157
+
158
+ - Python 3.9+
159
+ - Dependencies: web3, eth-account, pydantic, aiofiles, httpx, typer, rich
160
+
161
+ ## Links
162
+
163
+ - [PyPI](https://pypi.org/project/agirails/)
164
+ - [Documentation](https://docs.agirails.io)
165
+ - [GitHub](https://github.com/agirails/sdk-python)
166
+ - [Discord](https://discord.gg/nuhCt75qe4)
167
+
168
+ ## License
169
+
170
+ Apache 2.0 — see [LICENSE](LICENSE) for details.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agirails"
7
- version = "2.2.0"
7
+ version = "2.3.1"
8
8
  description = "AGIRAILS Python SDK - Agent Commerce Transaction Protocol"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -5,7 +5,11 @@ Provides different API levels for ACTP transactions:
5
5
 
6
6
  - BasicAdapter: Simple pay() method for quick transactions
7
7
  - StandardAdapter: Full lifecycle control with separate methods
8
+ - X402Adapter: HTTP 402 Payment Required atomic payments
8
9
  - BaseAdapter: Shared utilities (not for direct use)
10
+ - AdapterRegistry: Central registry for managing adapters
11
+ - AdapterRouter: Intelligent adapter selection with guard-rails
12
+ - IAdapter: Common protocol interface for all adapters
9
13
 
10
14
  Usage:
11
15
  >>> from agirails import ACTPClient
@@ -17,6 +21,11 @@ Usage:
17
21
  >>> # Standard API (more control)
18
22
  >>> tx_id = await client.standard.create_transaction(...)
19
23
  >>> escrow_id = await client.standard.link_escrow(tx_id)
24
+ >>>
25
+ >>> # X402 API (atomic HTTP payments)
26
+ >>> from agirails.adapters import X402Adapter, X402AdapterConfig
27
+ >>> adapter = X402Adapter("0x...", X402AdapterConfig(...))
28
+ >>> result = await adapter.pay(UnifiedPayParams(to="https://...", amount="10"))
20
29
  """
21
30
 
22
31
  from agirails.adapters.base import (
@@ -38,6 +47,22 @@ from agirails.adapters.standard import (
38
47
  StandardTransactionParams,
39
48
  TransactionDetails,
40
49
  )
50
+ from agirails.adapters.x402_adapter import (
51
+ X402Adapter,
52
+ X402AdapterConfig,
53
+ X402PayParams,
54
+ X402PayResult,
55
+ )
56
+ from agirails.adapters.types import (
57
+ AdapterMetadata,
58
+ AdapterSelectionResult,
59
+ PaymentIdentity,
60
+ PaymentMetadata,
61
+ UnifiedPayParams,
62
+ )
63
+ from agirails.adapters.i_adapter import IAdapter
64
+ from agirails.adapters.adapter_registry import AdapterRegistry
65
+ from agirails.adapters.adapter_router import AdapterRouter
41
66
 
42
67
  __all__ = [
43
68
  # Base
@@ -56,4 +81,20 @@ __all__ = [
56
81
  "StandardAdapter",
57
82
  "StandardTransactionParams",
58
83
  "TransactionDetails",
84
+ # X402
85
+ "X402Adapter",
86
+ "X402AdapterConfig",
87
+ "X402PayParams",
88
+ "X402PayResult",
89
+ # Types
90
+ "AdapterMetadata",
91
+ "AdapterSelectionResult",
92
+ "PaymentIdentity",
93
+ "PaymentMetadata",
94
+ "UnifiedPayParams",
95
+ # Interface
96
+ "IAdapter",
97
+ # Registry & Router
98
+ "AdapterRegistry",
99
+ "AdapterRouter",
59
100
  ]
@@ -0,0 +1,150 @@
1
+ """
2
+ AdapterRegistry - Central registry for payment adapters.
3
+
4
+ Manages the collection of available adapters and provides
5
+ methods for registration, lookup, and priority-based retrieval.
6
+
7
+ 1:1 port of TypeScript SDK AdapterRegistry.ts.
8
+
9
+ @module adapters/AdapterRegistry
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import Dict, List, Optional
15
+
16
+ from agirails.adapters.i_adapter import IAdapter
17
+
18
+
19
+ class AdapterRegistry:
20
+ """
21
+ AdapterRegistry - Central registry for managing available adapters.
22
+
23
+ The registry maintains a collection of adapters indexed by their ID.
24
+ It provides methods for:
25
+ - Registration and unregistration
26
+ - Lookup by ID
27
+ - Priority-sorted retrieval
28
+
29
+ Example::
30
+
31
+ registry = AdapterRegistry()
32
+
33
+ # Register adapters
34
+ registry.register(basic_adapter)
35
+ registry.register(standard_adapter)
36
+
37
+ # Lookup by ID
38
+ adapter = registry.get('basic')
39
+
40
+ # Get all adapters sorted by priority
41
+ adapters = registry.get_by_priority()
42
+ """
43
+
44
+ def __init__(self) -> None:
45
+ """Initialize an empty adapter registry."""
46
+ self._adapters: Dict[str, IAdapter] = {}
47
+
48
+ def register(self, adapter: IAdapter) -> None:
49
+ """
50
+ Register an adapter.
51
+
52
+ If an adapter with the same ID already exists, it will be replaced.
53
+
54
+ Args:
55
+ adapter: Adapter to register.
56
+
57
+ Raises:
58
+ ValueError: If adapter has no metadata.id.
59
+ """
60
+ if not hasattr(adapter, "metadata") or not adapter.metadata or not adapter.metadata.id:
61
+ raise ValueError("Cannot register adapter without metadata.id")
62
+ self._adapters[adapter.metadata.id] = adapter
63
+
64
+ def unregister(self, adapter_id: str) -> bool:
65
+ """
66
+ Unregister an adapter by ID.
67
+
68
+ Args:
69
+ adapter_id: Adapter ID to remove.
70
+
71
+ Returns:
72
+ True if adapter was found and removed, False otherwise.
73
+ """
74
+ if adapter_id in self._adapters:
75
+ del self._adapters[adapter_id]
76
+ return True
77
+ return False
78
+
79
+ def get(self, adapter_id: str) -> Optional[IAdapter]:
80
+ """
81
+ Get an adapter by ID.
82
+
83
+ Args:
84
+ adapter_id: Adapter ID to look up.
85
+
86
+ Returns:
87
+ The adapter or None if not found.
88
+ """
89
+ return self._adapters.get(adapter_id)
90
+
91
+ def get_all(self) -> List[IAdapter]:
92
+ """
93
+ Get all registered adapters.
94
+
95
+ Returns adapters in insertion order.
96
+
97
+ Returns:
98
+ List of all registered adapters.
99
+ """
100
+ return list(self._adapters.values())
101
+
102
+ def has(self, adapter_id: str) -> bool:
103
+ """
104
+ Check if an adapter is registered.
105
+
106
+ Args:
107
+ adapter_id: Adapter ID to check.
108
+
109
+ Returns:
110
+ True if adapter is registered.
111
+ """
112
+ return adapter_id in self._adapters
113
+
114
+ def get_by_priority(self) -> List[IAdapter]:
115
+ """
116
+ Get adapters sorted by priority (highest first).
117
+
118
+ Higher priority adapters are tried first during selection.
119
+
120
+ Returns:
121
+ List of adapters sorted by priority descending.
122
+ """
123
+ return sorted(self.get_all(), key=lambda a: a.metadata.priority, reverse=True)
124
+
125
+ @property
126
+ def size(self) -> int:
127
+ """
128
+ Get the number of registered adapters.
129
+
130
+ Returns:
131
+ Number of adapters.
132
+ """
133
+ return len(self._adapters)
134
+
135
+ def get_ids(self) -> List[str]:
136
+ """
137
+ Get all adapter IDs.
138
+
139
+ Returns:
140
+ List of adapter IDs.
141
+ """
142
+ return list(self._adapters.keys())
143
+
144
+ def clear(self) -> None:
145
+ """
146
+ Clear all registered adapters.
147
+
148
+ Primarily useful for testing.
149
+ """
150
+ self._adapters.clear()