selectools 0.25.1__tar.gz → 0.27.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {selectools-0.25.1/src/selectools.egg-info → selectools-0.27.0}/PKG-INFO +54 -12
- {selectools-0.25.1 → selectools-0.27.0}/README.md +47 -11
- {selectools-0.25.1 → selectools-0.27.0}/pyproject.toml +10 -1
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/__init__.py +34 -2
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/a2a/server.py +6 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/_memory_manager.py +16 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/config_groups.py +86 -1
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/core.py +99 -13
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/gemini.py +35 -9
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/__init__.py +2 -0
- selectools-0.27.0/src/selectools/guardrails/injection.py +181 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/models.py +296 -516
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/pending.py +22 -1
- selectools-0.27.0/src/selectools/pricing.py +216 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/_openai_compat.py +31 -2
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/anthropic_provider.py +18 -10
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/gemini_provider.py +26 -4
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/litellm_provider.py +9 -1
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/ollama_provider.py +7 -1
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/openai_provider.py +11 -3
- selectools-0.27.0/src/selectools/scheduler.py +460 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/_static/builder.js +17 -14
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/sessions.py +386 -2
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/__init__.py +56 -1
- selectools-0.27.0/src/selectools/toolbox/browser_tools.py +143 -0
- selectools-0.27.0/src/selectools/toolbox/discord_tools.py +170 -0
- selectools-0.27.0/src/selectools/toolbox/image_tools.py +116 -0
- selectools-0.27.0/src/selectools/toolbox/memory_tools.py +147 -0
- selectools-0.27.0/src/selectools/toolbox/reasoning_tools.py +199 -0
- selectools-0.27.0/src/selectools/toolbox/s3_tools.py +212 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/unified_memory.py +12 -2
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/usage.py +8 -4
- {selectools-0.25.1 → selectools-0.27.0/src/selectools.egg-info}/PKG-INFO +54 -12
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools.egg-info/SOURCES.txt +13 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools.egg-info/requires.txt +9 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_architecture.py +14 -0
- selectools-0.27.0/tests/test_bake_window_hunt.py +115 -0
- selectools-0.27.0/tests/test_guardrails_injection.py +142 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge.py +216 -2
- selectools-0.27.0/tests/test_scheduler.py +319 -0
- selectools-0.27.0/tests/test_sessions_dynamodb.py +234 -0
- selectools-0.27.0/tests/test_sessions_mongo.py +243 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_token_estimation.py +3 -3
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_unified_memory.py +17 -0
- selectools-0.27.0/tests/test_unified_memory_config.py +333 -0
- selectools-0.25.1/src/selectools/pricing.py +0 -117
- selectools-0.25.1/src/selectools/toolbox/memory_tools.py +0 -68
- {selectools-0.25.1 → selectools-0.27.0}/LICENSE +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/setup.cfg +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/_async_utils.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/_json_utils.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/a2a/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/a2a/client.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/a2a/types.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/_lifecycle.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/_planning.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/_provider_caller.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/_tool_executor.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/agent/config.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/analytics.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/audit.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/cache.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/cache_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/cache_semantic.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/cancellation.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/checkpoint_postgres.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/coherence.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/compose.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/anthropic.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/cohere.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/openai.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/embeddings/provider.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/entity_memory.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/env.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/__main__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/badge.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/dataset.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/evaluators.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/generator.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/history.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/html.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/junit.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/llm_evaluators.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/pairwise.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/regression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/report.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/serve.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/snapshot.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/suite.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/templates.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/evals/types.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/exceptions.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/base.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/format.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/length.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/pii.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/pipeline.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/topic.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/guardrails/toxicity.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge_backends.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge_graph.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge_sanitizers.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge_store_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/knowledge_store_supabase.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/loop_detection.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/_loop.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/bridge.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/client.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/config.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/multi.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/mcp/server.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/memory.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/observe/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/observe/langfuse.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/observe/otel.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/observe/trace_store.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/checkpoint.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/graph.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/node.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/state.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/orchestration/supervisor.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/parser.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/patterns/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/patterns/debate.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/patterns/plan_and_execute.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/patterns/reflective.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/patterns/team_lead.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/pipeline.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/policy.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/prompt.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/azure_openai_provider.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/base.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/fallback.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/router.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/providers/stubs.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/bm25.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/chunking.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/hybrid.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/loaders.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/reranker.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/chroma.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/faiss.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/memory.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/pgvector.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/pinecone.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/qdrant.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/stores/sqlite.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/rag/vector_store.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/results.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/security.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/_starlette_app.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/_static/builder.css +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/_static/builder.html +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/api.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/app.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/builder.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/cli.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/models.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/serve/playground.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/stability.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/structured.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/code_reviewer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/customer_support.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/data_analyst.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/rag_chatbot.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/templates/research_assistant.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/token_estimation.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/calculator_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/code_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/data_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/datetime_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/db_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/email_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/file_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/github_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/linear_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/notion_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/pdf_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/search_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/slack_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/text_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/toolbox/web_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/tools/__init__.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/tools/base.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/tools/decorators.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/tools/loader.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/tools/registry.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/trace.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools/types.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools.egg-info/dependency_links.txt +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools.egg-info/entry_points.txt +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/src/selectools.egg-info/top_level.txt +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_a2a.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_agent_api.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_agent_hitl.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_approval_gate.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_async_observers.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_audit.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_budget.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_bug_hunt_batch1_core.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_bug_hunt_batch1_security.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_bug_hunt_batch1_tools.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_bug_hunt_regression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_cache.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_cache_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_cancellation.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_checkpoint_postgres.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_coherence.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_concurrency_smoke.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_consolidation_regression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_conversation_branching.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_coverage_orchestration.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_document_loaders_extended.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_e2e_langfuse_observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_e2e_multimodal.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_e2e_otel_observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_e2e_v0_21_0_apps.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_e2e_v0_21_0_simulations.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_entity_memory.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_env.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_advanced.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_cli.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_e2e.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_final.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_hardening.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_html_report.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_new_evaluators.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_ralph_bugs.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_release.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_serve.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_v017_features.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_evals_v0191.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_features_in_graph.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_final_coverage_a.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_final_coverage_b.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_guardrails.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_hardening.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_backend.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_backend_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_backend_supabase.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_graph.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_sanitizers.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_store_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_store_supabase.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_stores.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_knowledge_stores_error_handling.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_langfuse_observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_loop_detection.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_mcp.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_mcp_coverage.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_memory.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_memory_async.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_memory_boundary.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_memory_integration.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_model_switching.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_multi_agent_edge_cases.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_multimodal.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_checkpoint.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_e2e.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_evals.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_graph.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_integration.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_primitives.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_orchestration_supervisor.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_otel_observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_parser.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_patterns.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_pending.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_pending_redis_smoke.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_phase1_design_patterns.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_pipeline.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_pipeline_coverage.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_policy.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_prompt.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_prompt_compression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_property_based.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_reasoning_strategy.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_remaining_coverage.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_results.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_routing_mode.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_security.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_semantic_cache.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_serve_app_coverage.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_serve_cli.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_sessions.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_sessions_edge_cases.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_sessions_redis.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_sessions_supabase.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_simple_observer.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_simulation_evals.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_stability.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_starlette_app.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_structured.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_structured_config.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_structured_tool_results.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_summarize_on_trim.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_templates_coverage.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_terminal_actions.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_tool_caching.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_tool_result_compression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_trace.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_trace_html.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_trace_store.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_v016_regression.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_v019_features.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_visual_builder.py +0 -0
- {selectools-0.25.1 → selectools-0.27.0}/tests/test_yaml_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: selectools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.27.0
|
|
4
4
|
Summary: Production-ready Python framework for AI agents with multi-agent graphs, hybrid RAG, guardrails, audit logging, 50 evaluators, and a visual builder. Supports OpenAI, Anthropic, Gemini, Ollama. By NichevLabs.
|
|
5
5
|
Author-email: John Nichev <johnnichev@gmail.com>
|
|
6
6
|
Maintainer-email: NichevLabs <support@nichevlabs.com>
|
|
@@ -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,37 @@ 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.0 — Scheduling, Reasoning & New Backends
|
|
120
|
+
|
|
121
|
+
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.
|
|
122
|
+
|
|
123
|
+
- **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`).
|
|
124
|
+
- **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.
|
|
125
|
+
- **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]`.
|
|
126
|
+
- **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.
|
|
127
|
+
- **Agentic memory completed** — the auto-injected `recall` tool joins `remember`, so the agent can both store and query its `KnowledgeMemory` on demand.
|
|
128
|
+
- **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.
|
|
129
|
+
- **Toolbox 48 → 56 tools** — added Discord, AWS S3, headless browser (Playwright), and image generation (OpenAI Images) categories.
|
|
130
|
+
- **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.
|
|
131
|
+
- **Performance benchmarks published** — framework overhead measured and documented (`docs/modules/BENCHMARKS.md`).
|
|
132
|
+
|
|
133
|
+
See `CHANGELOG.md` for the full entry (7,700+ tests, 115 examples, 115 models).
|
|
134
|
+
|
|
135
|
+
## What's New in v0.26
|
|
136
|
+
|
|
137
|
+
### v0.26.0 — Safety Patch & Verified Registry
|
|
138
|
+
|
|
139
|
+
A mid-bake safety patch plus a fully source-verified model registry.
|
|
140
|
+
|
|
141
|
+
- **Confirm parser safety fix** — `RegexConfirmParser` treated replies like "se você não pode apagar, tudo bem" / "tú no puedes borrar" as confirmations: the restated-verb branch matched the action verb without checking for negation elsewhere in the reply. A negation token anywhere now vetoes that branch; bare confirms are unaffected. **All `selectools.pending` consumers should upgrade immediately.**
|
|
142
|
+
- **Model registry refresh** — 152 → 115 models, every entry source-verified: claude-fable-5 / opus-4-8 / opus-4-7, the gpt-5.5 family, and the gemini-3.5 line added; retired and shut-down models removed (**BREAKING** if you referenced their registry constants — e.g. `AnthropicModels.CLAUDE_3_5_SONNET` — but those IDs 404 at their providers regardless); `claude-opus-4-1` mispricing corrected ($5/$25 → $15/$75); gpt-5 family context specs fixed (400k/128k); `GeminiEmbeddingProvider` default moved off the retired `text-embedding-004` to `gemini-embedding-001`.
|
|
143
|
+
- **Cache-aware cost calculation** — `calculate_cost(..., cache_read_input_tokens=..., cache_creation_input_tokens=...)` prices prompt-cache traffic at Anthropic's published rates (reads 0.1×, 5-min writes 1.25×); `AnthropicProvider`'s `UsageStats.cost_usd` is now cache-accurate.
|
|
144
|
+
- **Fixes** — A2A returns JSON-RPC -32602 (not HTTP 500) for non-dict `message.parts` elements; Gemini embedding dimension constant corrected to the actual 3072 for `gemini-embedding-001`/`-2` (vectors themselves unchanged); bake-hunt test module no longer requires optional extras in CI.
|
|
145
|
+
|
|
146
|
+
See `CHANGELOG.md` for the full entry (7,420 tests, 111 examples, 115 models).
|
|
147
|
+
|
|
111
148
|
## What's New in v0.25
|
|
112
149
|
|
|
113
150
|
### v0.25.0 — Hardening & v1.0 Prep
|
|
@@ -618,11 +655,13 @@ report.to_html("report.html")
|
|
|
618
655
|
| **Dynamic Tools** | Load tools from files/directories at runtime. Add, remove, replace tools without restarting. |
|
|
619
656
|
| **Response Caching** | LRU + TTL in-memory cache and Redis backend. Avoid redundant LLM calls for identical requests. |
|
|
620
657
|
| **Routing Mode** | Agent selects a tool without executing it. Use for intent classification and request routing. |
|
|
621
|
-
| **Guardrails Engine** | Input/output validation pipeline with PII redaction, topic blocking, toxicity detection, and format enforcement. |
|
|
658
|
+
| **Guardrails Engine** | Input/output validation pipeline with PII redaction, prompt-injection detection, topic blocking, toxicity detection, and format enforcement. |
|
|
622
659
|
| **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
|
|
623
660
|
| **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
|
|
624
661
|
| **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
|
|
625
|
-
| **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and
|
|
662
|
+
| **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, Supabase, MongoDB, and DynamoDB backends. Auto-save/load with TTL expiry, cross-session `search()`. |
|
|
663
|
+
| **Scheduled Agents** | `AgentScheduler` runs an agent on a `cron()` or `every()` schedule — async loop, per-job `max_runs`, failure isolation, injectable clock. |
|
|
664
|
+
| **Reasoning Tools** | `make_reasoning_tools()` adds `think`/`analyze` tools that make reasoning explicit and inspectable, bounded by `min_steps`/`max_steps`. |
|
|
626
665
|
| **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
|
|
627
666
|
| **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
|
|
628
667
|
| **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
|
|
@@ -633,7 +672,7 @@ report.to_html("report.html")
|
|
|
633
672
|
| **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
|
|
634
673
|
| **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
|
|
635
674
|
| **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
|
|
636
|
-
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember`
|
|
675
|
+
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` + `recall` tools. |
|
|
637
676
|
| **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
|
|
638
677
|
| **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. |
|
|
639
678
|
| **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
|
|
@@ -659,9 +698,12 @@ report.to_html("report.html")
|
|
|
659
698
|
- **Advanced Chunking**: Semantic + contextual chunking for better retrieval
|
|
660
699
|
- **Dynamic Tool Loading**: Plugin system with hot-reload support
|
|
661
700
|
- **Response Caching**: InMemoryCache and RedisCache with stats tracking
|
|
662
|
-
- **
|
|
663
|
-
- **Pre-built Toolbox**:
|
|
664
|
-
- **Persistent Sessions**:
|
|
701
|
+
- **115 Model Registry**: Type-safe constants with pricing and metadata
|
|
702
|
+
- **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
|
|
703
|
+
- **Persistent Sessions**: 6 backends (JSON file, SQLite, Redis, Supabase, MongoDB, DynamoDB) with TTL and cross-session search
|
|
704
|
+
- **Scheduled Agents**: `AgentScheduler` runs an agent on a cron or interval schedule with per-job max-runs, failure isolation, and an async loop
|
|
705
|
+
- **Reasoning Tools**: `think`/`analyze` tools make reasoning explicit, inspectable, and bounded by min/max steps
|
|
706
|
+
- **Prompt-Injection Guardrail**: `PromptInjectionGuardrail` — heuristic jailbreak/injection detection with high-precision patterns
|
|
665
707
|
- **Entity Memory**: LLM-based named entity extraction and tracking
|
|
666
708
|
- **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
|
|
667
709
|
- **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
|
|
@@ -669,7 +711,7 @@ report.to_html("report.html")
|
|
|
669
711
|
- **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
|
|
670
712
|
- **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
|
|
671
713
|
- **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
|
|
672
|
-
- **Cross-Session Knowledge**: Daily logs + persistent memory with `remember`
|
|
714
|
+
- **Cross-Session Knowledge**: Daily logs + persistent memory with auto-injected `remember` + `recall` tools, pluggable stores (File, SQLite), importance scoring, TTL
|
|
673
715
|
- **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
|
|
674
716
|
- **Token Estimation**: `estimate_run_tokens()` for pre-execution budget checks
|
|
675
717
|
- **Model Switching**: `model_selector` callback for per-iteration model selection
|
|
@@ -678,10 +720,10 @@ report.to_html("report.html")
|
|
|
678
720
|
- **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
|
|
679
721
|
- **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
|
|
680
722
|
- **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
|
|
681
|
-
- **
|
|
723
|
+
- **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
|
|
682
724
|
- **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
|
|
683
725
|
- **AgentObserver Protocol**: 46 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
|
|
684
|
-
- **
|
|
726
|
+
- **7700+ Tests**: Unit, integration, regression, and E2E with real API calls
|
|
685
727
|
|
|
686
728
|
## Install
|
|
687
729
|
|
|
@@ -1035,7 +1077,7 @@ See [docs/modules/STREAMING.md](https://github.com/johnnichev/selectools/blob/ma
|
|
|
1035
1077
|
```python
|
|
1036
1078
|
from selectools.models import OpenAI, Anthropic, Gemini, Ollama
|
|
1037
1079
|
|
|
1038
|
-
# IDE autocomplete for all
|
|
1080
|
+
# IDE autocomplete for all 115 models with pricing metadata
|
|
1039
1081
|
model = OpenAI.GPT_4O_MINI
|
|
1040
1082
|
print(f"Cost: ${model.prompt_cost}/${model.completion_cost} per 1M tokens")
|
|
1041
1083
|
print(f"Context: {model.context_window:,} tokens")
|
|
@@ -1183,7 +1225,7 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
|
|
|
1183
1225
|
|---|---|---|---|
|
|
1184
1226
|
| 01 | `01_hello_world.py` | First agent, `@tool`, `ask()` | No |
|
|
1185
1227
|
| 02 | `02_search_weather.py` | ToolRegistry, multiple tools | No |
|
|
1186
|
-
| 03 | `03_toolbox.py` |
|
|
1228
|
+
| 03 | `03_toolbox.py` | 56 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
|
|
1187
1229
|
| 04 | `04_conversation_memory.py` | Multi-turn memory | Yes |
|
|
1188
1230
|
| 05 | `05_cost_tracking.py` | Token counting, cost warnings | Yes |
|
|
1189
1231
|
| 06 | `06_async_agent.py` | `arun()`, concurrent agents, FastAPI | Yes |
|
|
@@ -30,6 +30,37 @@ 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.0 — Scheduling, Reasoning & New Backends
|
|
36
|
+
|
|
37
|
+
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.
|
|
38
|
+
|
|
39
|
+
- **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`).
|
|
40
|
+
- **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.
|
|
41
|
+
- **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]`.
|
|
42
|
+
- **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.
|
|
43
|
+
- **Agentic memory completed** — the auto-injected `recall` tool joins `remember`, so the agent can both store and query its `KnowledgeMemory` on demand.
|
|
44
|
+
- **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.
|
|
45
|
+
- **Toolbox 48 → 56 tools** — added Discord, AWS S3, headless browser (Playwright), and image generation (OpenAI Images) categories.
|
|
46
|
+
- **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.
|
|
47
|
+
- **Performance benchmarks published** — framework overhead measured and documented (`docs/modules/BENCHMARKS.md`).
|
|
48
|
+
|
|
49
|
+
See `CHANGELOG.md` for the full entry (7,700+ tests, 115 examples, 115 models).
|
|
50
|
+
|
|
51
|
+
## What's New in v0.26
|
|
52
|
+
|
|
53
|
+
### v0.26.0 — Safety Patch & Verified Registry
|
|
54
|
+
|
|
55
|
+
A mid-bake safety patch plus a fully source-verified model registry.
|
|
56
|
+
|
|
57
|
+
- **Confirm parser safety fix** — `RegexConfirmParser` treated replies like "se você não pode apagar, tudo bem" / "tú no puedes borrar" as confirmations: the restated-verb branch matched the action verb without checking for negation elsewhere in the reply. A negation token anywhere now vetoes that branch; bare confirms are unaffected. **All `selectools.pending` consumers should upgrade immediately.**
|
|
58
|
+
- **Model registry refresh** — 152 → 115 models, every entry source-verified: claude-fable-5 / opus-4-8 / opus-4-7, the gpt-5.5 family, and the gemini-3.5 line added; retired and shut-down models removed (**BREAKING** if you referenced their registry constants — e.g. `AnthropicModels.CLAUDE_3_5_SONNET` — but those IDs 404 at their providers regardless); `claude-opus-4-1` mispricing corrected ($5/$25 → $15/$75); gpt-5 family context specs fixed (400k/128k); `GeminiEmbeddingProvider` default moved off the retired `text-embedding-004` to `gemini-embedding-001`.
|
|
59
|
+
- **Cache-aware cost calculation** — `calculate_cost(..., cache_read_input_tokens=..., cache_creation_input_tokens=...)` prices prompt-cache traffic at Anthropic's published rates (reads 0.1×, 5-min writes 1.25×); `AnthropicProvider`'s `UsageStats.cost_usd` is now cache-accurate.
|
|
60
|
+
- **Fixes** — A2A returns JSON-RPC -32602 (not HTTP 500) for non-dict `message.parts` elements; Gemini embedding dimension constant corrected to the actual 3072 for `gemini-embedding-001`/`-2` (vectors themselves unchanged); bake-hunt test module no longer requires optional extras in CI.
|
|
61
|
+
|
|
62
|
+
See `CHANGELOG.md` for the full entry (7,420 tests, 111 examples, 115 models).
|
|
63
|
+
|
|
33
64
|
## What's New in v0.25
|
|
34
65
|
|
|
35
66
|
### v0.25.0 — Hardening & v1.0 Prep
|
|
@@ -540,11 +571,13 @@ report.to_html("report.html")
|
|
|
540
571
|
| **Dynamic Tools** | Load tools from files/directories at runtime. Add, remove, replace tools without restarting. |
|
|
541
572
|
| **Response Caching** | LRU + TTL in-memory cache and Redis backend. Avoid redundant LLM calls for identical requests. |
|
|
542
573
|
| **Routing Mode** | Agent selects a tool without executing it. Use for intent classification and request routing. |
|
|
543
|
-
| **Guardrails Engine** | Input/output validation pipeline with PII redaction, topic blocking, toxicity detection, and format enforcement. |
|
|
574
|
+
| **Guardrails Engine** | Input/output validation pipeline with PII redaction, prompt-injection detection, topic blocking, toxicity detection, and format enforcement. |
|
|
544
575
|
| **Audit Logging** | JSONL audit trail with privacy controls (redact, hash, omit) and daily rotation. |
|
|
545
576
|
| **Tool Output Screening** | Prompt injection detection with 15 built-in patterns. Per-tool or global. |
|
|
546
577
|
| **Coherence Checking** | LLM-based verification that tool calls match user intent — catches injection-driven tool misuse. |
|
|
547
|
-
| **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, and
|
|
578
|
+
| **Persistent Sessions** | `SessionStore` with JSON file, SQLite, Redis, Supabase, MongoDB, and DynamoDB backends. Auto-save/load with TTL expiry, cross-session `search()`. |
|
|
579
|
+
| **Scheduled Agents** | `AgentScheduler` runs an agent on a `cron()` or `every()` schedule — async loop, per-job `max_runs`, failure isolation, injectable clock. |
|
|
580
|
+
| **Reasoning Tools** | `make_reasoning_tools()` adds `think`/`analyze` tools that make reasoning explicit and inspectable, bounded by `min_steps`/`max_steps`. |
|
|
548
581
|
| **Agent-as-API** | `AgentAPI` serves any agent as a Starlette REST API — chat, SSE streaming, session CRUD, bearer auth, per-user session isolation. |
|
|
549
582
|
| **A2A Protocol** | `A2AServer` + `A2AClient`: Agent Card discovery and JSON-RPC 2.0 messaging between agents. |
|
|
550
583
|
| **LiteLLM Bridge** | `LiteLLMProvider` unlocks 100+ models (DeepSeek, Groq, Bedrock, ...) through one provider class. |
|
|
@@ -555,7 +588,7 @@ report.to_html("report.html")
|
|
|
555
588
|
| **Prompt Caching** | Anthropic `cache_system`/`cache_tools` markers with cache hit-rate fields on `UsageStats`. |
|
|
556
589
|
| **Entity Memory** | LLM-based entity extraction with deduplication, LRU pruning, and system prompt injection. |
|
|
557
590
|
| **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
|
|
558
|
-
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember`
|
|
591
|
+
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` + `recall` tools. |
|
|
559
592
|
| **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
|
|
560
593
|
| **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. |
|
|
561
594
|
| **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
|
|
@@ -581,9 +614,12 @@ report.to_html("report.html")
|
|
|
581
614
|
- **Advanced Chunking**: Semantic + contextual chunking for better retrieval
|
|
582
615
|
- **Dynamic Tool Loading**: Plugin system with hot-reload support
|
|
583
616
|
- **Response Caching**: InMemoryCache and RedisCache with stats tracking
|
|
584
|
-
- **
|
|
585
|
-
- **Pre-built Toolbox**:
|
|
586
|
-
- **Persistent Sessions**:
|
|
617
|
+
- **115 Model Registry**: Type-safe constants with pricing and metadata
|
|
618
|
+
- **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
|
|
619
|
+
- **Persistent Sessions**: 6 backends (JSON file, SQLite, Redis, Supabase, MongoDB, DynamoDB) with TTL and cross-session search
|
|
620
|
+
- **Scheduled Agents**: `AgentScheduler` runs an agent on a cron or interval schedule with per-job max-runs, failure isolation, and an async loop
|
|
621
|
+
- **Reasoning Tools**: `think`/`analyze` tools make reasoning explicit, inspectable, and bounded by min/max steps
|
|
622
|
+
- **Prompt-Injection Guardrail**: `PromptInjectionGuardrail` — heuristic jailbreak/injection detection with high-precision patterns
|
|
587
623
|
- **Entity Memory**: LLM-based named entity extraction and tracking
|
|
588
624
|
- **Unified Memory**: tiered conversation/knowledge/entity/episodic memory with token-aware compaction
|
|
589
625
|
- **Knowledge Backends**: Supabase/Redis blob persistence for KnowledgeMemory on ephemeral infra
|
|
@@ -591,7 +627,7 @@ report.to_html("report.html")
|
|
|
591
627
|
- **Deferred Confirmation**: `selectools.pending` for chat-channel destructive-tool confirmation
|
|
592
628
|
- **Anthropic Prompt Caching**: `cache_system`/`cache_tools` with hit-rate visibility on `UsageStats`
|
|
593
629
|
- **Knowledge Graph**: Triple extraction with in-memory and SQLite storage
|
|
594
|
-
- **Cross-Session Knowledge**: Daily logs + persistent memory with `remember`
|
|
630
|
+
- **Cross-Session Knowledge**: Daily logs + persistent memory with auto-injected `remember` + `recall` tools, pluggable stores (File, SQLite), importance scoring, TTL
|
|
595
631
|
- **Token Budget & Cancellation**: `max_total_tokens`, `max_cost_usd` hard limits; `CancellationToken` for cooperative stopping
|
|
596
632
|
- **Token Estimation**: `estimate_run_tokens()` for pre-execution budget checks
|
|
597
633
|
- **Model Switching**: `model_selector` callback for per-iteration model selection
|
|
@@ -600,10 +636,10 @@ report.to_html("report.html")
|
|
|
600
636
|
- **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
|
|
601
637
|
- **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
|
|
602
638
|
- **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
|
|
603
|
-
- **
|
|
639
|
+
- **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
|
|
604
640
|
- **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
|
|
605
641
|
- **AgentObserver Protocol**: 46 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
|
|
606
|
-
- **
|
|
642
|
+
- **7700+ Tests**: Unit, integration, regression, and E2E with real API calls
|
|
607
643
|
|
|
608
644
|
## Install
|
|
609
645
|
|
|
@@ -957,7 +993,7 @@ See [docs/modules/STREAMING.md](https://github.com/johnnichev/selectools/blob/ma
|
|
|
957
993
|
```python
|
|
958
994
|
from selectools.models import OpenAI, Anthropic, Gemini, Ollama
|
|
959
995
|
|
|
960
|
-
# IDE autocomplete for all
|
|
996
|
+
# IDE autocomplete for all 115 models with pricing metadata
|
|
961
997
|
model = OpenAI.GPT_4O_MINI
|
|
962
998
|
print(f"Cost: ${model.prompt_cost}/${model.completion_cost} per 1M tokens")
|
|
963
999
|
print(f"Context: {model.context_window:,} tokens")
|
|
@@ -1105,7 +1141,7 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
|
|
|
1105
1141
|
|---|---|---|---|
|
|
1106
1142
|
| 01 | `01_hello_world.py` | First agent, `@tool`, `ask()` | No |
|
|
1107
1143
|
| 02 | `02_search_weather.py` | ToolRegistry, multiple tools | No |
|
|
1108
|
-
| 03 | `03_toolbox.py` |
|
|
1144
|
+
| 03 | `03_toolbox.py` | 56 pre-built tools (file, data, text, datetime, web, code, search, and more) | No |
|
|
1109
1145
|
| 04 | `04_conversation_memory.py` | Multi-turn memory | Yes |
|
|
1110
1146
|
| 05 | `05_cost_tracking.py` | Token counting, cost warnings | Yes |
|
|
1111
1147
|
| 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.
|
|
7
|
+
version = "0.27.0"
|
|
8
8
|
description = "Production-ready Python framework for AI agents with multi-agent graphs, hybrid RAG, guardrails, audit logging, 50 evaluators, and a visual builder. Supports OpenAI, Anthropic, Gemini, Ollama. By NichevLabs."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -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.
|
|
3
|
+
__version__ = "0.27.0"
|
|
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
|
|
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",
|
|
@@ -94,6 +94,10 @@ def _extract_prompt(parts: List[Dict[str, Any]]) -> str:
|
|
|
94
94
|
"""
|
|
95
95
|
chunks: List[str] = []
|
|
96
96
|
for part in parts:
|
|
97
|
+
if not isinstance(part, dict):
|
|
98
|
+
# Defensive: validation rejects non-dict parts up front, but a
|
|
99
|
+
# stray list element must never crash prompt assembly.
|
|
100
|
+
continue
|
|
97
101
|
kind = part.get("kind")
|
|
98
102
|
if kind == "text" and isinstance(part.get("text"), str):
|
|
99
103
|
chunks.append(part["text"])
|
|
@@ -300,6 +304,8 @@ class A2AServer:
|
|
|
300
304
|
parts = message.get("parts")
|
|
301
305
|
if not isinstance(parts, list) or not parts:
|
|
302
306
|
return None, "'message.parts' must be a non-empty array"
|
|
307
|
+
if not all(isinstance(p, dict) for p in parts):
|
|
308
|
+
return None, "every entry in 'message.parts' must be an object"
|
|
303
309
|
if not any(
|
|
304
310
|
isinstance(p, dict) and p.get("kind") == "text" and isinstance(p.get("text"), str)
|
|
305
311
|
for p in parts
|
|
@@ -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
|
|
@@ -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
|