selectools 0.19.1__tar.gz → 0.19.2__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 (228) hide show
  1. {selectools-0.19.1/src/selectools.egg-info → selectools-0.19.2}/PKG-INFO +30 -4
  2. {selectools-0.19.1 → selectools-0.19.2}/README.md +29 -3
  3. {selectools-0.19.1 → selectools-0.19.2}/pyproject.toml +1 -1
  4. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/__init__.py +8 -2
  5. selectools-0.19.2/src/selectools/stability.py +111 -0
  6. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/trace.py +176 -1
  7. {selectools-0.19.1 → selectools-0.19.2/src/selectools.egg-info}/PKG-INFO +30 -4
  8. {selectools-0.19.1 → selectools-0.19.2}/src/selectools.egg-info/SOURCES.txt +3 -0
  9. selectools-0.19.2/tests/test_stability.py +195 -0
  10. selectools-0.19.2/tests/test_trace_html.py +159 -0
  11. {selectools-0.19.1 → selectools-0.19.2}/LICENSE +0 -0
  12. {selectools-0.19.1 → selectools-0.19.2}/setup.cfg +0 -0
  13. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/__init__.py +0 -0
  14. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/_lifecycle.py +0 -0
  15. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/_memory_manager.py +0 -0
  16. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/_provider_caller.py +0 -0
  17. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/_tool_executor.py +0 -0
  18. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/config.py +0 -0
  19. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/config_groups.py +0 -0
  20. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/agent/core.py +0 -0
  21. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/analytics.py +0 -0
  22. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/audit.py +0 -0
  23. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/cache.py +0 -0
  24. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/cache_redis.py +0 -0
  25. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/cache_semantic.py +0 -0
  26. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/cancellation.py +0 -0
  27. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/checkpoint_postgres.py +0 -0
  28. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/coherence.py +0 -0
  29. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/compose.py +0 -0
  30. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/__init__.py +0 -0
  31. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/anthropic.py +0 -0
  32. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/cohere.py +0 -0
  33. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/gemini.py +0 -0
  34. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/openai.py +0 -0
  35. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/embeddings/provider.py +0 -0
  36. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/entity_memory.py +0 -0
  37. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/env.py +0 -0
  38. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/__init__.py +0 -0
  39. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/__main__.py +0 -0
  40. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/badge.py +0 -0
  41. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/dataset.py +0 -0
  42. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/evaluators.py +0 -0
  43. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/generator.py +0 -0
  44. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/history.py +0 -0
  45. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/html.py +0 -0
  46. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/junit.py +0 -0
  47. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/llm_evaluators.py +0 -0
  48. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/pairwise.py +0 -0
  49. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/regression.py +0 -0
  50. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/report.py +0 -0
  51. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/serve.py +0 -0
  52. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/snapshot.py +0 -0
  53. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/suite.py +0 -0
  54. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/templates.py +0 -0
  55. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/evals/types.py +0 -0
  56. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/exceptions.py +0 -0
  57. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/__init__.py +0 -0
  58. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/base.py +0 -0
  59. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/format.py +0 -0
  60. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/length.py +0 -0
  61. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/pii.py +0 -0
  62. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/pipeline.py +0 -0
  63. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/topic.py +0 -0
  64. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/guardrails/toxicity.py +0 -0
  65. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/knowledge.py +0 -0
  66. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/knowledge_graph.py +0 -0
  67. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/knowledge_store_redis.py +0 -0
  68. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/knowledge_store_supabase.py +0 -0
  69. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/__init__.py +0 -0
  70. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/_loop.py +0 -0
  71. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/bridge.py +0 -0
  72. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/client.py +0 -0
  73. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/config.py +0 -0
  74. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/multi.py +0 -0
  75. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/mcp/server.py +0 -0
  76. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/memory.py +0 -0
  77. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/models.py +0 -0
  78. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/observe/__init__.py +0 -0
  79. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/observe/trace_store.py +0 -0
  80. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/observer.py +0 -0
  81. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/__init__.py +0 -0
  82. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/checkpoint.py +0 -0
  83. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/graph.py +0 -0
  84. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/node.py +0 -0
  85. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/state.py +0 -0
  86. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/orchestration/supervisor.py +0 -0
  87. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/parser.py +0 -0
  88. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/patterns/__init__.py +0 -0
  89. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/patterns/debate.py +0 -0
  90. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/patterns/plan_and_execute.py +0 -0
  91. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/patterns/reflective.py +0 -0
  92. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/patterns/team_lead.py +0 -0
  93. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/pipeline.py +0 -0
  94. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/policy.py +0 -0
  95. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/pricing.py +0 -0
  96. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/prompt.py +0 -0
  97. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/__init__.py +0 -0
  98. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/_openai_compat.py +0 -0
  99. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/anthropic_provider.py +0 -0
  100. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/base.py +0 -0
  101. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/fallback.py +0 -0
  102. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/gemini_provider.py +0 -0
  103. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/ollama_provider.py +0 -0
  104. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/openai_provider.py +0 -0
  105. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/providers/stubs.py +0 -0
  106. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/__init__.py +0 -0
  107. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/bm25.py +0 -0
  108. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/chunking.py +0 -0
  109. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/hybrid.py +0 -0
  110. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/loaders.py +0 -0
  111. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/reranker.py +0 -0
  112. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/stores/__init__.py +0 -0
  113. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/stores/chroma.py +0 -0
  114. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/stores/memory.py +0 -0
  115. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/stores/pinecone.py +0 -0
  116. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/stores/sqlite.py +0 -0
  117. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/tools.py +0 -0
  118. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/rag/vector_store.py +0 -0
  119. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/security.py +0 -0
  120. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/serve/__init__.py +0 -0
  121. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/serve/app.py +0 -0
  122. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/serve/cli.py +0 -0
  123. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/serve/models.py +0 -0
  124. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/serve/playground.py +0 -0
  125. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/sessions.py +0 -0
  126. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/structured.py +0 -0
  127. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/__init__.py +0 -0
  128. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/code_reviewer.py +0 -0
  129. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/customer_support.py +0 -0
  130. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/data_analyst.py +0 -0
  131. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/rag_chatbot.py +0 -0
  132. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/templates/research_assistant.py +0 -0
  133. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/token_estimation.py +0 -0
  134. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/__init__.py +0 -0
  135. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/data_tools.py +0 -0
  136. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/datetime_tools.py +0 -0
  137. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/file_tools.py +0 -0
  138. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/memory_tools.py +0 -0
  139. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/text_tools.py +0 -0
  140. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/toolbox/web_tools.py +0 -0
  141. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/tools/__init__.py +0 -0
  142. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/tools/base.py +0 -0
  143. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/tools/decorators.py +0 -0
  144. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/tools/loader.py +0 -0
  145. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/tools/registry.py +0 -0
  146. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/types.py +0 -0
  147. {selectools-0.19.1 → selectools-0.19.2}/src/selectools/usage.py +0 -0
  148. {selectools-0.19.1 → selectools-0.19.2}/src/selectools.egg-info/dependency_links.txt +0 -0
  149. {selectools-0.19.1 → selectools-0.19.2}/src/selectools.egg-info/entry_points.txt +0 -0
  150. {selectools-0.19.1 → selectools-0.19.2}/src/selectools.egg-info/requires.txt +0 -0
  151. {selectools-0.19.1 → selectools-0.19.2}/src/selectools.egg-info/top_level.txt +0 -0
  152. {selectools-0.19.1 → selectools-0.19.2}/tests/test_approval_gate.py +0 -0
  153. {selectools-0.19.1 → selectools-0.19.2}/tests/test_architecture.py +0 -0
  154. {selectools-0.19.1 → selectools-0.19.2}/tests/test_async_observers.py +0 -0
  155. {selectools-0.19.1 → selectools-0.19.2}/tests/test_audit.py +0 -0
  156. {selectools-0.19.1 → selectools-0.19.2}/tests/test_budget.py +0 -0
  157. {selectools-0.19.1 → selectools-0.19.2}/tests/test_bug_hunt_batch1_core.py +0 -0
  158. {selectools-0.19.1 → selectools-0.19.2}/tests/test_bug_hunt_batch1_security.py +0 -0
  159. {selectools-0.19.1 → selectools-0.19.2}/tests/test_bug_hunt_batch1_tools.py +0 -0
  160. {selectools-0.19.1 → selectools-0.19.2}/tests/test_bug_hunt_regression.py +0 -0
  161. {selectools-0.19.1 → selectools-0.19.2}/tests/test_cache.py +0 -0
  162. {selectools-0.19.1 → selectools-0.19.2}/tests/test_cache_redis.py +0 -0
  163. {selectools-0.19.1 → selectools-0.19.2}/tests/test_cancellation.py +0 -0
  164. {selectools-0.19.1 → selectools-0.19.2}/tests/test_coherence.py +0 -0
  165. {selectools-0.19.1 → selectools-0.19.2}/tests/test_concurrency_smoke.py +0 -0
  166. {selectools-0.19.1 → selectools-0.19.2}/tests/test_consolidation_regression.py +0 -0
  167. {selectools-0.19.1 → selectools-0.19.2}/tests/test_conversation_branching.py +0 -0
  168. {selectools-0.19.1 → selectools-0.19.2}/tests/test_entity_memory.py +0 -0
  169. {selectools-0.19.1 → selectools-0.19.2}/tests/test_env.py +0 -0
  170. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals.py +0 -0
  171. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_advanced.py +0 -0
  172. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_e2e.py +0 -0
  173. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_final.py +0 -0
  174. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_hardening.py +0 -0
  175. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_new_evaluators.py +0 -0
  176. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_release.py +0 -0
  177. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_v017_features.py +0 -0
  178. {selectools-0.19.1 → selectools-0.19.2}/tests/test_evals_v0191.py +0 -0
  179. {selectools-0.19.1 → selectools-0.19.2}/tests/test_features_in_graph.py +0 -0
  180. {selectools-0.19.1 → selectools-0.19.2}/tests/test_guardrails.py +0 -0
  181. {selectools-0.19.1 → selectools-0.19.2}/tests/test_hardening.py +0 -0
  182. {selectools-0.19.1 → selectools-0.19.2}/tests/test_knowledge.py +0 -0
  183. {selectools-0.19.1 → selectools-0.19.2}/tests/test_knowledge_graph.py +0 -0
  184. {selectools-0.19.1 → selectools-0.19.2}/tests/test_knowledge_store_redis.py +0 -0
  185. {selectools-0.19.1 → selectools-0.19.2}/tests/test_knowledge_store_supabase.py +0 -0
  186. {selectools-0.19.1 → selectools-0.19.2}/tests/test_knowledge_stores.py +0 -0
  187. {selectools-0.19.1 → selectools-0.19.2}/tests/test_mcp.py +0 -0
  188. {selectools-0.19.1 → selectools-0.19.2}/tests/test_memory.py +0 -0
  189. {selectools-0.19.1 → selectools-0.19.2}/tests/test_memory_async.py +0 -0
  190. {selectools-0.19.1 → selectools-0.19.2}/tests/test_memory_boundary.py +0 -0
  191. {selectools-0.19.1 → selectools-0.19.2}/tests/test_memory_integration.py +0 -0
  192. {selectools-0.19.1 → selectools-0.19.2}/tests/test_model_switching.py +0 -0
  193. {selectools-0.19.1 → selectools-0.19.2}/tests/test_multi_agent_edge_cases.py +0 -0
  194. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_checkpoint.py +0 -0
  195. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_e2e.py +0 -0
  196. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_evals.py +0 -0
  197. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_graph.py +0 -0
  198. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_integration.py +0 -0
  199. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_primitives.py +0 -0
  200. {selectools-0.19.1 → selectools-0.19.2}/tests/test_orchestration_supervisor.py +0 -0
  201. {selectools-0.19.1 → selectools-0.19.2}/tests/test_parser.py +0 -0
  202. {selectools-0.19.1 → selectools-0.19.2}/tests/test_patterns.py +0 -0
  203. {selectools-0.19.1 → selectools-0.19.2}/tests/test_phase1_design_patterns.py +0 -0
  204. {selectools-0.19.1 → selectools-0.19.2}/tests/test_pipeline.py +0 -0
  205. {selectools-0.19.1 → selectools-0.19.2}/tests/test_policy.py +0 -0
  206. {selectools-0.19.1 → selectools-0.19.2}/tests/test_prompt.py +0 -0
  207. {selectools-0.19.1 → selectools-0.19.2}/tests/test_prompt_compression.py +0 -0
  208. {selectools-0.19.1 → selectools-0.19.2}/tests/test_property_based.py +0 -0
  209. {selectools-0.19.1 → selectools-0.19.2}/tests/test_reasoning_strategy.py +0 -0
  210. {selectools-0.19.1 → selectools-0.19.2}/tests/test_routing_mode.py +0 -0
  211. {selectools-0.19.1 → selectools-0.19.2}/tests/test_security.py +0 -0
  212. {selectools-0.19.1 → selectools-0.19.2}/tests/test_semantic_cache.py +0 -0
  213. {selectools-0.19.1 → selectools-0.19.2}/tests/test_sessions.py +0 -0
  214. {selectools-0.19.1 → selectools-0.19.2}/tests/test_sessions_edge_cases.py +0 -0
  215. {selectools-0.19.1 → selectools-0.19.2}/tests/test_sessions_redis.py +0 -0
  216. {selectools-0.19.1 → selectools-0.19.2}/tests/test_simple_observer.py +0 -0
  217. {selectools-0.19.1 → selectools-0.19.2}/tests/test_simulation_evals.py +0 -0
  218. {selectools-0.19.1 → selectools-0.19.2}/tests/test_structured.py +0 -0
  219. {selectools-0.19.1 → selectools-0.19.2}/tests/test_structured_config.py +0 -0
  220. {selectools-0.19.1 → selectools-0.19.2}/tests/test_structured_tool_results.py +0 -0
  221. {selectools-0.19.1 → selectools-0.19.2}/tests/test_summarize_on_trim.py +0 -0
  222. {selectools-0.19.1 → selectools-0.19.2}/tests/test_terminal_actions.py +0 -0
  223. {selectools-0.19.1 → selectools-0.19.2}/tests/test_token_estimation.py +0 -0
  224. {selectools-0.19.1 → selectools-0.19.2}/tests/test_tool_caching.py +0 -0
  225. {selectools-0.19.1 → selectools-0.19.2}/tests/test_trace.py +0 -0
  226. {selectools-0.19.1 → selectools-0.19.2}/tests/test_v016_regression.py +0 -0
  227. {selectools-0.19.1 → selectools-0.19.2}/tests/test_v019_features.py +0 -0
  228. {selectools-0.19.1 → selectools-0.19.2}/tests/test_yaml_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: selectools
3
- Version: 0.19.1
3
+ Version: 0.19.2
4
4
  Summary: Production-ready AI agents with tool calling, structured output, execution traces, and RAG. Provider-agnostic (OpenAI, Anthropic, Gemini, Ollama) with fallback chains, batch processing, tool policies, streaming, caching, and cost tracking.
5
5
  Author-email: John Nichev <johnnichev@gmail.com>
6
6
  Maintainer-email: NichevLabs <support@nichevlabs.com>
@@ -86,6 +86,32 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
86
86
 
87
87
  ## What's New in v0.19
88
88
 
89
+ ### v0.19.2 — Enterprise Hardening
90
+
91
+ ```python
92
+ from selectools.stability import stable, beta, deprecated
93
+ from selectools import trace_to_html
94
+
95
+ # Mark your own extensions with stability levels
96
+ @stable
97
+ class MyProductionAgent: ...
98
+
99
+ @beta
100
+ class MyExperimentalFeature: ...
101
+
102
+ @deprecated(since="0.19", replacement="MyProductionAgent")
103
+ class MyOldAgent: ...
104
+
105
+ # Visualise any trace as a waterfall HTML timeline
106
+ Path("trace.html").write_text(trace_to_html(result.trace))
107
+ ```
108
+
109
+ - **Stability markers** — `@stable`, `@beta`, `@deprecated(since, replacement)` for public API signalling
110
+ - **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
111
+ - **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
112
+ - **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
113
+ - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (3135 tests total)
114
+
89
115
  ### v0.19.1 — Advanced Agent Patterns
90
116
 
91
117
  ```python
@@ -437,10 +463,10 @@ report.to_html("report.html")
437
463
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
438
464
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
439
465
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
440
- - **73 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, and more
466
+ - **75 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
441
467
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
442
468
  - **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
443
- - **2918 Tests**: Unit, integration, regression, and E2E with real API calls
469
+ - **3135 Tests**: Unit, integration, regression, and E2E with real API calls
444
470
 
445
471
  ## Install
446
472
 
@@ -1054,7 +1080,7 @@ pytest tests/ -x -q # All tests
1054
1080
  pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
1055
1081
  ```
1056
1082
 
1057
- 2918 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, and E2E integration with real API calls.
1083
+ 3135 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
1058
1084
 
1059
1085
  ## License
1060
1086
 
@@ -26,6 +26,32 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
26
26
 
27
27
  ## What's New in v0.19
28
28
 
29
+ ### v0.19.2 — Enterprise Hardening
30
+
31
+ ```python
32
+ from selectools.stability import stable, beta, deprecated
33
+ from selectools import trace_to_html
34
+
35
+ # Mark your own extensions with stability levels
36
+ @stable
37
+ class MyProductionAgent: ...
38
+
39
+ @beta
40
+ class MyExperimentalFeature: ...
41
+
42
+ @deprecated(since="0.19", replacement="MyProductionAgent")
43
+ class MyOldAgent: ...
44
+
45
+ # Visualise any trace as a waterfall HTML timeline
46
+ Path("trace.html").write_text(trace_to_html(result.trace))
47
+ ```
48
+
49
+ - **Stability markers** — `@stable`, `@beta`, `@deprecated(since, replacement)` for public API signalling
50
+ - **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
51
+ - **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
52
+ - **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
53
+ - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (3135 tests total)
54
+
29
55
  ### v0.19.1 — Advanced Agent Patterns
30
56
 
31
57
  ```python
@@ -377,10 +403,10 @@ report.to_html("report.html")
377
403
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
378
404
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
379
405
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
380
- - **73 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, and more
406
+ - **75 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
381
407
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
382
408
  - **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
383
- - **2918 Tests**: Unit, integration, regression, and E2E with real API calls
409
+ - **3135 Tests**: Unit, integration, regression, and E2E with real API calls
384
410
 
385
411
  ## Install
386
412
 
@@ -994,7 +1020,7 @@ pytest tests/ -x -q # All tests
994
1020
  pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
995
1021
  ```
996
1022
 
997
- 2918 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, and E2E integration with real API calls.
1023
+ 3135 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
998
1024
 
999
1025
  ## License
1000
1026
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "selectools"
7
- version = "0.19.1"
7
+ version = "0.19.2"
8
8
  description = "Production-ready AI agents with tool calling, structured output, execution traces, and RAG. Provider-agnostic (OpenAI, Anthropic, Gemini, Ollama) with fallback chains, batch processing, tool policies, streaming, caching, and cost tracking."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,6 +1,6 @@
1
1
  """Public exports for the selectools package."""
2
2
 
3
- __version__ = "0.19.1"
3
+ __version__ = "0.19.2"
4
4
 
5
5
  # Import submodules (lazy loading for optional dependencies)
6
6
  from . import embeddings, evals, guardrails, models, patterns, rag, toolbox
@@ -129,10 +129,11 @@ from .sessions import (
129
129
  SessionStore,
130
130
  SQLiteSessionStore,
131
131
  )
132
+ from .stability import beta, deprecated, stable
132
133
  from .structured import ResponseFormat
133
134
  from .token_estimation import TokenEstimate, estimate_run_tokens, estimate_tokens
134
135
  from .tools import Tool, ToolParameter, ToolRegistry, tool
135
- from .trace import AgentTrace, StepType, TraceStep
136
+ from .trace import AgentTrace, StepType, TraceStep, trace_to_html
136
137
  from .types import AgentResult, Message, Role, ToolCall
137
138
  from .usage import AgentUsage, UsageStats
138
139
 
@@ -201,6 +202,10 @@ __all__ = [
201
202
  "PolicyResult",
202
203
  # Structured output
203
204
  "ResponseFormat",
205
+ # Stability markers
206
+ "stable",
207
+ "beta",
208
+ "deprecated",
204
209
  # Observability
205
210
  "AgentObserver",
206
211
  "AsyncAgentObserver",
@@ -209,6 +214,7 @@ __all__ = [
209
214
  "AgentTrace",
210
215
  "StepType",
211
216
  "TraceStep",
217
+ "trace_to_html",
212
218
  # Guardrails
213
219
  "guardrails",
214
220
  "Guardrail",
@@ -0,0 +1,111 @@
1
+ """
2
+ Stability markers for the selectools public API.
3
+
4
+ Use these decorators to signal the stability of any public function or class:
5
+
6
+ - ``@stable`` — API is frozen; breaking changes require a major version bump.
7
+ - ``@beta`` — API may change in a minor release; no deprecation cycle guaranteed.
8
+ - ``@deprecated(since, replacement)`` — Emits ``DeprecationWarning`` on use and will
9
+ be removed after the minimum deprecation window (2 minor releases).
10
+
11
+ Examples::
12
+
13
+ from selectools.stability import stable, beta, deprecated
14
+
15
+ @stable
16
+ def my_function(): ...
17
+
18
+ @beta
19
+ class MyExperimentalClass: ...
20
+
21
+ @deprecated(since="0.19", replacement="NewThing")
22
+ def old_function(): ...
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ import functools
28
+ import inspect
29
+ import warnings
30
+ from typing import Any, Callable, Optional, TypeVar, Union, overload
31
+
32
+ _F = TypeVar("_F", bound=Callable[..., Any])
33
+ _C = TypeVar("_C", bound=type)
34
+
35
+
36
+ def stable(obj: Union[_F, _C]) -> Union[_F, _C]:
37
+ """Set stability marker to 'stable' (API is frozen)."""
38
+ obj.__stability__ = "stable" # type: ignore[union-attr]
39
+ return obj
40
+
41
+
42
+ def beta(obj: Union[_F, _C]) -> Union[_F, _C]:
43
+ """Set stability marker to 'beta' (API may change in minor releases)."""
44
+ obj.__stability__ = "beta" # type: ignore[union-attr]
45
+ return obj
46
+
47
+
48
+ def deprecated(
49
+ since: str,
50
+ replacement: Optional[str] = None,
51
+ ) -> Callable[[Union[_F, _C]], Union[_F, _C]]:
52
+ """Mark a function or class as deprecated.
53
+
54
+ Emits a ``DeprecationWarning`` on every call or instantiation.
55
+
56
+ Args:
57
+ since: The version in which the deprecation was introduced (e.g. ``"0.19"``).
58
+ replacement: Optional name of the replacement API to suggest in the warning.
59
+
60
+ Example::
61
+
62
+ @deprecated(since="0.19", replacement="NewProvider")
63
+ class OldProvider:
64
+ ...
65
+ """
66
+
67
+ def _make_message(name: str) -> str:
68
+ msg = f"{name} is deprecated since v{since}."
69
+ if replacement:
70
+ msg += f" Use {replacement} instead."
71
+ return msg
72
+
73
+ @overload
74
+ def decorator(obj: _C) -> _C: ...
75
+
76
+ @overload
77
+ def decorator(obj: _F) -> _F: ...
78
+
79
+ def decorator(obj: Union[_F, _C]) -> Union[_F, _C]:
80
+ if inspect.isclass(obj):
81
+ # Wrap __init__ so the warning fires on instantiation.
82
+ original_init = obj.__init__ # type: ignore[misc]
83
+ message = _make_message(obj.__qualname__)
84
+
85
+ @functools.wraps(original_init)
86
+ def _new_init(self: Any, *args: Any, **kwargs: Any) -> None:
87
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
88
+ original_init(self, *args, **kwargs)
89
+
90
+ obj.__init__ = _new_init # type: ignore[method-assign]
91
+ obj.__stability__ = "deprecated" # type: ignore[union-attr]
92
+ obj.__deprecated_since__ = since # type: ignore[union-attr]
93
+ obj.__deprecated_replacement__ = replacement # type: ignore[union-attr]
94
+ return obj # type: ignore[return-value]
95
+ else:
96
+ message = _make_message(obj.__qualname__)
97
+
98
+ @functools.wraps(obj)
99
+ def _wrapper(*args: Any, **kwargs: Any) -> Any:
100
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
101
+ return obj(*args, **kwargs)
102
+
103
+ _wrapper.__stability__ = "deprecated" # type: ignore[attr-defined]
104
+ _wrapper.__deprecated_since__ = since # type: ignore[attr-defined]
105
+ _wrapper.__deprecated_replacement__ = replacement # type: ignore[attr-defined]
106
+ return _wrapper # type: ignore[return-value]
107
+
108
+ return decorator # type: ignore[return-value]
109
+
110
+
111
+ __all__ = ["stable", "beta", "deprecated"]
@@ -300,4 +300,179 @@ def _span_id() -> str:
300
300
  return uuid.uuid4().hex[:16]
301
301
 
302
302
 
303
- __all__ = ["TraceStep", "AgentTrace", "StepType"]
303
+ # ---------------------------------------------------------------------------
304
+ # HTML trace viewer
305
+ # ---------------------------------------------------------------------------
306
+
307
+ _STEP_COLORS: Dict[str, str] = {
308
+ "llm_call": "#3b82f6",
309
+ "tool_execution": "#8b5cf6",
310
+ "tool_selection": "#a78bfa",
311
+ "cache_hit": "#4ade80",
312
+ "error": "#f87171",
313
+ "guardrail": "#fbbf24",
314
+ "output_screening": "#fbbf24",
315
+ "coherence_check": "#fbbf24",
316
+ "graph_node_start": "#06b6d4",
317
+ "graph_node_end": "#06b6d4",
318
+ "graph_routing": "#06b6d4",
319
+ "graph_checkpoint": "#06b6d4",
320
+ "graph_interrupt": "#06b6d4",
321
+ "graph_resume": "#06b6d4",
322
+ "graph_parallel_start": "#06b6d4",
323
+ "graph_parallel_end": "#06b6d4",
324
+ "graph_stall": "#f97316",
325
+ "graph_loop_detected": "#f97316",
326
+ }
327
+ _DEFAULT_COLOR = "#64748b"
328
+
329
+
330
+ def trace_to_html(trace: "AgentTrace") -> str:
331
+ """Render an AgentTrace as a standalone HTML waterfall timeline.
332
+
333
+ Returns a self-contained HTML string (no external dependencies).
334
+ The caller is responsible for writing it to disk if desired::
335
+
336
+ from selectools import trace_to_html
337
+ Path("trace.html").write_text(trace_to_html(result.trace))
338
+
339
+ Args:
340
+ trace: The ``AgentTrace`` to visualise.
341
+
342
+ Returns:
343
+ A complete HTML document as a string.
344
+ """
345
+ import html as _html
346
+
347
+ max_dur = max((s.duration_ms for s in trace.steps), default=1.0)
348
+ max_dur = max(max_dur, 1.0) # guard against all-zero durations
349
+
350
+ total_ms = trace.total_duration_ms
351
+ llm_ms = trace.llm_duration_ms
352
+ tool_ms = trace.tool_duration_ms
353
+ llm_pct = f"{llm_ms / max(total_ms, 1) * 100:.0f}%"
354
+ tool_pct = f"{tool_ms / max(total_ms, 1) * 100:.0f}%"
355
+
356
+ def _esc(v: Any) -> str:
357
+ return _html.escape(str(v)) if v is not None else ""
358
+
359
+ def _detail(step: "TraceStep") -> str:
360
+ parts = []
361
+ if step.model:
362
+ parts.append(f"<b>model:</b> {_esc(step.model)}")
363
+ if step.prompt_tokens is not None:
364
+ parts.append(f"<b>prompt tokens:</b> {step.prompt_tokens}")
365
+ if step.completion_tokens is not None:
366
+ parts.append(f"<b>completion tokens:</b> {step.completion_tokens}")
367
+ if step.cost_usd is not None:
368
+ parts.append(f"<b>cost:</b> ${step.cost_usd:.6f}")
369
+ if step.tool_name:
370
+ parts.append(f"<b>tool:</b> {_esc(step.tool_name)}")
371
+ if step.tool_args:
372
+ parts.append(f"<b>args:</b> <code>{_esc(json.dumps(step.tool_args))}</code>")
373
+ if step.tool_result:
374
+ truncated = str(step.tool_result)[:300]
375
+ parts.append(f"<b>result:</b> <code>{_esc(truncated)}</code>")
376
+ if step.error:
377
+ parts.append(f"<b>error:</b> <span style='color:#f87171'>{_esc(step.error)}</span>")
378
+ if step.node_name:
379
+ parts.append(f"<b>node:</b> {_esc(step.node_name)}")
380
+ if step.from_node or step.to_node:
381
+ parts.append(f"<b>route:</b> {_esc(step.from_node)} → {_esc(step.to_node)}")
382
+ if step.summary:
383
+ parts.append(f"<b>summary:</b> {_esc(step.summary)}")
384
+ if step.reasoning:
385
+ parts.append(f"<b>reasoning:</b> {_esc(step.reasoning[:200])}")
386
+ return "<br>".join(parts) if parts else "<i>no details</i>"
387
+
388
+ rows = []
389
+ for i, step in enumerate(trace.steps):
390
+ type_val = step.type.value if hasattr(step.type, "value") else str(step.type)
391
+ color = _STEP_COLORS.get(type_val, _DEFAULT_COLOR)
392
+ bar_pct = step.duration_ms / max_dur * 100
393
+ label = step.summary or type_val
394
+ detail_html = _detail(step)
395
+ rows.append(
396
+ f"""
397
+ <tr onclick="toggleDetail('d{i}')" style="cursor:pointer">
398
+ <td style="color:#94a3b8;width:32px;text-align:right;padding-right:12px">{i + 1}</td>
399
+ <td style="width:160px">
400
+ <span style="background:{color};color:#0f172a;font-size:11px;font-weight:600;
401
+ padding:2px 7px;border-radius:4px">{_esc(type_val)}</span>
402
+ </td>
403
+ <td style="width:200px;padding:0 12px">
404
+ <div style="background:#1e3a5f;border-radius:3px;height:10px;width:100%">
405
+ <div style="background:{color};border-radius:3px;height:10px;width:{bar_pct:.1f}%"></div>
406
+ </div>
407
+ </td>
408
+ <td style="color:#94a3b8;width:70px;text-align:right;padding-right:12px">
409
+ {step.duration_ms:.1f}ms
410
+ </td>
411
+ <td style="color:#e2e8f0">{_esc(label)}</td>
412
+ </tr>
413
+ <tr id="d{i}" style="display:none">
414
+ <td colspan="5" style="padding:8px 16px 12px 44px;color:#94a3b8;
415
+ font-size:12px;background:#0f2035;border-bottom:1px solid #1e3a5f">
416
+ {detail_html}
417
+ </td>
418
+ </tr>"""
419
+ )
420
+
421
+ rows_html = "\n".join(rows)
422
+ run_id_display = _esc(trace.run_id[:16]) + "…" if len(trace.run_id) > 16 else _esc(trace.run_id)
423
+ step_count = len(trace.steps)
424
+
425
+ return f"""<!DOCTYPE html>
426
+ <html lang="en">
427
+ <head>
428
+ <meta charset="utf-8">
429
+ <meta name="viewport" content="width=device-width, initial-scale=1">
430
+ <title>Agent Trace — {run_id_display}</title>
431
+ <style>
432
+ * {{ box-sizing: border-box; margin: 0; padding: 0; }}
433
+ body {{ background: #0f172a; color: #e2e8f0; font-family: 'JetBrains Mono', 'Fira Code', monospace;
434
+ font-size: 13px; padding: 24px; }}
435
+ h1 {{ font-size: 16px; font-weight: 600; color: #f8fafc; margin-bottom: 4px; }}
436
+ .meta {{ color: #64748b; font-size: 12px; margin-bottom: 24px; }}
437
+ .stat {{ display: inline-block; margin-right: 24px; }}
438
+ .stat b {{ color: #e2e8f0; }}
439
+ table {{ width: 100%; border-collapse: collapse; }}
440
+ tr:hover td {{ background: #1a2744; }}
441
+ td {{ padding: 7px 4px; border-bottom: 1px solid #1e293b; vertical-align: middle; }}
442
+ code {{ background: #1e293b; padding: 1px 4px; border-radius: 3px; font-size: 11px; }}
443
+ </style>
444
+ </head>
445
+ <body>
446
+ <h1>Agent Trace</h1>
447
+ <div class="meta">
448
+ <span class="stat"><b>run:</b> {run_id_display}</span>
449
+ <span class="stat"><b>steps:</b> {step_count}</span>
450
+ <span class="stat"><b>total:</b> {total_ms:.1f}ms</span>
451
+ <span class="stat"><b>llm:</b> {llm_ms:.1f}ms ({llm_pct})</span>
452
+ <span class="stat"><b>tools:</b> {tool_ms:.1f}ms ({tool_pct})</span>
453
+ </div>
454
+ <table>
455
+ <thead>
456
+ <tr>
457
+ <th style="color:#475569;text-align:right;padding-right:12px">#</th>
458
+ <th style="color:#475569;text-align:left">type</th>
459
+ <th style="color:#475569;padding:0 12px">duration</th>
460
+ <th style="color:#475569;text-align:right;padding-right:12px">ms</th>
461
+ <th style="color:#475569;text-align:left">label</th>
462
+ </tr>
463
+ </thead>
464
+ <tbody>
465
+ {rows_html}
466
+ </tbody>
467
+ </table>
468
+ <script>
469
+ function toggleDetail(id) {{
470
+ var el = document.getElementById(id);
471
+ el.style.display = el.style.display === 'none' ? 'table-row' : 'none';
472
+ }}
473
+ </script>
474
+ </body>
475
+ </html>"""
476
+
477
+
478
+ __all__ = ["TraceStep", "AgentTrace", "StepType", "trace_to_html"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: selectools
3
- Version: 0.19.1
3
+ Version: 0.19.2
4
4
  Summary: Production-ready AI agents with tool calling, structured output, execution traces, and RAG. Provider-agnostic (OpenAI, Anthropic, Gemini, Ollama) with fallback chains, batch processing, tool policies, streaming, caching, and cost tracking.
5
5
  Author-email: John Nichev <johnnichev@gmail.com>
6
6
  Maintainer-email: NichevLabs <support@nichevlabs.com>
@@ -86,6 +86,32 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
86
86
 
87
87
  ## What's New in v0.19
88
88
 
89
+ ### v0.19.2 — Enterprise Hardening
90
+
91
+ ```python
92
+ from selectools.stability import stable, beta, deprecated
93
+ from selectools import trace_to_html
94
+
95
+ # Mark your own extensions with stability levels
96
+ @stable
97
+ class MyProductionAgent: ...
98
+
99
+ @beta
100
+ class MyExperimentalFeature: ...
101
+
102
+ @deprecated(since="0.19", replacement="MyProductionAgent")
103
+ class MyOldAgent: ...
104
+
105
+ # Visualise any trace as a waterfall HTML timeline
106
+ Path("trace.html").write_text(trace_to_html(result.trace))
107
+ ```
108
+
109
+ - **Stability markers** — `@stable`, `@beta`, `@deprecated(since, replacement)` for public API signalling
110
+ - **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
111
+ - **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
112
+ - **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
113
+ - **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (3135 tests total)
114
+
89
115
  ### v0.19.1 — Advanced Agent Patterns
90
116
 
91
117
  ```python
@@ -437,10 +463,10 @@ report.to_html("report.html")
437
463
  - **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
438
464
  - **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
439
465
  - **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
440
- - **73 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, and more
466
+ - **75 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
441
467
  - **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
442
468
  - **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
443
- - **2918 Tests**: Unit, integration, regression, and E2E with real API calls
469
+ - **3135 Tests**: Unit, integration, regression, and E2E with real API calls
444
470
 
445
471
  ## Install
446
472
 
@@ -1054,7 +1080,7 @@ pytest tests/ -x -q # All tests
1054
1080
  pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
1055
1081
  ```
1056
1082
 
1057
- 2918 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, and E2E integration with real API calls.
1083
+ 3135 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
1058
1084
 
1059
1085
  ## License
1060
1086
 
@@ -28,6 +28,7 @@ src/selectools/pricing.py
28
28
  src/selectools/prompt.py
29
29
  src/selectools/security.py
30
30
  src/selectools/sessions.py
31
+ src/selectools/stability.py
31
32
  src/selectools/structured.py
32
33
  src/selectools/token_estimation.py
33
34
  src/selectools/trace.py
@@ -210,6 +211,7 @@ tests/test_sessions_edge_cases.py
210
211
  tests/test_sessions_redis.py
211
212
  tests/test_simple_observer.py
212
213
  tests/test_simulation_evals.py
214
+ tests/test_stability.py
213
215
  tests/test_structured.py
214
216
  tests/test_structured_config.py
215
217
  tests/test_structured_tool_results.py
@@ -218,6 +220,7 @@ tests/test_terminal_actions.py
218
220
  tests/test_token_estimation.py
219
221
  tests/test_tool_caching.py
220
222
  tests/test_trace.py
223
+ tests/test_trace_html.py
221
224
  tests/test_v016_regression.py
222
225
  tests/test_v019_features.py
223
226
  tests/test_yaml_config.py