fast-agent-mcp 0.1.11__tar.gz → 0.1.13__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.
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/PKG-INFO +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/pyproject.toml +17 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/agents/agent.py +37 -102
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/app.py +16 -27
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/commands/bootstrap.py +22 -52
- fast_agent_mcp-0.1.13/src/mcp_agent/cli/commands/config.py +11 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/commands/setup.py +11 -26
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/main.py +6 -9
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/terminal.py +2 -2
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/config.py +1 -5
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/context.py +13 -26
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/context_dependent.py +3 -7
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/agent_app.py +46 -122
- fast_agent_mcp-0.1.13/src/mcp_agent/core/agent_types.py +43 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/agent_utils.py +3 -5
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/decorators.py +6 -14
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/enhanced_prompt.py +25 -52
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/error_handling.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/exceptions.py +8 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/factory.py +30 -72
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/fastagent.py +48 -88
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/mcp_content.py +10 -19
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/prompt.py +8 -15
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/proxies.py +34 -25
- fast_agent_mcp-0.1.13/src/mcp_agent/core/request_params.py +46 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/types.py +6 -6
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/validation.py +16 -16
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/decorator_registry.py +11 -23
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/executor.py +8 -17
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/task_registry.py +2 -4
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/temporal.py +28 -74
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/workflow.py +3 -5
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/workflow_signal.py +17 -29
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/handler.py +4 -9
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/types.py +2 -3
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/events.py +1 -5
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/json_serializer.py +7 -6
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/listeners.py +20 -23
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/logger.py +15 -17
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/rich_progress.py +10 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/tracing.py +4 -6
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/transport.py +24 -24
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/gen_client.py +4 -12
- fast_agent_mcp-0.1.13/src/mcp_agent/mcp/interfaces.py +171 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_agent_client_session.py +11 -19
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_agent_server.py +8 -10
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_aggregator.py +49 -122
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_connection_manager.py +16 -37
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompt_message_multipart.py +12 -18
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompt_serialization.py +13 -38
- fast_agent_mcp-0.1.13/src/mcp_agent/mcp/prompts/prompt_load.py +99 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/prompt_server.py +21 -128
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/prompt_template.py +20 -42
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/resource_utils.py +8 -17
- fast_agent_mcp-0.1.13/src/mcp_agent/mcp/sampling.py +131 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/stdio.py +11 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server/__init__.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server/agent_server.py +10 -17
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server_registry.py +13 -35
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/analysis.py +1 -1
- fast_agent_mcp-0.1.13/src/mcp_agent/resources/examples/data-analysis/slides.py +110 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/agent.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/job.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/prompt_category.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +3 -5
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/sizer.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/social.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/__init__.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/agent.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/image_server.py +5 -11
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +3 -4
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/agent_build.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/chaining.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/evaluator.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/human_input.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/orchestrator.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/parallel.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/router.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/sse.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/telemetry/usage_tracking.py +2 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/ui/console_display.py +17 -41
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_base.py +1 -4
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_cohere.py +2 -2
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_openai.py +4 -13
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +23 -57
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_base.py +5 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +7 -11
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +4 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +4 -8
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +11 -22
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +3 -3
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +4 -6
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/anthropic_utils.py +8 -29
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm.py +94 -332
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_anthropic.py +43 -76
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_openai.py +46 -100
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_passthrough.py +42 -20
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_playback.py +8 -6
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/memory.py +103 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/model_factory.py +9 -21
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/openai_utils.py +1 -1
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/prompt_utils.py +39 -27
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/providers/multipart_converter_anthropic.py +410 -0
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/providers/multipart_converter_openai.py +436 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/openai_multipart.py +19 -61
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/providers/sampling_converter_anthropic.py +57 -0
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/providers/sampling_converter_openai.py +27 -0
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/sampling_converter.py +117 -0
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/sampling_format_converter.py +22 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator.py +24 -67
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator_models.py +14 -40
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/fan_in.py +17 -47
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/fan_out.py +6 -12
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/parallel_llm.py +9 -26
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_base.py +29 -59
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding.py +11 -25
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding_cohere.py +2 -2
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding_openai.py +2 -2
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_llm.py +12 -28
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/swarm.py +20 -48
- fast_agent_mcp-0.1.11/src/mcp_agent/cli/commands/config.py +0 -11
- fast_agent_mcp-0.1.11/src/mcp_agent/core/agent_types.py +0 -16
- fast_agent_mcp-0.1.11/src/mcp_agent/mcp/interfaces.py +0 -152
- fast_agent_mcp-0.1.11/src/mcp_agent/mcp/sampling.py +0 -133
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/llm_selector.py +0 -345
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/providers/multipart_converter_anthropic.py +0 -348
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/providers/multipart_converter_openai.py +0 -426
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/providers/sampling_converter_anthropic.py +0 -258
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/providers/sampling_converter_openai.py +0 -229
- fast_agent_mcp-0.1.11/src/mcp_agent/workflows/llm/sampling_format_converter.py +0 -39
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/.gitignore +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/LICENSE +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/README.md +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/agents/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/__main__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/console.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/eval/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/event_progress.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_activity.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mime_utils.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/progress_display.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/telemetry/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/__init__.py +0 -0
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/swarm_anthropic.py +2 -2
- {fast_agent_mcp-0.1.11 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/swarm_openai.py +2 -2
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fast-agent-mcp
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.13
|
4
4
|
Summary: Define, Prompt and Test MCP enabled Agents and Workflows
|
5
5
|
Author-email: Shaun Smith <fastagent@llmindset.co.uk>, Sarmad Qadri <sarmad@lastmileai.dev>
|
6
6
|
License: Apache License
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "fast-agent-mcp"
|
3
|
-
version = "0.1.
|
3
|
+
version = "0.1.13"
|
4
4
|
description = "Define, Prompt and Test MCP enabled Agents and Workflows"
|
5
5
|
readme = "README.md"
|
6
6
|
license = { file = "LICENSE" }
|
@@ -112,3 +112,19 @@ mcp_agent = [
|
|
112
112
|
"resources/examples/**/mount-point/*.csv"
|
113
113
|
]
|
114
114
|
|
115
|
+
[tool.ruff]
|
116
|
+
line-length = 160
|
117
|
+
target-version = "py310"
|
118
|
+
|
119
|
+
[tool.ruff.lint]
|
120
|
+
select = [
|
121
|
+
"E", # pycodestyle errors
|
122
|
+
"F", # pyflakes
|
123
|
+
"I", # isort
|
124
|
+
"TCH" # type checking
|
125
|
+
]
|
126
|
+
ignore=["E501"]
|
127
|
+
|
128
|
+
# More lenient settings for existing code
|
129
|
+
[tool.ruff.lint.per-file-ignores]
|
130
|
+
"tests/*" = ["ANN"] # Don't require type annotations in tests
|
@@ -1,30 +1,30 @@
|
|
1
1
|
import asyncio
|
2
2
|
import uuid
|
3
|
-
from
|
4
|
-
from typing import Callable, Dict, List, Optional, TypeVar, Union, TYPE_CHECKING
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, TypeVar, Union
|
5
4
|
|
6
5
|
from mcp.server.fastmcp.tools import Tool as FastTool
|
7
6
|
from mcp.types import (
|
8
7
|
CallToolResult,
|
8
|
+
EmbeddedResource,
|
9
9
|
ListToolsResult,
|
10
|
+
ReadResourceResult,
|
10
11
|
TextContent,
|
11
12
|
Tool,
|
12
|
-
EmbeddedResource,
|
13
|
-
ReadResourceResult,
|
14
13
|
)
|
15
|
-
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
16
14
|
|
15
|
+
from mcp_agent.core.agent_types import AgentConfig
|
17
16
|
from mcp_agent.core.exceptions import PromptExitError
|
18
|
-
from mcp_agent.
|
19
|
-
from mcp_agent.workflows.llm.augmented_llm import RequestParams
|
17
|
+
from mcp_agent.core.request_params import RequestParams
|
20
18
|
from mcp_agent.human_input.types import (
|
19
|
+
HUMAN_INPUT_SIGNAL_NAME,
|
21
20
|
HumanInputCallback,
|
22
21
|
HumanInputRequest,
|
23
22
|
HumanInputResponse,
|
24
|
-
HUMAN_INPUT_SIGNAL_NAME,
|
25
23
|
)
|
26
|
-
from mcp_agent.workflows.llm.augmented_llm import AugmentedLLM
|
27
24
|
from mcp_agent.logging.logger import get_logger
|
25
|
+
from mcp_agent.mcp.mcp_aggregator import MCPAggregator
|
26
|
+
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
27
|
+
from mcp_agent.workflows.llm.augmented_llm import AugmentedLLMProtocol
|
28
28
|
|
29
29
|
if TYPE_CHECKING:
|
30
30
|
from mcp_agent.context import Context
|
@@ -33,33 +33,11 @@ import traceback
|
|
33
33
|
logger = get_logger(__name__)
|
34
34
|
|
35
35
|
# Define a TypeVar for AugmentedLLM and its subclasses
|
36
|
-
LLM = TypeVar("LLM", bound=
|
36
|
+
LLM = TypeVar("LLM", bound=AugmentedLLMProtocol)
|
37
37
|
|
38
38
|
HUMAN_INPUT_TOOL_NAME = "__human_input__"
|
39
39
|
|
40
40
|
|
41
|
-
@dataclass
|
42
|
-
class AgentConfig:
|
43
|
-
"""Configuration for an Agent instance"""
|
44
|
-
|
45
|
-
name: str
|
46
|
-
instruction: Union[str, Callable[[Dict], str]]
|
47
|
-
servers: List[str]
|
48
|
-
model: Optional[str] = None
|
49
|
-
use_history: bool = True
|
50
|
-
default_request_params: Optional[RequestParams] = None
|
51
|
-
human_input: bool = False
|
52
|
-
|
53
|
-
def __post_init__(self):
|
54
|
-
"""Ensure default_request_params exists with proper history setting"""
|
55
|
-
|
56
|
-
if self.default_request_params is None:
|
57
|
-
self.default_request_params = RequestParams(use_history=self.use_history)
|
58
|
-
else:
|
59
|
-
# Override the request params history setting if explicitly configured
|
60
|
-
self.default_request_params.use_history = self.use_history
|
61
|
-
|
62
|
-
|
63
41
|
class Agent(MCPAggregator):
|
64
42
|
"""
|
65
43
|
An Agent is an entity that has access to a set of MCP servers and can interact with them.
|
@@ -68,17 +46,15 @@ class Agent(MCPAggregator):
|
|
68
46
|
|
69
47
|
def __init__(
|
70
48
|
self,
|
71
|
-
config: Union[
|
72
|
-
AgentConfig, str
|
73
|
-
], # Can be AgentConfig or backward compatible str name
|
49
|
+
config: Union[AgentConfig, str], # Can be AgentConfig or backward compatible str name
|
74
50
|
instruction: Optional[Union[str, Callable[[Dict], str]]] = None,
|
75
51
|
server_names: Optional[List[str]] = None,
|
76
52
|
functions: Optional[List[Callable]] = None,
|
77
53
|
connection_persistence: bool = True,
|
78
54
|
human_input_callback: Optional[HumanInputCallback] = None,
|
79
55
|
context: Optional["Context"] = None,
|
80
|
-
**kwargs,
|
81
|
-
):
|
56
|
+
**kwargs: dict[str, Any],
|
57
|
+
) -> None:
|
82
58
|
# Handle backward compatibility where first arg was name
|
83
59
|
if isinstance(config, str):
|
84
60
|
self.config = AgentConfig(
|
@@ -117,14 +93,12 @@ class Agent(MCPAggregator):
|
|
117
93
|
if self.context.human_input_handler:
|
118
94
|
self.human_input_callback = self.context.human_input_handler
|
119
95
|
|
120
|
-
async def initialize(self):
|
96
|
+
async def initialize(self) -> None:
|
121
97
|
"""
|
122
98
|
Initialize the agent and connect to the MCP servers.
|
123
99
|
NOTE: This method is called automatically when the agent is used as an async context manager.
|
124
100
|
"""
|
125
|
-
await (
|
126
|
-
self.__aenter__()
|
127
|
-
) # This initializes the connection manager and loads the servers
|
101
|
+
await self.__aenter__() # This initializes the connection manager and loads the servers
|
128
102
|
|
129
103
|
for function in self.functions:
|
130
104
|
tool: FastTool = FastTool.from_function(function)
|
@@ -142,11 +116,9 @@ class Agent(MCPAggregator):
|
|
142
116
|
Returns:
|
143
117
|
An instance of AugmentedLLM or one of its subclasses.
|
144
118
|
"""
|
145
|
-
return llm_factory(
|
146
|
-
agent=self, default_request_params=self._default_request_params
|
147
|
-
)
|
119
|
+
return llm_factory(agent=self, default_request_params=self._default_request_params)
|
148
120
|
|
149
|
-
async def shutdown(self):
|
121
|
+
async def shutdown(self) -> None:
|
150
122
|
"""
|
151
123
|
Shutdown the agent and close all MCP server connections.
|
152
124
|
NOTE: This method is called automatically when the agent is used as an async context manager.
|
@@ -176,8 +148,9 @@ class Agent(MCPAggregator):
|
|
176
148
|
request.metadata = {"agent_name": self.name}
|
177
149
|
self.logger.debug("Requesting human input:", data=request)
|
178
150
|
|
179
|
-
async def call_callback_and_signal():
|
151
|
+
async def call_callback_and_signal() -> None:
|
180
152
|
try:
|
153
|
+
assert self.human_input_callback is not None
|
181
154
|
user_input = await self.human_input_callback(request)
|
182
155
|
|
183
156
|
self.logger.debug("Received human input:", data=user_input)
|
@@ -190,9 +163,7 @@ class Agent(MCPAggregator):
|
|
190
163
|
payload={"exit_requested": True, "error": str(e)},
|
191
164
|
)
|
192
165
|
except Exception as e:
|
193
|
-
await self.executor.signal(
|
194
|
-
request_id, payload=f"Error getting human input: {str(e)}"
|
195
|
-
)
|
166
|
+
await self.executor.signal(request_id, payload=f"Error getting human input: {str(e)}")
|
196
167
|
|
197
168
|
asyncio.create_task(call_callback_and_signal())
|
198
169
|
|
@@ -209,9 +180,7 @@ class Agent(MCPAggregator):
|
|
209
180
|
)
|
210
181
|
|
211
182
|
if isinstance(result, dict) and result.get("exit_requested", False):
|
212
|
-
raise PromptExitError(
|
213
|
-
result.get("error", "User requested to exit FastAgent session")
|
214
|
-
)
|
183
|
+
raise PromptExitError(result.get("error", "User requested to exit FastAgent session"))
|
215
184
|
self.logger.debug("Received human input signal", data=result)
|
216
185
|
return result
|
217
186
|
|
@@ -249,9 +218,7 @@ class Agent(MCPAggregator):
|
|
249
218
|
return result
|
250
219
|
|
251
220
|
# todo would prefer to use tool_name to disambiguate agent name
|
252
|
-
async def call_tool(
|
253
|
-
self, name: str, arguments: dict | None = None
|
254
|
-
) -> CallToolResult:
|
221
|
+
async def call_tool(self, name: str, arguments: dict | None = None) -> CallToolResult:
|
255
222
|
if name == HUMAN_INPUT_TOOL_NAME:
|
256
223
|
# Call the human input tool
|
257
224
|
return await self._call_human_input_tool(arguments)
|
@@ -263,9 +230,7 @@ class Agent(MCPAggregator):
|
|
263
230
|
else:
|
264
231
|
return await super().call_tool(name, arguments)
|
265
232
|
|
266
|
-
async def _call_human_input_tool(
|
267
|
-
self, arguments: dict | None = None
|
268
|
-
) -> CallToolResult:
|
233
|
+
async def _call_human_input_tool(self, arguments: dict | None = None) -> CallToolResult:
|
269
234
|
# Handle human input request
|
270
235
|
try:
|
271
236
|
# Make sure arguments is not None
|
@@ -287,17 +252,9 @@ class Agent(MCPAggregator):
|
|
287
252
|
result = await self.request_human_input(request=request)
|
288
253
|
|
289
254
|
# Use response attribute if available, otherwise use the result directly
|
290
|
-
response_text = (
|
291
|
-
result.response
|
292
|
-
if isinstance(result, HumanInputResponse)
|
293
|
-
else str(result)
|
294
|
-
)
|
255
|
+
response_text = result.response if isinstance(result, HumanInputResponse) else str(result)
|
295
256
|
|
296
|
-
return CallToolResult(
|
297
|
-
content=[
|
298
|
-
TextContent(type="text", text=f"Human response: {response_text}")
|
299
|
-
]
|
300
|
-
)
|
257
|
+
return CallToolResult(content=[TextContent(type="text", text=f"Human response: {response_text}")])
|
301
258
|
|
302
259
|
except PromptExitError:
|
303
260
|
raise
|
@@ -316,21 +273,10 @@ class Agent(MCPAggregator):
|
|
316
273
|
|
317
274
|
return CallToolResult(
|
318
275
|
isError=True,
|
319
|
-
content=[
|
320
|
-
TextContent(
|
321
|
-
type="text", text=f"Error requesting human input: {str(e)}"
|
322
|
-
)
|
323
|
-
],
|
276
|
+
content=[TextContent(type="text", text=f"Error requesting human input: {str(e)}")],
|
324
277
|
)
|
325
278
|
|
326
|
-
async def
|
327
|
-
self, server_name: str, resource_name: str
|
328
|
-
) -> ReadResourceResult:
|
329
|
-
return None
|
330
|
-
|
331
|
-
async def apply_prompt(
|
332
|
-
self, prompt_name: str, arguments: dict[str, str] = None
|
333
|
-
) -> str:
|
279
|
+
async def apply_prompt(self, prompt_name: str, arguments: dict[str, str] | None) -> str:
|
334
280
|
"""
|
335
281
|
Apply an MCP Server Prompt by name and return the assistant's response.
|
336
282
|
Will search all available servers for the prompt if not namespaced.
|
@@ -354,9 +300,7 @@ class Agent(MCPAggregator):
|
|
354
300
|
prompt_result = await self.get_prompt(prompt_name, arguments)
|
355
301
|
|
356
302
|
if not prompt_result or not prompt_result.messages:
|
357
|
-
error_msg =
|
358
|
-
f"Prompt '{prompt_name}' could not be found or contains no messages"
|
359
|
-
)
|
303
|
+
error_msg = f"Prompt '{prompt_name}' could not be found or contains no messages"
|
360
304
|
self.logger.warning(error_msg)
|
361
305
|
return error_msg
|
362
306
|
|
@@ -395,16 +339,10 @@ class Agent(MCPAggregator):
|
|
395
339
|
resource_result = await server.get_resource(resource_name)
|
396
340
|
return resource_result
|
397
341
|
except Exception as e:
|
398
|
-
self.logger.error(
|
399
|
-
|
400
|
-
)
|
401
|
-
raise ValueError(
|
402
|
-
f"Failed to retrieve resource '{resource_name}' from server '{server_name}': {str(e)}"
|
403
|
-
)
|
342
|
+
self.logger.error(f"Error retrieving resource '{resource_name}' from server '{server_name}': {str(e)}")
|
343
|
+
raise ValueError(f"Failed to retrieve resource '{resource_name}' from server '{server_name}': {str(e)}")
|
404
344
|
|
405
|
-
async def get_embedded_resources(
|
406
|
-
self, server_name: str, resource_name: str
|
407
|
-
) -> List[EmbeddedResource]:
|
345
|
+
async def get_embedded_resources(self, server_name: str, resource_name: str) -> List[EmbeddedResource]:
|
408
346
|
"""
|
409
347
|
Get a resource from an MCP server and return it as a list of embedded resources ready for use in prompts.
|
410
348
|
|
@@ -419,20 +357,19 @@ class Agent(MCPAggregator):
|
|
419
357
|
ValueError: If the server doesn't exist or the resource couldn't be found
|
420
358
|
"""
|
421
359
|
# Get the raw resource result
|
422
|
-
result: ReadResourceResult = await super().get_resource(
|
423
|
-
server_name, resource_name
|
424
|
-
)
|
360
|
+
result: ReadResourceResult = await super().get_resource(server_name, resource_name)
|
425
361
|
|
426
362
|
# Convert each resource content to an EmbeddedResource
|
427
363
|
embedded_resources: List[EmbeddedResource] = []
|
428
364
|
for resource_content in result.contents:
|
429
|
-
embedded_resource = EmbeddedResource(
|
430
|
-
type="resource", resource=resource_content, annotations=None
|
431
|
-
)
|
365
|
+
embedded_resource = EmbeddedResource(type="resource", resource=resource_content, annotations=None)
|
432
366
|
embedded_resources.append(embedded_resource)
|
433
367
|
|
434
368
|
return embedded_resources
|
435
369
|
|
370
|
+
async def apply_prompt_messages(self, prompts: List[PromptMessageMultipart], request_params: RequestParams | None) -> str:
|
371
|
+
return self._llm.apply_prompt_messages(prompts, request_params)
|
372
|
+
|
436
373
|
async def with_resource(
|
437
374
|
self,
|
438
375
|
prompt_content: Union[str, PromptMessageMultipart],
|
@@ -451,9 +388,7 @@ class Agent(MCPAggregator):
|
|
451
388
|
The agent's response as a string
|
452
389
|
"""
|
453
390
|
# Get the embedded resources
|
454
|
-
embedded_resources: List[EmbeddedResource] = await self.get_embedded_resources(
|
455
|
-
server_name, resource_name
|
456
|
-
)
|
391
|
+
embedded_resources: List[EmbeddedResource] = await self.get_embedded_resources(server_name, resource_name)
|
457
392
|
|
458
393
|
# Create or update the prompt message
|
459
394
|
prompt: PromptMessageMultipart
|
@@ -1,17 +1,18 @@
|
|
1
|
-
from typing import Any, Dict, Optional, Type, TypeVar, Callable
|
2
|
-
from datetime import timedelta
|
3
1
|
import asyncio
|
4
2
|
from contextlib import asynccontextmanager
|
3
|
+
from datetime import timedelta
|
4
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Type, TypeVar
|
5
5
|
|
6
|
-
from mcp import ServerSession
|
7
|
-
from mcp_agent.context import Context, initialize_context, cleanup_context
|
8
6
|
from mcp_agent.config import Settings
|
7
|
+
from mcp_agent.context import Context, cleanup_context, initialize_context
|
9
8
|
from mcp_agent.event_progress import ProgressAction
|
10
|
-
from mcp_agent.logging.logger import get_logger
|
11
9
|
from mcp_agent.executor.workflow_signal import SignalWaitCallback
|
12
|
-
from mcp_agent.human_input.types import HumanInputCallback
|
13
10
|
from mcp_agent.human_input.handler import console_input_callback
|
14
|
-
from mcp_agent.
|
11
|
+
from mcp_agent.human_input.types import HumanInputCallback
|
12
|
+
from mcp_agent.logging.logger import get_logger
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from mcp import ServerSession
|
15
16
|
|
16
17
|
R = TypeVar("R")
|
17
18
|
|
@@ -44,8 +45,7 @@ class MCPApp:
|
|
44
45
|
human_input_callback: Optional[HumanInputCallback] = console_input_callback,
|
45
46
|
signal_notification: Optional[SignalWaitCallback] = None,
|
46
47
|
upstream_session: Optional["ServerSession"] = None,
|
47
|
-
|
48
|
-
):
|
48
|
+
) -> None:
|
49
49
|
"""
|
50
50
|
Initialize the application with a name and optional settings.
|
51
51
|
Args:
|
@@ -55,7 +55,6 @@ class MCPApp:
|
|
55
55
|
human_input_callback: Callback for handling human input
|
56
56
|
signal_notification: Callback for getting notified on workflow signals/events.
|
57
57
|
upstream_session: Optional upstream session if the MCPApp is running as a server to an MCP client.
|
58
|
-
initialize_model_selector: Initializes the built-in ModelSelector to help with model selection. Defaults to False.
|
59
58
|
"""
|
60
59
|
self.name = name
|
61
60
|
|
@@ -64,7 +63,6 @@ class MCPApp:
|
|
64
63
|
self._human_input_callback = human_input_callback
|
65
64
|
self._signal_notification = signal_notification
|
66
65
|
self._upstream_session = upstream_session
|
67
|
-
self._model_selector = model_selector
|
68
66
|
|
69
67
|
self._workflows: Dict[str, Type] = {} # id to workflow class
|
70
68
|
self._logger = None
|
@@ -74,9 +72,7 @@ class MCPApp:
|
|
74
72
|
@property
|
75
73
|
def context(self) -> Context:
|
76
74
|
if self._context is None:
|
77
|
-
raise RuntimeError(
|
78
|
-
"MCPApp not initialized, please call initialize() first, or use async with app.run()."
|
79
|
-
)
|
75
|
+
raise RuntimeError("MCPApp not initialized, please call initialize() first, or use async with app.run().")
|
80
76
|
return self._context
|
81
77
|
|
82
78
|
@property
|
@@ -100,7 +96,7 @@ class MCPApp:
|
|
100
96
|
return self._context.upstream_session
|
101
97
|
|
102
98
|
@upstream_session.setter
|
103
|
-
def upstream_session(self, value):
|
99
|
+
def upstream_session(self, value) -> None:
|
104
100
|
self._context.upstream_session = value
|
105
101
|
|
106
102
|
@property
|
@@ -117,7 +113,7 @@ class MCPApp:
|
|
117
113
|
self._logger = get_logger(f"mcp_agent.{self.name}")
|
118
114
|
return self._logger
|
119
115
|
|
120
|
-
async def initialize(self):
|
116
|
+
async def initialize(self) -> None:
|
121
117
|
"""Initialize the application."""
|
122
118
|
if self._initialized:
|
123
119
|
return
|
@@ -128,7 +124,6 @@ class MCPApp:
|
|
128
124
|
self._context.human_input_handler = self._human_input_callback
|
129
125
|
self._context.signal_notification = self._signal_notification
|
130
126
|
self._context.upstream_session = self._upstream_session
|
131
|
-
self._context.model_selector = self._model_selector
|
132
127
|
|
133
128
|
self._initialized = True
|
134
129
|
self.logger.info(
|
@@ -140,7 +135,7 @@ class MCPApp:
|
|
140
135
|
},
|
141
136
|
)
|
142
137
|
|
143
|
-
async def cleanup(self):
|
138
|
+
async def cleanup(self) -> None:
|
144
139
|
"""Cleanup application resources."""
|
145
140
|
if not self._initialized:
|
146
141
|
return
|
@@ -178,9 +173,7 @@ class MCPApp:
|
|
178
173
|
finally:
|
179
174
|
await self.cleanup()
|
180
175
|
|
181
|
-
def workflow(
|
182
|
-
self, cls: Type, *args, workflow_id: str | None = None, **kwargs
|
183
|
-
) -> Type:
|
176
|
+
def workflow(self, cls: Type, *args, workflow_id: str | None = None, **kwargs) -> Type:
|
184
177
|
"""
|
185
178
|
Decorator for a workflow class. By default it's a no-op,
|
186
179
|
but different executors can use this to customize behavior
|
@@ -192,9 +185,7 @@ class MCPApp:
|
|
192
185
|
"""
|
193
186
|
decorator_registry = self.context.decorator_registry
|
194
187
|
execution_engine = self.engine
|
195
|
-
workflow_defn_decorator = decorator_registry.get_workflow_defn_decorator(
|
196
|
-
execution_engine
|
197
|
-
)
|
188
|
+
workflow_defn_decorator = decorator_registry.get_workflow_defn_decorator(execution_engine)
|
198
189
|
|
199
190
|
if workflow_defn_decorator:
|
200
191
|
return workflow_defn_decorator(cls, *args, **kwargs)
|
@@ -216,9 +207,7 @@ class MCPApp:
|
|
216
207
|
|
217
208
|
decorator_registry = self.context.decorator_registry
|
218
209
|
execution_engine = self.engine
|
219
|
-
workflow_run_decorator = decorator_registry.get_workflow_run_decorator(
|
220
|
-
execution_engine
|
221
|
-
)
|
210
|
+
workflow_run_decorator = decorator_registry.get_workflow_run_decorator(execution_engine)
|
222
211
|
|
223
212
|
if workflow_run_decorator:
|
224
213
|
return workflow_run_decorator(fn)
|
@@ -2,10 +2,11 @@
|
|
2
2
|
|
3
3
|
import shutil
|
4
4
|
from pathlib import Path
|
5
|
+
|
5
6
|
import typer
|
6
7
|
from rich.console import Console
|
7
|
-
from rich.table import Table
|
8
8
|
from rich.panel import Panel
|
9
|
+
from rich.table import Table
|
9
10
|
|
10
11
|
app = typer.Typer(
|
11
12
|
help="Create example applications",
|
@@ -49,9 +50,7 @@ EXAMPLE_TYPES = {
|
|
49
50
|
}
|
50
51
|
|
51
52
|
|
52
|
-
def copy_example_files(
|
53
|
-
example_type: str, target_dir: Path, force: bool = False
|
54
|
-
) -> list[str]:
|
53
|
+
def copy_example_files(example_type: str, target_dir: Path, force: bool = False) -> list[str]:
|
55
54
|
"""Copy example files from resources to target directory."""
|
56
55
|
created = []
|
57
56
|
|
@@ -72,12 +71,7 @@ def copy_example_files(
|
|
72
71
|
console.print(f"Created mount-point directory: {mount_point_dir}")
|
73
72
|
|
74
73
|
# Use the resources directory from the package
|
75
|
-
source_dir = (
|
76
|
-
Path(__file__).parent.parent.parent
|
77
|
-
/ "resources"
|
78
|
-
/ "examples"
|
79
|
-
/ ("workflows" if example_type == "workflow" else f"{example_type}")
|
80
|
-
)
|
74
|
+
source_dir = Path(__file__).parent.parent.parent / "resources" / "examples" / ("workflows" if example_type == "workflow" else f"{example_type}")
|
81
75
|
|
82
76
|
if not source_dir.exists():
|
83
77
|
console.print(f"[red]Error: Source directory not found: {source_dir}[/red]")
|
@@ -116,9 +110,7 @@ def copy_example_files(
|
|
116
110
|
continue
|
117
111
|
|
118
112
|
if target.exists() and not force:
|
119
|
-
console.print(
|
120
|
-
f"[yellow]Skipping[/yellow] mount-point/{filename} (already exists)"
|
121
|
-
)
|
113
|
+
console.print(f"[yellow]Skipping[/yellow] mount-point/{filename} (already exists)")
|
122
114
|
continue
|
123
115
|
|
124
116
|
shutil.copy2(source, target)
|
@@ -126,22 +118,18 @@ def copy_example_files(
|
|
126
118
|
console.print(f"[green]Created[/green] mount-point/{filename}")
|
127
119
|
|
128
120
|
except Exception as e:
|
129
|
-
console.print(
|
130
|
-
f"[red]Error copying mount-point/{filename}: {str(e)}[/red]"
|
131
|
-
)
|
121
|
+
console.print(f"[red]Error copying mount-point/{filename}: {str(e)}[/red]")
|
132
122
|
|
133
123
|
return created
|
134
124
|
|
135
125
|
|
136
|
-
def show_overview():
|
126
|
+
def show_overview() -> None:
|
137
127
|
"""Display an overview of available examples in a nicely formatted table."""
|
138
128
|
console.print("\n[bold cyan]fast-agent Example Applications[/bold cyan]")
|
139
129
|
console.print("Build agents and compose workflows through practical examples\n")
|
140
130
|
|
141
131
|
# Create a table for better organization
|
142
|
-
table = Table(
|
143
|
-
show_header=True, header_style="bold magenta", box=None, padding=(0, 2)
|
144
|
-
)
|
132
|
+
table = Table(show_header=True, header_style="bold magenta", box=None, padding=(0, 2))
|
145
133
|
table.add_column("Example")
|
146
134
|
table.add_column("Description")
|
147
135
|
table.add_column("Files")
|
@@ -149,9 +137,7 @@ def show_overview():
|
|
149
137
|
for name, info in EXAMPLE_TYPES.items():
|
150
138
|
files_list = "\n".join(f"• {f}" for f in info["files"])
|
151
139
|
if "mount_point_files" in info:
|
152
|
-
files_list += "\n[blue]mount-point:[/blue]\n" + "\n".join(
|
153
|
-
f"• {f}" for f in info["mount_point_files"]
|
154
|
-
)
|
140
|
+
files_list += "\n[blue]mount-point:[/blue]\n" + "\n".join(f"• {f}" for f in info["mount_point_files"])
|
155
141
|
table.add_row(f"[green]{name}[/green]", info["description"], files_list)
|
156
142
|
|
157
143
|
console.print(table)
|
@@ -178,10 +164,8 @@ def workflow(
|
|
178
164
|
Path("."),
|
179
165
|
help="Directory where workflow examples will be created",
|
180
166
|
),
|
181
|
-
force: bool = typer.Option(
|
182
|
-
|
183
|
-
),
|
184
|
-
):
|
167
|
+
force: bool = typer.Option(False, "--force", "-f", help="Force overwrite existing files"),
|
168
|
+
) -> None:
|
185
169
|
"""Create workflow pattern examples."""
|
186
170
|
target_dir = directory.resolve()
|
187
171
|
if not target_dir.exists():
|
@@ -198,10 +182,8 @@ def researcher(
|
|
198
182
|
Path("."),
|
199
183
|
help="Directory where researcher examples will be created (in 'researcher' subdirectory)",
|
200
184
|
),
|
201
|
-
force: bool = typer.Option(
|
202
|
-
|
203
|
-
),
|
204
|
-
):
|
185
|
+
force: bool = typer.Option(False, "--force", "-f", help="Force overwrite existing files"),
|
186
|
+
) -> None:
|
205
187
|
"""Create researcher pattern examples."""
|
206
188
|
target_dir = directory.resolve()
|
207
189
|
if not target_dir.exists():
|
@@ -218,10 +200,8 @@ def data_analysis(
|
|
218
200
|
Path("."),
|
219
201
|
help="Directory where data analysis examples will be created (creates 'data-analysis' subdirectory with mount-point)",
|
220
202
|
),
|
221
|
-
force: bool = typer.Option(
|
222
|
-
|
223
|
-
),
|
224
|
-
):
|
203
|
+
force: bool = typer.Option(False, "--force", "-f", help="Force overwrite existing files"),
|
204
|
+
) -> None:
|
225
205
|
"""Create data analysis examples with sample dataset."""
|
226
206
|
target_dir = directory.resolve()
|
227
207
|
if not target_dir.exists():
|
@@ -232,7 +212,7 @@ def data_analysis(
|
|
232
212
|
_show_completion_message("data-analysis", created)
|
233
213
|
|
234
214
|
|
235
|
-
def _show_completion_message(example_type: str, created: list[str]):
|
215
|
+
def _show_completion_message(example_type: str, created: list[str]) -> None:
|
236
216
|
"""Show completion message and next steps."""
|
237
217
|
if created:
|
238
218
|
console.print("\n[green]Setup completed successfully![/green]")
|
@@ -249,33 +229,23 @@ def _show_completion_message(example_type: str, created: list[str]):
|
|
249
229
|
console.print(" - evaluator.py: Add evaluation capabilities")
|
250
230
|
console.print(" - human_input.py: Incorporate human feedback")
|
251
231
|
console.print("3. Run an example with: uv run <example>.py")
|
252
|
-
console.print(
|
253
|
-
"4. Try a different model with --model=<model>, or update the agent config"
|
254
|
-
)
|
232
|
+
console.print("4. Try a different model with --model=<model>, or update the agent config")
|
255
233
|
|
256
234
|
elif example_type == "researcher":
|
257
|
-
console.print(
|
258
|
-
"1. Set up the Brave MCP Server (get an API key from https://brave.com/search/api/)"
|
259
|
-
)
|
235
|
+
console.print("1. Set up the Brave MCP Server (get an API key from https://brave.com/search/api/)")
|
260
236
|
console.print("2. Try `uv run researcher.py` for the basic version")
|
261
|
-
console.print(
|
262
|
-
"3. Try `uv run researcher-eval.py` for the eval/optimize version"
|
263
|
-
)
|
237
|
+
console.print("3. Try `uv run researcher-eval.py` for the eval/optimize version")
|
264
238
|
elif example_type == "data-analysis":
|
265
|
-
console.print(
|
266
|
-
"1. Run uv `analysis.py` to perform data analysis and visualization"
|
267
|
-
)
|
239
|
+
console.print("1. Run uv `analysis.py` to perform data analysis and visualization")
|
268
240
|
console.print("2. The dataset is available in the mount-point directory:")
|
269
241
|
console.print(" - mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv")
|
270
|
-
console.print(
|
271
|
-
"On Windows platforms, please edit the fastagent.config.yaml and adjust the volume mount point."
|
272
|
-
)
|
242
|
+
console.print("On Windows platforms, please edit the fastagent.config.yaml and adjust the volume mount point.")
|
273
243
|
else:
|
274
244
|
console.print("\n[yellow]No files were created.[/yellow]")
|
275
245
|
|
276
246
|
|
277
247
|
@app.callback(invoke_without_command=True)
|
278
|
-
def main(ctx: typer.Context):
|
248
|
+
def main(ctx: typer.Context) -> None:
|
279
249
|
"""Create example applications and learn FastAgent patterns."""
|
280
250
|
if ctx.invoked_subcommand is None:
|
281
251
|
show_overview()
|