fast-agent-mcp 0.1.12__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.12 → fast_agent_mcp-0.1.13}/PKG-INFO +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/pyproject.toml +17 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/agents/agent.py +37 -79
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/app.py +16 -22
- {fast_agent_mcp-0.1.12 → 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.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/commands/setup.py +11 -26
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/main.py +6 -9
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/terminal.py +2 -2
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/config.py +1 -5
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/context.py +13 -24
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/context_dependent.py +3 -7
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/agent_app.py +45 -121
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/agent_utils.py +3 -5
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/decorators.py +5 -12
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/enhanced_prompt.py +25 -52
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/exceptions.py +8 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/factory.py +29 -70
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/fastagent.py +48 -88
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/mcp_content.py +8 -16
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/prompt.py +8 -15
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/proxies.py +34 -25
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/request_params.py +6 -3
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/types.py +4 -6
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/validation.py +4 -3
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/decorator_registry.py +11 -23
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/executor.py +8 -17
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/task_registry.py +2 -4
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/temporal.py +28 -74
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/workflow.py +3 -5
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/workflow_signal.py +17 -29
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/handler.py +4 -9
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/types.py +2 -3
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/events.py +1 -5
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/json_serializer.py +7 -6
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/listeners.py +20 -23
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/logger.py +15 -17
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/rich_progress.py +10 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/tracing.py +4 -6
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/transport.py +22 -22
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/gen_client.py +4 -12
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/interfaces.py +71 -86
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_agent_client_session.py +11 -19
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_agent_server.py +8 -10
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_aggregator.py +45 -117
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_connection_manager.py +16 -37
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompt_message_multipart.py +12 -18
- {fast_agent_mcp-0.1.12 → 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.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/prompt_server.py +21 -128
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/prompt_template.py +20 -42
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/resource_utils.py +8 -17
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/sampling.py +5 -14
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/stdio.py +11 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server/agent_server.py +10 -17
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server_registry.py +13 -35
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +1 -1
- {fast_agent_mcp-0.1.12 → 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.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/agent.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/job.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/prompt_category.py +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +3 -5
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/sizer.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/social.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/agent.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/image_server.py +5 -11
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +3 -4
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/researcher.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/agent_build.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/chaining.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/evaluator.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/human_input.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/orchestrator.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/parallel.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/router.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/sse.py +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/telemetry/usage_tracking.py +2 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/ui/console_display.py +15 -39
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_base.py +1 -4
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_cohere.py +2 -2
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/embedding_openai.py +4 -13
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +23 -57
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_base.py +5 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +7 -11
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +4 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +4 -8
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +11 -22
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +3 -3
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +4 -6
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/anthropic_utils.py +8 -29
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm.py +69 -247
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_anthropic.py +39 -73
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_openai.py +42 -97
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/augmented_llm_passthrough.py +13 -20
- {fast_agent_mcp-0.1.12 → 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.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/model_factory.py +8 -20
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/openai_utils.py +1 -1
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/prompt_utils.py +1 -3
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/multipart_converter_anthropic.py +47 -89
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/multipart_converter_openai.py +20 -55
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/openai_multipart.py +19 -61
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/sampling_converter_anthropic.py +10 -12
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/sampling_converter_openai.py +7 -11
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/sampling_converter.py +4 -11
- fast_agent_mcp-0.1.13/src/mcp_agent/workflows/llm/sampling_format_converter.py +22 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator.py +24 -67
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator_models.py +14 -40
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/fan_in.py +17 -47
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/fan_out.py +6 -12
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/parallel_llm.py +9 -26
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_base.py +19 -49
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding.py +11 -25
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding_cohere.py +2 -2
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_embedding_openai.py +2 -2
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/router_llm.py +12 -28
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/swarm.py +20 -48
- fast_agent_mcp-0.1.12/src/mcp_agent/cli/commands/config.py +0 -11
- fast_agent_mcp-0.1.12/src/mcp_agent/workflows/llm/sampling_format_converter.py +0 -22
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/.gitignore +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/LICENSE +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/README.md +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/agents/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/cli/__main__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/console.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/agent_types.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/core/error_handling.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/eval/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/event_progress.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/executor/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/human_input/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/logging/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mcp_activity.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/mime_utils.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/mcp_server/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/progress_display.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.12 → 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.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/telemetry/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/embedding/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/llm/providers/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/parallel/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/router/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/__init__.py +0 -0
- {fast_agent_mcp-0.1.12 → fast_agent_mcp-0.1.13}/src/mcp_agent/workflows/swarm/swarm_anthropic.py +2 -2
- {fast_agent_mcp-0.1.12 → 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,29 +1,30 @@
|
|
1
1
|
import asyncio
|
2
2
|
import uuid
|
3
|
-
from typing import Callable, Dict, List, Optional, TypeVar, Union
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, TypeVar, Union
|
4
4
|
|
5
5
|
from mcp.server.fastmcp.tools import Tool as FastTool
|
6
6
|
from mcp.types import (
|
7
7
|
CallToolResult,
|
8
|
+
EmbeddedResource,
|
8
9
|
ListToolsResult,
|
10
|
+
ReadResourceResult,
|
9
11
|
TextContent,
|
10
12
|
Tool,
|
11
|
-
EmbeddedResource,
|
12
|
-
ReadResourceResult,
|
13
13
|
)
|
14
|
-
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
15
14
|
|
16
|
-
from mcp_agent.core.exceptions import PromptExitError
|
17
|
-
from mcp_agent.mcp.mcp_aggregator import MCPAggregator
|
18
15
|
from mcp_agent.core.agent_types import AgentConfig
|
16
|
+
from mcp_agent.core.exceptions import PromptExitError
|
17
|
+
from mcp_agent.core.request_params import RequestParams
|
19
18
|
from mcp_agent.human_input.types import (
|
19
|
+
HUMAN_INPUT_SIGNAL_NAME,
|
20
20
|
HumanInputCallback,
|
21
21
|
HumanInputRequest,
|
22
22
|
HumanInputResponse,
|
23
|
-
HUMAN_INPUT_SIGNAL_NAME,
|
24
23
|
)
|
25
|
-
from mcp_agent.workflows.llm.augmented_llm import AugmentedLLM
|
26
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
|
27
28
|
|
28
29
|
if TYPE_CHECKING:
|
29
30
|
from mcp_agent.context import Context
|
@@ -32,7 +33,7 @@ import traceback
|
|
32
33
|
logger = get_logger(__name__)
|
33
34
|
|
34
35
|
# Define a TypeVar for AugmentedLLM and its subclasses
|
35
|
-
LLM = TypeVar("LLM", bound=
|
36
|
+
LLM = TypeVar("LLM", bound=AugmentedLLMProtocol)
|
36
37
|
|
37
38
|
HUMAN_INPUT_TOOL_NAME = "__human_input__"
|
38
39
|
|
@@ -45,17 +46,15 @@ class Agent(MCPAggregator):
|
|
45
46
|
|
46
47
|
def __init__(
|
47
48
|
self,
|
48
|
-
config: Union[
|
49
|
-
AgentConfig, str
|
50
|
-
], # Can be AgentConfig or backward compatible str name
|
49
|
+
config: Union[AgentConfig, str], # Can be AgentConfig or backward compatible str name
|
51
50
|
instruction: Optional[Union[str, Callable[[Dict], str]]] = None,
|
52
51
|
server_names: Optional[List[str]] = None,
|
53
52
|
functions: Optional[List[Callable]] = None,
|
54
53
|
connection_persistence: bool = True,
|
55
54
|
human_input_callback: Optional[HumanInputCallback] = None,
|
56
55
|
context: Optional["Context"] = None,
|
57
|
-
**kwargs,
|
58
|
-
):
|
56
|
+
**kwargs: dict[str, Any],
|
57
|
+
) -> None:
|
59
58
|
# Handle backward compatibility where first arg was name
|
60
59
|
if isinstance(config, str):
|
61
60
|
self.config = AgentConfig(
|
@@ -94,14 +93,12 @@ class Agent(MCPAggregator):
|
|
94
93
|
if self.context.human_input_handler:
|
95
94
|
self.human_input_callback = self.context.human_input_handler
|
96
95
|
|
97
|
-
async def initialize(self):
|
96
|
+
async def initialize(self) -> None:
|
98
97
|
"""
|
99
98
|
Initialize the agent and connect to the MCP servers.
|
100
99
|
NOTE: This method is called automatically when the agent is used as an async context manager.
|
101
100
|
"""
|
102
|
-
await (
|
103
|
-
self.__aenter__()
|
104
|
-
) # This initializes the connection manager and loads the servers
|
101
|
+
await self.__aenter__() # This initializes the connection manager and loads the servers
|
105
102
|
|
106
103
|
for function in self.functions:
|
107
104
|
tool: FastTool = FastTool.from_function(function)
|
@@ -119,11 +116,9 @@ class Agent(MCPAggregator):
|
|
119
116
|
Returns:
|
120
117
|
An instance of AugmentedLLM or one of its subclasses.
|
121
118
|
"""
|
122
|
-
return llm_factory(
|
123
|
-
agent=self, default_request_params=self._default_request_params
|
124
|
-
)
|
119
|
+
return llm_factory(agent=self, default_request_params=self._default_request_params)
|
125
120
|
|
126
|
-
async def shutdown(self):
|
121
|
+
async def shutdown(self) -> None:
|
127
122
|
"""
|
128
123
|
Shutdown the agent and close all MCP server connections.
|
129
124
|
NOTE: This method is called automatically when the agent is used as an async context manager.
|
@@ -153,8 +148,9 @@ class Agent(MCPAggregator):
|
|
153
148
|
request.metadata = {"agent_name": self.name}
|
154
149
|
self.logger.debug("Requesting human input:", data=request)
|
155
150
|
|
156
|
-
async def call_callback_and_signal():
|
151
|
+
async def call_callback_and_signal() -> None:
|
157
152
|
try:
|
153
|
+
assert self.human_input_callback is not None
|
158
154
|
user_input = await self.human_input_callback(request)
|
159
155
|
|
160
156
|
self.logger.debug("Received human input:", data=user_input)
|
@@ -167,9 +163,7 @@ class Agent(MCPAggregator):
|
|
167
163
|
payload={"exit_requested": True, "error": str(e)},
|
168
164
|
)
|
169
165
|
except Exception as e:
|
170
|
-
await self.executor.signal(
|
171
|
-
request_id, payload=f"Error getting human input: {str(e)}"
|
172
|
-
)
|
166
|
+
await self.executor.signal(request_id, payload=f"Error getting human input: {str(e)}")
|
173
167
|
|
174
168
|
asyncio.create_task(call_callback_and_signal())
|
175
169
|
|
@@ -186,9 +180,7 @@ class Agent(MCPAggregator):
|
|
186
180
|
)
|
187
181
|
|
188
182
|
if isinstance(result, dict) and result.get("exit_requested", False):
|
189
|
-
raise PromptExitError(
|
190
|
-
result.get("error", "User requested to exit FastAgent session")
|
191
|
-
)
|
183
|
+
raise PromptExitError(result.get("error", "User requested to exit FastAgent session"))
|
192
184
|
self.logger.debug("Received human input signal", data=result)
|
193
185
|
return result
|
194
186
|
|
@@ -226,9 +218,7 @@ class Agent(MCPAggregator):
|
|
226
218
|
return result
|
227
219
|
|
228
220
|
# todo would prefer to use tool_name to disambiguate agent name
|
229
|
-
async def call_tool(
|
230
|
-
self, name: str, arguments: dict | None = None
|
231
|
-
) -> CallToolResult:
|
221
|
+
async def call_tool(self, name: str, arguments: dict | None = None) -> CallToolResult:
|
232
222
|
if name == HUMAN_INPUT_TOOL_NAME:
|
233
223
|
# Call the human input tool
|
234
224
|
return await self._call_human_input_tool(arguments)
|
@@ -240,9 +230,7 @@ class Agent(MCPAggregator):
|
|
240
230
|
else:
|
241
231
|
return await super().call_tool(name, arguments)
|
242
232
|
|
243
|
-
async def _call_human_input_tool(
|
244
|
-
self, arguments: dict | None = None
|
245
|
-
) -> CallToolResult:
|
233
|
+
async def _call_human_input_tool(self, arguments: dict | None = None) -> CallToolResult:
|
246
234
|
# Handle human input request
|
247
235
|
try:
|
248
236
|
# Make sure arguments is not None
|
@@ -264,17 +252,9 @@ class Agent(MCPAggregator):
|
|
264
252
|
result = await self.request_human_input(request=request)
|
265
253
|
|
266
254
|
# Use response attribute if available, otherwise use the result directly
|
267
|
-
response_text = (
|
268
|
-
result.response
|
269
|
-
if isinstance(result, HumanInputResponse)
|
270
|
-
else str(result)
|
271
|
-
)
|
255
|
+
response_text = result.response if isinstance(result, HumanInputResponse) else str(result)
|
272
256
|
|
273
|
-
return CallToolResult(
|
274
|
-
content=[
|
275
|
-
TextContent(type="text", text=f"Human response: {response_text}")
|
276
|
-
]
|
277
|
-
)
|
257
|
+
return CallToolResult(content=[TextContent(type="text", text=f"Human response: {response_text}")])
|
278
258
|
|
279
259
|
except PromptExitError:
|
280
260
|
raise
|
@@ -293,21 +273,10 @@ class Agent(MCPAggregator):
|
|
293
273
|
|
294
274
|
return CallToolResult(
|
295
275
|
isError=True,
|
296
|
-
content=[
|
297
|
-
TextContent(
|
298
|
-
type="text", text=f"Error requesting human input: {str(e)}"
|
299
|
-
)
|
300
|
-
],
|
276
|
+
content=[TextContent(type="text", text=f"Error requesting human input: {str(e)}")],
|
301
277
|
)
|
302
278
|
|
303
|
-
async def
|
304
|
-
self, server_name: str, resource_name: str
|
305
|
-
) -> ReadResourceResult:
|
306
|
-
return None
|
307
|
-
|
308
|
-
async def apply_prompt(
|
309
|
-
self, prompt_name: str, arguments: dict[str, str] = None
|
310
|
-
) -> str:
|
279
|
+
async def apply_prompt(self, prompt_name: str, arguments: dict[str, str] | None) -> str:
|
311
280
|
"""
|
312
281
|
Apply an MCP Server Prompt by name and return the assistant's response.
|
313
282
|
Will search all available servers for the prompt if not namespaced.
|
@@ -331,9 +300,7 @@ class Agent(MCPAggregator):
|
|
331
300
|
prompt_result = await self.get_prompt(prompt_name, arguments)
|
332
301
|
|
333
302
|
if not prompt_result or not prompt_result.messages:
|
334
|
-
error_msg =
|
335
|
-
f"Prompt '{prompt_name}' could not be found or contains no messages"
|
336
|
-
)
|
303
|
+
error_msg = f"Prompt '{prompt_name}' could not be found or contains no messages"
|
337
304
|
self.logger.warning(error_msg)
|
338
305
|
return error_msg
|
339
306
|
|
@@ -372,16 +339,10 @@ class Agent(MCPAggregator):
|
|
372
339
|
resource_result = await server.get_resource(resource_name)
|
373
340
|
return resource_result
|
374
341
|
except Exception as e:
|
375
|
-
self.logger.error(
|
376
|
-
|
377
|
-
)
|
378
|
-
raise ValueError(
|
379
|
-
f"Failed to retrieve resource '{resource_name}' from server '{server_name}': {str(e)}"
|
380
|
-
)
|
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)}")
|
381
344
|
|
382
|
-
async def get_embedded_resources(
|
383
|
-
self, server_name: str, resource_name: str
|
384
|
-
) -> List[EmbeddedResource]:
|
345
|
+
async def get_embedded_resources(self, server_name: str, resource_name: str) -> List[EmbeddedResource]:
|
385
346
|
"""
|
386
347
|
Get a resource from an MCP server and return it as a list of embedded resources ready for use in prompts.
|
387
348
|
|
@@ -396,20 +357,19 @@ class Agent(MCPAggregator):
|
|
396
357
|
ValueError: If the server doesn't exist or the resource couldn't be found
|
397
358
|
"""
|
398
359
|
# Get the raw resource result
|
399
|
-
result: ReadResourceResult = await super().get_resource(
|
400
|
-
server_name, resource_name
|
401
|
-
)
|
360
|
+
result: ReadResourceResult = await super().get_resource(server_name, resource_name)
|
402
361
|
|
403
362
|
# Convert each resource content to an EmbeddedResource
|
404
363
|
embedded_resources: List[EmbeddedResource] = []
|
405
364
|
for resource_content in result.contents:
|
406
|
-
embedded_resource = EmbeddedResource(
|
407
|
-
type="resource", resource=resource_content, annotations=None
|
408
|
-
)
|
365
|
+
embedded_resource = EmbeddedResource(type="resource", resource=resource_content, annotations=None)
|
409
366
|
embedded_resources.append(embedded_resource)
|
410
367
|
|
411
368
|
return embedded_resources
|
412
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
|
+
|
413
373
|
async def with_resource(
|
414
374
|
self,
|
415
375
|
prompt_content: Union[str, PromptMessageMultipart],
|
@@ -428,9 +388,7 @@ class Agent(MCPAggregator):
|
|
428
388
|
The agent's response as a string
|
429
389
|
"""
|
430
390
|
# Get the embedded resources
|
431
|
-
embedded_resources: List[EmbeddedResource] = await self.get_embedded_resources(
|
432
|
-
server_name, resource_name
|
433
|
-
)
|
391
|
+
embedded_resources: List[EmbeddedResource] = await self.get_embedded_resources(server_name, resource_name)
|
434
392
|
|
435
393
|
# Create or update the prompt message
|
436
394
|
prompt: PromptMessageMultipart
|
@@ -1,16 +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
|
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
|
14
16
|
|
15
17
|
R = TypeVar("R")
|
16
18
|
|
@@ -43,7 +45,7 @@ class MCPApp:
|
|
43
45
|
human_input_callback: Optional[HumanInputCallback] = console_input_callback,
|
44
46
|
signal_notification: Optional[SignalWaitCallback] = None,
|
45
47
|
upstream_session: Optional["ServerSession"] = None,
|
46
|
-
):
|
48
|
+
) -> None:
|
47
49
|
"""
|
48
50
|
Initialize the application with a name and optional settings.
|
49
51
|
Args:
|
@@ -70,9 +72,7 @@ class MCPApp:
|
|
70
72
|
@property
|
71
73
|
def context(self) -> Context:
|
72
74
|
if self._context is None:
|
73
|
-
raise RuntimeError(
|
74
|
-
"MCPApp not initialized, please call initialize() first, or use async with app.run()."
|
75
|
-
)
|
75
|
+
raise RuntimeError("MCPApp not initialized, please call initialize() first, or use async with app.run().")
|
76
76
|
return self._context
|
77
77
|
|
78
78
|
@property
|
@@ -96,7 +96,7 @@ class MCPApp:
|
|
96
96
|
return self._context.upstream_session
|
97
97
|
|
98
98
|
@upstream_session.setter
|
99
|
-
def upstream_session(self, value):
|
99
|
+
def upstream_session(self, value) -> None:
|
100
100
|
self._context.upstream_session = value
|
101
101
|
|
102
102
|
@property
|
@@ -113,7 +113,7 @@ class MCPApp:
|
|
113
113
|
self._logger = get_logger(f"mcp_agent.{self.name}")
|
114
114
|
return self._logger
|
115
115
|
|
116
|
-
async def initialize(self):
|
116
|
+
async def initialize(self) -> None:
|
117
117
|
"""Initialize the application."""
|
118
118
|
if self._initialized:
|
119
119
|
return
|
@@ -135,7 +135,7 @@ class MCPApp:
|
|
135
135
|
},
|
136
136
|
)
|
137
137
|
|
138
|
-
async def cleanup(self):
|
138
|
+
async def cleanup(self) -> None:
|
139
139
|
"""Cleanup application resources."""
|
140
140
|
if not self._initialized:
|
141
141
|
return
|
@@ -173,9 +173,7 @@ class MCPApp:
|
|
173
173
|
finally:
|
174
174
|
await self.cleanup()
|
175
175
|
|
176
|
-
def workflow(
|
177
|
-
self, cls: Type, *args, workflow_id: str | None = None, **kwargs
|
178
|
-
) -> Type:
|
176
|
+
def workflow(self, cls: Type, *args, workflow_id: str | None = None, **kwargs) -> Type:
|
179
177
|
"""
|
180
178
|
Decorator for a workflow class. By default it's a no-op,
|
181
179
|
but different executors can use this to customize behavior
|
@@ -187,9 +185,7 @@ class MCPApp:
|
|
187
185
|
"""
|
188
186
|
decorator_registry = self.context.decorator_registry
|
189
187
|
execution_engine = self.engine
|
190
|
-
workflow_defn_decorator = decorator_registry.get_workflow_defn_decorator(
|
191
|
-
execution_engine
|
192
|
-
)
|
188
|
+
workflow_defn_decorator = decorator_registry.get_workflow_defn_decorator(execution_engine)
|
193
189
|
|
194
190
|
if workflow_defn_decorator:
|
195
191
|
return workflow_defn_decorator(cls, *args, **kwargs)
|
@@ -211,9 +207,7 @@ class MCPApp:
|
|
211
207
|
|
212
208
|
decorator_registry = self.context.decorator_registry
|
213
209
|
execution_engine = self.engine
|
214
|
-
workflow_run_decorator = decorator_registry.get_workflow_run_decorator(
|
215
|
-
execution_engine
|
216
|
-
)
|
210
|
+
workflow_run_decorator = decorator_registry.get_workflow_run_decorator(execution_engine)
|
217
211
|
|
218
212
|
if workflow_run_decorator:
|
219
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()
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from pathlib import Path
|
2
|
+
|
2
3
|
import typer
|
3
|
-
from rich.prompt import Confirm
|
4
4
|
from rich.console import Console
|
5
|
+
from rich.prompt import Confirm
|
5
6
|
|
6
7
|
app = typer.Typer()
|
7
8
|
console = Console()
|
@@ -166,17 +167,13 @@ def init(
|
|
166
167
|
"-c",
|
167
168
|
help="Directory where configuration files will be created",
|
168
169
|
),
|
169
|
-
force: bool = typer.Option(
|
170
|
-
|
171
|
-
),
|
172
|
-
):
|
170
|
+
force: bool = typer.Option(False, "--force", "-f", help="Force overwrite existing files"),
|
171
|
+
) -> None:
|
173
172
|
"""Initialize a new FastAgent project with configuration files and example agent."""
|
174
173
|
|
175
174
|
config_path = Path(config_dir).resolve()
|
176
175
|
if not config_path.exists():
|
177
|
-
should_create = Confirm.ask(
|
178
|
-
f"Directory {config_path} does not exist. Create it?", default=True
|
179
|
-
)
|
176
|
+
should_create = Confirm.ask(f"Directory {config_path} does not exist. Create it?", default=True)
|
180
177
|
if should_create:
|
181
178
|
config_path.mkdir(parents=True)
|
182
179
|
else:
|
@@ -198,38 +195,26 @@ def init(
|
|
198
195
|
|
199
196
|
# Create configuration files
|
200
197
|
created = []
|
201
|
-
if create_file(
|
202
|
-
config_path / "fastagent.config.yaml", FASTAGENT_CONFIG_TEMPLATE, force
|
203
|
-
):
|
198
|
+
if create_file(config_path / "fastagent.config.yaml", FASTAGENT_CONFIG_TEMPLATE, force):
|
204
199
|
created.append("fastagent.yaml")
|
205
200
|
|
206
|
-
if create_file(
|
207
|
-
config_path / "fastagent.secrets.yaml", FASTAGENT_SECRETS_TEMPLATE, force
|
208
|
-
):
|
201
|
+
if create_file(config_path / "fastagent.secrets.yaml", FASTAGENT_SECRETS_TEMPLATE, force):
|
209
202
|
created.append("fastagent.secrets.yaml")
|
210
203
|
|
211
204
|
if create_file(config_path / "agent.py", AGENT_EXAMPLE_TEMPLATE, force):
|
212
205
|
created.append("agent.py")
|
213
206
|
|
214
207
|
# Only create .gitignore if none exists in parent directories
|
215
|
-
if needs_gitignore and create_file(
|
216
|
-
config_path / ".gitignore", GITIGNORE_TEMPLATE, force
|
217
|
-
):
|
208
|
+
if needs_gitignore and create_file(config_path / ".gitignore", GITIGNORE_TEMPLATE, force):
|
218
209
|
created.append(".gitignore")
|
219
210
|
|
220
211
|
if created:
|
221
212
|
console.print("\n[green]Setup completed successfully![/green]")
|
222
213
|
if "fastagent.secrets.yaml" in created:
|
223
214
|
console.print("\n[yellow]Important:[/yellow] Remember to:")
|
224
|
-
console.print(
|
225
|
-
|
226
|
-
)
|
227
|
-
console.print(
|
228
|
-
"2. Keep fastagent.secrets.yaml secure and never commit it to version control"
|
229
|
-
)
|
230
|
-
console.print(
|
231
|
-
"3. Update fastagent.config.yaml to set a default model (currently system default is 'haiku')"
|
232
|
-
)
|
215
|
+
console.print("1. Add your API keys to fastagent-secrets.yaml or set OPENAI_API_KEY and ANTHROPIC_API_KEY environment variables")
|
216
|
+
console.print("2. Keep fastagent.secrets.yaml secure and never commit it to version control")
|
217
|
+
console.print("3. Update fastagent.config.yaml to set a default model (currently system default is 'haiku')")
|
233
218
|
console.print("\nTo get started, run:")
|
234
219
|
console.print(" uv run agent.py")
|
235
220
|
else:
|