agent-framework-lib 0.6.3__tar.gz → 0.6.3.post3__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.
- {agent_framework_lib-0.6.3/agent_framework_lib.egg-info → agent_framework_lib-0.6.3.post3}/PKG-INFO +3 -1
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/__init__.py +1 -1
- agent_framework_lib-0.6.3.post3/agent_framework/capabilities/__init__.py +10 -0
- agent_framework_lib-0.6.3.post3/agent_framework/capabilities/resolver.py +175 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/scratchpad_compressor.py +128 -5
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/implementations/budget_aware_agent.py +61 -8
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/implementations/llamaindex_agent.py +17 -4
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/agent_mixin.py +64 -12
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/base.py +4 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/__init__.py +31 -22
- agent_framework_lib-0.6.3.post3/agent_framework/skills/markdown_loader.py +293 -0
- agent_framework_lib-0.6.3.post3/agent_framework/subagents/__init__.py +10 -0
- agent_framework_lib-0.6.3.post3/agent_framework/subagents/spawn_tool.py +187 -0
- agent_framework_lib-0.6.3.post3/agent_framework/tools/activity_callback.py +47 -0
- agent_framework_lib-0.6.3.post3/agent_framework/tools/shell_tool.py +165 -0
- agent_framework_lib-0.6.3.post3/agent_framework/tools/web_fetch_tool.py +137 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/web_search_tools.py +85 -18
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3/agent_framework_lib.egg-info}/PKG-INFO +3 -1
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework_lib.egg-info/SOURCES.txt +9 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework_lib.egg-info/requires.txt +2 -0
- agent_framework_lib-0.6.3.post3/docs/SKILLS_AND_SUBAGENTS_ANALYSIS.md +345 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/pyproject.toml +3 -1
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/ARCHITECTURE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/LICENSE +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/MANIFEST.in +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/README.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/base.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/a2a_router.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/agent_card_builder.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/agent_card_skill_builder.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/jsonrpc_dispatcher.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/models_jsonrpc.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/sse_wrapper.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/endpoints/translation_layer.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/models.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/providers/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/providers/elasticsearch_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/a2a/providers/postgres_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/chart_generation/llm_refinement_loop.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/activity_formatter.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/agent_interface.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/agent_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/base_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/context_budget.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/context_summarizer.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/elasticsearch_config_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/implementation_validator.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/knowledge_state.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/loop_detector.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/model_clients.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/model_config.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/model_router.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/models.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/provider_calibration.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/rich_content_prompt_unsused_to_be_deleted.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/state_manager.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/step_display_config.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/core/streaming_parts_accumulator.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/implementations/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/implementations/llamaindex_memory_adapter.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/implementations/microsoft_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/agent_mixin.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/base.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/config.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/manager.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/personalization.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/providers/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/providers/graphiti_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/providers/memori_provider.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/memory/tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/api_timing_tracker.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/elasticsearch_circuit_breaker.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/elasticsearch_logging.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/error_handling.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/error_logging.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/llm_auto_instrumentor.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/llm_metrics.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/llm_metrics_collector.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/llm_metrics_extractor.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/metrics_aggregator.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/metrics_config.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/observability_manager.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/otel_instrumentor.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/otel_logging_handler.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/otel_metrics_recorder.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/otel_setup.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/performance_monitor.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/progress_tracker.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/resource_manager.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/resource_metrics_collector.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/streaming_latency_tracer.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/timing_tracker.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/token_counter.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/monitoring/tracing_context.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/processing/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/processing/ai_content_management.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/processing/markdown_converter.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/processing/multimodal_integration.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/processing/rich_content_validation.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/py.typed +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/session/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/session/elasticsearch_session_storage.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/session/session_storage.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/chart_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/drawio_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/excel_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/file_access_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/file_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/form_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/image_display_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/mermaid_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/multimodal_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/optionsblock_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/pdf_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/pdf_with_images_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/table_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/unified_pdf_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/builtin/web_search_skill.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/discovery_prompt.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/storage/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/storage/file_storages.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/storage/file_system_management.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/storage/storage_optimizer.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/adaptive_pdf_css.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/base.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/chart_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/drawio_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/excel_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/file_access_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/file_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/html_content_analyzer.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/mermaid_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/multimodal_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/pdf_image_scaler.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/pdf_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/pdf_with_images_tool.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/sizing_config.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/tabledata_tools.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/tools/unified_pdf_tool.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/path_utils.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/post_install.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/session_title_generator.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/source_detector.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/utils/special_blocks.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/__init__.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/admin_auth.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/admin_models.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/admin_router.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/admin_services.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/api_timing_middleware.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/A2A_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/CREATING_AGENTS.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/DOCKER_SETUP.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/Dockerfile +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/GETTING_STARTED.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/MEMORY_INSTALLATION.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/README.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/TOOLS_AND_MCP_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/api-reference.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/configuration.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/docker-compose.yml +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_example_multi_skills.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_file_storage.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_mcp.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_memory.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_memory_graphiti.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_memory_hybrid.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/agent_with_memory_simple.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/custom_framework_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/simple_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/examples/skills_demo_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/docs/installation-guide.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/documentation_generator.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/helper_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/helper_ui.html +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/modern_ui.html +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/observability/kibana-llm-dashboard-setup.json +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/observability/kibana-resource-metrics-dashboard.json +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/otel_tracing_middleware.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/server.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/web/test_app.html +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework_lib.egg-info/dependency_links.txt +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework_lib.egg-info/entry_points.txt +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework_lib.egg-info/top_level.txt +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/A2A_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/ACTIVITY_OUTPUT_PART.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/ARCHITECTURE_DIAGRAM.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/CONCURRENCE_VS_PARALLELISME_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/CREATING_AGENTS.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/DOCKER_SETUP.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/ELASTICSEARCH_DATA_STRUCTURES.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/FILE_DOWNLOAD_LINKS.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/FILE_STORAGE_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/GETTING_STARTED.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/HISTORY_MESSAGE_FORMAT.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/IMPLEMENTATION_GUIDE_NEW_AGENT.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/MEMORY_INSTALLATION.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/MODIFICATIONS_CONCURRENCE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/MULTIMODAL_TOOLS_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/OBSERVABILITY_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/PYPI_PUBLISHING.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/QA_STREAMING_LATENCY.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/SPEC_CROSS_MODEL_HISTORY_CONVERSION.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/STREAMING_EVENTS_FRONTEND.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/TOOLS_AND_MCP_GUIDE.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/api-reference.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/configuration.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/framework_audit_remarques.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/docs/installation-guide.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/README.md +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_context_budget_test.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_example_multi_skills.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_exemple_test.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_training_with_apo.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_custom_tools_file_storage.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_file_storage.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_mcp.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_memory_graphiti.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_memory_hybrid.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_memory_simple.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/agent_with_personalization.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/biagenttest.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/custom_framework_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/dependencies/docker-compose.yaml +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/pyproject.toml +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/simple_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/examples/skills_demo_agent.py +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/setup.cfg +0 -0
- {agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/setup.py +0 -0
{agent_framework_lib-0.6.3/agent_framework_lib.egg-info → agent_framework_lib-0.6.3.post3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-framework-lib
|
|
3
|
-
Version: 0.6.3
|
|
3
|
+
Version: 0.6.3.post3
|
|
4
4
|
Summary: A comprehensive Python framework for building and serving conversational AI agents with FastAPI
|
|
5
5
|
Author-email: Sebastian Pavel <sebastian@cinco.ai>, Elliott Girard <elliott.girard@icloud.com>
|
|
6
6
|
Maintainer-email: Sebastian Pavel <sebastian@cinco.ai>
|
|
@@ -53,6 +53,8 @@ Requires-Dist: markdown>=3.5
|
|
|
53
53
|
Requires-Dist: playwright>=1.56.0
|
|
54
54
|
Requires-Dist: elasticsearch<9.0.0,>=8.11.0
|
|
55
55
|
Requires-Dist: ddgs>=9.9.3
|
|
56
|
+
Requires-Dist: httpx>=0.28.1
|
|
57
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
56
58
|
Requires-Dist: llama-index>=0.14.16
|
|
57
59
|
Requires-Dist: llama-index-core>=0.14.16
|
|
58
60
|
Requires-Dist: llama-index-workflows>=2.16.0
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CapabilitySet and CapabilityResolver — token-based capability resolution.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import contextlib
|
|
8
|
+
import json
|
|
9
|
+
import logging
|
|
10
|
+
import os
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class CapabilitySet:
|
|
22
|
+
"""Set of capabilities authorized for a session."""
|
|
23
|
+
|
|
24
|
+
skill_ids: list[str] = field(default_factory=list)
|
|
25
|
+
native_tools: list[str] = field(default_factory=list)
|
|
26
|
+
max_subagent_depth: int = 0
|
|
27
|
+
env_overrides: dict[str, str] = field(default_factory=dict)
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def empty(cls) -> "CapabilitySet":
|
|
31
|
+
"""Return an empty CapabilitySet (no capabilities authorized)."""
|
|
32
|
+
return cls()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class CapabilityResolverError(Exception):
|
|
36
|
+
"""Raised when the capability source is unreachable or invalid."""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class CapabilityResolver:
|
|
40
|
+
"""Resolves authorized capabilities from a token.
|
|
41
|
+
|
|
42
|
+
Sources are checked in priority order:
|
|
43
|
+
1. CAPABILITY_MAP environment variable (JSON inline)
|
|
44
|
+
2. Local JSON file (json_path)
|
|
45
|
+
3. HTTP endpoint (http_url)
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(
|
|
49
|
+
self,
|
|
50
|
+
json_path: Path | None = None,
|
|
51
|
+
http_url: str | None = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize CapabilityResolver.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
json_path: Optional path to a local JSON capability map.
|
|
57
|
+
http_url: Optional HTTP URL to fetch capabilities from.
|
|
58
|
+
"""
|
|
59
|
+
self._json_path = json_path
|
|
60
|
+
self._http_url = http_url
|
|
61
|
+
|
|
62
|
+
def resolve(self, api_token: str) -> CapabilitySet:
|
|
63
|
+
"""Return the CapabilitySet authorized for api_token.
|
|
64
|
+
|
|
65
|
+
Unknown tokens return CapabilitySet.empty().
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
api_token: The API token to resolve.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
CapabilitySet for the token.
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
CapabilityResolverError: If the configured source is unreachable or invalid.
|
|
75
|
+
"""
|
|
76
|
+
capability_map = self._load_map()
|
|
77
|
+
data = capability_map.get(api_token)
|
|
78
|
+
if data is None:
|
|
79
|
+
return CapabilitySet.empty()
|
|
80
|
+
return self._parse_capability_set(data)
|
|
81
|
+
|
|
82
|
+
@contextlib.contextmanager
|
|
83
|
+
def apply_env_overrides(self, capability_set: CapabilitySet) -> Iterator[None]:
|
|
84
|
+
"""Context manager that injects env_overrides into os.environ.
|
|
85
|
+
|
|
86
|
+
Keys that were absent before the block are removed on exit.
|
|
87
|
+
Keys that existed before are restored to their original value.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
capability_set: CapabilitySet whose env_overrides to apply.
|
|
91
|
+
"""
|
|
92
|
+
overrides = capability_set.env_overrides
|
|
93
|
+
previous: dict[str, str | None] = {}
|
|
94
|
+
for key in overrides:
|
|
95
|
+
previous[key] = os.environ.get(key)
|
|
96
|
+
os.environ[key] = overrides[key]
|
|
97
|
+
try:
|
|
98
|
+
yield
|
|
99
|
+
finally:
|
|
100
|
+
for key, old_value in previous.items():
|
|
101
|
+
if old_value is None:
|
|
102
|
+
os.environ.pop(key, None)
|
|
103
|
+
else:
|
|
104
|
+
os.environ[key] = old_value
|
|
105
|
+
|
|
106
|
+
# ------------------------------------------------------------------
|
|
107
|
+
# Internal helpers
|
|
108
|
+
# ------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
def _load_map(self) -> dict[str, Any]:
|
|
111
|
+
"""Load the capability map from the highest-priority source."""
|
|
112
|
+
env_json = os.environ.get("CAPABILITY_MAP")
|
|
113
|
+
if env_json:
|
|
114
|
+
try:
|
|
115
|
+
data = json.loads(env_json)
|
|
116
|
+
if not isinstance(data, dict):
|
|
117
|
+
raise CapabilityResolverError(
|
|
118
|
+
"CAPABILITY_MAP must be a JSON object"
|
|
119
|
+
)
|
|
120
|
+
return data
|
|
121
|
+
except json.JSONDecodeError as exc:
|
|
122
|
+
raise CapabilityResolverError(
|
|
123
|
+
f"Invalid JSON in CAPABILITY_MAP: {exc}"
|
|
124
|
+
) from exc
|
|
125
|
+
|
|
126
|
+
if self._json_path is not None:
|
|
127
|
+
try:
|
|
128
|
+
raw = Path(self._json_path).read_text(encoding="utf-8")
|
|
129
|
+
data = json.loads(raw)
|
|
130
|
+
if not isinstance(data, dict):
|
|
131
|
+
raise CapabilityResolverError(
|
|
132
|
+
f"JSON file must contain an object: {self._json_path}"
|
|
133
|
+
)
|
|
134
|
+
return data
|
|
135
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
136
|
+
raise CapabilityResolverError(
|
|
137
|
+
f"Cannot load capability map from {self._json_path}: {exc}"
|
|
138
|
+
) from exc
|
|
139
|
+
|
|
140
|
+
if self._http_url is not None:
|
|
141
|
+
try:
|
|
142
|
+
import httpx
|
|
143
|
+
|
|
144
|
+
resp = httpx.get(self._http_url, timeout=10)
|
|
145
|
+
resp.raise_for_status()
|
|
146
|
+
data = resp.json()
|
|
147
|
+
if not isinstance(data, dict):
|
|
148
|
+
raise CapabilityResolverError(
|
|
149
|
+
f"HTTP response must be a JSON object: {self._http_url}"
|
|
150
|
+
)
|
|
151
|
+
return data
|
|
152
|
+
except Exception as exc:
|
|
153
|
+
raise CapabilityResolverError(
|
|
154
|
+
f"Cannot reach capability source at {self._http_url}: {exc}"
|
|
155
|
+
) from exc
|
|
156
|
+
|
|
157
|
+
return {}
|
|
158
|
+
|
|
159
|
+
@staticmethod
|
|
160
|
+
def _parse_capability_set(data: Any) -> CapabilitySet:
|
|
161
|
+
if not isinstance(data, dict):
|
|
162
|
+
return CapabilitySet.empty()
|
|
163
|
+
return CapabilitySet(
|
|
164
|
+
skill_ids=list(data.get("skill_ids") or []),
|
|
165
|
+
native_tools=list(data.get("native_tools") or []),
|
|
166
|
+
max_subagent_depth=int(data.get("max_subagent_depth") or 0),
|
|
167
|
+
env_overrides=dict(data.get("env_overrides") or {}),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
__all__ = [
|
|
172
|
+
"CapabilitySet",
|
|
173
|
+
"CapabilityResolver",
|
|
174
|
+
"CapabilityResolverError",
|
|
175
|
+
]
|
|
@@ -29,6 +29,11 @@ logger = logging.getLogger(__name__)
|
|
|
29
29
|
|
|
30
30
|
TRUNCATION_MARKER = "\n\n[... contenu tronqué ...]\n\n"
|
|
31
31
|
|
|
32
|
+
# OpenAI enforces a 10 485 760 character limit per message content.
|
|
33
|
+
# We use a conservative 8M limit to leave headroom for JSON serialization
|
|
34
|
+
# overhead, tool_call metadata, and other wrapper text added by the SDK.
|
|
35
|
+
MAX_MESSAGE_CONTENT_CHARS = 8_000_000
|
|
36
|
+
|
|
32
37
|
|
|
33
38
|
class ScratchpadCompressor:
|
|
34
39
|
"""Compresse le scratchpad de la boucle d'outils pour respecter le budget."""
|
|
@@ -106,22 +111,100 @@ class ScratchpadCompressor:
|
|
|
106
111
|
# Pas de paire trouvée, tout est considéré comme dernière paire
|
|
107
112
|
return [], list(scratchpad)
|
|
108
113
|
|
|
114
|
+
@staticmethod
|
|
115
|
+
def _flatten_message_content(message: ChatMessage) -> str:
|
|
116
|
+
"""Aplatit tous les blocks d'un message en une seule chaîne de texte.
|
|
117
|
+
|
|
118
|
+
LlamaIndex stocke le contenu des messages dans des blocks typés
|
|
119
|
+
(TextBlock, ToolCallBlock, ToolResultBlock, etc.). La propriété
|
|
120
|
+
.content ne retourne que le texte des TextBlock. Cette méthode
|
|
121
|
+
sérialise TOUS les blocks pour que la troncature opère sur le
|
|
122
|
+
contenu réel envoyé à l'API.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
message: ChatMessage à aplatir.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
Texte complet incluant tous les blocks.
|
|
129
|
+
"""
|
|
130
|
+
if not hasattr(message, "blocks") or not message.blocks:
|
|
131
|
+
return message.content or ""
|
|
132
|
+
|
|
133
|
+
parts: list[str] = []
|
|
134
|
+
for block in message.blocks:
|
|
135
|
+
block_type = type(block).__name__
|
|
136
|
+
if hasattr(block, "text"):
|
|
137
|
+
parts.append(block.text or "")
|
|
138
|
+
elif hasattr(block, "tool_kwargs"):
|
|
139
|
+
tool_name = getattr(block, "tool_name", "") or ""
|
|
140
|
+
kwargs = getattr(block, "tool_kwargs", None)
|
|
141
|
+
if kwargs:
|
|
142
|
+
import json as _json
|
|
143
|
+
try:
|
|
144
|
+
kwargs_str = _json.dumps(kwargs) if isinstance(kwargs, dict) else str(kwargs)
|
|
145
|
+
except (TypeError, ValueError):
|
|
146
|
+
kwargs_str = str(kwargs)
|
|
147
|
+
parts.append(f"[tool_call: {tool_name}({kwargs_str})]")
|
|
148
|
+
else:
|
|
149
|
+
parts.append(f"[tool_call: {tool_name}()]")
|
|
150
|
+
elif hasattr(block, "tool_output"):
|
|
151
|
+
output = str(getattr(block, "tool_output", "") or "")
|
|
152
|
+
parts.append(output)
|
|
153
|
+
elif block_type == "ImageBlock":
|
|
154
|
+
parts.append("[image]")
|
|
155
|
+
else:
|
|
156
|
+
try:
|
|
157
|
+
block_str = str(block)
|
|
158
|
+
if len(block_str) > 10:
|
|
159
|
+
parts.append(block_str)
|
|
160
|
+
except Exception:
|
|
161
|
+
parts.append("[block non sérialisable]")
|
|
162
|
+
|
|
163
|
+
return "\n".join(parts)
|
|
164
|
+
|
|
109
165
|
def _truncate_single_result(
|
|
110
166
|
self, message: ChatMessage, target_tokens: int
|
|
111
167
|
) -> ChatMessage:
|
|
112
168
|
"""Tronque le contenu d'un tool_result en gardant début + marqueur + fin.
|
|
113
169
|
|
|
170
|
+
Aplatit d'abord tous les blocks en texte brut pour que la troncature
|
|
171
|
+
opère sur le contenu réel (pas seulement .content/TextBlock).
|
|
172
|
+
|
|
173
|
+
Applique deux niveaux de troncature :
|
|
174
|
+
1. Par tokens (budget du context window)
|
|
175
|
+
2. Par caractères bruts (limite API OpenAI de 10M chars par message)
|
|
176
|
+
|
|
114
177
|
Args:
|
|
115
178
|
message: Message tool_result à tronquer.
|
|
116
179
|
target_tokens: Nombre cible de tokens pour le message tronqué.
|
|
117
180
|
|
|
118
181
|
Returns:
|
|
119
|
-
Nouveau ChatMessage avec le contenu
|
|
182
|
+
Nouveau ChatMessage avec le contenu tronqué (blocks nettoyés).
|
|
120
183
|
"""
|
|
121
|
-
content = message
|
|
184
|
+
content = self._flatten_message_content(message)
|
|
185
|
+
|
|
186
|
+
# Garde-fou caractères bruts : tronquer d'abord si on dépasse la
|
|
187
|
+
# limite API (10M chars) pour éviter un 400 même si le budget
|
|
188
|
+
# tokens semble OK.
|
|
189
|
+
content = self._enforce_char_limit(content)
|
|
190
|
+
|
|
122
191
|
current_tokens = self._token_counter.count_tokens(content).count
|
|
123
192
|
|
|
193
|
+
# Nettoyer additional_kwargs pour ne pas conserver les blocks originaux
|
|
194
|
+
# qui seraient re-sérialisés par LlamaIndex en plus du content tronqué.
|
|
195
|
+
clean_kwargs = {
|
|
196
|
+
k: v
|
|
197
|
+
for k, v in (message.additional_kwargs or {}).items()
|
|
198
|
+
if k not in ("tool_calls",)
|
|
199
|
+
}
|
|
200
|
+
|
|
124
201
|
if current_tokens <= target_tokens or target_tokens <= 0:
|
|
202
|
+
if content != (message.content or ""):
|
|
203
|
+
return ChatMessage(
|
|
204
|
+
role=message.role,
|
|
205
|
+
content=content,
|
|
206
|
+
additional_kwargs=clean_kwargs,
|
|
207
|
+
)
|
|
125
208
|
return message
|
|
126
209
|
|
|
127
210
|
# Réserver des tokens pour le marqueur de troncature
|
|
@@ -142,6 +225,12 @@ class ScratchpadCompressor:
|
|
|
142
225
|
end_chars = max(0, int(end_tokens * chars_per_token))
|
|
143
226
|
|
|
144
227
|
if begin_chars + end_chars >= len(content):
|
|
228
|
+
if content != (message.content or ""):
|
|
229
|
+
return ChatMessage(
|
|
230
|
+
role=message.role,
|
|
231
|
+
content=content,
|
|
232
|
+
additional_kwargs=clean_kwargs,
|
|
233
|
+
)
|
|
145
234
|
return message
|
|
146
235
|
|
|
147
236
|
begin_part = content[:begin_chars]
|
|
@@ -151,9 +240,40 @@ class ScratchpadCompressor:
|
|
|
151
240
|
return ChatMessage(
|
|
152
241
|
role=message.role,
|
|
153
242
|
content=truncated_content,
|
|
154
|
-
additional_kwargs=
|
|
243
|
+
additional_kwargs=clean_kwargs,
|
|
155
244
|
)
|
|
156
245
|
|
|
246
|
+
@staticmethod
|
|
247
|
+
def _enforce_char_limit(content: str, limit: int = MAX_MESSAGE_CONTENT_CHARS) -> str:
|
|
248
|
+
"""Tronque le contenu si sa longueur dépasse la limite en caractères.
|
|
249
|
+
|
|
250
|
+
Garde 60% du début et 40% de la fin pour préserver le contexte.
|
|
251
|
+
|
|
252
|
+
Args:
|
|
253
|
+
content: Texte brut du message.
|
|
254
|
+
limit: Limite en caractères (défaut : MAX_MESSAGE_CONTENT_CHARS).
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
Contenu tronqué si nécessaire, sinon inchangé.
|
|
258
|
+
"""
|
|
259
|
+
if len(content) <= limit:
|
|
260
|
+
return content
|
|
261
|
+
|
|
262
|
+
marker_len = len(TRUNCATION_MARKER)
|
|
263
|
+
available = max(0, limit - marker_len)
|
|
264
|
+
begin_chars = int(available * 0.6)
|
|
265
|
+
end_chars = available - begin_chars
|
|
266
|
+
|
|
267
|
+
logger.warning(
|
|
268
|
+
"Message content exceeds char limit (%d > %d), truncating",
|
|
269
|
+
len(content),
|
|
270
|
+
limit,
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
begin_part = content[:begin_chars]
|
|
274
|
+
end_part = content[-end_chars:] if end_chars > 0 else ""
|
|
275
|
+
return begin_part + TRUNCATION_MARKER + end_part
|
|
276
|
+
|
|
157
277
|
async def compress(
|
|
158
278
|
self,
|
|
159
279
|
scratchpad: list[ChatMessage],
|
|
@@ -316,7 +436,7 @@ class ScratchpadCompressor:
|
|
|
316
436
|
result = list(old_entries)
|
|
317
437
|
while result and total > target_tokens:
|
|
318
438
|
removed = result.pop(0)
|
|
319
|
-
total -= self.
|
|
439
|
+
total -= self._count_tokens([removed])
|
|
320
440
|
return result
|
|
321
441
|
|
|
322
442
|
def _truncate_last_pair(
|
|
@@ -326,6 +446,9 @@ class ScratchpadCompressor:
|
|
|
326
446
|
) -> list[ChatMessage]:
|
|
327
447
|
"""Tronque le tool_result dans la dernière paire pour respecter le budget.
|
|
328
448
|
|
|
449
|
+
Utilise _count_tokens (blocks-aware) pour compter les tokens du
|
|
450
|
+
message ASSISTANT, pas seulement .content.
|
|
451
|
+
|
|
329
452
|
Args:
|
|
330
453
|
last_pair: Dernière paire de messages (tool_call + tool_result).
|
|
331
454
|
available_tokens: Tokens disponibles pour toute la paire.
|
|
@@ -341,7 +464,7 @@ class ScratchpadCompressor:
|
|
|
341
464
|
remaining = max(0, available_tokens - tokens_used)
|
|
342
465
|
result.append(self._truncate_single_result(msg, remaining))
|
|
343
466
|
else:
|
|
344
|
-
tokens_used += self.
|
|
467
|
+
tokens_used += self._count_tokens([msg])
|
|
345
468
|
result.append(msg)
|
|
346
469
|
|
|
347
470
|
return result
|
|
@@ -20,6 +20,7 @@ from llama_index.core.workflow import Context
|
|
|
20
20
|
|
|
21
21
|
from agent_framework.core.knowledge_state import ToolCallSignature
|
|
22
22
|
from agent_framework.core.loop_detector import LoopDetector
|
|
23
|
+
from agent_framework.core.scratchpad_compressor import MAX_MESSAGE_CONTENT_CHARS
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
from agent_framework.core.context_budget import ContextBudgetManager
|
|
@@ -176,14 +177,66 @@ class BudgetAwareFunctionAgent(FunctionAgent):
|
|
|
176
177
|
"Compressing scratchpad: usage %.1f%% >= 80%% threshold",
|
|
177
178
|
usage_percent,
|
|
178
179
|
)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
180
|
+
|
|
181
|
+
# Boucle de compression : re-vérifier après chaque passe
|
|
182
|
+
# car la première compression peut ne pas suffire (ex: blocks
|
|
183
|
+
# non aplatis, écart de tokenisation).
|
|
184
|
+
max_compression_passes = 3
|
|
185
|
+
for compression_pass in range(max_compression_passes):
|
|
186
|
+
compressed_scratchpad = await self._scratchpad_compressor.compress(
|
|
187
|
+
scratchpad=scratchpad,
|
|
188
|
+
llm_input=llm_input,
|
|
189
|
+
context_window=context_window,
|
|
190
|
+
sacred_zone_tokens=sacred_zone_tokens,
|
|
191
|
+
model_name=getattr(self.llm, "model", None),
|
|
192
|
+
)
|
|
193
|
+
await ctx.store.set(self.scratchpad_key, compressed_scratchpad)
|
|
194
|
+
|
|
195
|
+
# Recalculer le total après compression
|
|
196
|
+
new_scratchpad_tokens = self._count_total_tokens([], compressed_scratchpad)
|
|
197
|
+
new_total = sacred_zone_tokens + llm_input_tokens + new_scratchpad_tokens
|
|
198
|
+
new_usage = new_total / context_window * 100 if context_window > 0 else 0.0
|
|
199
|
+
|
|
200
|
+
logger.info(
|
|
201
|
+
"Post-compression pass %d: %d/%d tokens (%.1f%%), scratchpad=%d",
|
|
202
|
+
compression_pass + 1,
|
|
203
|
+
new_total,
|
|
204
|
+
context_window,
|
|
205
|
+
new_usage,
|
|
206
|
+
new_scratchpad_tokens,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
if new_usage < 80:
|
|
210
|
+
break
|
|
211
|
+
|
|
212
|
+
# Préparer la prochaine passe avec le scratchpad compressé
|
|
213
|
+
scratchpad = compressed_scratchpad
|
|
214
|
+
|
|
215
|
+
if compression_pass == max_compression_passes - 1:
|
|
216
|
+
logger.error(
|
|
217
|
+
"Scratchpad still at %.1f%% after %d compression passes",
|
|
218
|
+
new_usage,
|
|
219
|
+
max_compression_passes,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Garde-fou caractères bruts : même après compression en tokens,
|
|
223
|
+
# un message peut dépasser la limite API (10M chars). On tronque
|
|
224
|
+
# chaque message du scratchpad qui dépasse avant l'appel LLM.
|
|
225
|
+
if self._scratchpad_compressor:
|
|
226
|
+
scratchpad = await ctx.store.get(self.scratchpad_key, default=[])
|
|
227
|
+
patched = False
|
|
228
|
+
for i, msg in enumerate(scratchpad):
|
|
229
|
+
content = msg.content or ""
|
|
230
|
+
if len(content) > MAX_MESSAGE_CONTENT_CHARS:
|
|
231
|
+
from agent_framework.core.scratchpad_compressor import ScratchpadCompressor
|
|
232
|
+
scratchpad[i] = ChatMessage(
|
|
233
|
+
role=msg.role,
|
|
234
|
+
content=ScratchpadCompressor._enforce_char_limit(content),
|
|
235
|
+
additional_kwargs=msg.additional_kwargs,
|
|
236
|
+
)
|
|
237
|
+
patched = True
|
|
238
|
+
if patched:
|
|
239
|
+
await ctx.store.set(self.scratchpad_key, scratchpad)
|
|
187
240
|
|
|
188
241
|
return await super().take_step(ctx, llm_input, tools, memory)
|
|
189
242
|
|
|
@@ -61,9 +61,18 @@ logger = logging.getLogger(__name__)
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def _detect_is_error(tool_output: str) -> bool:
|
|
64
|
-
"""Return True if tool_output contains an error marker (case-insensitive).
|
|
64
|
+
"""Return True if tool_output contains an error marker (case-insensitive).
|
|
65
|
+
|
|
66
|
+
Excludes false positives like 'isError=False' or 'is_error: false' where
|
|
67
|
+
the word 'error' appears only as part of a negative flag.
|
|
68
|
+
"""
|
|
69
|
+
import re
|
|
70
|
+
|
|
65
71
|
lowered = tool_output.lower()
|
|
66
|
-
|
|
72
|
+
# Strip patterns like "iserror=false", "is_error=false", "iserror: false"
|
|
73
|
+
# before checking for error markers to avoid false positives from MCP tool output.
|
|
74
|
+
cleaned = re.sub(r"is_?error\s*[=:]\s*false", "", lowered)
|
|
75
|
+
return any(marker in cleaned for marker in ("error", "exception", "failed"))
|
|
67
76
|
|
|
68
77
|
|
|
69
78
|
class _StreamingActivityAccumulator:
|
|
@@ -1104,8 +1113,12 @@ class LlamaIndexAgent(BaseAgent):
|
|
|
1104
1113
|
tool_name = getattr(event, "tool_name", "unknown_tool")
|
|
1105
1114
|
tool_kwargs = getattr(event, "tool_kwargs", {}) or {}
|
|
1106
1115
|
call_id = getattr(event, "call_id", None) or "unknown"
|
|
1107
|
-
|
|
1108
|
-
|
|
1116
|
+
raw_tool_output = getattr(event, "tool_output", "")
|
|
1117
|
+
tool_output = str(raw_tool_output)
|
|
1118
|
+
# Prefer the structured is_error flag from ToolOutput when available,
|
|
1119
|
+
# fall back to text-based heuristic detection.
|
|
1120
|
+
native_is_error = getattr(raw_tool_output, "is_error", None)
|
|
1121
|
+
is_error = native_is_error if isinstance(native_is_error, bool) else _detect_is_error(tool_output)
|
|
1109
1122
|
ts = datetime.now(timezone.utc).isoformat()
|
|
1110
1123
|
|
|
1111
1124
|
self._pending_events.append({
|
{agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/agent_mixin.py
RENAMED
|
@@ -28,6 +28,7 @@ The mixin provides:
|
|
|
28
28
|
|
|
29
29
|
import logging
|
|
30
30
|
from collections.abc import Callable
|
|
31
|
+
from pathlib import Path
|
|
31
32
|
from typing import TYPE_CHECKING, Any
|
|
32
33
|
|
|
33
34
|
|
|
@@ -126,23 +127,21 @@ class SkillsMixin:
|
|
|
126
127
|
self._skill_registry.unload(name)
|
|
127
128
|
logger.info(f"Unloaded skill '{name}' for agent '{getattr(self, 'agent_id', 'unknown')}'")
|
|
128
129
|
|
|
129
|
-
def register_builtin_skills(self) -> None:
|
|
130
|
-
"""
|
|
131
|
-
Register all built-in skills with this agent.
|
|
130
|
+
def register_builtin_skills(self, source: str = "python") -> None:
|
|
131
|
+
"""Register all built-in skills with this agent.
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
Args:
|
|
134
|
+
source: Loading strategy passed to ``get_all_builtin_skills``.
|
|
135
|
+
Use ``"python"`` (default) for Python factory functions or
|
|
136
|
+
``"markdown"`` to load from SKILL.md files.
|
|
137
|
+
Skills already registered are skipped.
|
|
138
138
|
"""
|
|
139
139
|
from .builtin import get_all_builtin_skills
|
|
140
140
|
|
|
141
|
-
builtin_skills = get_all_builtin_skills()
|
|
141
|
+
builtin_skills = get_all_builtin_skills(source=source) # type: ignore[call-arg]
|
|
142
142
|
registered_count = 0
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
for skill in builtin_skills:
|
|
145
|
-
# Skip if already registered
|
|
146
145
|
if self._skill_registry.get(skill.metadata.name) is not None:
|
|
147
146
|
continue
|
|
148
147
|
self.register_skill(skill)
|
|
@@ -151,7 +150,7 @@ class SkillsMixin:
|
|
|
151
150
|
if registered_count > 0:
|
|
152
151
|
logger.info(
|
|
153
152
|
f"Registered {registered_count} built-in skills "
|
|
154
|
-
f"for agent '{getattr(self, 'agent_id', 'unknown')}'"
|
|
153
|
+
f"for agent '{getattr(self, 'agent_id', 'unknown')}' (source={source!r})"
|
|
155
154
|
)
|
|
156
155
|
elif builtin_skills:
|
|
157
156
|
logger.debug(
|
|
@@ -328,6 +327,59 @@ class SkillsMixin:
|
|
|
328
327
|
logger.info(f"🔧 Configured context for {configured_count} skill tools")
|
|
329
328
|
|
|
330
329
|
|
|
330
|
+
def register_skills_from_dir(self, skills_dir: Path) -> None:
|
|
331
|
+
"""Load all SKILL.md files from a directory and register them.
|
|
332
|
+
|
|
333
|
+
Native tools (ShellTool, WebFetchTool) are attached to each loaded skill
|
|
334
|
+
if not already present.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
skills_dir: Directory containing SKILL.md files.
|
|
338
|
+
|
|
339
|
+
Raises:
|
|
340
|
+
ValueError: If the directory does not exist.
|
|
341
|
+
"""
|
|
342
|
+
from agent_framework.skills.markdown_loader import MarkdownSkillLoader
|
|
343
|
+
from agent_framework.tools.shell_tool import ShellTool
|
|
344
|
+
from agent_framework.tools.web_fetch_tool import WebFetchTool
|
|
345
|
+
|
|
346
|
+
skills_dir = Path(skills_dir)
|
|
347
|
+
if not skills_dir.exists() or not skills_dir.is_dir():
|
|
348
|
+
raise ValueError(f"Skills directory not found: {skills_dir}")
|
|
349
|
+
|
|
350
|
+
loader = MarkdownSkillLoader()
|
|
351
|
+
skills = loader.load_from_dir(skills_dir)
|
|
352
|
+
|
|
353
|
+
for skill in skills:
|
|
354
|
+
existing_types = {type(t) for t in skill.tools}
|
|
355
|
+
if ShellTool not in existing_types:
|
|
356
|
+
skill.tools.append(ShellTool())
|
|
357
|
+
if WebFetchTool not in existing_types:
|
|
358
|
+
skill.tools.append(WebFetchTool())
|
|
359
|
+
try:
|
|
360
|
+
self._skill_registry.register(skill)
|
|
361
|
+
logger.debug("Registered SKILL.md skill '%s'", skill.metadata.name)
|
|
362
|
+
except Exception as exc:
|
|
363
|
+
logger.warning(
|
|
364
|
+
"Could not register skill '%s': %s", skill.metadata.name, exc
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
def apply_capability_set(self, capability_set: "Any") -> None:
|
|
368
|
+
"""Filter the SkillRegistry to only keep skills in capability_set.skill_ids.
|
|
369
|
+
|
|
370
|
+
This method is idempotent: applying the same CapabilitySet twice produces
|
|
371
|
+
the same registry state.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
capability_set: A CapabilitySet instance with a skill_ids attribute.
|
|
375
|
+
"""
|
|
376
|
+
allowed = set(capability_set.skill_ids)
|
|
377
|
+
all_names = [m.name for m in self._skill_registry.list_all()]
|
|
378
|
+
for name in all_names:
|
|
379
|
+
if name not in allowed:
|
|
380
|
+
self._skill_registry.unregister(name)
|
|
381
|
+
|
|
382
|
+
|
|
331
383
|
__all__ = [
|
|
332
384
|
"SkillsMixin",
|
|
333
385
|
]
|
{agent_framework_lib-0.6.3 → agent_framework_lib-0.6.3.post3}/agent_framework/skills/base.py
RENAMED
|
@@ -52,6 +52,10 @@ class SkillMetadata(BaseModel):
|
|
|
52
52
|
default="general", description="Category: document, data, web, visualization, etc."
|
|
53
53
|
)
|
|
54
54
|
version: str = Field(default="1.0.0", description="Skill version")
|
|
55
|
+
requires_bins: list[str] = Field(default_factory=list, description="Required system binaries")
|
|
56
|
+
requires_env: list[str] = Field(
|
|
57
|
+
default_factory=list, description="Required environment variables"
|
|
58
|
+
)
|
|
55
59
|
|
|
56
60
|
def matches_query(self, query: str) -> bool:
|
|
57
61
|
"""
|