selectools 0.22.0__tar.gz → 0.24.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. {selectools-0.22.0/src/selectools.egg-info → selectools-0.24.0}/PKG-INFO +86 -10
  2. {selectools-0.22.0 → selectools-0.24.0}/README.md +76 -9
  3. {selectools-0.22.0 → selectools-0.24.0}/pyproject.toml +13 -1
  4. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/__init__.py +69 -1
  5. selectools-0.24.0/src/selectools/a2a/__init__.py +54 -0
  6. selectools-0.24.0/src/selectools/a2a/client.py +174 -0
  7. selectools-0.24.0/src/selectools/a2a/server.py +406 -0
  8. selectools-0.24.0/src/selectools/a2a/types.py +169 -0
  9. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/_tool_executor.py +13 -2
  10. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/core.py +9 -0
  11. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/entity_memory.py +4 -0
  12. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/knowledge.py +174 -2
  13. selectools-0.24.0/src/selectools/knowledge_backends.py +220 -0
  14. selectools-0.24.0/src/selectools/pending.py +1123 -0
  15. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/__init__.py +5 -0
  16. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/anthropic_provider.py +70 -8
  17. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/gemini_provider.py +105 -14
  18. selectools-0.24.0/src/selectools/providers/litellm_provider.py +192 -0
  19. selectools-0.24.0/src/selectools/providers/router.py +610 -0
  20. selectools-0.24.0/src/selectools/results.py +224 -0
  21. selectools-0.24.0/src/selectools/serve/__init__.py +54 -0
  22. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/_static/builder.css +6 -1
  23. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/_static/builder.html +10 -0
  24. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/_static/builder.js +396 -30
  25. selectools-0.24.0/src/selectools/serve/api.py +552 -0
  26. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/cli.py +34 -0
  27. selectools-0.24.0/src/selectools/sessions.py +1295 -0
  28. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/__init__.py +75 -1
  29. selectools-0.24.0/src/selectools/toolbox/calculator_tools.py +332 -0
  30. selectools-0.24.0/src/selectools/toolbox/email_tools.py +245 -0
  31. selectools-0.24.0/src/selectools/toolbox/linear_tools.py +286 -0
  32. selectools-0.24.0/src/selectools/toolbox/notion_tools.py +259 -0
  33. selectools-0.24.0/src/selectools/toolbox/pdf_tools.py +155 -0
  34. selectools-0.24.0/src/selectools/toolbox/slack_tools.py +201 -0
  35. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/tools/base.py +8 -0
  36. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/types.py +3 -0
  37. selectools-0.24.0/src/selectools/unified_memory.py +926 -0
  38. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/usage.py +8 -0
  39. {selectools-0.22.0 → selectools-0.24.0/src/selectools.egg-info}/PKG-INFO +86 -10
  40. {selectools-0.22.0 → selectools-0.24.0}/src/selectools.egg-info/SOURCES.txt +26 -0
  41. {selectools-0.22.0 → selectools-0.24.0}/src/selectools.egg-info/requires.txt +12 -0
  42. selectools-0.24.0/tests/test_a2a.py +455 -0
  43. selectools-0.24.0/tests/test_agent_api.py +430 -0
  44. {selectools-0.22.0 → selectools-0.24.0}/tests/test_entity_memory.py +9 -0
  45. selectools-0.24.0/tests/test_knowledge_backend.py +255 -0
  46. selectools-0.24.0/tests/test_knowledge_backend_redis.py +171 -0
  47. selectools-0.24.0/tests/test_knowledge_backend_supabase.py +231 -0
  48. selectools-0.24.0/tests/test_pending.py +1024 -0
  49. selectools-0.24.0/tests/test_results.py +366 -0
  50. {selectools-0.22.0 → selectools-0.24.0}/tests/test_serve_cli.py +39 -0
  51. {selectools-0.22.0 → selectools-0.24.0}/tests/test_sessions.py +334 -0
  52. {selectools-0.22.0 → selectools-0.24.0}/tests/test_sessions_redis.py +68 -0
  53. selectools-0.24.0/tests/test_sessions_supabase.py +643 -0
  54. selectools-0.24.0/tests/test_unified_memory.py +427 -0
  55. {selectools-0.22.0 → selectools-0.24.0}/tests/test_visual_builder.py +221 -5
  56. selectools-0.22.0/src/selectools/serve/__init__.py +0 -24
  57. selectools-0.22.0/src/selectools/sessions.py +0 -594
  58. {selectools-0.22.0 → selectools-0.24.0}/LICENSE +0 -0
  59. {selectools-0.22.0 → selectools-0.24.0}/setup.cfg +0 -0
  60. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/_async_utils.py +0 -0
  61. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/__init__.py +0 -0
  62. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/_lifecycle.py +0 -0
  63. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/_memory_manager.py +0 -0
  64. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/_provider_caller.py +0 -0
  65. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/config.py +0 -0
  66. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/agent/config_groups.py +0 -0
  67. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/analytics.py +0 -0
  68. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/audit.py +0 -0
  69. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/cache.py +0 -0
  70. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/cache_redis.py +0 -0
  71. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/cache_semantic.py +0 -0
  72. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/cancellation.py +0 -0
  73. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/checkpoint_postgres.py +0 -0
  74. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/coherence.py +0 -0
  75. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/compose.py +0 -0
  76. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/__init__.py +0 -0
  77. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/anthropic.py +0 -0
  78. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/cohere.py +0 -0
  79. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/gemini.py +0 -0
  80. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/openai.py +0 -0
  81. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/embeddings/provider.py +0 -0
  82. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/env.py +0 -0
  83. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/__init__.py +0 -0
  84. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/__main__.py +0 -0
  85. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/badge.py +0 -0
  86. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/dataset.py +0 -0
  87. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/evaluators.py +0 -0
  88. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/generator.py +0 -0
  89. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/history.py +0 -0
  90. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/html.py +0 -0
  91. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/junit.py +0 -0
  92. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/llm_evaluators.py +0 -0
  93. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/pairwise.py +0 -0
  94. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/regression.py +0 -0
  95. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/report.py +0 -0
  96. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/serve.py +0 -0
  97. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/snapshot.py +0 -0
  98. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/suite.py +0 -0
  99. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/templates.py +0 -0
  100. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/evals/types.py +0 -0
  101. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/exceptions.py +0 -0
  102. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/__init__.py +0 -0
  103. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/base.py +0 -0
  104. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/format.py +0 -0
  105. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/length.py +0 -0
  106. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/pii.py +0 -0
  107. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/pipeline.py +0 -0
  108. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/topic.py +0 -0
  109. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/guardrails/toxicity.py +0 -0
  110. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/knowledge_graph.py +0 -0
  111. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/knowledge_store_redis.py +0 -0
  112. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/knowledge_store_supabase.py +0 -0
  113. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/loop_detection.py +0 -0
  114. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/__init__.py +0 -0
  115. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/_loop.py +0 -0
  116. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/bridge.py +0 -0
  117. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/client.py +0 -0
  118. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/config.py +0 -0
  119. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/multi.py +0 -0
  120. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/mcp/server.py +0 -0
  121. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/memory.py +0 -0
  122. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/models.py +0 -0
  123. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/observe/__init__.py +0 -0
  124. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/observe/langfuse.py +0 -0
  125. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/observe/otel.py +0 -0
  126. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/observe/trace_store.py +0 -0
  127. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/observer.py +0 -0
  128. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/__init__.py +0 -0
  129. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/checkpoint.py +0 -0
  130. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/graph.py +0 -0
  131. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/node.py +0 -0
  132. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/state.py +0 -0
  133. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/orchestration/supervisor.py +0 -0
  134. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/parser.py +0 -0
  135. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/patterns/__init__.py +0 -0
  136. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/patterns/debate.py +0 -0
  137. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/patterns/plan_and_execute.py +0 -0
  138. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/patterns/reflective.py +0 -0
  139. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/patterns/team_lead.py +0 -0
  140. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/pipeline.py +0 -0
  141. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/policy.py +0 -0
  142. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/pricing.py +0 -0
  143. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/prompt.py +0 -0
  144. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/_openai_compat.py +0 -0
  145. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/azure_openai_provider.py +0 -0
  146. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/base.py +0 -0
  147. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/fallback.py +0 -0
  148. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/ollama_provider.py +0 -0
  149. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/openai_provider.py +0 -0
  150. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/providers/stubs.py +0 -0
  151. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/__init__.py +0 -0
  152. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/bm25.py +0 -0
  153. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/chunking.py +0 -0
  154. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/hybrid.py +0 -0
  155. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/loaders.py +0 -0
  156. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/reranker.py +0 -0
  157. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/__init__.py +0 -0
  158. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/chroma.py +0 -0
  159. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/faiss.py +0 -0
  160. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/memory.py +0 -0
  161. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/pgvector.py +0 -0
  162. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/pinecone.py +0 -0
  163. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/qdrant.py +0 -0
  164. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/stores/sqlite.py +0 -0
  165. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/tools.py +0 -0
  166. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/rag/vector_store.py +0 -0
  167. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/security.py +0 -0
  168. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/_starlette_app.py +0 -0
  169. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/app.py +0 -0
  170. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/builder.py +0 -0
  171. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/models.py +0 -0
  172. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/serve/playground.py +0 -0
  173. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/stability.py +0 -0
  174. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/structured.py +0 -0
  175. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/__init__.py +0 -0
  176. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/code_reviewer.py +0 -0
  177. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/customer_support.py +0 -0
  178. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/data_analyst.py +0 -0
  179. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/rag_chatbot.py +0 -0
  180. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/templates/research_assistant.py +0 -0
  181. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/token_estimation.py +0 -0
  182. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/code_tools.py +0 -0
  183. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/data_tools.py +0 -0
  184. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/datetime_tools.py +0 -0
  185. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/db_tools.py +0 -0
  186. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/file_tools.py +0 -0
  187. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/github_tools.py +0 -0
  188. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/memory_tools.py +0 -0
  189. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/search_tools.py +0 -0
  190. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/text_tools.py +0 -0
  191. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/toolbox/web_tools.py +0 -0
  192. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/tools/__init__.py +0 -0
  193. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/tools/decorators.py +0 -0
  194. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/tools/loader.py +0 -0
  195. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/tools/registry.py +0 -0
  196. {selectools-0.22.0 → selectools-0.24.0}/src/selectools/trace.py +0 -0
  197. {selectools-0.22.0 → selectools-0.24.0}/src/selectools.egg-info/dependency_links.txt +0 -0
  198. {selectools-0.22.0 → selectools-0.24.0}/src/selectools.egg-info/entry_points.txt +0 -0
  199. {selectools-0.22.0 → selectools-0.24.0}/src/selectools.egg-info/top_level.txt +0 -0
  200. {selectools-0.22.0 → selectools-0.24.0}/tests/test_approval_gate.py +0 -0
  201. {selectools-0.22.0 → selectools-0.24.0}/tests/test_architecture.py +0 -0
  202. {selectools-0.22.0 → selectools-0.24.0}/tests/test_async_observers.py +0 -0
  203. {selectools-0.22.0 → selectools-0.24.0}/tests/test_audit.py +0 -0
  204. {selectools-0.22.0 → selectools-0.24.0}/tests/test_budget.py +0 -0
  205. {selectools-0.22.0 → selectools-0.24.0}/tests/test_bug_hunt_batch1_core.py +0 -0
  206. {selectools-0.22.0 → selectools-0.24.0}/tests/test_bug_hunt_batch1_security.py +0 -0
  207. {selectools-0.22.0 → selectools-0.24.0}/tests/test_bug_hunt_batch1_tools.py +0 -0
  208. {selectools-0.22.0 → selectools-0.24.0}/tests/test_bug_hunt_regression.py +0 -0
  209. {selectools-0.22.0 → selectools-0.24.0}/tests/test_cache.py +0 -0
  210. {selectools-0.22.0 → selectools-0.24.0}/tests/test_cache_redis.py +0 -0
  211. {selectools-0.22.0 → selectools-0.24.0}/tests/test_cancellation.py +0 -0
  212. {selectools-0.22.0 → selectools-0.24.0}/tests/test_checkpoint_postgres.py +0 -0
  213. {selectools-0.22.0 → selectools-0.24.0}/tests/test_coherence.py +0 -0
  214. {selectools-0.22.0 → selectools-0.24.0}/tests/test_concurrency_smoke.py +0 -0
  215. {selectools-0.22.0 → selectools-0.24.0}/tests/test_consolidation_regression.py +0 -0
  216. {selectools-0.22.0 → selectools-0.24.0}/tests/test_conversation_branching.py +0 -0
  217. {selectools-0.22.0 → selectools-0.24.0}/tests/test_coverage_orchestration.py +0 -0
  218. {selectools-0.22.0 → selectools-0.24.0}/tests/test_document_loaders_extended.py +0 -0
  219. {selectools-0.22.0 → selectools-0.24.0}/tests/test_e2e_langfuse_observer.py +0 -0
  220. {selectools-0.22.0 → selectools-0.24.0}/tests/test_e2e_multimodal.py +0 -0
  221. {selectools-0.22.0 → selectools-0.24.0}/tests/test_e2e_otel_observer.py +0 -0
  222. {selectools-0.22.0 → selectools-0.24.0}/tests/test_e2e_v0_21_0_apps.py +0 -0
  223. {selectools-0.22.0 → selectools-0.24.0}/tests/test_e2e_v0_21_0_simulations.py +0 -0
  224. {selectools-0.22.0 → selectools-0.24.0}/tests/test_env.py +0 -0
  225. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals.py +0 -0
  226. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_advanced.py +0 -0
  227. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_cli.py +0 -0
  228. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_e2e.py +0 -0
  229. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_final.py +0 -0
  230. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_hardening.py +0 -0
  231. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_html_report.py +0 -0
  232. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_new_evaluators.py +0 -0
  233. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_ralph_bugs.py +0 -0
  234. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_release.py +0 -0
  235. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_serve.py +0 -0
  236. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_v017_features.py +0 -0
  237. {selectools-0.22.0 → selectools-0.24.0}/tests/test_evals_v0191.py +0 -0
  238. {selectools-0.22.0 → selectools-0.24.0}/tests/test_features_in_graph.py +0 -0
  239. {selectools-0.22.0 → selectools-0.24.0}/tests/test_final_coverage_a.py +0 -0
  240. {selectools-0.22.0 → selectools-0.24.0}/tests/test_final_coverage_b.py +0 -0
  241. {selectools-0.22.0 → selectools-0.24.0}/tests/test_guardrails.py +0 -0
  242. {selectools-0.22.0 → selectools-0.24.0}/tests/test_hardening.py +0 -0
  243. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge.py +0 -0
  244. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge_graph.py +0 -0
  245. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge_store_redis.py +0 -0
  246. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge_store_supabase.py +0 -0
  247. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge_stores.py +0 -0
  248. {selectools-0.22.0 → selectools-0.24.0}/tests/test_knowledge_stores_error_handling.py +0 -0
  249. {selectools-0.22.0 → selectools-0.24.0}/tests/test_langfuse_observer.py +0 -0
  250. {selectools-0.22.0 → selectools-0.24.0}/tests/test_loop_detection.py +0 -0
  251. {selectools-0.22.0 → selectools-0.24.0}/tests/test_mcp.py +0 -0
  252. {selectools-0.22.0 → selectools-0.24.0}/tests/test_mcp_coverage.py +0 -0
  253. {selectools-0.22.0 → selectools-0.24.0}/tests/test_memory.py +0 -0
  254. {selectools-0.22.0 → selectools-0.24.0}/tests/test_memory_async.py +0 -0
  255. {selectools-0.22.0 → selectools-0.24.0}/tests/test_memory_boundary.py +0 -0
  256. {selectools-0.22.0 → selectools-0.24.0}/tests/test_memory_integration.py +0 -0
  257. {selectools-0.22.0 → selectools-0.24.0}/tests/test_model_switching.py +0 -0
  258. {selectools-0.22.0 → selectools-0.24.0}/tests/test_multi_agent_edge_cases.py +0 -0
  259. {selectools-0.22.0 → selectools-0.24.0}/tests/test_multimodal.py +0 -0
  260. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_checkpoint.py +0 -0
  261. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_e2e.py +0 -0
  262. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_evals.py +0 -0
  263. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_graph.py +0 -0
  264. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_integration.py +0 -0
  265. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_primitives.py +0 -0
  266. {selectools-0.22.0 → selectools-0.24.0}/tests/test_orchestration_supervisor.py +0 -0
  267. {selectools-0.22.0 → selectools-0.24.0}/tests/test_otel_observer.py +0 -0
  268. {selectools-0.22.0 → selectools-0.24.0}/tests/test_parser.py +0 -0
  269. {selectools-0.22.0 → selectools-0.24.0}/tests/test_patterns.py +0 -0
  270. {selectools-0.22.0 → selectools-0.24.0}/tests/test_phase1_design_patterns.py +0 -0
  271. {selectools-0.22.0 → selectools-0.24.0}/tests/test_pipeline.py +0 -0
  272. {selectools-0.22.0 → selectools-0.24.0}/tests/test_pipeline_coverage.py +0 -0
  273. {selectools-0.22.0 → selectools-0.24.0}/tests/test_policy.py +0 -0
  274. {selectools-0.22.0 → selectools-0.24.0}/tests/test_prompt.py +0 -0
  275. {selectools-0.22.0 → selectools-0.24.0}/tests/test_prompt_compression.py +0 -0
  276. {selectools-0.22.0 → selectools-0.24.0}/tests/test_property_based.py +0 -0
  277. {selectools-0.22.0 → selectools-0.24.0}/tests/test_reasoning_strategy.py +0 -0
  278. {selectools-0.22.0 → selectools-0.24.0}/tests/test_remaining_coverage.py +0 -0
  279. {selectools-0.22.0 → selectools-0.24.0}/tests/test_routing_mode.py +0 -0
  280. {selectools-0.22.0 → selectools-0.24.0}/tests/test_security.py +0 -0
  281. {selectools-0.22.0 → selectools-0.24.0}/tests/test_semantic_cache.py +0 -0
  282. {selectools-0.22.0 → selectools-0.24.0}/tests/test_serve_app_coverage.py +0 -0
  283. {selectools-0.22.0 → selectools-0.24.0}/tests/test_sessions_edge_cases.py +0 -0
  284. {selectools-0.22.0 → selectools-0.24.0}/tests/test_simple_observer.py +0 -0
  285. {selectools-0.22.0 → selectools-0.24.0}/tests/test_simulation_evals.py +0 -0
  286. {selectools-0.22.0 → selectools-0.24.0}/tests/test_stability.py +0 -0
  287. {selectools-0.22.0 → selectools-0.24.0}/tests/test_starlette_app.py +0 -0
  288. {selectools-0.22.0 → selectools-0.24.0}/tests/test_structured.py +0 -0
  289. {selectools-0.22.0 → selectools-0.24.0}/tests/test_structured_config.py +0 -0
  290. {selectools-0.22.0 → selectools-0.24.0}/tests/test_structured_tool_results.py +0 -0
  291. {selectools-0.22.0 → selectools-0.24.0}/tests/test_summarize_on_trim.py +0 -0
  292. {selectools-0.22.0 → selectools-0.24.0}/tests/test_templates_coverage.py +0 -0
  293. {selectools-0.22.0 → selectools-0.24.0}/tests/test_terminal_actions.py +0 -0
  294. {selectools-0.22.0 → selectools-0.24.0}/tests/test_token_estimation.py +0 -0
  295. {selectools-0.22.0 → selectools-0.24.0}/tests/test_tool_caching.py +0 -0
  296. {selectools-0.22.0 → selectools-0.24.0}/tests/test_trace.py +0 -0
  297. {selectools-0.22.0 → selectools-0.24.0}/tests/test_trace_html.py +0 -0
  298. {selectools-0.22.0 → selectools-0.24.0}/tests/test_trace_store.py +0 -0
  299. {selectools-0.22.0 → selectools-0.24.0}/tests/test_v016_regression.py +0 -0
  300. {selectools-0.22.0 → selectools-0.24.0}/tests/test_v019_features.py +0 -0
  301. {selectools-0.22.0 → selectools-0.24.0}/tests/test_yaml_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: selectools
3
- Version: 0.22.0
3
+ Version: 0.24.0
4
4
  Summary: Production-ready Python framework for AI agents with multi-agent graphs, hybrid RAG, guardrails, audit logging, 50 evaluators, and a visual builder. Supports OpenAI, Anthropic, Gemini, Ollama. By NichevLabs.
5
5
  Author-email: John Nichev <johnnichev@gmail.com>
6
6
  Maintainer-email: NichevLabs <support@nichevlabs.com>
@@ -55,16 +55,25 @@ Requires-Dist: beautifulsoup4>=4.12.0; extra == "rag"
55
55
  Provides-Extra: observe
56
56
  Requires-Dist: opentelemetry-api>=1.20.0; extra == "observe"
57
57
  Requires-Dist: langfuse>=2.0.0; extra == "observe"
58
+ Provides-Extra: toolbox
59
+ Requires-Dist: requests>=2.28.0; extra == "toolbox"
60
+ Requires-Dist: slack-sdk>=3.27.0; extra == "toolbox"
61
+ Requires-Dist: pdfplumber>=0.11.0; extra == "toolbox"
58
62
  Provides-Extra: evals
59
63
  Requires-Dist: pyyaml>=6.0.0; extra == "evals"
60
64
  Provides-Extra: mcp
61
65
  Requires-Dist: mcp<2.0.0,>=1.0.0; extra == "mcp"
66
+ Provides-Extra: litellm
67
+ Requires-Dist: litellm>=1.0.0; extra == "litellm"
62
68
  Provides-Extra: postgres
63
69
  Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgres"
70
+ Provides-Extra: supabase
71
+ Requires-Dist: supabase>=2.0.0; extra == "supabase"
64
72
  Provides-Extra: serve
65
73
  Requires-Dist: pyyaml>=6.0.0; extra == "serve"
66
74
  Requires-Dist: starlette>=0.27.0; extra == "serve"
67
75
  Requires-Dist: uvicorn[standard]>=0.24.0; extra == "serve"
76
+ Requires-Dist: httpx>=0.24.0; extra == "serve"
68
77
  Dynamic: license-file
69
78
 
70
79
  ```
@@ -99,6 +108,56 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
99
108
  # selectools serve agent.yaml
100
109
  ```
101
110
 
111
+ ## What's New in v0.24
112
+
113
+ ### v0.24.0 — Production Interop
114
+
115
+ Twelve features focused on running agents in production and connecting them to everything else: serve agents as REST APIs, talk to other agents over A2A, reach 100+ models through LiteLLM, route by cost, and persist memory anywhere.
116
+
117
+ - **Agent-as-API** — `selectools.serve.AgentAPI` turns any Agent (or list of agents) into a production Starlette ASGI app: `POST /v1/chat`, SSE streaming, session CRUD, bearer auth, per-user session isolation. CLI: `selectools serve agent.yaml --api --port 8000`.
118
+ - **A2A protocol** — `A2AServer` + `A2AClient` for agent-to-agent communication: Agent Card discovery (`/.well-known/agent.json`) and JSON-RPC 2.0 `message/send`/`tasks/get`/`tasks/cancel`.
119
+ - **LiteLLMProvider** — instant access to 100+ models (DeepSeek, Groq, Bedrock, ...) via `pip install selectools[litellm]`.
120
+ - **RouterProvider** — cost-optimized routing across model tiers with a deterministic complexity classifier and failure escalation.
121
+ - **Anthropic prompt caching** — opt-in `cache_system=True` / `cache_tools=True` with cache hit-rate fields on `UsageStats`.
122
+ - **UnifiedMemory** — tiered memory orchestrating conversation, knowledge, entity, and the new episodic tier, with token-aware compaction and federated `recall()`.
123
+ - **Cross-session search** — `store.search(query)` on all four SessionStore backends (FTS5-accelerated on SQLite).
124
+ - **KnowledgeBackend** — Supabase/Redis blob persistence for `KnowledgeMemory` on ephemeral infrastructure (Railway, Lambda, Cloud Run).
125
+ - **ToolResult + Artifact** — typed tool results with a `kind` discriminator, plus an `emit_artifact()` side-channel surfaced on `AgentResult.artifacts`.
126
+ - **Deferred confirmation flow** — `selectools.pending` for chat-channel destructive tools where the user's "yes" arrives as a separate webhook turn.
127
+ - **Toolbox expansion** — 15 new tools (33 → 48): safe calculator, email, PDF extraction, Slack, Notion, Linear.
128
+ - **Gemini schema sanitization** — bare `list` and `Dict[K, V]` tool parameters no longer 400 on the Gemini API; loud warnings for flash-lite's silent-empty-response failure mode.
129
+
130
+ ```python
131
+ from selectools.serve import AgentAPI
132
+
133
+ api = AgentAPI(agent, auth_key="secret") # ASGI app: uvicorn main:api
134
+ ```
135
+
136
+ See `CHANGELOG.md` for the full entry (5,968 tests, 106 examples).
137
+
138
+ ## What's New in v0.23
139
+
140
+ ### v0.23.0 — Supabase Sessions + Builder RAG
141
+
142
+ Two user-facing features plus a post-ship bug-hunt sweep that pinned 8 code-generator fixes in the visual builder.
143
+
144
+ - **`SupabaseSessionStore`** — 4th `SessionStore` backend alongside JSON, SQLite, and Redis. Postgres-backed via Supabase PostgREST, with idempotent upserts, namespace isolation, and the same validation guards as `RedisSessionStore`. Optional dep: `pip install selectools[supabase]`. Demo: [`examples/96_supabase_session_store.py`](https://github.com/johnnichev/selectools/blob/main/examples/96_supabase_session_store.py).
145
+
146
+ - **Visual builder: first-class RAG + session nodes** — drag `Retriever (RAG)` onto the canvas and pick any of 7 vector stores (memory, SQLite, Chroma, Pinecone, FAISS, Qdrant, pgvector), toggle Hybrid (BM25 + vector + RRF) and cross-encoder Rerank. Drag `Session Store` as a resource node and wire it into an agent via the new Session Store dropdown. Two new presets: **Hybrid RAG** and **Multi-Tenant RAG**. Python + YAML code generators emit real, runnable code.
147
+
148
+ ```python
149
+ from supabase import create_client
150
+ from selectools import SupabaseSessionStore, Agent, AgentConfig
151
+
152
+ store = SupabaseSessionStore(client=create_client(URL, KEY))
153
+ agent = Agent(
154
+ tools=[...],
155
+ config=AgentConfig(session_store=store, session_id="u-1", max_iterations=5),
156
+ )
157
+ ```
158
+
159
+ See `CHANGELOG.md` for the full entry including the 8 builder code-gen fixes.
160
+
102
161
  ## What's New in v0.22
103
162
 
104
163
  ### v0.22.0 — Competitor-Informed Bug Fixes
@@ -176,7 +235,7 @@ The first AI agent framework to ship a visual graph builder in a single `pip ins
176
235
 
177
236
  **[Try the builder in your browser →](https://selectools.dev/builder/)** — no install required.
178
237
 
179
- [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/johnnichev/selectools/blob/main/notebooks/getting_started.ipynb) [![Examples Gallery](https://img.shields.io/badge/examples-94_scripts-06b6d4)](https://selectools.dev/examples/)
238
+ [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/johnnichev/selectools/blob/main/notebooks/getting_started.ipynb) [![Examples Gallery](https://img.shields.io/badge/examples-96_scripts-06b6d4)](https://selectools.dev/examples/)
180
239
 
181
240
  ```bash
182
241
  pip install selectools
@@ -233,7 +292,7 @@ Path("trace.html").write_text(trace_to_html(result.trace))
233
292
  - **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
234
293
  - **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
235
294
  - **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
236
- - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (5343 tests total)
295
+ - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (5332 tests total)
237
296
 
238
297
  ### v0.19.1 — Advanced Agent Patterns
239
298
 
@@ -545,7 +604,15 @@ report.to_html("report.html")
545
604
  | **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
546
605
  | **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
547
606
  | **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
548
- | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, and Redis backends. Auto-save/load with TTL expiry. |
607
+ | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and Supabase backends. Auto-save/load with TTL expiry, cross-session `search()`. |
608
+ | **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
609
+ | **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
610
+ | **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
611
+ | **Cost-Based Routing** | `RouterProvider` classifies request complexity and routes to model tiers with automatic failure escalation. |
612
+ | **Unified Memory** | `UnifiedMemory` orchestrates conversation, knowledge, entity, and episodic tiers with token-aware compaction and federated `recall()`. |
613
+ | **Typed Tool Results** | `ToolResult` base with `kind` discriminator; `emit_artifact()` side-channel surfaces files/URLs on `AgentResult.artifacts`. |
614
+ | **Deferred Confirmation** | `selectools.pending` — confirm destructive chat-channel tools across webhook turns with TTL, scope, and args-digest matching. |
615
+ | **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
549
616
  | **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
550
617
  | **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
551
618
  | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
@@ -560,7 +627,9 @@ report.to_html("report.html")
560
627
 
561
628
  ## What's Included
562
629
 
563
- - **5 LLM Providers**: OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama + FallbackProvider (auto-failover)
630
+ - **6 LLM Providers**: OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama, LiteLLM (100+ models) + FallbackProvider (auto-failover) + RouterProvider (cost-based routing)
631
+ - **Agent-as-API**: `AgentAPI` — production REST endpoints (chat, SSE streaming, sessions) from any agent
632
+ - **A2A Protocol**: Agent Card discovery + JSON-RPC 2.0 agent-to-agent messaging
564
633
  - **Structured Output**: Pydantic / JSON Schema `response_format` with auto-retry
565
634
  - **Execution Traces**: `result.trace` with typed timeline of every agent step
566
635
  - **Reasoning Visibility**: `result.reasoning` explains *why* the agent chose a tool
@@ -573,9 +642,14 @@ report.to_html("report.html")
573
642
  - **Dynamic Tool Loading**: Plugin system with hot-reload support
574
643
  - **Response Caching**: InMemoryCache and RedisCache with stats tracking
575
644
  - **152 Model Registry**: Type-safe constants with pricing and metadata
576
- - **Pre-built Toolbox**: 24 tools for files, data, text, datetime, web
577
- - **Persistent Sessions**: 3 backends (JSON file, SQLite, Redis) with TTL
645
+ - **Pre-built Toolbox**: 48 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear
646
+ - **Persistent Sessions**: 4 backends (JSON file, SQLite, Redis, Supabase) with TTL and cross-session search
578
647
  - **Entity Memory**: LLM-based named entity extraction and tracking
648
+ - **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
649
+ - **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
650
+ - **Typed Tool Results**: `ToolResult` base class + `Artifact` side-channel via `emit_artifact()`
651
+ - **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
652
+ - **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
579
653
  - **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
580
654
  - **Cross-Session Knowledge**: Daily logs + persistent memory with `remember` tool, pluggable stores (File, SQLite), importance scoring, TTL
581
655
  - **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
@@ -586,10 +660,10 @@ report.to_html("report.html")
586
660
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
587
661
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
588
662
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
589
- - **76 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
663
+ - **106 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions (incl. Supabase), entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, agent-as-API, A2A, routing, unified memory, and more
590
664
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
591
665
  - **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
592
- - **5343 Tests**: Unit, integration, regression, and E2E with real API calls
666
+ - **5968 Tests**: Unit, integration, regression, and E2E with real API calls
593
667
 
594
668
  ## Install
595
669
 
@@ -935,6 +1009,8 @@ See [docs/modules/STREAMING.md](https://github.com/johnnichev/selectools/blob/ma
935
1009
  | **Anthropic** | Yes | Yes | Yes | Paid |
936
1010
  | **Gemini** | Yes | Yes | Yes | Free tier |
937
1011
  | **Ollama** | Yes | No | No | Free (local) |
1012
+ | **LiteLLM** | Yes | Yes | Yes | Varies (100+ models) |
1013
+ | **Router** | Yes | Yes | Yes | Varies (cost-routes tiers) |
938
1014
  | **Fallback** | Yes | Yes | Yes | Varies (wraps others) |
939
1015
  | **Local** | No | No | No | Free (testing) |
940
1016
 
@@ -1213,7 +1289,7 @@ pytest tests/ -x -q # All tests
1213
1289
  pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
1214
1290
  ```
1215
1291
 
1216
- 5343 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
1292
+ 5968 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, serve API, A2A, routing, and E2E integration with real API calls.
1217
1293
 
1218
1294
  ## License
1219
1295
 
@@ -30,6 +30,56 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
30
30
  # selectools serve agent.yaml
31
31
  ```
32
32
 
33
+ ## What's New in v0.24
34
+
35
+ ### v0.24.0 — Production Interop
36
+
37
+ Twelve features focused on running agents in production and connecting them to everything else: serve agents as REST APIs, talk to other agents over A2A, reach 100+ models through LiteLLM, route by cost, and persist memory anywhere.
38
+
39
+ - **Agent-as-API** — `selectools.serve.AgentAPI` turns any Agent (or list of agents) into a production Starlette ASGI app: `POST /v1/chat`, SSE streaming, session CRUD, bearer auth, per-user session isolation. CLI: `selectools serve agent.yaml --api --port 8000`.
40
+ - **A2A protocol** — `A2AServer` + `A2AClient` for agent-to-agent communication: Agent Card discovery (`/.well-known/agent.json`) and JSON-RPC 2.0 `message/send`/`tasks/get`/`tasks/cancel`.
41
+ - **LiteLLMProvider** — instant access to 100+ models (DeepSeek, Groq, Bedrock, ...) via `pip install selectools[litellm]`.
42
+ - **RouterProvider** — cost-optimized routing across model tiers with a deterministic complexity classifier and failure escalation.
43
+ - **Anthropic prompt caching** — opt-in `cache_system=True` / `cache_tools=True` with cache hit-rate fields on `UsageStats`.
44
+ - **UnifiedMemory** — tiered memory orchestrating conversation, knowledge, entity, and the new episodic tier, with token-aware compaction and federated `recall()`.
45
+ - **Cross-session search** — `store.search(query)` on all four SessionStore backends (FTS5-accelerated on SQLite).
46
+ - **KnowledgeBackend** — Supabase/Redis blob persistence for `KnowledgeMemory` on ephemeral infrastructure (Railway, Lambda, Cloud Run).
47
+ - **ToolResult + Artifact** — typed tool results with a `kind` discriminator, plus an `emit_artifact()` side-channel surfaced on `AgentResult.artifacts`.
48
+ - **Deferred confirmation flow** — `selectools.pending` for chat-channel destructive tools where the user's "yes" arrives as a separate webhook turn.
49
+ - **Toolbox expansion** — 15 new tools (33 → 48): safe calculator, email, PDF extraction, Slack, Notion, Linear.
50
+ - **Gemini schema sanitization** — bare `list` and `Dict[K, V]` tool parameters no longer 400 on the Gemini API; loud warnings for flash-lite's silent-empty-response failure mode.
51
+
52
+ ```python
53
+ from selectools.serve import AgentAPI
54
+
55
+ api = AgentAPI(agent, auth_key="secret") # ASGI app: uvicorn main:api
56
+ ```
57
+
58
+ See `CHANGELOG.md` for the full entry (5,968 tests, 106 examples).
59
+
60
+ ## What's New in v0.23
61
+
62
+ ### v0.23.0 — Supabase Sessions + Builder RAG
63
+
64
+ Two user-facing features plus a post-ship bug-hunt sweep that pinned 8 code-generator fixes in the visual builder.
65
+
66
+ - **`SupabaseSessionStore`** — 4th `SessionStore` backend alongside JSON, SQLite, and Redis. Postgres-backed via Supabase PostgREST, with idempotent upserts, namespace isolation, and the same validation guards as `RedisSessionStore`. Optional dep: `pip install selectools[supabase]`. Demo: [`examples/96_supabase_session_store.py`](https://github.com/johnnichev/selectools/blob/main/examples/96_supabase_session_store.py).
67
+
68
+ - **Visual builder: first-class RAG + session nodes** — drag `Retriever (RAG)` onto the canvas and pick any of 7 vector stores (memory, SQLite, Chroma, Pinecone, FAISS, Qdrant, pgvector), toggle Hybrid (BM25 + vector + RRF) and cross-encoder Rerank. Drag `Session Store` as a resource node and wire it into an agent via the new Session Store dropdown. Two new presets: **Hybrid RAG** and **Multi-Tenant RAG**. Python + YAML code generators emit real, runnable code.
69
+
70
+ ```python
71
+ from supabase import create_client
72
+ from selectools import SupabaseSessionStore, Agent, AgentConfig
73
+
74
+ store = SupabaseSessionStore(client=create_client(URL, KEY))
75
+ agent = Agent(
76
+ tools=[...],
77
+ config=AgentConfig(session_store=store, session_id="u-1", max_iterations=5),
78
+ )
79
+ ```
80
+
81
+ See `CHANGELOG.md` for the full entry including the 8 builder code-gen fixes.
82
+
33
83
  ## What's New in v0.22
34
84
 
35
85
  ### v0.22.0 — Competitor-Informed Bug Fixes
@@ -107,7 +157,7 @@ The first AI agent framework to ship a visual graph builder in a single `pip ins
107
157
 
108
158
  **[Try the builder in your browser →](https://selectools.dev/builder/)** — no install required.
109
159
 
110
- [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/johnnichev/selectools/blob/main/notebooks/getting_started.ipynb) [![Examples Gallery](https://img.shields.io/badge/examples-94_scripts-06b6d4)](https://selectools.dev/examples/)
160
+ [![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/johnnichev/selectools/blob/main/notebooks/getting_started.ipynb) [![Examples Gallery](https://img.shields.io/badge/examples-96_scripts-06b6d4)](https://selectools.dev/examples/)
111
161
 
112
162
  ```bash
113
163
  pip install selectools
@@ -164,7 +214,7 @@ Path("trace.html").write_text(trace_to_html(result.trace))
164
214
  - **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
165
215
  - **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
166
216
  - **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
167
- - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (5343 tests total)
217
+ - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (5332 tests total)
168
218
 
169
219
  ### v0.19.1 — Advanced Agent Patterns
170
220
 
@@ -476,7 +526,15 @@ report.to_html("report.html")
476
526
  | **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
477
527
  | **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
478
528
  | **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
479
- | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, and Redis backends. Auto-save/load with TTL expiry. |
529
+ | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and Supabase backends. Auto-save/load with TTL expiry, cross-session `search()`. |
530
+ | **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
531
+ | **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
532
+ | **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
533
+ | **Cost-Based Routing** | `RouterProvider` classifies request complexity and routes to model tiers with automatic failure escalation. |
534
+ | **Unified Memory** | `UnifiedMemory` orchestrates conversation, knowledge, entity, and episodic tiers with token-aware compaction and federated `recall()`. |
535
+ | **Typed Tool Results** | `ToolResult` base with `kind` discriminator; `emit_artifact()` side-channel surfaces files/URLs on `AgentResult.artifacts`. |
536
+ | **Deferred Confirmation** | `selectools.pending` — confirm destructive chat-channel tools across webhook turns with TTL, scope, and args-digest matching. |
537
+ | **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
480
538
  | **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
481
539
  | **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
482
540
  | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
@@ -491,7 +549,9 @@ report.to_html("report.html")
491
549
 
492
550
  ## What's Included
493
551
 
494
- - **5 LLM Providers**: OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama + FallbackProvider (auto-failover)
552
+ - **6 LLM Providers**: OpenAI, Azure OpenAI, Anthropic, Gemini, Ollama, LiteLLM (100+ models) + FallbackProvider (auto-failover) + RouterProvider (cost-based routing)
553
+ - **Agent-as-API**: `AgentAPI` — production REST endpoints (chat, SSE streaming, sessions) from any agent
554
+ - **A2A Protocol**: Agent Card discovery + JSON-RPC 2.0 agent-to-agent messaging
495
555
  - **Structured Output**: Pydantic / JSON Schema `response_format` with auto-retry
496
556
  - **Execution Traces**: `result.trace` with typed timeline of every agent step
497
557
  - **Reasoning Visibility**: `result.reasoning` explains *why* the agent chose a tool
@@ -504,9 +564,14 @@ report.to_html("report.html")
504
564
  - **Dynamic Tool Loading**: Plugin system with hot-reload support
505
565
  - **Response Caching**: InMemoryCache and RedisCache with stats tracking
506
566
  - **152 Model Registry**: Type-safe constants with pricing and metadata
507
- - **Pre-built Toolbox**: 24 tools for files, data, text, datetime, web
508
- - **Persistent Sessions**: 3 backends (JSON file, SQLite, Redis) with TTL
567
+ - **Pre-built Toolbox**: 48 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear
568
+ - **Persistent Sessions**: 4 backends (JSON file, SQLite, Redis, Supabase) with TTL and cross-session search
509
569
  - **Entity Memory**: LLM-based named entity extraction and tracking
570
+ - **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
571
+ - **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
572
+ - **Typed Tool Results**: `ToolResult` base class + `Artifact` side-channel via `emit_artifact()`
573
+ - **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
574
+ - **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
510
575
  - **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
511
576
  - **Cross-Session Knowledge**: Daily logs + persistent memory with `remember` tool, pluggable stores (File, SQLite), importance scoring, TTL
512
577
  - **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
@@ -517,10 +582,10 @@ report.to_html("report.html")
517
582
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
518
583
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
519
584
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
520
- - **76 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
585
+ - **106 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions (incl. Supabase), entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, agent-as-API, A2A, routing, unified memory, and more
521
586
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
522
587
  - **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
523
- - **5343 Tests**: Unit, integration, regression, and E2E with real API calls
588
+ - **5968 Tests**: Unit, integration, regression, and E2E with real API calls
524
589
 
525
590
  ## Install
526
591
 
@@ -866,6 +931,8 @@ See [docs/modules/STREAMING.md](https://github.com/johnnichev/selectools/blob/ma
866
931
  | **Anthropic** | Yes | Yes | Yes | Paid |
867
932
  | **Gemini** | Yes | Yes | Yes | Free tier |
868
933
  | **Ollama** | Yes | No | No | Free (local) |
934
+ | **LiteLLM** | Yes | Yes | Yes | Varies (100+ models) |
935
+ | **Router** | Yes | Yes | Yes | Varies (cost-routes tiers) |
869
936
  | **Fallback** | Yes | Yes | Yes | Varies (wraps others) |
870
937
  | **Local** | No | No | No | Free (testing) |
871
938
 
@@ -1144,7 +1211,7 @@ pytest tests/ -x -q # All tests
1144
1211
  pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
1145
1212
  ```
1146
1213
 
1147
- 5343 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
1214
+ 5968 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, serve API, A2A, routing, and E2E integration with real API calls.
1148
1215
 
1149
1216
  ## License
1150
1217
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "selectools"
7
- version = "0.22.0"
7
+ version = "0.24.0"
8
8
  description = "Production-ready Python framework for AI agents with multi-agent graphs, hybrid RAG, guardrails, audit logging, 50 evaluators, and a visual builder. Supports OpenAI, Anthropic, Gemini, Ollama. By NichevLabs."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -75,19 +75,31 @@ observe = [
75
75
  "opentelemetry-api>=1.20.0",
76
76
  "langfuse>=2.0.0",
77
77
  ]
78
+ toolbox = [
79
+ "requests>=2.28.0",
80
+ "slack-sdk>=3.27.0",
81
+ "pdfplumber>=0.11.0",
82
+ ]
78
83
  evals = [
79
84
  "pyyaml>=6.0.0",
80
85
  ]
81
86
  mcp = [
82
87
  "mcp>=1.0.0,<2.0.0",
83
88
  ]
89
+ litellm = [
90
+ "litellm>=1.0.0",
91
+ ]
84
92
  postgres = [
85
93
  "psycopg2-binary>=2.9.0",
86
94
  ]
95
+ supabase = [
96
+ "supabase>=2.0.0",
97
+ ]
87
98
  serve = [
88
99
  "pyyaml>=6.0.0",
89
100
  "starlette>=0.27.0",
90
101
  "uvicorn[standard]>=0.24.0",
102
+ "httpx>=0.24.0",
91
103
  ]
92
104
 
93
105
  [project.scripts]
@@ -1,6 +1,6 @@
1
1
  """Public exports for the selectools package."""
2
2
 
3
- __version__ = "0.22.0"
3
+ __version__ = "0.24.0"
4
4
 
5
5
  # Import submodules (lazy loading for optional dependencies)
6
6
  from . import embeddings, evals, guardrails, models, observe, patterns, rag, toolbox
@@ -50,11 +50,16 @@ from .guardrails import (
50
50
  )
51
51
  from .knowledge import (
52
52
  FileKnowledgeStore,
53
+ KnowledgeBackend,
53
54
  KnowledgeEntry,
54
55
  KnowledgeMemory,
55
56
  KnowledgeStore,
56
57
  SQLiteKnowledgeStore,
57
58
  )
59
+ from .knowledge_backends import (
60
+ RedisKnowledgeBackend,
61
+ SupabaseKnowledgeBackend,
62
+ )
58
63
  from .knowledge_graph import (
59
64
  InMemoryTripleStore,
60
65
  KnowledgeGraphMemory,
@@ -122,6 +127,20 @@ from .patterns import (
122
127
  TeamLeadAgent,
123
128
  TeamLeadResult,
124
129
  )
130
+ from .pending import (
131
+ ChannelAgent,
132
+ ConfirmOutcome,
133
+ ConfirmParser,
134
+ InMemoryPendingStore,
135
+ PendingAction,
136
+ PendingActionExistsError,
137
+ PendingActionStore,
138
+ PendingConfirmation,
139
+ RedisPendingStore,
140
+ RegexConfirmParser,
141
+ compute_args_digest,
142
+ stash_pending,
143
+ )
125
144
  from .pipeline import Pipeline, Step, StepResult, branch, cache_step, parallel, retry, step
126
145
  from .policy import PolicyDecision, PolicyResult, ToolPolicy
127
146
  from .pricing import PRICING, calculate_cost, calculate_embedding_cost, get_model_pricing
@@ -130,15 +149,19 @@ from .providers.anthropic_provider import AnthropicProvider
130
149
  from .providers.azure_openai_provider import AzureOpenAIProvider
131
150
  from .providers.fallback import FallbackProvider
132
151
  from .providers.gemini_provider import GeminiProvider
152
+ from .providers.litellm_provider import LiteLLMProvider
133
153
  from .providers.ollama_provider import OllamaProvider
134
154
  from .providers.openai_provider import OpenAIProvider
135
155
  from .providers.stubs import LocalProvider
156
+ from .results import Ambiguous, Artifact, NotFound, ToolResult, emit_artifact
136
157
  from .sessions import (
137
158
  JsonFileSessionStore,
138
159
  RedisSessionStore,
139
160
  SessionMetadata,
161
+ SessionSearchResult,
140
162
  SessionStore,
141
163
  SQLiteSessionStore,
164
+ SupabaseSessionStore,
142
165
  )
143
166
  from .stability import beta, deprecated, stable
144
167
  from .structured import ResponseFormat
@@ -146,6 +169,16 @@ from .token_estimation import TokenEstimate, estimate_run_tokens, estimate_token
146
169
  from .tools import Tool, ToolParameter, ToolRegistry, tool
147
170
  from .trace import AgentTrace, StepType, TraceStep, trace_to_html, trace_to_json
148
171
  from .types import AgentResult, ContentPart, Message, Role, ToolCall, image_message, text_content
172
+ from .unified_memory import (
173
+ DEFAULT_IMPORTANCE_RULES,
174
+ Episode,
175
+ EpisodicMemory,
176
+ ImportanceRule,
177
+ InMemoryKnowledgeStore,
178
+ RecallResult,
179
+ UnifiedMemory,
180
+ score_importance,
181
+ )
149
182
  from .usage import AgentUsage, UsageStats
150
183
 
151
184
  __all__ = [
@@ -171,6 +204,7 @@ __all__ = [
171
204
  "AnthropicProvider",
172
205
  "GeminiProvider",
173
206
  "OllamaProvider",
207
+ "LiteLLMProvider",
174
208
  "LocalProvider",
175
209
  "FallbackProvider",
176
210
  "ToolRegistry",
@@ -217,6 +251,25 @@ __all__ = [
217
251
  "PolicyResult",
218
252
  # Structured output
219
253
  "ResponseFormat",
254
+ # Typed tool results + artifact side-channel (issue #59)
255
+ "ToolResult",
256
+ "Ambiguous",
257
+ "NotFound",
258
+ "Artifact",
259
+ "emit_artifact",
260
+ # Deferred confirmation flow (issue #58)
261
+ "PendingAction",
262
+ "PendingActionStore",
263
+ "PendingActionExistsError",
264
+ "InMemoryPendingStore",
265
+ "RedisPendingStore",
266
+ "ConfirmOutcome",
267
+ "ConfirmParser",
268
+ "RegexConfirmParser",
269
+ "PendingConfirmation",
270
+ "ChannelAgent",
271
+ "stash_pending",
272
+ "compute_args_digest",
220
273
  # Stability markers
221
274
  "stable",
222
275
  "beta",
@@ -260,9 +313,11 @@ __all__ = [
260
313
  # Sessions
261
314
  "SessionStore",
262
315
  "SessionMetadata",
316
+ "SessionSearchResult",
263
317
  "JsonFileSessionStore",
264
318
  "SQLiteSessionStore",
265
319
  "RedisSessionStore",
320
+ "SupabaseSessionStore",
266
321
  # Entity Memory
267
322
  "Entity",
268
323
  "EntityMemory",
@@ -275,6 +330,10 @@ __all__ = [
275
330
  # Knowledge stores (optional deps: redis, supabase)
276
331
  # from selectools.knowledge_store_redis import RedisKnowledgeStore
277
332
  # from selectools.knowledge_store_supabase import SupabaseKnowledgeStore
333
+ # Knowledge backends (blob persistence between deploys; lazy optional deps)
334
+ "KnowledgeBackend",
335
+ "SupabaseKnowledgeBackend",
336
+ "RedisKnowledgeBackend",
278
337
  # Token estimation
279
338
  "TokenEstimate",
280
339
  "estimate_tokens",
@@ -285,6 +344,15 @@ __all__ = [
285
344
  "InMemoryTripleStore",
286
345
  "SQLiteTripleStore",
287
346
  "KnowledgeGraphMemory",
347
+ # Unified Memory (tiered memory with auto-promotion)
348
+ "UnifiedMemory",
349
+ "EpisodicMemory",
350
+ "Episode",
351
+ "ImportanceRule",
352
+ "InMemoryKnowledgeStore",
353
+ "RecallResult",
354
+ "DEFAULT_IMPORTANCE_RULES",
355
+ "score_importance",
288
356
  # Submodules (for lazy loading)
289
357
  "embeddings",
290
358
  "observe",
@@ -0,0 +1,54 @@
1
+ """
2
+ A2A protocol — agent-to-agent communication (Google-backed standard).
3
+
4
+ Serving::
5
+
6
+ from selectools.serve import A2AServer # or selectools.a2a
7
+
8
+ server = A2AServer(agent=my_agent, auth_token="sk-...")
9
+ server.serve(port=8000)
10
+
11
+ Consuming::
12
+
13
+ from selectools.a2a import A2AClient
14
+
15
+ client = A2AClient("https://other-agent.example.com")
16
+ card = await client.discover() # reads /.well-known/agent.json
17
+ result = await client.send_task("Research quantum computing trends")
18
+
19
+ The server requires ``starlette`` and the client requires ``httpx``
20
+ (both ship with ``pip install selectools[serve]``); imports are lazy so
21
+ this package loads without them.
22
+ """
23
+
24
+ from typing import Any
25
+
26
+ from .types import A2AError, A2ATask, AgentCard, AgentSkill, TaskState
27
+
28
+ __all__ = [
29
+ "A2AClient",
30
+ "A2AError",
31
+ "A2AServer",
32
+ "A2ATask",
33
+ "AgentCard",
34
+ "AgentSkill",
35
+ "TaskState",
36
+ ]
37
+
38
+
39
+ def __getattr__(name: str) -> Any:
40
+ """Lazily import the server (starlette) and client (httpx)."""
41
+ if name == "A2AServer":
42
+ try:
43
+ from .server import A2AServer
44
+ except ImportError as exc:
45
+ raise ImportError(
46
+ "A2AServer requires the 'starlette' package. "
47
+ "Install it with: pip install selectools[serve]"
48
+ ) from exc
49
+ return A2AServer
50
+ if name == "A2AClient":
51
+ from .client import A2AClient
52
+
53
+ return A2AClient
54
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")