selectools 0.26.0__tar.gz → 0.27.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (320) hide show
  1. {selectools-0.26.0/src/selectools.egg-info → selectools-0.27.1}/PKG-INFO +43 -10
  2. {selectools-0.26.0 → selectools-0.27.1}/README.md +36 -9
  3. {selectools-0.26.0 → selectools-0.27.1}/pyproject.toml +10 -1
  4. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/__init__.py +34 -2
  5. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/_memory_manager.py +16 -0
  6. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/config.py +13 -0
  7. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/config_groups.py +86 -1
  8. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/core.py +120 -13
  9. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/__init__.py +2 -0
  10. selectools-0.27.1/src/selectools/guardrails/injection.py +190 -0
  11. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/models.py +68 -3
  12. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/pricing.py +68 -2
  13. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/_openai_compat.py +31 -2
  14. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/azure_openai_provider.py +0 -1
  15. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/gemini_provider.py +26 -4
  16. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/litellm_provider.py +9 -1
  17. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/ollama_provider.py +7 -1
  18. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/openai_provider.py +11 -3
  19. selectools-0.27.1/src/selectools/scheduler.py +474 -0
  20. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/sessions.py +386 -2
  21. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/__init__.py +56 -1
  22. selectools-0.27.1/src/selectools/toolbox/browser_tools.py +143 -0
  23. selectools-0.27.1/src/selectools/toolbox/discord_tools.py +194 -0
  24. selectools-0.27.1/src/selectools/toolbox/image_tools.py +119 -0
  25. selectools-0.27.1/src/selectools/toolbox/memory_tools.py +153 -0
  26. selectools-0.27.1/src/selectools/toolbox/reasoning_tools.py +199 -0
  27. selectools-0.27.1/src/selectools/toolbox/s3_tools.py +218 -0
  28. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/unified_memory.py +12 -2
  29. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/usage.py +8 -4
  30. {selectools-0.26.0 → selectools-0.27.1/src/selectools.egg-info}/PKG-INFO +43 -10
  31. {selectools-0.26.0 → selectools-0.27.1}/src/selectools.egg-info/SOURCES.txt +12 -0
  32. {selectools-0.26.0 → selectools-0.27.1}/src/selectools.egg-info/requires.txt +9 -0
  33. {selectools-0.26.0 → selectools-0.27.1}/tests/test_architecture.py +14 -0
  34. selectools-0.27.1/tests/test_guardrails_injection.py +180 -0
  35. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge.py +216 -2
  36. selectools-0.27.1/tests/test_scheduler.py +341 -0
  37. selectools-0.27.1/tests/test_sessions_dynamodb.py +234 -0
  38. selectools-0.27.1/tests/test_sessions_mongo.py +243 -0
  39. {selectools-0.26.0 → selectools-0.27.1}/tests/test_unified_memory.py +17 -0
  40. selectools-0.27.1/tests/test_unified_memory_config.py +384 -0
  41. selectools-0.26.0/src/selectools/toolbox/memory_tools.py +0 -68
  42. {selectools-0.26.0 → selectools-0.27.1}/LICENSE +0 -0
  43. {selectools-0.26.0 → selectools-0.27.1}/setup.cfg +0 -0
  44. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/_async_utils.py +0 -0
  45. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/_json_utils.py +0 -0
  46. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/a2a/__init__.py +0 -0
  47. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/a2a/client.py +0 -0
  48. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/a2a/server.py +0 -0
  49. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/a2a/types.py +0 -0
  50. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/__init__.py +0 -0
  51. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/_lifecycle.py +0 -0
  52. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/_planning.py +0 -0
  53. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/_provider_caller.py +0 -0
  54. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/agent/_tool_executor.py +0 -0
  55. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/analytics.py +0 -0
  56. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/audit.py +0 -0
  57. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/cache.py +0 -0
  58. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/cache_redis.py +0 -0
  59. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/cache_semantic.py +0 -0
  60. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/cancellation.py +0 -0
  61. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/checkpoint_postgres.py +0 -0
  62. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/coherence.py +0 -0
  63. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/compose.py +0 -0
  64. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/__init__.py +0 -0
  65. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/anthropic.py +0 -0
  66. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/cohere.py +0 -0
  67. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/gemini.py +0 -0
  68. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/openai.py +0 -0
  69. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/embeddings/provider.py +0 -0
  70. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/entity_memory.py +0 -0
  71. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/env.py +0 -0
  72. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/__init__.py +0 -0
  73. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/__main__.py +0 -0
  74. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/badge.py +0 -0
  75. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/dataset.py +0 -0
  76. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/evaluators.py +0 -0
  77. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/generator.py +0 -0
  78. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/history.py +0 -0
  79. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/html.py +0 -0
  80. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/junit.py +0 -0
  81. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/llm_evaluators.py +0 -0
  82. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/pairwise.py +0 -0
  83. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/regression.py +0 -0
  84. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/report.py +0 -0
  85. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/serve.py +0 -0
  86. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/snapshot.py +0 -0
  87. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/suite.py +0 -0
  88. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/templates.py +0 -0
  89. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/evals/types.py +0 -0
  90. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/exceptions.py +0 -0
  91. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/base.py +0 -0
  92. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/format.py +0 -0
  93. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/length.py +0 -0
  94. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/pii.py +0 -0
  95. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/pipeline.py +0 -0
  96. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/topic.py +0 -0
  97. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/guardrails/toxicity.py +0 -0
  98. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge.py +0 -0
  99. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge_backends.py +0 -0
  100. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge_graph.py +0 -0
  101. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge_sanitizers.py +0 -0
  102. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge_store_redis.py +0 -0
  103. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/knowledge_store_supabase.py +0 -0
  104. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/loop_detection.py +0 -0
  105. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/__init__.py +0 -0
  106. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/_loop.py +0 -0
  107. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/bridge.py +0 -0
  108. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/client.py +0 -0
  109. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/config.py +0 -0
  110. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/multi.py +0 -0
  111. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/mcp/server.py +0 -0
  112. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/memory.py +0 -0
  113. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/observe/__init__.py +0 -0
  114. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/observe/langfuse.py +0 -0
  115. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/observe/otel.py +0 -0
  116. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/observe/trace_store.py +0 -0
  117. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/observer.py +0 -0
  118. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/__init__.py +0 -0
  119. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/checkpoint.py +0 -0
  120. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/graph.py +0 -0
  121. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/node.py +0 -0
  122. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/state.py +0 -0
  123. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/orchestration/supervisor.py +0 -0
  124. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/parser.py +0 -0
  125. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/patterns/__init__.py +0 -0
  126. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/patterns/debate.py +0 -0
  127. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/patterns/plan_and_execute.py +0 -0
  128. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/patterns/reflective.py +0 -0
  129. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/patterns/team_lead.py +0 -0
  130. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/pending.py +0 -0
  131. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/pipeline.py +0 -0
  132. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/policy.py +0 -0
  133. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/prompt.py +0 -0
  134. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/__init__.py +0 -0
  135. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/anthropic_provider.py +0 -0
  136. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/base.py +0 -0
  137. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/fallback.py +0 -0
  138. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/router.py +0 -0
  139. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/providers/stubs.py +0 -0
  140. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/__init__.py +0 -0
  141. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/bm25.py +0 -0
  142. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/chunking.py +0 -0
  143. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/hybrid.py +0 -0
  144. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/loaders.py +0 -0
  145. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/reranker.py +0 -0
  146. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/__init__.py +0 -0
  147. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/chroma.py +0 -0
  148. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/faiss.py +0 -0
  149. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/memory.py +0 -0
  150. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/pgvector.py +0 -0
  151. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/pinecone.py +0 -0
  152. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/qdrant.py +0 -0
  153. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/stores/sqlite.py +0 -0
  154. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/tools.py +0 -0
  155. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/rag/vector_store.py +0 -0
  156. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/results.py +0 -0
  157. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/security.py +0 -0
  158. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/__init__.py +0 -0
  159. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/_starlette_app.py +0 -0
  160. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/_static/builder.css +0 -0
  161. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/_static/builder.html +0 -0
  162. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/_static/builder.js +0 -0
  163. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/api.py +0 -0
  164. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/app.py +0 -0
  165. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/builder.py +0 -0
  166. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/cli.py +0 -0
  167. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/models.py +0 -0
  168. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/serve/playground.py +0 -0
  169. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/stability.py +0 -0
  170. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/structured.py +0 -0
  171. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/__init__.py +0 -0
  172. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/code_reviewer.py +0 -0
  173. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/customer_support.py +0 -0
  174. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/data_analyst.py +0 -0
  175. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/rag_chatbot.py +0 -0
  176. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/templates/research_assistant.py +0 -0
  177. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/token_estimation.py +0 -0
  178. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/calculator_tools.py +0 -0
  179. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/code_tools.py +0 -0
  180. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/data_tools.py +0 -0
  181. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/datetime_tools.py +0 -0
  182. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/db_tools.py +0 -0
  183. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/email_tools.py +0 -0
  184. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/file_tools.py +0 -0
  185. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/github_tools.py +0 -0
  186. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/linear_tools.py +0 -0
  187. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/notion_tools.py +0 -0
  188. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/pdf_tools.py +0 -0
  189. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/search_tools.py +0 -0
  190. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/slack_tools.py +0 -0
  191. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/text_tools.py +0 -0
  192. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/toolbox/web_tools.py +0 -0
  193. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/tools/__init__.py +0 -0
  194. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/tools/base.py +0 -0
  195. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/tools/decorators.py +0 -0
  196. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/tools/loader.py +0 -0
  197. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/tools/registry.py +0 -0
  198. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/trace.py +0 -0
  199. {selectools-0.26.0 → selectools-0.27.1}/src/selectools/types.py +0 -0
  200. {selectools-0.26.0 → selectools-0.27.1}/src/selectools.egg-info/dependency_links.txt +0 -0
  201. {selectools-0.26.0 → selectools-0.27.1}/src/selectools.egg-info/entry_points.txt +0 -0
  202. {selectools-0.26.0 → selectools-0.27.1}/src/selectools.egg-info/top_level.txt +0 -0
  203. {selectools-0.26.0 → selectools-0.27.1}/tests/test_a2a.py +0 -0
  204. {selectools-0.26.0 → selectools-0.27.1}/tests/test_agent_api.py +0 -0
  205. {selectools-0.26.0 → selectools-0.27.1}/tests/test_agent_hitl.py +0 -0
  206. {selectools-0.26.0 → selectools-0.27.1}/tests/test_approval_gate.py +0 -0
  207. {selectools-0.26.0 → selectools-0.27.1}/tests/test_async_observers.py +0 -0
  208. {selectools-0.26.0 → selectools-0.27.1}/tests/test_audit.py +0 -0
  209. {selectools-0.26.0 → selectools-0.27.1}/tests/test_bake_window_hunt.py +0 -0
  210. {selectools-0.26.0 → selectools-0.27.1}/tests/test_budget.py +0 -0
  211. {selectools-0.26.0 → selectools-0.27.1}/tests/test_bug_hunt_batch1_core.py +0 -0
  212. {selectools-0.26.0 → selectools-0.27.1}/tests/test_bug_hunt_batch1_security.py +0 -0
  213. {selectools-0.26.0 → selectools-0.27.1}/tests/test_bug_hunt_batch1_tools.py +0 -0
  214. {selectools-0.26.0 → selectools-0.27.1}/tests/test_bug_hunt_regression.py +0 -0
  215. {selectools-0.26.0 → selectools-0.27.1}/tests/test_cache.py +0 -0
  216. {selectools-0.26.0 → selectools-0.27.1}/tests/test_cache_redis.py +0 -0
  217. {selectools-0.26.0 → selectools-0.27.1}/tests/test_cancellation.py +0 -0
  218. {selectools-0.26.0 → selectools-0.27.1}/tests/test_checkpoint_postgres.py +0 -0
  219. {selectools-0.26.0 → selectools-0.27.1}/tests/test_coherence.py +0 -0
  220. {selectools-0.26.0 → selectools-0.27.1}/tests/test_concurrency_smoke.py +0 -0
  221. {selectools-0.26.0 → selectools-0.27.1}/tests/test_consolidation_regression.py +0 -0
  222. {selectools-0.26.0 → selectools-0.27.1}/tests/test_conversation_branching.py +0 -0
  223. {selectools-0.26.0 → selectools-0.27.1}/tests/test_coverage_orchestration.py +0 -0
  224. {selectools-0.26.0 → selectools-0.27.1}/tests/test_document_loaders_extended.py +0 -0
  225. {selectools-0.26.0 → selectools-0.27.1}/tests/test_e2e_langfuse_observer.py +0 -0
  226. {selectools-0.26.0 → selectools-0.27.1}/tests/test_e2e_multimodal.py +0 -0
  227. {selectools-0.26.0 → selectools-0.27.1}/tests/test_e2e_otel_observer.py +0 -0
  228. {selectools-0.26.0 → selectools-0.27.1}/tests/test_e2e_v0_21_0_apps.py +0 -0
  229. {selectools-0.26.0 → selectools-0.27.1}/tests/test_e2e_v0_21_0_simulations.py +0 -0
  230. {selectools-0.26.0 → selectools-0.27.1}/tests/test_entity_memory.py +0 -0
  231. {selectools-0.26.0 → selectools-0.27.1}/tests/test_env.py +0 -0
  232. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals.py +0 -0
  233. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_advanced.py +0 -0
  234. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_cli.py +0 -0
  235. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_e2e.py +0 -0
  236. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_final.py +0 -0
  237. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_hardening.py +0 -0
  238. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_html_report.py +0 -0
  239. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_new_evaluators.py +0 -0
  240. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_ralph_bugs.py +0 -0
  241. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_release.py +0 -0
  242. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_serve.py +0 -0
  243. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_v017_features.py +0 -0
  244. {selectools-0.26.0 → selectools-0.27.1}/tests/test_evals_v0191.py +0 -0
  245. {selectools-0.26.0 → selectools-0.27.1}/tests/test_features_in_graph.py +0 -0
  246. {selectools-0.26.0 → selectools-0.27.1}/tests/test_final_coverage_a.py +0 -0
  247. {selectools-0.26.0 → selectools-0.27.1}/tests/test_final_coverage_b.py +0 -0
  248. {selectools-0.26.0 → selectools-0.27.1}/tests/test_guardrails.py +0 -0
  249. {selectools-0.26.0 → selectools-0.27.1}/tests/test_hardening.py +0 -0
  250. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_backend.py +0 -0
  251. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_backend_redis.py +0 -0
  252. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_backend_supabase.py +0 -0
  253. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_graph.py +0 -0
  254. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_sanitizers.py +0 -0
  255. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_store_redis.py +0 -0
  256. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_store_supabase.py +0 -0
  257. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_stores.py +0 -0
  258. {selectools-0.26.0 → selectools-0.27.1}/tests/test_knowledge_stores_error_handling.py +0 -0
  259. {selectools-0.26.0 → selectools-0.27.1}/tests/test_langfuse_observer.py +0 -0
  260. {selectools-0.26.0 → selectools-0.27.1}/tests/test_loop_detection.py +0 -0
  261. {selectools-0.26.0 → selectools-0.27.1}/tests/test_mcp.py +0 -0
  262. {selectools-0.26.0 → selectools-0.27.1}/tests/test_mcp_coverage.py +0 -0
  263. {selectools-0.26.0 → selectools-0.27.1}/tests/test_memory.py +0 -0
  264. {selectools-0.26.0 → selectools-0.27.1}/tests/test_memory_async.py +0 -0
  265. {selectools-0.26.0 → selectools-0.27.1}/tests/test_memory_boundary.py +0 -0
  266. {selectools-0.26.0 → selectools-0.27.1}/tests/test_memory_integration.py +0 -0
  267. {selectools-0.26.0 → selectools-0.27.1}/tests/test_model_switching.py +0 -0
  268. {selectools-0.26.0 → selectools-0.27.1}/tests/test_multi_agent_edge_cases.py +0 -0
  269. {selectools-0.26.0 → selectools-0.27.1}/tests/test_multimodal.py +0 -0
  270. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_checkpoint.py +0 -0
  271. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_e2e.py +0 -0
  272. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_evals.py +0 -0
  273. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_graph.py +0 -0
  274. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_integration.py +0 -0
  275. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_primitives.py +0 -0
  276. {selectools-0.26.0 → selectools-0.27.1}/tests/test_orchestration_supervisor.py +0 -0
  277. {selectools-0.26.0 → selectools-0.27.1}/tests/test_otel_observer.py +0 -0
  278. {selectools-0.26.0 → selectools-0.27.1}/tests/test_parser.py +0 -0
  279. {selectools-0.26.0 → selectools-0.27.1}/tests/test_patterns.py +0 -0
  280. {selectools-0.26.0 → selectools-0.27.1}/tests/test_pending.py +0 -0
  281. {selectools-0.26.0 → selectools-0.27.1}/tests/test_pending_redis_smoke.py +0 -0
  282. {selectools-0.26.0 → selectools-0.27.1}/tests/test_phase1_design_patterns.py +0 -0
  283. {selectools-0.26.0 → selectools-0.27.1}/tests/test_pipeline.py +0 -0
  284. {selectools-0.26.0 → selectools-0.27.1}/tests/test_pipeline_coverage.py +0 -0
  285. {selectools-0.26.0 → selectools-0.27.1}/tests/test_policy.py +0 -0
  286. {selectools-0.26.0 → selectools-0.27.1}/tests/test_prompt.py +0 -0
  287. {selectools-0.26.0 → selectools-0.27.1}/tests/test_prompt_compression.py +0 -0
  288. {selectools-0.26.0 → selectools-0.27.1}/tests/test_property_based.py +0 -0
  289. {selectools-0.26.0 → selectools-0.27.1}/tests/test_reasoning_strategy.py +0 -0
  290. {selectools-0.26.0 → selectools-0.27.1}/tests/test_remaining_coverage.py +0 -0
  291. {selectools-0.26.0 → selectools-0.27.1}/tests/test_results.py +0 -0
  292. {selectools-0.26.0 → selectools-0.27.1}/tests/test_routing_mode.py +0 -0
  293. {selectools-0.26.0 → selectools-0.27.1}/tests/test_security.py +0 -0
  294. {selectools-0.26.0 → selectools-0.27.1}/tests/test_semantic_cache.py +0 -0
  295. {selectools-0.26.0 → selectools-0.27.1}/tests/test_serve_app_coverage.py +0 -0
  296. {selectools-0.26.0 → selectools-0.27.1}/tests/test_serve_cli.py +0 -0
  297. {selectools-0.26.0 → selectools-0.27.1}/tests/test_sessions.py +0 -0
  298. {selectools-0.26.0 → selectools-0.27.1}/tests/test_sessions_edge_cases.py +0 -0
  299. {selectools-0.26.0 → selectools-0.27.1}/tests/test_sessions_redis.py +0 -0
  300. {selectools-0.26.0 → selectools-0.27.1}/tests/test_sessions_supabase.py +0 -0
  301. {selectools-0.26.0 → selectools-0.27.1}/tests/test_simple_observer.py +0 -0
  302. {selectools-0.26.0 → selectools-0.27.1}/tests/test_simulation_evals.py +0 -0
  303. {selectools-0.26.0 → selectools-0.27.1}/tests/test_stability.py +0 -0
  304. {selectools-0.26.0 → selectools-0.27.1}/tests/test_starlette_app.py +0 -0
  305. {selectools-0.26.0 → selectools-0.27.1}/tests/test_structured.py +0 -0
  306. {selectools-0.26.0 → selectools-0.27.1}/tests/test_structured_config.py +0 -0
  307. {selectools-0.26.0 → selectools-0.27.1}/tests/test_structured_tool_results.py +0 -0
  308. {selectools-0.26.0 → selectools-0.27.1}/tests/test_summarize_on_trim.py +0 -0
  309. {selectools-0.26.0 → selectools-0.27.1}/tests/test_templates_coverage.py +0 -0
  310. {selectools-0.26.0 → selectools-0.27.1}/tests/test_terminal_actions.py +0 -0
  311. {selectools-0.26.0 → selectools-0.27.1}/tests/test_token_estimation.py +0 -0
  312. {selectools-0.26.0 → selectools-0.27.1}/tests/test_tool_caching.py +0 -0
  313. {selectools-0.26.0 → selectools-0.27.1}/tests/test_tool_result_compression.py +0 -0
  314. {selectools-0.26.0 → selectools-0.27.1}/tests/test_trace.py +0 -0
  315. {selectools-0.26.0 → selectools-0.27.1}/tests/test_trace_html.py +0 -0
  316. {selectools-0.26.0 → selectools-0.27.1}/tests/test_trace_store.py +0 -0
  317. {selectools-0.26.0 → selectools-0.27.1}/tests/test_v016_regression.py +0 -0
  318. {selectools-0.26.0 → selectools-0.27.1}/tests/test_v019_features.py +0 -0
  319. {selectools-0.26.0 → selectools-0.27.1}/tests/test_visual_builder.py +0 -0
  320. {selectools-0.26.0 → selectools-0.27.1}/tests/test_yaml_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: selectools
3
- Version: 0.26.0
3
+ Version: 0.27.1
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>
@@ -59,6 +59,12 @@ Provides-Extra: toolbox
59
59
  Requires-Dist: requests>=2.28.0; extra == "toolbox"
60
60
  Requires-Dist: slack-sdk>=3.27.0; extra == "toolbox"
61
61
  Requires-Dist: pdfplumber>=0.11.0; extra == "toolbox"
62
+ Provides-Extra: aws
63
+ Requires-Dist: boto3>=1.34.0; extra == "aws"
64
+ Provides-Extra: browser
65
+ Requires-Dist: playwright>=1.40.0; extra == "browser"
66
+ Provides-Extra: mongo
67
+ Requires-Dist: pymongo>=4.0.0; extra == "mongo"
62
68
  Provides-Extra: evals
63
69
  Requires-Dist: pyyaml>=6.0.0; extra == "evals"
64
70
  Provides-Extra: mcp
@@ -108,6 +114,28 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
108
114
  # selectools serve agent.yaml
109
115
  ```
110
116
 
117
+ ## What's New in v0.27
118
+
119
+ ### v0.27.1 — Bug-Hunt Patch
120
+
121
+ An adversarial bug hunt of the v0.27.0 surface fixed 10 confirmed bugs (no API changes, no breaking changes). Highlights: scheduled agents recorded the `AgentResult` repr instead of the answer text; `PromptInjectionGuardrail` blocked benign requests ("pretend you are a pirate", "show the rules"); `s3_get_object` leaked its HTTP connection; and unified memory persisted un-redacted input in async mode. See `CHANGELOG.md` for the full list.
122
+
123
+ ### v0.27.0 — Scheduling, Reasoning & New Backends
124
+
125
+ A feature release landing the post-1.0 backlog: scheduled agents, composable reasoning, two new session backends, an injection guardrail, and the rest of the v1.1 candidate set. All additive (`@beta`); no breaking changes.
126
+
127
+ - **Scheduled agents** — `AgentScheduler` runs an agent on a `cron("0 9 * * *")` or `every(minutes=5)` schedule. Async loop that sleeps until the next due job, per-job `max_runs` / `on_result` / `start_immediately`, failure isolation, and an injectable clock for tests. Stdlib-only (`selectools.scheduler`).
128
+ - **Reasoning tools** — `make_reasoning_tools(min_steps, max_steps)` adds `think` / `analyze` tools that make the agent's reasoning explicit, inspectable steps (vs the passive `reasoning_strategy` prompt). `max_steps` is enforced (a real guard against reasoning loops); `min_steps` is guidance.
129
+ - **Two new session backends** — `MongoSessionStore` and `DynamoDBSessionStore` bring the `SessionStore` count to six. Full protocol (save/load/list/delete/exists/branch/search), namespace isolation, and optional server-side TTL. `pip install selectools[mongo]` / `selectools[aws]`.
130
+ - **Prompt-injection guardrail** — `PromptInjectionGuardrail` catches templated jailbreak/injection attacks ("ignore previous instructions", "reveal your system prompt", `<system>`/`[INST]` spoofing, "developer mode"/"DAN") with high-precision patterns. Heuristic tier — no model hosting required.
131
+ - **Agentic memory completed** — the auto-injected `recall` tool joins `remember`, so the agent can both store and query its `KnowledgeMemory` on demand.
132
+ - **UnifiedMemory via config** — `AgentConfig(memory=MemoryConfig(unified=True, ...))` makes the tiered `UnifiedMemory` (STM→LTM auto-promotion, entity + episodic tiers, token-aware compaction) reachable from config; default off.
133
+ - **Toolbox 48 → 56 tools** — added Discord, AWS S3, headless browser (Playwright), and image generation (OpenAI Images) categories.
134
+ - **Cache-rate cost for OpenAI + Gemini** — `calculate_cost_with_cached_input()` prices cached prompt tokens at each provider's published rate (`cached_prompt_cost` on `ModelInfo`); 24 rates source-verified.
135
+ - **Performance benchmarks published** — framework overhead measured and documented (`docs/modules/BENCHMARKS.md`).
136
+
137
+ See `CHANGELOG.md` for the full entry (7,700+ tests, 115 examples, 115 models).
138
+
111
139
  ## What's New in v0.26
112
140
 
113
141
  ### v0.26.0 — Safety Patch & Verified Registry
@@ -631,11 +659,13 @@ report.to_html("report.html")
631
659
  | **Dynamic Tools** | Load tools from files/directories at runtime. Add, remove, replace tools without restarting. |
632
660
  | **Response Caching** | LRU + TTL in-memory cache and Redis backend. Avoid redundant LLM calls for identical requests. |
633
661
  | **Routing Mode** | Agent selects a tool without executing it. Use for intent classification and request routing. |
634
- | **Guardrails Engine** | Input/output validation pipeline with PII redaction, topic blocking, toxicity detection, and format enforcement. |
662
+ | **Guardrails Engine** | Input/output validation pipeline with PII redaction, prompt-injection detection, topic blocking, toxicity detection, and format enforcement. |
635
663
  | **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
636
664
  | **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
637
665
  | **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
638
- | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and Supabase backends. Auto-save/load with TTL expiry, cross-session `search()`. |
666
+ | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, Supabase, MongoDB, and DynamoDB backends. Auto-save/load with TTL expiry, cross-session `search()`. |
667
+ | **Scheduled Agents** | `AgentScheduler` runs an agent on a `cron()` or `every()` schedule — async loop, per-job `max_runs`, failure isolation, injectable clock. |
668
+ | **Reasoning Tools** | `make_reasoning_tools()` adds `think`/`analyze` tools that make reasoning explicit and inspectable, bounded by `min_steps`/`max_steps`. |
639
669
  | **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
640
670
  | **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
641
671
  | **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
@@ -646,7 +676,7 @@ report.to_html("report.html")
646
676
  | **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
647
677
  | **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
648
678
  | **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
649
- | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
679
+ | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` + `recall` tools. |
650
680
  | **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
651
681
  | **Eval Framework** | 50 built-in evaluators (30 deterministic + 21 LLM-as-judge). A/B testing, regression detection, snapshot testing, HTML reports, JUnit XML, CI integration. |
652
682
  | **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
@@ -673,8 +703,11 @@ report.to_html("report.html")
673
703
  - **Dynamic Tool Loading**: Plugin system with hot-reload support
674
704
  - **Response Caching**: InMemoryCache and RedisCache with stats tracking
675
705
  - **115 Model Registry**: Type-safe constants with pricing and metadata
676
- - **Pre-built Toolbox**: 48 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear
677
- - **Persistent Sessions**: 4 backends (JSON file, SQLite, Redis, Supabase) with TTL and cross-session search
706
+ - **Pre-built Toolbox**: 56 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear, Discord, S3, browser, image gen
707
+ - **Persistent Sessions**: 6 backends (JSON file, SQLite, Redis, Supabase, MongoDB, DynamoDB) with TTL and cross-session search
708
+ - **Scheduled Agents**: `AgentScheduler` runs an agent on a cron or interval schedule with per-job max-runs, failure isolation, and an async loop
709
+ - **Reasoning Tools**: `think`/`analyze` tools make reasoning explicit, inspectable, and bounded by min/max steps
710
+ - **Prompt-Injection Guardrail**: `PromptInjectionGuardrail` — heuristic jailbreak/injection detection with high-precision patterns
678
711
  - **Entity Memory**: LLM-based named entity extraction and tracking
679
712
  - **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
680
713
  - **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
@@ -682,7 +715,7 @@ report.to_html("report.html")
682
715
  - **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
683
716
  - **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
684
717
  - **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
685
- - **Cross-Session Knowledge**: Daily logs + persistent memory with `remember` tool, pluggable stores (File, SQLite), importance scoring, TTL
718
+ - **Cross-Session Knowledge**: Daily logs + persistent memory with auto-injected `remember` + `recall` tools, pluggable stores (File, SQLite), importance scoring, TTL
686
719
  - **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
687
720
  - **Token Estimation**: `estimate_run_tokens()` for pre-execution budget checks
688
721
  - **Model Switching**: `model_selector` callback for per-iteration model selection
@@ -691,10 +724,10 @@ report.to_html("report.html")
691
724
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
692
725
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
693
726
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
694
- - **111 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
727
+ - **115 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, scheduled agents, reasoning tools, and more
695
728
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
696
729
  - **AgentObserver Protocol**: 46 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
697
- - **7268 Tests**: Unit, integration, regression, and E2E with real API calls
730
+ - **7700+ Tests**: Unit, integration, regression, and E2E with real API calls
698
731
 
699
732
  ## Install
700
733
 
@@ -1196,7 +1229,7 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
1196
1229
  |---|---|---|---|
1197
1230
  | 01 | `01_hello_world.py` | First agent, `@tool`, `ask()` | No |
1198
1231
  | 02 | `02_search_weather.py` | ToolRegistry, multiple tools | No |
1199
- | 03 | `03_toolbox.py` | 48 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
1232
+ | 03 | `03_toolbox.py` | 56 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
1200
1233
  | 04 | `04_conversation_memory.py` | Multi-turn memory | Yes |
1201
1234
  | 05 | `05_cost_tracking.py` | Token counting, cost warnings | Yes |
1202
1235
  | 06 | `06_async_agent.py` | `arun()`, concurrent agents, FastAPI | Yes |
@@ -30,6 +30,28 @@ 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.27
34
+
35
+ ### v0.27.1 — Bug-Hunt Patch
36
+
37
+ An adversarial bug hunt of the v0.27.0 surface fixed 10 confirmed bugs (no API changes, no breaking changes). Highlights: scheduled agents recorded the `AgentResult` repr instead of the answer text; `PromptInjectionGuardrail` blocked benign requests ("pretend you are a pirate", "show the rules"); `s3_get_object` leaked its HTTP connection; and unified memory persisted un-redacted input in async mode. See `CHANGELOG.md` for the full list.
38
+
39
+ ### v0.27.0 — Scheduling, Reasoning & New Backends
40
+
41
+ A feature release landing the post-1.0 backlog: scheduled agents, composable reasoning, two new session backends, an injection guardrail, and the rest of the v1.1 candidate set. All additive (`@beta`); no breaking changes.
42
+
43
+ - **Scheduled agents** — `AgentScheduler` runs an agent on a `cron("0 9 * * *")` or `every(minutes=5)` schedule. Async loop that sleeps until the next due job, per-job `max_runs` / `on_result` / `start_immediately`, failure isolation, and an injectable clock for tests. Stdlib-only (`selectools.scheduler`).
44
+ - **Reasoning tools** — `make_reasoning_tools(min_steps, max_steps)` adds `think` / `analyze` tools that make the agent's reasoning explicit, inspectable steps (vs the passive `reasoning_strategy` prompt). `max_steps` is enforced (a real guard against reasoning loops); `min_steps` is guidance.
45
+ - **Two new session backends** — `MongoSessionStore` and `DynamoDBSessionStore` bring the `SessionStore` count to six. Full protocol (save/load/list/delete/exists/branch/search), namespace isolation, and optional server-side TTL. `pip install selectools[mongo]` / `selectools[aws]`.
46
+ - **Prompt-injection guardrail** — `PromptInjectionGuardrail` catches templated jailbreak/injection attacks ("ignore previous instructions", "reveal your system prompt", `<system>`/`[INST]` spoofing, "developer mode"/"DAN") with high-precision patterns. Heuristic tier — no model hosting required.
47
+ - **Agentic memory completed** — the auto-injected `recall` tool joins `remember`, so the agent can both store and query its `KnowledgeMemory` on demand.
48
+ - **UnifiedMemory via config** — `AgentConfig(memory=MemoryConfig(unified=True, ...))` makes the tiered `UnifiedMemory` (STM→LTM auto-promotion, entity + episodic tiers, token-aware compaction) reachable from config; default off.
49
+ - **Toolbox 48 → 56 tools** — added Discord, AWS S3, headless browser (Playwright), and image generation (OpenAI Images) categories.
50
+ - **Cache-rate cost for OpenAI + Gemini** — `calculate_cost_with_cached_input()` prices cached prompt tokens at each provider's published rate (`cached_prompt_cost` on `ModelInfo`); 24 rates source-verified.
51
+ - **Performance benchmarks published** — framework overhead measured and documented (`docs/modules/BENCHMARKS.md`).
52
+
53
+ See `CHANGELOG.md` for the full entry (7,700+ tests, 115 examples, 115 models).
54
+
33
55
  ## What's New in v0.26
34
56
 
35
57
  ### v0.26.0 — Safety Patch & Verified Registry
@@ -553,11 +575,13 @@ report.to_html("report.html")
553
575
  | **Dynamic Tools** | Load tools from files/directories at runtime. Add, remove, replace tools without restarting. |
554
576
  | **Response Caching** | LRU + TTL in-memory cache and Redis backend. Avoid redundant LLM calls for identical requests. |
555
577
  | **Routing Mode** | Agent selects a tool without executing it. Use for intent classification and request routing. |
556
- | **Guardrails Engine** | Input/output validation pipeline with PII redaction, topic blocking, toxicity detection, and format enforcement. |
578
+ | **Guardrails Engine** | Input/output validation pipeline with PII redaction, prompt-injection detection, topic blocking, toxicity detection, and format enforcement. |
557
579
  | **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
558
580
  | **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
559
581
  | **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
560
- | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and Supabase backends. Auto-save/load with TTL expiry, cross-session `search()`. |
582
+ | **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, Supabase, MongoDB, and DynamoDB backends. Auto-save/load with TTL expiry, cross-session `search()`. |
583
+ | **Scheduled Agents** | `AgentScheduler` runs an agent on a `cron()` or `every()` schedule — async loop, per-job `max_runs`, failure isolation, injectable clock. |
584
+ | **Reasoning Tools** | `make_reasoning_tools()` adds `think`/`analyze` tools that make reasoning explicit and inspectable, bounded by `min_steps`/`max_steps`. |
561
585
  | **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
562
586
  | **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
563
587
  | **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
@@ -568,7 +592,7 @@ report.to_html("report.html")
568
592
  | **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
569
593
  | **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
570
594
  | **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
571
- | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
595
+ | **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` + `recall` tools. |
572
596
  | **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
573
597
  | **Eval Framework** | 50 built-in evaluators (30 deterministic + 21 LLM-as-judge). A/B testing, regression detection, snapshot testing, HTML reports, JUnit XML, CI integration. |
574
598
  | **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
@@ -595,8 +619,11 @@ report.to_html("report.html")
595
619
  - **Dynamic Tool Loading**: Plugin system with hot-reload support
596
620
  - **Response Caching**: InMemoryCache and RedisCache with stats tracking
597
621
  - **115 Model Registry**: Type-safe constants with pricing and metadata
598
- - **Pre-built Toolbox**: 48 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear
599
- - **Persistent Sessions**: 4 backends (JSON file, SQLite, Redis, Supabase) with TTL and cross-session search
622
+ - **Pre-built Toolbox**: 56 tools for files, data, text, datetime, web, code, search, GitHub, DB, calculator, email, PDF, Slack, Notion, Linear, Discord, S3, browser, image gen
623
+ - **Persistent Sessions**: 6 backends (JSON file, SQLite, Redis, Supabase, MongoDB, DynamoDB) with TTL and cross-session search
624
+ - **Scheduled Agents**: `AgentScheduler` runs an agent on a cron or interval schedule with per-job max-runs, failure isolation, and an async loop
625
+ - **Reasoning Tools**: `think`/`analyze` tools make reasoning explicit, inspectable, and bounded by min/max steps
626
+ - **Prompt-Injection Guardrail**: `PromptInjectionGuardrail` — heuristic jailbreak/injection detection with high-precision patterns
600
627
  - **Entity Memory**: LLM-based named entity extraction and tracking
601
628
  - **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
602
629
  - **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
@@ -604,7 +631,7 @@ report.to_html("report.html")
604
631
  - **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
605
632
  - **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
606
633
  - **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
607
- - **Cross-Session Knowledge**: Daily logs + persistent memory with `remember` tool, pluggable stores (File, SQLite), importance scoring, TTL
634
+ - **Cross-Session Knowledge**: Daily logs + persistent memory with auto-injected `remember` + `recall` tools, pluggable stores (File, SQLite), importance scoring, TTL
608
635
  - **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
609
636
  - **Token Estimation**: `estimate_run_tokens()` for pre-execution budget checks
610
637
  - **Model Switching**: `model_selector` callback for per-iteration model selection
@@ -613,10 +640,10 @@ report.to_html("report.html")
613
640
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
614
641
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
615
642
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
616
- - **111 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
643
+ - **115 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, scheduled agents, reasoning tools, and more
617
644
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
618
645
  - **AgentObserver Protocol**: 46 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
619
- - **7268 Tests**: Unit, integration, regression, and E2E with real API calls
646
+ - **7700+ Tests**: Unit, integration, regression, and E2E with real API calls
620
647
 
621
648
  ## Install
622
649
 
@@ -1118,7 +1145,7 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
1118
1145
  |---|---|---|---|
1119
1146
  | 01 | `01_hello_world.py` | First agent, `@tool`, `ask()` | No |
1120
1147
  | 02 | `02_search_weather.py` | ToolRegistry, multiple tools | No |
1121
- | 03 | `03_toolbox.py` | 48 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
1148
+ | 03 | `03_toolbox.py` | 56 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
1122
1149
  | 04 | `04_conversation_memory.py` | Multi-turn memory | Yes |
1123
1150
  | 05 | `05_cost_tracking.py` | Token counting, cost warnings | Yes |
1124
1151
  | 06 | `06_async_agent.py` | `arun()`, concurrent agents, FastAPI | Yes |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "selectools"
7
- version = "0.26.0"
7
+ version = "0.27.1"
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"
@@ -80,6 +80,15 @@ toolbox = [
80
80
  "slack-sdk>=3.27.0",
81
81
  "pdfplumber>=0.11.0",
82
82
  ]
83
+ aws = [
84
+ "boto3>=1.34.0",
85
+ ]
86
+ browser = [
87
+ "playwright>=1.40.0",
88
+ ]
89
+ mongo = [
90
+ "pymongo>=4.0.0",
91
+ ]
83
92
  evals = [
84
93
  "pyyaml>=6.0.0",
85
94
  ]
@@ -1,6 +1,6 @@
1
1
  """Public exports for the selectools package."""
2
2
 
3
- __version__ = "0.26.0"
3
+ __version__ = "0.27.1"
4
4
 
5
5
  # Import submodules (lazy loading for optional dependencies)
6
6
  from . import embeddings, evals, guardrails, models, observe, patterns, rag, toolbox
@@ -45,6 +45,7 @@ from .guardrails import (
45
45
  GuardrailsPipeline,
46
46
  LengthGuardrail,
47
47
  PIIGuardrail,
48
+ PromptInjectionGuardrail,
48
49
  TopicGuardrail,
49
50
  ToxicityGuardrail,
50
51
  )
@@ -149,7 +150,13 @@ from .pending import (
149
150
  )
150
151
  from .pipeline import Pipeline, Step, StepResult, branch, cache_step, parallel, retry, step
151
152
  from .policy import ApprovalRequest, PolicyDecision, PolicyResult, ToolPolicy
152
- from .pricing import PRICING, calculate_cost, calculate_embedding_cost, get_model_pricing
153
+ from .pricing import (
154
+ PRICING,
155
+ calculate_cost,
156
+ calculate_cost_with_cached_input,
157
+ calculate_embedding_cost,
158
+ get_model_pricing,
159
+ )
153
160
  from .prompt import REASONING_STRATEGIES, PromptBuilder
154
161
  from .providers.anthropic_provider import AnthropicProvider
155
162
  from .providers.azure_openai_provider import AzureOpenAIProvider
@@ -161,8 +168,20 @@ from .providers.openai_provider import OpenAIProvider
161
168
  from .providers.router import RouterConfig, RouterProvider
162
169
  from .providers.stubs import LocalProvider
163
170
  from .results import Ambiguous, Artifact, NotFound, ToolResult, emit_artifact
171
+ from .scheduler import (
172
+ AgentScheduler,
173
+ CronSchedule,
174
+ IntervalSchedule,
175
+ JobResult,
176
+ Schedule,
177
+ ScheduledJob,
178
+ cron,
179
+ every,
180
+ )
164
181
  from .sessions import (
182
+ DynamoDBSessionStore,
165
183
  JsonFileSessionStore,
184
+ MongoSessionStore,
166
185
  RedisSessionStore,
167
186
  SessionMetadata,
168
187
  SessionSearchResult,
@@ -246,6 +265,7 @@ __all__ = [
246
265
  # Pricing
247
266
  "PRICING",
248
267
  "calculate_cost",
268
+ "calculate_cost_with_cached_input",
249
269
  "calculate_embedding_cost",
250
270
  "get_model_pricing",
251
271
  # Model Registry
@@ -314,6 +334,15 @@ __all__ = [
314
334
  "RepeatDetector",
315
335
  "StallDetector",
316
336
  "PingPongDetector",
337
+ # Scheduled agents
338
+ "AgentScheduler",
339
+ "ScheduledJob",
340
+ "JobResult",
341
+ "Schedule",
342
+ "CronSchedule",
343
+ "IntervalSchedule",
344
+ "cron",
345
+ "every",
317
346
  # Guardrails
318
347
  "guardrails",
319
348
  "Guardrail",
@@ -326,6 +355,7 @@ __all__ = [
326
355
  "PIIGuardrail",
327
356
  "TopicGuardrail",
328
357
  "ToxicityGuardrail",
358
+ "PromptInjectionGuardrail",
329
359
  # Audit
330
360
  "AuditLogger",
331
361
  "PrivacyLevel",
@@ -339,6 +369,8 @@ __all__ = [
339
369
  "SQLiteSessionStore",
340
370
  "RedisSessionStore",
341
371
  "SupabaseSessionStore",
372
+ "MongoSessionStore",
373
+ "DynamoDBSessionStore",
342
374
  # Entity Memory
343
375
  "Entity",
344
376
  "EntityMemory",
@@ -10,6 +10,7 @@ from ..types import Message, Role
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from ..memory import ConversationMemory
13
+ from .core import _RunContext
13
14
 
14
15
 
15
16
  _MAX_SUMMARY_CHARS = 4000 # ~1000 tokens, well under any provider's context window
@@ -132,6 +133,21 @@ class _MemoryManagerMixin:
132
133
  except Exception: # nosec B110
133
134
  pass # never crash the agent for a persistence failure
134
135
 
136
+ def _unified_memory_record(self, ctx: "_RunContext", final_response: Message) -> None:
137
+ """Persist the completed turn into unified memory, if configured.
138
+
139
+ Drives ``UnifiedMemory.add_turn()`` — the single write path that
140
+ records the episode, feeds the entity tier (when present), and
141
+ promotes aged-out short-term items to long-term memory.
142
+ """
143
+ unified = getattr(self, "unified_memory", None)
144
+ if unified is None:
145
+ return
146
+ try:
147
+ unified.add_turn(ctx.unified_user_text, final_response)
148
+ except Exception: # nosec B110
149
+ pass # never crash the agent for a memory persistence failure
150
+
135
151
  def _extract_entities(self, run_id: str) -> None:
136
152
  """Extract entities from recent messages if entity_memory is configured."""
137
153
  em = self.config.entity_memory
@@ -308,6 +308,19 @@ class AgentConfig:
308
308
  )
309
309
 
310
310
  if isinstance(self.memory, MemoryConfig):
311
+ # Unified memory manages its own tiers; a flat entity_memory/
312
+ # knowledge_graph/knowledge_memory passed alongside it would be
313
+ # silently dropped by the overwrite below. Fail loudly instead.
314
+ if self.memory._unified_enabled and (
315
+ self.entity_memory is not None
316
+ or self.knowledge_graph is not None
317
+ or self.knowledge_memory is not None
318
+ ):
319
+ raise ValueError(
320
+ "AgentConfig: entity_memory / knowledge_graph / knowledge_memory are "
321
+ "mutually exclusive with MemoryConfig(unified=True). Inject custom tiers "
322
+ "via MemoryConfig(unified_memory=UnifiedMemory(entity_memory=...)) instead."
323
+ )
311
324
  self.entity_memory = self.memory.entity_memory
312
325
  self.knowledge_graph = self.memory.knowledge_graph
313
326
  self.knowledge_memory = self.memory.knowledge_memory
@@ -39,6 +39,7 @@ if TYPE_CHECKING:
39
39
  from ..policy import ToolPolicy
40
40
  from ..providers.base import Provider
41
41
  from ..sessions import SessionStore
42
+ from ..unified_memory import UnifiedMemory
42
43
  from ..usage import AgentUsage
43
44
 
44
45
 
@@ -199,11 +200,95 @@ class SummarizeConfig:
199
200
  @stable
200
201
  @dataclass
201
202
  class MemoryConfig:
202
- """Memory subsystem settings."""
203
+ """Memory subsystem settings.
204
+
205
+ The ``unified*`` fields below are **beta** (v1.1): they wire
206
+ :class:`~selectools.unified_memory.UnifiedMemory` into the agent so it
207
+ builds context from all tiers before each call and persists the completed
208
+ turn (with STM -> LTM auto-promotion) after each run.
209
+
210
+ Attributes:
211
+ entity_memory: Optional EntityMemory for per-turn entity extraction
212
+ and context injection.
213
+ knowledge_graph: Optional KnowledgeGraphMemory for relationship
214
+ triple extraction and query-scoped context.
215
+ knowledge_memory: Optional KnowledgeMemory for durable facts and the
216
+ auto-injected ``remember`` tool.
217
+ unified: Enable unified tiered memory (beta). The agent builds a
218
+ :class:`~selectools.unified_memory.UnifiedMemory` from the tier
219
+ parameters below and drives it for context assembly and post-turn
220
+ persistence. Mutually exclusive with ``entity_memory``,
221
+ ``knowledge_graph``, ``knowledge_memory``, the Agent ``memory=``
222
+ parameter, and ``session_store``. Default: False.
223
+ unified_memory: Optional pre-built UnifiedMemory instance (beta).
224
+ Implies ``unified=True``. Use this to inject custom tiers
225
+ (``UnifiedMemory(short_term=..., long_term=..., entity_memory=...)``,
226
+ custom scorers, summarizers). When set, the scalar tier
227
+ parameters below are ignored — the instance's own settings win.
228
+ Default: None.
229
+ importance_threshold: Minimum importance score (0.0-1.0) for STM ->
230
+ LTM promotion. Default: 0.7.
231
+ short_term_limit: Rolling short-term window size, in messages
232
+ (one turn = two messages). Default: 100.
233
+ long_term_limit: Maximum long-term entries before importance-based
234
+ eviction. Default: 1000.
235
+ episodic_retention_days: Episodes older than this are pruned.
236
+ Default: 30.
237
+ auto_promote: Score and promote short-term items as they age out of
238
+ the rolling window. Default: True.
239
+ context_max_tokens: Token budget passed to
240
+ ``UnifiedMemory.assemble_context()`` when the agent injects
241
+ unified context; compaction triggers at 70% of this budget.
242
+ Default: 4000.
243
+
244
+ Raises:
245
+ ValueError: If unified memory is enabled together with
246
+ ``entity_memory``, ``knowledge_graph``, or ``knowledge_memory``;
247
+ or if any unified tier parameter is out of range while unified
248
+ memory is enabled (the parameters are inert otherwise).
249
+ """
203
250
 
204
251
  entity_memory: Optional["EntityMemory"] = None
205
252
  knowledge_graph: Optional["KnowledgeGraphMemory"] = None
206
253
  knowledge_memory: Optional["KnowledgeMemory"] = None
254
+ # -- Unified tiered memory (beta, v1.1) --
255
+ unified: bool = False
256
+ unified_memory: Optional["UnifiedMemory"] = None
257
+ importance_threshold: float = 0.7
258
+ short_term_limit: int = 100
259
+ long_term_limit: int = 1000
260
+ episodic_retention_days: int = 30
261
+ auto_promote: bool = True
262
+ context_max_tokens: int = 4000
263
+
264
+ @property
265
+ def _unified_enabled(self) -> bool:
266
+ """Whether unified memory is requested (flag or injected instance)."""
267
+ return self.unified or self.unified_memory is not None
268
+
269
+ def __post_init__(self) -> None:
270
+ if not self._unified_enabled:
271
+ return
272
+ if (
273
+ self.entity_memory is not None
274
+ or self.knowledge_graph is not None
275
+ or self.knowledge_memory is not None
276
+ ):
277
+ raise ValueError(
278
+ "MemoryConfig: unified memory is mutually exclusive with "
279
+ "entity_memory/knowledge_graph/knowledge_memory. Inject custom "
280
+ "tiers via MemoryConfig(unified_memory=UnifiedMemory(...)) instead."
281
+ )
282
+ if not 0.0 <= self.importance_threshold <= 1.0:
283
+ raise ValueError("MemoryConfig.importance_threshold must be between 0.0 and 1.0")
284
+ if self.short_term_limit < 1:
285
+ raise ValueError("MemoryConfig.short_term_limit must be at least 1")
286
+ if self.long_term_limit < 1:
287
+ raise ValueError("MemoryConfig.long_term_limit must be at least 1")
288
+ if self.episodic_retention_days < 1:
289
+ raise ValueError("MemoryConfig.episodic_retention_days must be at least 1")
290
+ if self.context_max_tokens < 1:
291
+ raise ValueError("MemoryConfig.context_max_tokens must be at least 1")
207
292
 
208
293
 
209
294
  @stable