selectools 0.28.0__tar.gz → 1.0.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 (321) hide show
  1. {selectools-0.28.0/src/selectools.egg-info → selectools-1.0.0}/PKG-INFO +40 -12
  2. {selectools-0.28.0 → selectools-1.0.0}/README.md +37 -8
  3. {selectools-0.28.0 → selectools-1.0.0}/pyproject.toml +4 -5
  4. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/__init__.py +1 -1
  5. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/_async_utils.py +7 -30
  6. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/_tool_executor.py +1 -1
  7. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/config.py +1 -1
  8. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/core.py +1 -1
  9. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/cache.py +1 -1
  10. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/cache_semantic.py +1 -1
  11. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/evaluators.py +1 -1
  12. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/pairwise.py +1 -1
  13. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/topic.py +1 -1
  14. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge.py +1 -1
  15. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge_graph.py +1 -1
  16. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/loop_detection.py +1 -1
  17. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/observe/trace_store.py +1 -1
  18. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/__init__.py +1 -1
  19. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/checkpoint.py +2 -2
  20. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/graph.py +3 -3
  21. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/node.py +1 -1
  22. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/state.py +1 -1
  23. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/orchestration/supervisor.py +1 -1
  24. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/patterns/__init__.py +1 -1
  25. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/patterns/debate.py +1 -1
  26. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/patterns/plan_and_execute.py +1 -1
  27. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/patterns/reflective.py +1 -1
  28. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/patterns/team_lead.py +1 -1
  29. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/policy.py +1 -1
  30. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/base.py +1 -1
  31. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/chunking.py +2 -2
  32. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/hybrid.py +2 -2
  33. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/faiss.py +1 -1
  34. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/pgvector.py +1 -1
  35. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/pinecone.py +1 -1
  36. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/qdrant.py +1 -1
  37. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/sqlite.py +1 -1
  38. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/sessions.py +1 -1
  39. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/stability.py +2 -2
  40. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/calculator_tools.py +3 -3
  41. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/code_tools.py +3 -3
  42. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/db_tools.py +3 -3
  43. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/email_tools.py +3 -3
  44. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/github_tools.py +4 -4
  45. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/linear_tools.py +4 -4
  46. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/notion_tools.py +4 -4
  47. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/pdf_tools.py +3 -3
  48. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/search_tools.py +3 -3
  49. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/slack_tools.py +4 -4
  50. {selectools-0.28.0 → selectools-1.0.0/src/selectools.egg-info}/PKG-INFO +40 -12
  51. {selectools-0.28.0 → selectools-1.0.0}/tests/test_architecture.py +12 -12
  52. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_integration.py +4 -1
  53. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions_supabase.py +31 -0
  54. {selectools-0.28.0 → selectools-1.0.0}/LICENSE +0 -0
  55. {selectools-0.28.0 → selectools-1.0.0}/setup.cfg +0 -0
  56. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/_json_utils.py +0 -0
  57. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/_ssrf.py +0 -0
  58. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/a2a/__init__.py +0 -0
  59. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/a2a/client.py +0 -0
  60. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/a2a/server.py +0 -0
  61. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/a2a/types.py +0 -0
  62. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/__init__.py +0 -0
  63. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/_lifecycle.py +0 -0
  64. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/_memory_manager.py +0 -0
  65. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/_planning.py +0 -0
  66. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/_provider_caller.py +0 -0
  67. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/agent/config_groups.py +0 -0
  68. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/analytics.py +0 -0
  69. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/audit.py +0 -0
  70. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/cache_redis.py +0 -0
  71. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/cancellation.py +0 -0
  72. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/checkpoint_postgres.py +0 -0
  73. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/coherence.py +0 -0
  74. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/compose.py +0 -0
  75. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/__init__.py +0 -0
  76. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/anthropic.py +0 -0
  77. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/cohere.py +0 -0
  78. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/gemini.py +0 -0
  79. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/openai.py +0 -0
  80. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/embeddings/provider.py +0 -0
  81. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/entity_memory.py +0 -0
  82. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/env.py +0 -0
  83. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/__init__.py +0 -0
  84. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/__main__.py +0 -0
  85. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/badge.py +0 -0
  86. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/dataset.py +0 -0
  87. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/generator.py +0 -0
  88. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/history.py +0 -0
  89. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/html.py +0 -0
  90. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/junit.py +0 -0
  91. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/llm_evaluators.py +0 -0
  92. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/regression.py +0 -0
  93. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/report.py +0 -0
  94. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/serve.py +0 -0
  95. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/snapshot.py +0 -0
  96. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/suite.py +0 -0
  97. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/templates.py +0 -0
  98. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/evals/types.py +0 -0
  99. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/exceptions.py +0 -0
  100. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/__init__.py +0 -0
  101. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/base.py +0 -0
  102. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/format.py +0 -0
  103. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/injection.py +0 -0
  104. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/length.py +0 -0
  105. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/pii.py +0 -0
  106. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/pipeline.py +0 -0
  107. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/guardrails/toxicity.py +0 -0
  108. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge_backends.py +0 -0
  109. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge_sanitizers.py +0 -0
  110. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge_store_redis.py +0 -0
  111. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/knowledge_store_supabase.py +0 -0
  112. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/__init__.py +0 -0
  113. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/_loop.py +0 -0
  114. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/bridge.py +0 -0
  115. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/client.py +0 -0
  116. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/config.py +0 -0
  117. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/multi.py +0 -0
  118. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/mcp/server.py +0 -0
  119. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/memory.py +0 -0
  120. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/models.py +0 -0
  121. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/observe/__init__.py +0 -0
  122. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/observe/langfuse.py +0 -0
  123. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/observe/otel.py +0 -0
  124. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/observer.py +0 -0
  125. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/parser.py +0 -0
  126. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/pending.py +0 -0
  127. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/pipeline.py +0 -0
  128. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/pricing.py +0 -0
  129. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/prompt.py +0 -0
  130. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/__init__.py +0 -0
  131. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/_openai_compat.py +0 -0
  132. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/anthropic_provider.py +0 -0
  133. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/azure_openai_provider.py +0 -0
  134. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/fallback.py +0 -0
  135. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/gemini_provider.py +0 -0
  136. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/litellm_provider.py +0 -0
  137. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/ollama_provider.py +0 -0
  138. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/openai_provider.py +0 -0
  139. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/router.py +0 -0
  140. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/providers/stubs.py +0 -0
  141. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/__init__.py +0 -0
  142. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/bm25.py +0 -0
  143. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/loaders.py +0 -0
  144. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/reranker.py +0 -0
  145. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/__init__.py +0 -0
  146. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/chroma.py +0 -0
  147. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/stores/memory.py +0 -0
  148. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/tools.py +0 -0
  149. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/rag/vector_store.py +0 -0
  150. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/results.py +0 -0
  151. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/scheduler.py +0 -0
  152. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/security.py +0 -0
  153. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/__init__.py +0 -0
  154. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/_starlette_app.py +0 -0
  155. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/_static/builder.css +0 -0
  156. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/_static/builder.html +0 -0
  157. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/_static/builder.js +0 -0
  158. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/api.py +0 -0
  159. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/app.py +0 -0
  160. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/builder.py +0 -0
  161. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/cli.py +0 -0
  162. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/models.py +0 -0
  163. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/serve/playground.py +0 -0
  164. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/structured.py +0 -0
  165. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/__init__.py +0 -0
  166. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/code_reviewer.py +0 -0
  167. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/customer_support.py +0 -0
  168. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/data_analyst.py +0 -0
  169. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/rag_chatbot.py +0 -0
  170. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/templates/research_assistant.py +0 -0
  171. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/token_estimation.py +0 -0
  172. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/__init__.py +0 -0
  173. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/browser_tools.py +0 -0
  174. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/data_tools.py +0 -0
  175. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/datetime_tools.py +0 -0
  176. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/discord_tools.py +0 -0
  177. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/file_tools.py +0 -0
  178. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/image_tools.py +0 -0
  179. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/memory_tools.py +0 -0
  180. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/reasoning_tools.py +0 -0
  181. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/s3_tools.py +0 -0
  182. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/text_tools.py +0 -0
  183. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/toolbox/web_tools.py +0 -0
  184. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/tools/__init__.py +0 -0
  185. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/tools/base.py +0 -0
  186. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/tools/decorators.py +0 -0
  187. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/tools/loader.py +0 -0
  188. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/tools/registry.py +0 -0
  189. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/trace.py +0 -0
  190. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/types.py +0 -0
  191. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/unified_memory.py +0 -0
  192. {selectools-0.28.0 → selectools-1.0.0}/src/selectools/usage.py +0 -0
  193. {selectools-0.28.0 → selectools-1.0.0}/src/selectools.egg-info/SOURCES.txt +0 -0
  194. {selectools-0.28.0 → selectools-1.0.0}/src/selectools.egg-info/dependency_links.txt +0 -0
  195. {selectools-0.28.0 → selectools-1.0.0}/src/selectools.egg-info/entry_points.txt +0 -0
  196. {selectools-0.28.0 → selectools-1.0.0}/src/selectools.egg-info/requires.txt +0 -0
  197. {selectools-0.28.0 → selectools-1.0.0}/src/selectools.egg-info/top_level.txt +0 -0
  198. {selectools-0.28.0 → selectools-1.0.0}/tests/test_a2a.py +0 -0
  199. {selectools-0.28.0 → selectools-1.0.0}/tests/test_agent_api.py +0 -0
  200. {selectools-0.28.0 → selectools-1.0.0}/tests/test_agent_hitl.py +0 -0
  201. {selectools-0.28.0 → selectools-1.0.0}/tests/test_approval_gate.py +0 -0
  202. {selectools-0.28.0 → selectools-1.0.0}/tests/test_async_observers.py +0 -0
  203. {selectools-0.28.0 → selectools-1.0.0}/tests/test_audit.py +0 -0
  204. {selectools-0.28.0 → selectools-1.0.0}/tests/test_bake_window_hunt.py +0 -0
  205. {selectools-0.28.0 → selectools-1.0.0}/tests/test_budget.py +0 -0
  206. {selectools-0.28.0 → selectools-1.0.0}/tests/test_bug_hunt_batch1_core.py +0 -0
  207. {selectools-0.28.0 → selectools-1.0.0}/tests/test_bug_hunt_batch1_security.py +0 -0
  208. {selectools-0.28.0 → selectools-1.0.0}/tests/test_bug_hunt_batch1_tools.py +0 -0
  209. {selectools-0.28.0 → selectools-1.0.0}/tests/test_bug_hunt_regression.py +0 -0
  210. {selectools-0.28.0 → selectools-1.0.0}/tests/test_cache.py +0 -0
  211. {selectools-0.28.0 → selectools-1.0.0}/tests/test_cache_redis.py +0 -0
  212. {selectools-0.28.0 → selectools-1.0.0}/tests/test_cancellation.py +0 -0
  213. {selectools-0.28.0 → selectools-1.0.0}/tests/test_checkpoint_postgres.py +0 -0
  214. {selectools-0.28.0 → selectools-1.0.0}/tests/test_coherence.py +0 -0
  215. {selectools-0.28.0 → selectools-1.0.0}/tests/test_concurrency_smoke.py +0 -0
  216. {selectools-0.28.0 → selectools-1.0.0}/tests/test_consolidation_regression.py +0 -0
  217. {selectools-0.28.0 → selectools-1.0.0}/tests/test_conversation_branching.py +0 -0
  218. {selectools-0.28.0 → selectools-1.0.0}/tests/test_coverage_orchestration.py +0 -0
  219. {selectools-0.28.0 → selectools-1.0.0}/tests/test_document_loaders_extended.py +0 -0
  220. {selectools-0.28.0 → selectools-1.0.0}/tests/test_e2e_langfuse_observer.py +0 -0
  221. {selectools-0.28.0 → selectools-1.0.0}/tests/test_e2e_multimodal.py +0 -0
  222. {selectools-0.28.0 → selectools-1.0.0}/tests/test_e2e_otel_observer.py +0 -0
  223. {selectools-0.28.0 → selectools-1.0.0}/tests/test_e2e_v0_21_0_apps.py +0 -0
  224. {selectools-0.28.0 → selectools-1.0.0}/tests/test_e2e_v0_21_0_simulations.py +0 -0
  225. {selectools-0.28.0 → selectools-1.0.0}/tests/test_entity_memory.py +0 -0
  226. {selectools-0.28.0 → selectools-1.0.0}/tests/test_env.py +0 -0
  227. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals.py +0 -0
  228. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_advanced.py +0 -0
  229. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_cli.py +0 -0
  230. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_e2e.py +0 -0
  231. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_final.py +0 -0
  232. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_hardening.py +0 -0
  233. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_html_report.py +0 -0
  234. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_new_evaluators.py +0 -0
  235. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_ralph_bugs.py +0 -0
  236. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_release.py +0 -0
  237. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_serve.py +0 -0
  238. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_v017_features.py +0 -0
  239. {selectools-0.28.0 → selectools-1.0.0}/tests/test_evals_v0191.py +0 -0
  240. {selectools-0.28.0 → selectools-1.0.0}/tests/test_features_in_graph.py +0 -0
  241. {selectools-0.28.0 → selectools-1.0.0}/tests/test_final_coverage_a.py +0 -0
  242. {selectools-0.28.0 → selectools-1.0.0}/tests/test_final_coverage_b.py +0 -0
  243. {selectools-0.28.0 → selectools-1.0.0}/tests/test_guardrails.py +0 -0
  244. {selectools-0.28.0 → selectools-1.0.0}/tests/test_guardrails_injection.py +0 -0
  245. {selectools-0.28.0 → selectools-1.0.0}/tests/test_hardening.py +0 -0
  246. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge.py +0 -0
  247. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_backend.py +0 -0
  248. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_backend_redis.py +0 -0
  249. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_backend_supabase.py +0 -0
  250. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_graph.py +0 -0
  251. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_sanitizers.py +0 -0
  252. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_store_redis.py +0 -0
  253. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_store_supabase.py +0 -0
  254. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_stores.py +0 -0
  255. {selectools-0.28.0 → selectools-1.0.0}/tests/test_knowledge_stores_error_handling.py +0 -0
  256. {selectools-0.28.0 → selectools-1.0.0}/tests/test_langfuse_observer.py +0 -0
  257. {selectools-0.28.0 → selectools-1.0.0}/tests/test_loop_detection.py +0 -0
  258. {selectools-0.28.0 → selectools-1.0.0}/tests/test_mcp.py +0 -0
  259. {selectools-0.28.0 → selectools-1.0.0}/tests/test_mcp_coverage.py +0 -0
  260. {selectools-0.28.0 → selectools-1.0.0}/tests/test_memory.py +0 -0
  261. {selectools-0.28.0 → selectools-1.0.0}/tests/test_memory_async.py +0 -0
  262. {selectools-0.28.0 → selectools-1.0.0}/tests/test_memory_boundary.py +0 -0
  263. {selectools-0.28.0 → selectools-1.0.0}/tests/test_memory_integration.py +0 -0
  264. {selectools-0.28.0 → selectools-1.0.0}/tests/test_model_switching.py +0 -0
  265. {selectools-0.28.0 → selectools-1.0.0}/tests/test_multi_agent_edge_cases.py +0 -0
  266. {selectools-0.28.0 → selectools-1.0.0}/tests/test_multimodal.py +0 -0
  267. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_checkpoint.py +0 -0
  268. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_e2e.py +0 -0
  269. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_evals.py +0 -0
  270. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_graph.py +0 -0
  271. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_primitives.py +0 -0
  272. {selectools-0.28.0 → selectools-1.0.0}/tests/test_orchestration_supervisor.py +0 -0
  273. {selectools-0.28.0 → selectools-1.0.0}/tests/test_otel_observer.py +0 -0
  274. {selectools-0.28.0 → selectools-1.0.0}/tests/test_parser.py +0 -0
  275. {selectools-0.28.0 → selectools-1.0.0}/tests/test_patterns.py +0 -0
  276. {selectools-0.28.0 → selectools-1.0.0}/tests/test_pending.py +0 -0
  277. {selectools-0.28.0 → selectools-1.0.0}/tests/test_pending_redis_smoke.py +0 -0
  278. {selectools-0.28.0 → selectools-1.0.0}/tests/test_phase1_design_patterns.py +0 -0
  279. {selectools-0.28.0 → selectools-1.0.0}/tests/test_pipeline.py +0 -0
  280. {selectools-0.28.0 → selectools-1.0.0}/tests/test_pipeline_coverage.py +0 -0
  281. {selectools-0.28.0 → selectools-1.0.0}/tests/test_policy.py +0 -0
  282. {selectools-0.28.0 → selectools-1.0.0}/tests/test_prompt.py +0 -0
  283. {selectools-0.28.0 → selectools-1.0.0}/tests/test_prompt_compression.py +0 -0
  284. {selectools-0.28.0 → selectools-1.0.0}/tests/test_property_based.py +0 -0
  285. {selectools-0.28.0 → selectools-1.0.0}/tests/test_reasoning_strategy.py +0 -0
  286. {selectools-0.28.0 → selectools-1.0.0}/tests/test_remaining_coverage.py +0 -0
  287. {selectools-0.28.0 → selectools-1.0.0}/tests/test_results.py +0 -0
  288. {selectools-0.28.0 → selectools-1.0.0}/tests/test_routing_mode.py +0 -0
  289. {selectools-0.28.0 → selectools-1.0.0}/tests/test_scheduler.py +0 -0
  290. {selectools-0.28.0 → selectools-1.0.0}/tests/test_security.py +0 -0
  291. {selectools-0.28.0 → selectools-1.0.0}/tests/test_semantic_cache.py +0 -0
  292. {selectools-0.28.0 → selectools-1.0.0}/tests/test_serve_app_coverage.py +0 -0
  293. {selectools-0.28.0 → selectools-1.0.0}/tests/test_serve_cli.py +0 -0
  294. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions.py +0 -0
  295. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions_dynamodb.py +0 -0
  296. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions_edge_cases.py +0 -0
  297. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions_mongo.py +0 -0
  298. {selectools-0.28.0 → selectools-1.0.0}/tests/test_sessions_redis.py +0 -0
  299. {selectools-0.28.0 → selectools-1.0.0}/tests/test_simple_observer.py +0 -0
  300. {selectools-0.28.0 → selectools-1.0.0}/tests/test_simulation_evals.py +0 -0
  301. {selectools-0.28.0 → selectools-1.0.0}/tests/test_ssrf.py +0 -0
  302. {selectools-0.28.0 → selectools-1.0.0}/tests/test_stability.py +0 -0
  303. {selectools-0.28.0 → selectools-1.0.0}/tests/test_starlette_app.py +0 -0
  304. {selectools-0.28.0 → selectools-1.0.0}/tests/test_structured.py +0 -0
  305. {selectools-0.28.0 → selectools-1.0.0}/tests/test_structured_config.py +0 -0
  306. {selectools-0.28.0 → selectools-1.0.0}/tests/test_structured_tool_results.py +0 -0
  307. {selectools-0.28.0 → selectools-1.0.0}/tests/test_summarize_on_trim.py +0 -0
  308. {selectools-0.28.0 → selectools-1.0.0}/tests/test_templates_coverage.py +0 -0
  309. {selectools-0.28.0 → selectools-1.0.0}/tests/test_terminal_actions.py +0 -0
  310. {selectools-0.28.0 → selectools-1.0.0}/tests/test_token_estimation.py +0 -0
  311. {selectools-0.28.0 → selectools-1.0.0}/tests/test_tool_caching.py +0 -0
  312. {selectools-0.28.0 → selectools-1.0.0}/tests/test_tool_result_compression.py +0 -0
  313. {selectools-0.28.0 → selectools-1.0.0}/tests/test_trace.py +0 -0
  314. {selectools-0.28.0 → selectools-1.0.0}/tests/test_trace_html.py +0 -0
  315. {selectools-0.28.0 → selectools-1.0.0}/tests/test_trace_store.py +0 -0
  316. {selectools-0.28.0 → selectools-1.0.0}/tests/test_unified_memory.py +0 -0
  317. {selectools-0.28.0 → selectools-1.0.0}/tests/test_unified_memory_config.py +0 -0
  318. {selectools-0.28.0 → selectools-1.0.0}/tests/test_v016_regression.py +0 -0
  319. {selectools-0.28.0 → selectools-1.0.0}/tests/test_v019_features.py +0 -0
  320. {selectools-0.28.0 → selectools-1.0.0}/tests/test_visual_builder.py +0 -0
  321. {selectools-0.28.0 → selectools-1.0.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.28.0
3
+ Version: 1.0.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>
@@ -14,17 +14,16 @@ Project-URL: Builder, https://selectools.dev/builder/
14
14
  Project-URL: Examples, https://selectools.dev/examples/
15
15
  Project-URL: NichevLabs, https://nichevlabs.com
16
16
  Keywords: llm,ai,agent,agents,multi-agent,agent-framework,tool-calling,openai,anthropic,gemini,ollama,rag,hybrid-search,vector-search,embeddings,guardrails,evals,evaluators,visual-builder,structured-output,observability,fallback,langchain-alternative
17
- Classifier: Development Status :: 4 - Beta
17
+ Classifier: Development Status :: 5 - Production/Stable
18
18
  Classifier: Intended Audience :: Developers
19
19
  Classifier: Programming Language :: Python :: 3
20
- Classifier: Programming Language :: Python :: 3.9
21
20
  Classifier: Programming Language :: Python :: 3.10
22
21
  Classifier: Programming Language :: Python :: 3.11
23
22
  Classifier: Programming Language :: Python :: 3.12
24
23
  Classifier: Programming Language :: Python :: 3.13
25
24
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
25
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
27
- Requires-Python: >=3.9
26
+ Requires-Python: >=3.10
28
27
  Description-Content-Type: text/markdown
29
28
  License-File: LICENSE
30
29
  Requires-Dist: openai<2.0.0,>=1.30.0
@@ -118,6 +117,29 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
118
117
  # selectools serve agent.yaml
119
118
  ```
120
119
 
120
+ ## What's New in v1.0
121
+
122
+ ### v1.0.0 — Stable
123
+
124
+ selectools is **1.0**. The public API is frozen and `@stable` symbols now carry a real compatibility promise — no removal or breaking signature change without a deprecation cycle spanning at least two minor releases. The package is `Development Status :: 5 - Production/Stable`.
125
+
126
+ - **Frozen, marked surface** — every public symbol carries a `@stable`/`@beta` marker (CI-enforced). The stable set covers the agent loop and config, providers, tools and the mature toolbox, sessions, memory, guardrails, orchestration graphs, the pattern agents, the policy layer, and the core types. RAG/embeddings, MCP, A2A, the evaluator catalog, unified memory, the scheduler, and the newest backends stay `@beta` and keep evolving in 1.x.
127
+ - **Python 3.10+** *(breaking)* — Python 3.9 reached end-of-life in October 2025 and is dropped; the minimum is now 3.10 (CI runs 3.10–3.13). Pin `selectools<1.0` to stay on 3.9.
128
+ - Aside from the 3.9 drop, code that ran deprecation-warning-free on the latest 0.x release runs unmodified on 1.0. See `docs/MIGRATION_1.0.md`.
129
+
130
+ ## What's New in v0.29
131
+
132
+ ### v0.29.0 — Stability Promotions (v1.0 Freeze Prep)
133
+
134
+ The first beta → stable promotion pass toward the 1.0 API freeze. Additive only — promotions strengthen guarantees, nothing is removed or renamed.
135
+
136
+ - **24 mature toolbox tools promoted to `@stable`** — calculator, code (incl. `execute_shell`), db, email, GitHub, Linear, Notion, PDF, web search, and Slack tools. They're 4–15 releases old with frozen signatures.
137
+ - **`orchestration`, `patterns`, and `policy` are now stable modules** — their public surfaces (AgentGraph, the checkpoint stores, all five pattern agents, ToolPolicy) were already frozen in v0.25; this aligns the module-level promise. Also promoted `SessionSearchResult` and `PlanningConfig`.
138
+ - **Held `@beta` on purpose** — the v0.27.0 additions (recall tool, injection guardrail, cache-rate cost, Mongo/Dynamo session stores) get one more cycle, and `evals` stays a beta module while its 50 evaluator classes keep growing (its 7 core types are `@stable`).
139
+ - **New `scripts/stability_audit.py`** reports any symbol whose marker disagrees with its module promise, so promotion passes are reproducible.
140
+
141
+ See `CHANGELOG.md` for the full entry.
142
+
121
143
  ## What's New in v0.28
122
144
 
123
145
  ### v0.28.0 — Hardening Sweep: Shell Safety, Session Namespaces & Typed Public API
@@ -336,19 +358,25 @@ selectools serve --builder
336
358
 
337
359
  ### v0.19.3 — Stability Markers Applied to All Public APIs
338
360
 
339
- Every public class and function exported from `selectools` now carries a stability marker:
361
+ Every public class and function exported from `selectools` carries a stability
362
+ marker. As of 1.0, `@stable` symbols carry a compatibility promise — no removal
363
+ or breaking signature change without a deprecation cycle of at least two minors:
340
364
 
341
365
  ```python
342
- from selectools import Agent, AgentGraph, PlanAndExecuteAgent
366
+ from selectools import Agent, AgentGraph, AgentScheduler
343
367
 
344
- print(Agent.__stability__) # "stable"
345
- print(AgentGraph.__stability__) # "beta"
346
- print(PlanAndExecuteAgent.__stability__) # "beta"
368
+ print(Agent.__stability__) # "stable"
369
+ print(AgentGraph.__stability__) # "stable" (promoted for 1.0)
370
+ print(AgentScheduler.__stability__) # "beta" (still iterating)
347
371
  ```
348
372
 
349
- **`@stable`** — 60+ core symbols (Agent, AgentConfig, providers, memory, tools, evals, guardrails, sessions, knowledge, cache, cancellation)
373
+ **`@stable`** — the frozen core: Agent, AgentConfig, providers, memory, tools and
374
+ the mature toolbox, sessions, guardrails, orchestration graphs, the pattern
375
+ agents, the policy layer, and the core types.
350
376
 
351
- **`@beta`** — 30+ newer symbols (AgentGraph, SupervisorAgent, Pipeline, @step, parallel, branch, all four patterns, compose)
377
+ **`@beta`** — subsystems still evolving in 1.x: RAG/embeddings, MCP, A2A, the
378
+ evaluator catalog, unified memory, the scheduler, and the newest backends. Run
379
+ `python scripts/stability_audit.py` for the live marker map.
352
380
 
353
381
  ### v0.19.2 — Enterprise Hardening
354
382
 
@@ -542,7 +570,7 @@ def web_search(query: str) -> str:
542
570
  return expensive_api_call(query)
543
571
  ```
544
572
 
545
- Also: Python 3.9–3.13 CI matrix (verified zero compatibility issues).
573
+ Also: Python 3.10–3.13 CI matrix (verified zero compatibility issues).
546
574
 
547
575
  </details>
548
576
 
@@ -30,6 +30,29 @@ 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 v1.0
34
+
35
+ ### v1.0.0 — Stable
36
+
37
+ selectools is **1.0**. The public API is frozen and `@stable` symbols now carry a real compatibility promise — no removal or breaking signature change without a deprecation cycle spanning at least two minor releases. The package is `Development Status :: 5 - Production/Stable`.
38
+
39
+ - **Frozen, marked surface** — every public symbol carries a `@stable`/`@beta` marker (CI-enforced). The stable set covers the agent loop and config, providers, tools and the mature toolbox, sessions, memory, guardrails, orchestration graphs, the pattern agents, the policy layer, and the core types. RAG/embeddings, MCP, A2A, the evaluator catalog, unified memory, the scheduler, and the newest backends stay `@beta` and keep evolving in 1.x.
40
+ - **Python 3.10+** *(breaking)* — Python 3.9 reached end-of-life in October 2025 and is dropped; the minimum is now 3.10 (CI runs 3.10–3.13). Pin `selectools<1.0` to stay on 3.9.
41
+ - Aside from the 3.9 drop, code that ran deprecation-warning-free on the latest 0.x release runs unmodified on 1.0. See `docs/MIGRATION_1.0.md`.
42
+
43
+ ## What's New in v0.29
44
+
45
+ ### v0.29.0 — Stability Promotions (v1.0 Freeze Prep)
46
+
47
+ The first beta → stable promotion pass toward the 1.0 API freeze. Additive only — promotions strengthen guarantees, nothing is removed or renamed.
48
+
49
+ - **24 mature toolbox tools promoted to `@stable`** — calculator, code (incl. `execute_shell`), db, email, GitHub, Linear, Notion, PDF, web search, and Slack tools. They're 4–15 releases old with frozen signatures.
50
+ - **`orchestration`, `patterns`, and `policy` are now stable modules** — their public surfaces (AgentGraph, the checkpoint stores, all five pattern agents, ToolPolicy) were already frozen in v0.25; this aligns the module-level promise. Also promoted `SessionSearchResult` and `PlanningConfig`.
51
+ - **Held `@beta` on purpose** — the v0.27.0 additions (recall tool, injection guardrail, cache-rate cost, Mongo/Dynamo session stores) get one more cycle, and `evals` stays a beta module while its 50 evaluator classes keep growing (its 7 core types are `@stable`).
52
+ - **New `scripts/stability_audit.py`** reports any symbol whose marker disagrees with its module promise, so promotion passes are reproducible.
53
+
54
+ See `CHANGELOG.md` for the full entry.
55
+
33
56
  ## What's New in v0.28
34
57
 
35
58
  ### v0.28.0 — Hardening Sweep: Shell Safety, Session Namespaces & Typed Public API
@@ -248,19 +271,25 @@ selectools serve --builder
248
271
 
249
272
  ### v0.19.3 — Stability Markers Applied to All Public APIs
250
273
 
251
- Every public class and function exported from `selectools` now carries a stability marker:
274
+ Every public class and function exported from `selectools` carries a stability
275
+ marker. As of 1.0, `@stable` symbols carry a compatibility promise — no removal
276
+ or breaking signature change without a deprecation cycle of at least two minors:
252
277
 
253
278
  ```python
254
- from selectools import Agent, AgentGraph, PlanAndExecuteAgent
279
+ from selectools import Agent, AgentGraph, AgentScheduler
255
280
 
256
- print(Agent.__stability__) # "stable"
257
- print(AgentGraph.__stability__) # "beta"
258
- print(PlanAndExecuteAgent.__stability__) # "beta"
281
+ print(Agent.__stability__) # "stable"
282
+ print(AgentGraph.__stability__) # "stable" (promoted for 1.0)
283
+ print(AgentScheduler.__stability__) # "beta" (still iterating)
259
284
  ```
260
285
 
261
- **`@stable`** — 60+ core symbols (Agent, AgentConfig, providers, memory, tools, evals, guardrails, sessions, knowledge, cache, cancellation)
286
+ **`@stable`** — the frozen core: Agent, AgentConfig, providers, memory, tools and
287
+ the mature toolbox, sessions, guardrails, orchestration graphs, the pattern
288
+ agents, the policy layer, and the core types.
262
289
 
263
- **`@beta`** — 30+ newer symbols (AgentGraph, SupervisorAgent, Pipeline, @step, parallel, branch, all four patterns, compose)
290
+ **`@beta`** — subsystems still evolving in 1.x: RAG/embeddings, MCP, A2A, the
291
+ evaluator catalog, unified memory, the scheduler, and the newest backends. Run
292
+ `python scripts/stability_audit.py` for the live marker map.
264
293
 
265
294
  ### v0.19.2 — Enterprise Hardening
266
295
 
@@ -454,7 +483,7 @@ def web_search(query: str) -> str:
454
483
  return expensive_api_call(query)
455
484
  ```
456
485
 
457
- Also: Python 3.9–3.13 CI matrix (verified zero compatibility issues).
486
+ Also: Python 3.10–3.13 CI matrix (verified zero compatibility issues).
458
487
 
459
488
  </details>
460
489
 
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "selectools"
7
- version = "0.28.0"
7
+ version = "1.0.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
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  license = "Apache-2.0"
12
12
  authors = [{name = "John Nichev", email = "johnnichev@gmail.com"}]
13
13
  maintainers = [{name = "NichevLabs", email = "support@nichevlabs.com"}]
@@ -25,10 +25,9 @@ keywords = [
25
25
  "structured-output", "observability", "fallback", "langchain-alternative",
26
26
  ]
27
27
  classifiers = [
28
- "Development Status :: 4 - Beta",
28
+ "Development Status :: 5 - Production/Stable",
29
29
  "Intended Audience :: Developers",
30
30
  "Programming Language :: Python :: 3",
31
- "Programming Language :: Python :: 3.9",
32
31
  "Programming Language :: Python :: 3.10",
33
32
  "Programming Language :: Python :: 3.11",
34
33
  "Programming Language :: Python :: 3.12",
@@ -130,7 +129,7 @@ where = ["src"]
130
129
 
131
130
  [tool.ruff]
132
131
  line-length = 100
133
- target-version = "py39"
132
+ target-version = "py310"
134
133
  extend-exclude = [
135
134
  ".eggs",
136
135
  ".git",
@@ -1,6 +1,6 @@
1
1
  """Public exports for the selectools package."""
2
2
 
3
- __version__ = "0.28.0"
3
+ __version__ = "1.0.0"
4
4
 
5
5
  # Import submodules (lazy loading for optional dependencies)
6
6
  from . import embeddings, evals, guardrails, models, observe, patterns, rag, toolbox
@@ -16,8 +16,15 @@ import asyncio
16
16
  import contextvars
17
17
  import threading
18
18
  from concurrent.futures import ThreadPoolExecutor
19
+ from contextlib import aclosing
19
20
  from typing import Any, Awaitable, Callable, Optional, TypeVar
20
21
 
22
+ # ``aclosing`` is re-exported from this module so existing call sites
23
+ # (agent._provider_caller, agent.core) and the regression test that imports it
24
+ # from here are unchanged. It was a local backport while selectools supported
25
+ # 3.9; the floor is now >=3.10, where ``contextlib.aclosing`` is stdlib.
26
+ __all__ = ["aclosing", "run_sync", "run_in_executor_copyctx"]
27
+
21
28
  T = TypeVar("T")
22
29
 
23
30
  # Module-level singleton for running coroutines from sync code that is
@@ -63,36 +70,6 @@ def run_sync(coro: Awaitable[T]) -> T:
63
70
  return future.result()
64
71
 
65
72
 
66
- class aclosing: # noqa: N801 — intentionally matches stdlib contextlib.aclosing
67
- """Async context manager that calls ``aclose()`` on exit.
68
-
69
- BUG-33 / Pydantic AI PRs #4476, #4205: ``async for item in gen:``
70
- without a context manager leaks the async generator when the loop
71
- body raises — ``gen.__aexit__`` runs under GC instead of
72
- deterministically. ``contextlib.aclosing`` fixes this, but was only
73
- added in Python 3.10 and selectools supports 3.9+. This class is a
74
- drop-in backport that works on any Python version.
75
-
76
- Usage::
77
-
78
- async with aclosing(provider.astream(...)) as gen:
79
- async for item in gen:
80
- if stop_condition(item):
81
- break # provider gen gets aclose()'d on exit
82
- """
83
-
84
- def __init__(self, thing: Any) -> None:
85
- self._thing = thing
86
-
87
- async def __aenter__(self) -> Any:
88
- """Return the wrapped async iterable so callers can iterate it."""
89
- return self._thing
90
-
91
- async def __aexit__(self, *_exc: Any) -> None:
92
- """Call ``aclose()`` on the wrapped async iterable on exit."""
93
- await self._thing.aclose()
94
-
95
-
96
73
  async def run_in_executor_copyctx(
97
74
  loop: asyncio.AbstractEventLoop,
98
75
  executor: Optional[Any],
@@ -1215,7 +1215,7 @@ class _ToolExecutorMixin:
1215
1215
  for i in candidate_indices
1216
1216
  ]
1217
1217
  )
1218
- for i, text in zip(candidate_indices, compressed_texts):
1218
+ for i, text in zip(candidate_indices, compressed_texts, strict=False):
1219
1219
  compressed_by_index[i] = text
1220
1220
  self._store_compressed_in_cache(
1221
1221
  results[i].tool, results[i].tool_call.parameters, results[i].result, text
@@ -404,7 +404,7 @@ step executes and must return one of:
404
404
  """
405
405
 
406
406
 
407
- @beta
407
+ @stable
408
408
  @dataclass
409
409
  class PlanningConfig:
410
410
  """Opt-in planning for any Agent: plan -> (approve) -> execute -> synthesize.
@@ -1593,7 +1593,7 @@ class Agent(_ToolExecutorMixin, _ProviderCallerMixin, _LifecycleMixin, _MemoryMa
1593
1593
  # finally block and releases HTTP connections — instead
1594
1594
  # of waiting for GC and emitting `async generator raised
1595
1595
  # StopAsyncIteration` warnings.
1596
- async with aclosing(
1596
+ async with aclosing( # type: ignore[type-var] # astream is an async generator (has aclose) but typed AsyncIterable
1597
1597
  self.provider.astream(
1598
1598
  model=self._effective_model,
1599
1599
  system_prompt=self._system_prompt,
@@ -287,7 +287,7 @@ class CacheKeyBuilder:
287
287
 
288
288
 
289
289
  # Cache is @runtime_checkable: a ``__stability__`` class attribute would become
290
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
290
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
291
291
  # for implementations that do not define it, so it is registered instead.
292
292
  register_stability("Cache", "stable")
293
293
 
@@ -210,7 +210,7 @@ class SemanticCache:
210
210
 
211
211
  def _cosine_similarity(a: List[float], b: List[float]) -> float:
212
212
  """Compute cosine similarity between two vectors (pure Python, no numpy)."""
213
- dot = sum(x * y for x, y in zip(a, b))
213
+ dot = sum(x * y for x, y in zip(a, b, strict=False))
214
214
  norm_a = math.sqrt(sum(x * x for x in a))
215
215
  norm_b = math.sqrt(sum(x * x for x in b))
216
216
  if norm_a == 0.0 or norm_b == 0.0:
@@ -1248,6 +1248,6 @@ DEFAULT_EVALUATORS: List[Any] = [
1248
1248
 
1249
1249
 
1250
1250
  # Evaluator is @runtime_checkable: a ``__stability__`` class attribute would become
1251
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
1251
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
1252
1252
  # for implementations that do not define it, so it is registered instead.
1253
1253
  register_stability("Evaluator", "beta")
@@ -167,7 +167,7 @@ class PairwiseEval:
167
167
  report_b = suite_b.run()
168
168
 
169
169
  pairwise_results: List[PairwiseCaseResult] = []
170
- for cr_a, cr_b in zip(report_a.case_results, report_b.case_results):
170
+ for cr_a, cr_b in zip(report_a.case_results, report_b.case_results, strict=False):
171
171
  winner, reason = self._compare_case(cr_a, cr_b)
172
172
  pairwise_results.append(
173
173
  PairwiseCaseResult(
@@ -49,7 +49,7 @@ class TopicGuardrail(Guardrail):
49
49
  normalized = re.sub(r"[\u200b\u200c\u200d\ufeff\u00ad]", "", normalized)
50
50
 
51
51
  matched: List[str] = []
52
- for pattern, topic in zip(self._patterns, self.deny):
52
+ for pattern, topic in zip(self._patterns, self.deny, strict=False):
53
53
  if pattern.search(normalized):
54
54
  matched.append(topic)
55
55
 
@@ -954,7 +954,7 @@ class KnowledgeMemory:
954
954
 
955
955
 
956
956
  # KnowledgeStore is @runtime_checkable: a ``__stability__`` class attribute would become
957
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
957
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
958
958
  # for implementations that do not define it, so it is registered instead.
959
959
  register_stability("KnowledgeStore", "stable")
960
960
 
@@ -491,7 +491,7 @@ class KnowledgeGraphMemory:
491
491
 
492
492
 
493
493
  # TripleStore is @runtime_checkable: a ``__stability__`` class attribute would become
494
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
494
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
495
495
  # for implementations that do not define it, so it is registered instead.
496
496
  register_stability("TripleStore", "beta")
497
497
 
@@ -159,7 +159,7 @@ class StallDetector(BaseDetector):
159
159
  result_window = tool_results[-self.threshold :]
160
160
  first_name = call_window[0].tool_name
161
161
  first_hash = _result_hash(result_window[0])
162
- for call, result in zip(call_window[1:], result_window[1:]):
162
+ for call, result in zip(call_window[1:], result_window[1:], strict=False):
163
163
  if call.tool_name != first_name:
164
164
  return None
165
165
  if _result_hash(result) != first_hash:
@@ -390,7 +390,7 @@ class JSONLTraceStore:
390
390
 
391
391
 
392
392
  # TraceStore is @runtime_checkable: a ``__stability__`` class attribute would become
393
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
393
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
394
394
  # for implementations that do not define it, so it is registered instead.
395
395
  register_stability("TraceStore", "beta")
396
396
 
@@ -58,7 +58,7 @@ from .state import (
58
58
  )
59
59
  from .supervisor import ModelSplit, SupervisorAgent, SupervisorStrategy
60
60
 
61
- __stability__ = "beta"
61
+ __stability__ = "stable"
62
62
 
63
63
  __all__ = [
64
64
  # Core graph
@@ -388,11 +388,11 @@ class SQLiteCheckpointStore:
388
388
 
389
389
 
390
390
  # CheckpointStore is @runtime_checkable: a ``__stability__`` class attribute would become
391
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
391
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
392
392
  # for implementations that do not define it, so it is registered instead.
393
393
  register_stability("CheckpointStore", "stable")
394
394
 
395
- __stability__ = "beta"
395
+ __stability__ = "stable"
396
396
 
397
397
  __all__ = [
398
398
  "CheckpointMetadata",
@@ -271,7 +271,7 @@ class AgentGraph:
271
271
  node_names = names or [f"step_{i}" for i in range(len(agents))]
272
272
  if len(node_names) != len(agents):
273
273
  raise ValueError(f"names length ({len(node_names)}) != agents length ({len(agents)})")
274
- for i, (nname, agent) in enumerate(zip(node_names, agents)):
274
+ for i, (nname, agent) in enumerate(zip(node_names, agents, strict=False)):
275
275
  graph.add_node(nname, agent)
276
276
  if i > 0:
277
277
  graph.add_edge(node_names[i - 1], nname)
@@ -1449,7 +1449,7 @@ class AgentGraph:
1449
1449
  child_outputs = await asyncio.gather(
1450
1450
  *[
1451
1451
  run_child(name, bstate)
1452
- for name, bstate in zip(node.child_node_names, branch_states)
1452
+ for name, bstate in zip(node.child_node_names, branch_states, strict=False)
1453
1453
  ],
1454
1454
  return_exceptions=True,
1455
1455
  )
@@ -1828,7 +1828,7 @@ class AgentGraph:
1828
1828
  print()
1829
1829
 
1830
1830
 
1831
- __stability__ = "beta"
1831
+ __stability__ = "stable"
1832
1832
 
1833
1833
  __all__ = [
1834
1834
  "AgentGraph",
@@ -183,7 +183,7 @@ def build_context_messages(node: GraphNode, state: GraphState) -> List[Any]:
183
183
  return default_input_transform(state)
184
184
 
185
185
 
186
- __stability__ = "beta"
186
+ __stability__ = "stable"
187
187
 
188
188
  __all__ = [
189
189
  "GraphNode",
@@ -342,7 +342,7 @@ def merge_states(states: List[GraphState], policy: MergePolicy) -> GraphState:
342
342
  )
343
343
 
344
344
 
345
- __stability__ = "beta"
345
+ __stability__ = "stable"
346
346
 
347
347
  __all__ = [
348
348
  "STATE_KEY_LAST_OUTPUT",
@@ -605,7 +605,7 @@ def _format_history(history: List[Any]) -> str:
605
605
  return "\n".join(lines) if lines else "No steps taken yet."
606
606
 
607
607
 
608
- __stability__ = "beta"
608
+ __stability__ = "stable"
609
609
 
610
610
  __all__ = [
611
611
  "SupervisorAgent",
@@ -25,7 +25,7 @@ from .plan_and_execute import PlanAndExecuteAgent, PlanStep
25
25
  from .reflective import ReflectionRound, ReflectiveAgent, ReflectiveResult
26
26
  from .team_lead import Subtask, TeamLeadAgent, TeamLeadResult
27
27
 
28
- __stability__ = "beta"
28
+ __stability__ = "stable"
29
29
 
30
30
  __all__ = [
31
31
  # PlanAndExecute
@@ -133,6 +133,6 @@ class DebateAgent:
133
133
  return DebateResult(conclusion=conclusion, rounds=rounds)
134
134
 
135
135
 
136
- __stability__ = "beta"
136
+ __stability__ = "stable"
137
137
 
138
138
  __all__ = ["DebateAgent", "DebateRound", "DebateResult"]
@@ -222,6 +222,6 @@ class PlanAndExecuteAgent:
222
222
  return steps
223
223
 
224
224
 
225
- __stability__ = "beta"
225
+ __stability__ = "stable"
226
226
 
227
227
  __all__ = ["PlanAndExecuteAgent", "PlanStep"]
@@ -135,6 +135,6 @@ class ReflectiveAgent:
135
135
  return ReflectiveResult(final_draft=draft, rounds=rounds, approved=approved)
136
136
 
137
137
 
138
- __stability__ = "beta"
138
+ __stability__ = "stable"
139
139
 
140
140
  __all__ = ["ReflectiveAgent", "ReflectionRound", "ReflectiveResult"]
@@ -305,6 +305,6 @@ class TeamLeadAgent:
305
305
  return TeamLeadResult(content=synthesis.content or work_log, subtasks=all_subtasks)
306
306
 
307
307
 
308
- __stability__ = "beta"
308
+ __stability__ = "stable"
309
309
 
310
310
  __all__ = ["TeamLeadAgent", "Subtask", "TeamLeadResult"]
@@ -233,6 +233,6 @@ class ToolPolicy:
233
233
  return cls.from_dict(data)
234
234
 
235
235
 
236
- __stability__ = "beta"
236
+ __stability__ = "stable"
237
237
 
238
238
  __all__ = ["ApprovalRequest", "ToolPolicy", "PolicyDecision", "PolicyResult"]
@@ -124,7 +124,7 @@ class Provider(Protocol):
124
124
 
125
125
 
126
126
  # Provider is @runtime_checkable: a ``__stability__`` class attribute would become
127
- # a structural protocol member on Python 3.9-3.11 and break ``isinstance()``
127
+ # a structural protocol member on Python 3.10-3.11 and break ``isinstance()``
128
128
  # for implementations that do not define it, so it is registered instead.
129
129
  register_stability("Provider", "stable")
130
130
 
@@ -301,7 +301,7 @@ def _split_into_sentences(text: str) -> List[str]:
301
301
 
302
302
  def _cosine_similarity(a: List[float], b: List[float]) -> float:
303
303
  """Compute cosine similarity between two vectors without numpy."""
304
- dot = sum(x * y for x, y in zip(a, b))
304
+ dot = sum(x * y for x, y in zip(a, b, strict=False))
305
305
  norm_a = math.sqrt(sum(x * x for x in a))
306
306
  norm_b = math.sqrt(sum(x * x for x in b))
307
307
  if norm_a == 0 or norm_b == 0:
@@ -531,7 +531,7 @@ class ContextualChunker:
531
531
  chunk_origins.extend([idx] * len(chunks))
532
532
 
533
533
  enriched: List[Document] = []
534
- for chunk_doc, origin_idx in zip(all_base_chunks, chunk_origins):
534
+ for chunk_doc, origin_idx in zip(all_base_chunks, chunk_origins, strict=False):
535
535
  full_text = doc_text_map[origin_idx]
536
536
  truncated_doc = full_text[: self.max_document_chars]
537
537
 
@@ -257,14 +257,14 @@ class HybridSearcher:
257
257
  doc_scores: Dict[int, float] = {}
258
258
  doc_map: Dict[int, SearchResult] = {}
259
259
 
260
- for result, norm_score in zip(vector_results, v_normalised):
260
+ for result, norm_score in zip(vector_results, v_normalised, strict=False):
261
261
  key = id(result.document)
262
262
  doc_scores[key] = self.vector_weight * norm_score
263
263
  doc_map[key] = result
264
264
 
265
265
  text_to_key = {doc_map[key].document.text: key for key in doc_map}
266
266
 
267
- for result, norm_score in zip(keyword_results, k_normalised):
267
+ for result, norm_score in zip(keyword_results, k_normalised, strict=False):
268
268
  matched_key = text_to_key.get(result.document.text)
269
269
  if matched_key is not None:
270
270
  key = matched_key
@@ -258,7 +258,7 @@ class FAISSVectorStore(VectorStore):
258
258
 
259
259
  results: List[SearchResult] = []
260
260
  seen_texts: set = set()
261
- for score, idx in zip(scores[0], indices[0]):
261
+ for score, idx in zip(scores[0], indices[0], strict=False):
262
262
  # FAISS returns -1 for empty slots
263
263
  if idx < 0:
264
264
  continue
@@ -282,7 +282,7 @@ class PgVectorStore(VectorStore):
282
282
  try:
283
283
  cursor = conn.cursor()
284
284
 
285
- for doc_id, doc, embedding in zip(ids, documents, embeddings):
285
+ for doc_id, doc, embedding in zip(ids, documents, embeddings, strict=False):
286
286
  embedding_str = "[" + ",".join(str(v) for v in embedding) + "]"
287
287
  metadata_json = json.dumps(doc.metadata or {})
288
288
 
@@ -116,7 +116,7 @@ class PineconeVectorStore(VectorStore):
116
116
  # Generate IDs and prepare vectors
117
117
  vectors = []
118
118
  ids = []
119
- for i, (doc, embedding) in enumerate(zip(documents, embeddings)):
119
+ for i, (doc, embedding) in enumerate(zip(documents, embeddings, strict=False)):
120
120
  doc_id = f"doc_{hashlib.sha256(doc.text.encode()).hexdigest()[:16]}_{i}"
121
121
  ids.append(doc_id)
122
122
 
@@ -218,7 +218,7 @@ class QdrantVectorStore(VectorStore):
218
218
  ids: List[str] = []
219
219
  points: List[Any] = []
220
220
 
221
- for doc, embedding in zip(documents, embeddings):
221
+ for doc, embedding in zip(documents, embeddings, strict=False):
222
222
  doc_id = uuid.uuid4().hex
223
223
  ids.append(doc_id)
224
224
 
@@ -131,7 +131,7 @@ class SQLiteVectorStore(VectorStore):
131
131
  conn = sqlite3.connect(self.db_path)
132
132
  try:
133
133
  cursor = conn.cursor()
134
- for doc_id, doc, embedding in zip(ids, documents, embeddings):
134
+ for doc_id, doc, embedding in zip(ids, documents, embeddings, strict=False):
135
135
  cursor.execute(
136
136
  """
137
137
  INSERT OR REPLACE INTO documents (id, text, metadata, embedding)