fast-agent-mcp 0.0.11__tar.gz → 0.0.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.
Potentially problematic release.
This version of fast-agent-mcp might be problematic. Click here for more details.
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/.gitignore +1 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/PKG-INFO +9 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/README.md +7 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/pyproject.toml +2 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/agents/agent.py +48 -8
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/commands/bootstrap.py +2 -5
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/commands/setup.py +1 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/main.py +6 -6
- fast_agent_mcp-0.0.13/src/mcp_agent/core/enhanced_prompt.py +358 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/core/exceptions.py +17 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/core/fastagent.py +108 -34
- fast_agent_mcp-0.0.13/src/mcp_agent/human_input/handler.py +78 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/mcp_connection_manager.py +14 -12
- fast_agent_mcp-0.0.13/src/mcp_agent/resources/examples/internal/agent.py +17 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/internal/job.py +1 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +1 -1
- fast_agent_mcp-0.0.13/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +53 -0
- fast_agent_mcp-0.0.13/src/mcp_agent/resources/examples/researcher/researcher-eval.py +53 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/chaining.py +5 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/evaluator.py +7 -4
- fast_agent_mcp-0.0.13/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +24 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/orchestrator.py +3 -2
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/parallel.py +2 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +31 -30
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/augmented_llm.py +8 -2
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/augmented_llm_anthropic.py +3 -1
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/augmented_llm_openai.py +20 -9
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/model_factory.py +7 -4
- fast_agent_mcp-0.0.11/src/mcp_agent/human_input/handler.py +0 -53
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/LICENSE +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/agents/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/app.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/__main__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/commands/config.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/cli/terminal.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/config.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/console.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/context.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/context_dependent.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/core/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/core/server_validation.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/eval/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/event_progress.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/decorator_registry.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/executor.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/task_registry.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/temporal.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/workflow.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/executor/workflow_signal.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/human_input/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/human_input/types.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/events.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/json_serializer.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/listeners.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/logger.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/rich_progress.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/tracing.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/logging/transport.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/gen_client.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/mcp_activity.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/mcp_agent_client_session.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/mcp_agent_server.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/mcp_aggregator.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp/stdio.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/mcp_server_registry.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/progress_display.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {fast_agent_mcp-0.0.11/src/mcp_agent/resources/examples/mcp_researcher → fast_agent_mcp-0.0.13/src/mcp_agent/resources/examples/researcher}/researcher.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/agent_build.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/telemetry/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/telemetry/usage_tracking.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/embedding/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/embedding/embedding_base.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/embedding/embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/embedding/embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/llm/llm_selector.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/orchestrator/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/orchestrator/orchestrator.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/orchestrator/orchestrator_models.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/orchestrator/orchestrator_prompts.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/parallel/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/parallel/fan_in.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/parallel/fan_out.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/parallel/parallel_llm.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/router_base.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/router_embedding.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/router_embedding_cohere.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/router_embedding_openai.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/router/router_llm.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/swarm/__init__.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/swarm/swarm.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/swarm/swarm_anthropic.py +0 -0
- {fast_agent_mcp-0.0.11 → fast_agent_mcp-0.0.13}/src/mcp_agent/workflows/swarm/swarm_openai.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fast-agent-mcp
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.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
|
|
@@ -217,6 +217,7 @@ Requires-Dist: numpy>=2.2.1
|
|
|
217
217
|
Requires-Dist: openai>=1.63.2
|
|
218
218
|
Requires-Dist: opentelemetry-distro>=0.50b0
|
|
219
219
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.29.0
|
|
220
|
+
Requires-Dist: prompt-toolkit>=3.0.50
|
|
220
221
|
Requires-Dist: pydantic-settings>=2.7.0
|
|
221
222
|
Requires-Dist: pydantic>=2.10.4
|
|
222
223
|
Requires-Dist: pyyaml>=6.0.2
|
|
@@ -268,9 +269,16 @@ Other bootstrap examples include a Researcher (with Evaluator-Optimizer workflow
|
|
|
268
269
|
|
|
269
270
|
> Windows Users - there are a couple of configuration changes needed for the Filesystem and Docker MCP Servers - necessary changes are detailed within the configuration files.
|
|
270
271
|
|
|
272
|
+
## Agent Development
|
|
273
|
+
|
|
274
|
+
FastAgent lets you interact with Agents during a workflow, enabling "warm-up" and diagnostic prompting to improve behaviour and refine prompts.
|
|
275
|
+
|
|
276
|
+
## MCP Server Development
|
|
277
|
+
|
|
271
278
|
### llmindset.co.uk fork:
|
|
272
279
|
|
|
273
280
|
- "FastAgent" style prototyping, with per-agent models
|
|
281
|
+
- Api keys through Environment Variables
|
|
274
282
|
- Warm-up / Post-Workflow Agent Interactions
|
|
275
283
|
- Quick Setup
|
|
276
284
|
- Interactive Prompt Mode
|
|
@@ -32,9 +32,16 @@ Other bootstrap examples include a Researcher (with Evaluator-Optimizer workflow
|
|
|
32
32
|
|
|
33
33
|
> Windows Users - there are a couple of configuration changes needed for the Filesystem and Docker MCP Servers - necessary changes are detailed within the configuration files.
|
|
34
34
|
|
|
35
|
+
## Agent Development
|
|
36
|
+
|
|
37
|
+
FastAgent lets you interact with Agents during a workflow, enabling "warm-up" and diagnostic prompting to improve behaviour and refine prompts.
|
|
38
|
+
|
|
39
|
+
## MCP Server Development
|
|
40
|
+
|
|
35
41
|
### llmindset.co.uk fork:
|
|
36
42
|
|
|
37
43
|
- "FastAgent" style prototyping, with per-agent models
|
|
44
|
+
- Api keys through Environment Variables
|
|
38
45
|
- Warm-up / Post-Workflow Agent Interactions
|
|
39
46
|
- Quick Setup
|
|
40
47
|
- Interactive Prompt Mode
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "fast-agent-mcp"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.13"
|
|
4
4
|
description = "Define, Prompt and Test MCP enabled Agents and Workflows"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -29,6 +29,7 @@ dependencies = [
|
|
|
29
29
|
"scikit-learn>=1.6.0",
|
|
30
30
|
"anthropic>=0.42.0",
|
|
31
31
|
"openai>=1.63.2",
|
|
32
|
+
"prompt-toolkit>=3.0.50",
|
|
32
33
|
]
|
|
33
34
|
|
|
34
35
|
[project.optional-dependencies]
|
|
@@ -11,6 +11,7 @@ from mcp.types import (
|
|
|
11
11
|
Tool,
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
+
from mcp_agent.core.exceptions import PromptExitError
|
|
14
15
|
from mcp_agent.mcp.mcp_aggregator import MCPAggregator
|
|
15
16
|
from mcp_agent.workflows.llm.augmented_llm import RequestParams
|
|
16
17
|
from mcp_agent.human_input.types import (
|
|
@@ -24,6 +25,7 @@ from mcp_agent.logging.logger import get_logger
|
|
|
24
25
|
|
|
25
26
|
if TYPE_CHECKING:
|
|
26
27
|
from mcp_agent.context import Context
|
|
28
|
+
import traceback
|
|
27
29
|
|
|
28
30
|
logger = get_logger(__name__)
|
|
29
31
|
|
|
@@ -148,10 +150,7 @@ class Agent(MCPAggregator):
|
|
|
148
150
|
"""
|
|
149
151
|
await super().close()
|
|
150
152
|
|
|
151
|
-
async def request_human_input(
|
|
152
|
-
self,
|
|
153
|
-
request: HumanInputRequest,
|
|
154
|
-
) -> str:
|
|
153
|
+
async def request_human_input(self, request: HumanInputRequest) -> str:
|
|
155
154
|
"""
|
|
156
155
|
Request input from a human user. Pauses the workflow until input is received.
|
|
157
156
|
|
|
@@ -170,14 +169,23 @@ class Agent(MCPAggregator):
|
|
|
170
169
|
# Generate a unique ID for this request to avoid signal collisions
|
|
171
170
|
request_id = f"{HUMAN_INPUT_SIGNAL_NAME}_{self.name}_{uuid.uuid4()}"
|
|
172
171
|
request.request_id = request_id
|
|
173
|
-
|
|
172
|
+
# Use metadata as a dictionary to pass agent name
|
|
173
|
+
request.metadata = {"agent_name": self.name}
|
|
174
174
|
self.logger.debug("Requesting human input:", data=request)
|
|
175
175
|
|
|
176
176
|
async def call_callback_and_signal():
|
|
177
177
|
try:
|
|
178
178
|
user_input = await self.human_input_callback(request)
|
|
179
|
+
|
|
179
180
|
self.logger.debug("Received human input:", data=user_input)
|
|
180
181
|
await self.executor.signal(signal_name=request_id, payload=user_input)
|
|
182
|
+
except PromptExitError as e:
|
|
183
|
+
# Propagate the exit error through the signal system
|
|
184
|
+
self.logger.info("User requested to exit session")
|
|
185
|
+
await self.executor.signal(
|
|
186
|
+
signal_name=request_id,
|
|
187
|
+
payload={"exit_requested": True, "error": str(e)},
|
|
188
|
+
)
|
|
181
189
|
except Exception as e:
|
|
182
190
|
await self.executor.signal(
|
|
183
191
|
request_id, payload=f"Error getting human input: {str(e)}"
|
|
@@ -197,6 +205,10 @@ class Agent(MCPAggregator):
|
|
|
197
205
|
signal_type=HumanInputResponse, # TODO: saqadri - should this be HumanInputResponse?
|
|
198
206
|
)
|
|
199
207
|
|
|
208
|
+
if isinstance(result, dict) and result.get("exit_requested", False):
|
|
209
|
+
raise PromptExitError(
|
|
210
|
+
result.get("error", "User requested to exit FastAgent session")
|
|
211
|
+
)
|
|
200
212
|
self.logger.debug("Received human input signal", data=result)
|
|
201
213
|
return result
|
|
202
214
|
|
|
@@ -253,13 +265,39 @@ class Agent(MCPAggregator):
|
|
|
253
265
|
) -> CallToolResult:
|
|
254
266
|
# Handle human input request
|
|
255
267
|
try:
|
|
256
|
-
|
|
257
|
-
|
|
268
|
+
# Make sure arguments is not None
|
|
269
|
+
if arguments is None:
|
|
270
|
+
arguments = {}
|
|
271
|
+
|
|
272
|
+
# Extract request data
|
|
273
|
+
request_data = arguments.get("request")
|
|
274
|
+
|
|
275
|
+
# Handle both string and dict request formats
|
|
276
|
+
if isinstance(request_data, str):
|
|
277
|
+
request = HumanInputRequest(prompt=request_data)
|
|
278
|
+
elif isinstance(request_data, dict):
|
|
279
|
+
request = HumanInputRequest(**request_data)
|
|
280
|
+
else:
|
|
281
|
+
# Fallback for invalid or missing request data
|
|
282
|
+
request = HumanInputRequest(prompt="Please provide input:")
|
|
283
|
+
|
|
284
|
+
result = await self.request_human_input(request=request)
|
|
285
|
+
|
|
286
|
+
# Use response attribute if available, otherwise use the result directly
|
|
287
|
+
response_text = (
|
|
288
|
+
result.response
|
|
289
|
+
if isinstance(result, HumanInputResponse)
|
|
290
|
+
else str(result)
|
|
291
|
+
)
|
|
292
|
+
|
|
258
293
|
return CallToolResult(
|
|
259
294
|
content=[
|
|
260
|
-
TextContent(type="text", text=f"Human response: {
|
|
295
|
+
TextContent(type="text", text=f"Human response: {response_text}")
|
|
261
296
|
]
|
|
262
297
|
)
|
|
298
|
+
|
|
299
|
+
except PromptExitError:
|
|
300
|
+
raise
|
|
263
301
|
except TimeoutError as e:
|
|
264
302
|
return CallToolResult(
|
|
265
303
|
isError=True,
|
|
@@ -271,6 +309,8 @@ class Agent(MCPAggregator):
|
|
|
271
309
|
],
|
|
272
310
|
)
|
|
273
311
|
except Exception as e:
|
|
312
|
+
print(f"Error in _call_human_input_tool: {traceback.format_exc()}")
|
|
313
|
+
|
|
274
314
|
return CallToolResult(
|
|
275
315
|
isError=True,
|
|
276
316
|
content=[
|
|
@@ -26,6 +26,7 @@ EXAMPLE_TYPES = {
|
|
|
26
26
|
"orchestrator.py",
|
|
27
27
|
"parallel.py",
|
|
28
28
|
"router.py",
|
|
29
|
+
"fastagent.config.yaml",
|
|
29
30
|
],
|
|
30
31
|
"create_subdir": False,
|
|
31
32
|
},
|
|
@@ -33,11 +34,7 @@ EXAMPLE_TYPES = {
|
|
|
33
34
|
"description": "Research agent example with additional evaluation/optimization\n"
|
|
34
35
|
"example. Uses Brave Search and Docker MCP Servers.\n"
|
|
35
36
|
"Creates examples in a 'researcher' subdirectory.",
|
|
36
|
-
"files": [
|
|
37
|
-
"researcher.py",
|
|
38
|
-
"researcher-eval.py",
|
|
39
|
-
"mcp_agent.secrets.yaml.example",
|
|
40
|
-
],
|
|
37
|
+
"files": ["researcher.py", "researcher-eval.py", "fastagent.config.yaml"],
|
|
41
38
|
"create_subdir": True,
|
|
42
39
|
},
|
|
43
40
|
"data-analysis": {
|
|
@@ -119,7 +119,7 @@ fast = FastAgent("FastAgent Example")
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
# Define the agent
|
|
122
|
-
@fast.agent(servers=["fetch"])
|
|
122
|
+
@fast.agent(instruction="You are a helpful AI Agent", servers=["fetch"])
|
|
123
123
|
async def main():
|
|
124
124
|
# use the --model command line switch or agent arguments to change model
|
|
125
125
|
async with fast.run() as agent:
|
|
@@ -32,7 +32,7 @@ def show_welcome():
|
|
|
32
32
|
|
|
33
33
|
table.add_row("setup", "Set up a new agent project with configuration files")
|
|
34
34
|
table.add_row(
|
|
35
|
-
"bootstrap", "Create example applications (
|
|
35
|
+
"bootstrap", "Create example applications (workflow, researcher, etc.)"
|
|
36
36
|
)
|
|
37
37
|
# table.add_row("config", "Manage agent configuration settings")
|
|
38
38
|
|
|
@@ -40,11 +40,11 @@ def show_welcome():
|
|
|
40
40
|
|
|
41
41
|
console.print("\n[bold]Getting Started:[/bold]")
|
|
42
42
|
console.print("1. Set up a new project:")
|
|
43
|
-
console.print("
|
|
44
|
-
console.print("\n2. Try an example:")
|
|
45
|
-
console.print("
|
|
43
|
+
console.print(" fastagent setup")
|
|
44
|
+
console.print("\n2. Try an example workflow:")
|
|
45
|
+
console.print(" fastagent bootstrap create workflow")
|
|
46
46
|
console.print("\nUse --help with any command for more information")
|
|
47
|
-
console.print("Example:
|
|
47
|
+
console.print("Example: fastagent bootstrap --help")
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
@app.callback(invoke_without_command=True)
|
|
@@ -56,7 +56,7 @@ def main(
|
|
|
56
56
|
True, "--color/--no-color", help="Enable/disable color output"
|
|
57
57
|
),
|
|
58
58
|
):
|
|
59
|
-
"""
|
|
59
|
+
"""FastAgent CLI - Build effective agents using Model Context Protocol (MCP).
|
|
60
60
|
|
|
61
61
|
Use --help with any command for detailed usage information.
|
|
62
62
|
"""
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enhanced prompt functionality with advanced prompt_toolkit features.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
from prompt_toolkit import PromptSession
|
|
7
|
+
from prompt_toolkit.formatted_text import HTML
|
|
8
|
+
from prompt_toolkit.history import InMemoryHistory
|
|
9
|
+
from prompt_toolkit.key_binding import KeyBindings
|
|
10
|
+
from prompt_toolkit.completion import Completer, Completion
|
|
11
|
+
from prompt_toolkit.lexers import PygmentsLexer
|
|
12
|
+
from prompt_toolkit.filters import Condition
|
|
13
|
+
from pygments.lexers.python import PythonLexer
|
|
14
|
+
from rich import print as rich_print
|
|
15
|
+
|
|
16
|
+
from mcp_agent.core.exceptions import PromptExitError
|
|
17
|
+
|
|
18
|
+
# Map of agent names to their history
|
|
19
|
+
agent_histories = {}
|
|
20
|
+
|
|
21
|
+
# Store available agents for auto-completion
|
|
22
|
+
available_agents = set()
|
|
23
|
+
|
|
24
|
+
# Keep track of multi-line mode state
|
|
25
|
+
in_multiline_mode = False
|
|
26
|
+
|
|
27
|
+
# Track which agents have already shown welcome messages
|
|
28
|
+
agent_messages_shown = set()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AgentCompleter(Completer):
|
|
32
|
+
"""Provide completion for agent names and common commands."""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self,
|
|
36
|
+
agents: List[str],
|
|
37
|
+
commands: List[str] = None,
|
|
38
|
+
agent_types: dict = None,
|
|
39
|
+
is_human_input: bool = False,
|
|
40
|
+
):
|
|
41
|
+
self.agents = agents
|
|
42
|
+
# Map commands to their descriptions for better completion hints
|
|
43
|
+
self.commands = {
|
|
44
|
+
"help": "Show available commands",
|
|
45
|
+
"clear": "Clear the screen",
|
|
46
|
+
"agents": "List available agents",
|
|
47
|
+
"STOP": "Stop this prompting session and move to next workflow step",
|
|
48
|
+
"EXIT": "Exit FastAgent, terminating any running workflows",
|
|
49
|
+
**(commands or {}), # Allow custom commands to be passed in
|
|
50
|
+
}
|
|
51
|
+
if is_human_input:
|
|
52
|
+
self.commands.pop("agents")
|
|
53
|
+
self.agent_types = agent_types or {}
|
|
54
|
+
|
|
55
|
+
def get_completions(self, document, complete_event):
|
|
56
|
+
"""Synchronous completions method - this is what prompt_toolkit expects by default"""
|
|
57
|
+
text = document.text_before_cursor.lower()
|
|
58
|
+
|
|
59
|
+
# Complete commands
|
|
60
|
+
if text.startswith("/"):
|
|
61
|
+
cmd = text[1:]
|
|
62
|
+
for command, description in self.commands.items():
|
|
63
|
+
if command.lower().startswith(cmd):
|
|
64
|
+
yield Completion(
|
|
65
|
+
command,
|
|
66
|
+
start_position=-len(cmd),
|
|
67
|
+
display=command,
|
|
68
|
+
display_meta=description,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# Complete agent names for agent-related commands
|
|
72
|
+
elif text.startswith("@"):
|
|
73
|
+
agent_name = text[1:]
|
|
74
|
+
for agent in self.agents:
|
|
75
|
+
if agent.lower().startswith(agent_name.lower()):
|
|
76
|
+
# Get agent type or default to "Agent"
|
|
77
|
+
agent_type = self.agent_types.get(agent, "Agent")
|
|
78
|
+
yield Completion(
|
|
79
|
+
agent,
|
|
80
|
+
start_position=-len(agent_name),
|
|
81
|
+
display=agent,
|
|
82
|
+
display_meta=agent_type,
|
|
83
|
+
style="bg:ansiblack fg:ansiblue",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def create_keybindings(on_toggle_multiline=None, app=None):
|
|
88
|
+
"""Create custom key bindings."""
|
|
89
|
+
kb = KeyBindings()
|
|
90
|
+
|
|
91
|
+
@kb.add("c-m", filter=Condition(lambda: not in_multiline_mode))
|
|
92
|
+
def _(event):
|
|
93
|
+
"""Enter: accept input when not in multiline mode."""
|
|
94
|
+
event.current_buffer.validate_and_handle()
|
|
95
|
+
|
|
96
|
+
@kb.add("c-m", filter=Condition(lambda: in_multiline_mode))
|
|
97
|
+
def _(event):
|
|
98
|
+
"""Enter: insert newline when in multiline mode."""
|
|
99
|
+
event.current_buffer.insert_text("\n")
|
|
100
|
+
|
|
101
|
+
# Use c-j (Ctrl+J) as an alternative to represent Ctrl+Enter in multiline mode
|
|
102
|
+
@kb.add("c-j", filter=Condition(lambda: in_multiline_mode))
|
|
103
|
+
def _(event):
|
|
104
|
+
"""Ctrl+J (equivalent to Ctrl+Enter): Submit in multiline mode."""
|
|
105
|
+
event.current_buffer.validate_and_handle()
|
|
106
|
+
|
|
107
|
+
@kb.add("c-t")
|
|
108
|
+
def _(event):
|
|
109
|
+
"""Ctrl+T: Toggle multiline mode."""
|
|
110
|
+
global in_multiline_mode
|
|
111
|
+
in_multiline_mode = not in_multiline_mode
|
|
112
|
+
|
|
113
|
+
# Force redraw the app to update toolbar
|
|
114
|
+
if event.app:
|
|
115
|
+
event.app.invalidate()
|
|
116
|
+
elif app:
|
|
117
|
+
app.invalidate()
|
|
118
|
+
|
|
119
|
+
# Call the toggle callback if provided
|
|
120
|
+
if on_toggle_multiline:
|
|
121
|
+
on_toggle_multiline(in_multiline_mode)
|
|
122
|
+
|
|
123
|
+
# Instead of printing, we'll just update the toolbar
|
|
124
|
+
# The toolbar will show the current mode
|
|
125
|
+
|
|
126
|
+
@kb.add("c-l")
|
|
127
|
+
def _(event):
|
|
128
|
+
"""Ctrl+L: Clear the input buffer."""
|
|
129
|
+
event.current_buffer.text = ""
|
|
130
|
+
|
|
131
|
+
return kb
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
async def get_enhanced_input(
|
|
135
|
+
agent_name: str,
|
|
136
|
+
default: str = "",
|
|
137
|
+
show_default: bool = False,
|
|
138
|
+
show_stop_hint: bool = False,
|
|
139
|
+
multiline: bool = False,
|
|
140
|
+
available_agent_names: List[str] = None,
|
|
141
|
+
syntax: str = None,
|
|
142
|
+
agent_types: dict = None,
|
|
143
|
+
is_human_input: bool = False,
|
|
144
|
+
toolbar_color: str = "ansiblue",
|
|
145
|
+
) -> str:
|
|
146
|
+
"""
|
|
147
|
+
Enhanced input with advanced prompt_toolkit features.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
agent_name: Name of the agent (used for prompt and history)
|
|
151
|
+
default: Default value if user presses enter
|
|
152
|
+
show_default: Whether to show the default value in the prompt
|
|
153
|
+
show_stop_hint: Whether to show the STOP hint
|
|
154
|
+
multiline: Start in multiline mode
|
|
155
|
+
available_agent_names: List of agent names for auto-completion
|
|
156
|
+
syntax: Syntax highlighting (e.g., 'python', 'sql')
|
|
157
|
+
agent_types: Dictionary mapping agent names to their types for display
|
|
158
|
+
is_human_input: Whether this is a human input request (disables agent selection features)
|
|
159
|
+
toolbar_color: Color to use for the agent name in the toolbar (default: "ansiblue")
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
User input string
|
|
163
|
+
"""
|
|
164
|
+
global in_multiline_mode, available_agents
|
|
165
|
+
|
|
166
|
+
# Update global state
|
|
167
|
+
in_multiline_mode = multiline
|
|
168
|
+
if available_agent_names:
|
|
169
|
+
available_agents = set(available_agent_names)
|
|
170
|
+
|
|
171
|
+
# Get or create history object for this agent
|
|
172
|
+
if agent_name not in agent_histories:
|
|
173
|
+
agent_histories[agent_name] = InMemoryHistory()
|
|
174
|
+
|
|
175
|
+
# Define callback for multiline toggle
|
|
176
|
+
def on_multiline_toggle(enabled):
|
|
177
|
+
nonlocal session
|
|
178
|
+
if hasattr(session, "app") and session.app:
|
|
179
|
+
session.app.invalidate()
|
|
180
|
+
|
|
181
|
+
# Define toolbar function that will update dynamically
|
|
182
|
+
def get_toolbar():
|
|
183
|
+
if in_multiline_mode:
|
|
184
|
+
mode_style = "ansired" # More noticeable for multiline mode
|
|
185
|
+
mode_text = "MULTILINE"
|
|
186
|
+
toggle_text = "Normal Editing"
|
|
187
|
+
else:
|
|
188
|
+
mode_style = "ansigreen"
|
|
189
|
+
mode_text = "NORMAL"
|
|
190
|
+
toggle_text = "Multiline Editing"
|
|
191
|
+
|
|
192
|
+
shortcuts = [
|
|
193
|
+
("Ctrl+T", toggle_text),
|
|
194
|
+
("Ctrl+L", "Clear"),
|
|
195
|
+
("↑/↓", "History"),
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
newline = (
|
|
199
|
+
"Ctrl+<Enter>:Submit" if in_multiline_mode else "<Enter>:Submit"
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Only show relevant shortcuts based on mode
|
|
203
|
+
shortcuts = [(k, v) for k, v in shortcuts if v]
|
|
204
|
+
|
|
205
|
+
shortcut_text = " | ".join(f"{key}:{action}" for key, action in shortcuts)
|
|
206
|
+
return HTML(
|
|
207
|
+
f" <{toolbar_color}> {agent_name} </{toolbar_color}> | <b>Mode:</b> <{mode_style}> {mode_text} </{mode_style}> {newline} | {shortcut_text}"
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# Create session with history and completions
|
|
211
|
+
session = PromptSession(
|
|
212
|
+
history=agent_histories[agent_name],
|
|
213
|
+
completer=AgentCompleter(
|
|
214
|
+
agents=list(available_agents) if available_agents else [],
|
|
215
|
+
agent_types=agent_types or {},
|
|
216
|
+
is_human_input=is_human_input,
|
|
217
|
+
),
|
|
218
|
+
complete_while_typing=True,
|
|
219
|
+
lexer=PygmentsLexer(PythonLexer) if syntax == "python" else None,
|
|
220
|
+
multiline=Condition(lambda: in_multiline_mode),
|
|
221
|
+
complete_in_thread=True,
|
|
222
|
+
mouse_support=False,
|
|
223
|
+
bottom_toolbar=get_toolbar, # Pass the function here
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Create key bindings with a reference to the app
|
|
227
|
+
bindings = create_keybindings(
|
|
228
|
+
on_toggle_multiline=on_multiline_toggle, app=session.app
|
|
229
|
+
)
|
|
230
|
+
session.app.key_bindings = bindings
|
|
231
|
+
|
|
232
|
+
# Create formatted prompt text
|
|
233
|
+
prompt_text = f"<ansicyan>{agent_name}</ansicyan> > "
|
|
234
|
+
|
|
235
|
+
# Add default value display if requested
|
|
236
|
+
if show_default and default and default != "STOP":
|
|
237
|
+
prompt_text = f"{prompt_text} [<ansigreen>{default}</ansigreen>] "
|
|
238
|
+
|
|
239
|
+
# Only show hints at startup if requested
|
|
240
|
+
if show_stop_hint:
|
|
241
|
+
if default == "STOP":
|
|
242
|
+
rich_print("[yellow]Press <ENTER> to finish.[/yellow]")
|
|
243
|
+
else:
|
|
244
|
+
rich_print("Enter a prompt, or [red]STOP[/red] to finish")
|
|
245
|
+
if default:
|
|
246
|
+
rich_print(
|
|
247
|
+
f"Press <ENTER> to use the default prompt:\n[cyan]{default}[/cyan]"
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
# Mention available features but only on first usage for this agent
|
|
251
|
+
if agent_name not in agent_messages_shown:
|
|
252
|
+
if is_human_input:
|
|
253
|
+
rich_print(
|
|
254
|
+
"[dim]Tip: Type /help for commands. Ctrl+T toggles multiline mode. Ctrl+Enter to submit in multiline mode.[/dim]"
|
|
255
|
+
)
|
|
256
|
+
else:
|
|
257
|
+
rich_print(
|
|
258
|
+
"[dim]Tip: Type /help for commands, @Agent to switch agent. Ctrl+T toggles multiline mode. [/dim]"
|
|
259
|
+
)
|
|
260
|
+
agent_messages_shown.add(agent_name)
|
|
261
|
+
|
|
262
|
+
# Process special commands
|
|
263
|
+
def pre_process_input(text):
|
|
264
|
+
# Command processing
|
|
265
|
+
if text and text.startswith("/"):
|
|
266
|
+
cmd = text[1:].strip().lower()
|
|
267
|
+
if cmd == "help":
|
|
268
|
+
return "HELP"
|
|
269
|
+
elif cmd == "clear":
|
|
270
|
+
return "CLEAR"
|
|
271
|
+
elif cmd == "agents":
|
|
272
|
+
return "LIST_AGENTS"
|
|
273
|
+
elif cmd == "exit":
|
|
274
|
+
return "EXIT"
|
|
275
|
+
elif cmd == "stop":
|
|
276
|
+
return "STOP"
|
|
277
|
+
|
|
278
|
+
# Agent switching
|
|
279
|
+
if text and text.startswith("@"):
|
|
280
|
+
return f"SWITCH:{text[1:].strip()}"
|
|
281
|
+
|
|
282
|
+
return text
|
|
283
|
+
|
|
284
|
+
# Get the input - using async version
|
|
285
|
+
try:
|
|
286
|
+
result = await session.prompt_async(HTML(prompt_text), default=default)
|
|
287
|
+
return pre_process_input(result)
|
|
288
|
+
except KeyboardInterrupt:
|
|
289
|
+
# Handle Ctrl+C gracefully
|
|
290
|
+
return "STOP"
|
|
291
|
+
except EOFError:
|
|
292
|
+
# Handle Ctrl+D gracefully
|
|
293
|
+
return "STOP"
|
|
294
|
+
except Exception as e:
|
|
295
|
+
# Log and gracefully handle other exceptions
|
|
296
|
+
print(f"\nInput error: {type(e).__name__}: {e}")
|
|
297
|
+
return "STOP"
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
async def handle_special_commands(command, agent_app=None):
|
|
301
|
+
"""Handle special input commands."""
|
|
302
|
+
# Quick guard for empty or None commands
|
|
303
|
+
if not command:
|
|
304
|
+
return False
|
|
305
|
+
|
|
306
|
+
# Check for special commands
|
|
307
|
+
if command == "HELP":
|
|
308
|
+
rich_print("\n[bold]Available Commands:[/bold]")
|
|
309
|
+
rich_print(" /help - Show this help")
|
|
310
|
+
rich_print(" /clear - Clear screen")
|
|
311
|
+
rich_print(" /agents - List available agents")
|
|
312
|
+
rich_print(" @agent_name - Switch to agent")
|
|
313
|
+
rich_print(" STOP - Return control back to the workflow")
|
|
314
|
+
rich_print(
|
|
315
|
+
" EXIT - Exit FastAgent, terminating any running workflows"
|
|
316
|
+
)
|
|
317
|
+
rich_print("\n[bold]Keyboard Shortcuts:[/bold]")
|
|
318
|
+
rich_print(
|
|
319
|
+
" Enter - Submit (normal mode) / New line (multiline mode)"
|
|
320
|
+
)
|
|
321
|
+
rich_print(" Ctrl+Enter - Always submit (even in multiline mode)")
|
|
322
|
+
rich_print(" Ctrl+T - Toggle multiline mode")
|
|
323
|
+
rich_print(" Ctrl+L - Clear input")
|
|
324
|
+
rich_print(" Up/Down - Navigate history")
|
|
325
|
+
return True
|
|
326
|
+
|
|
327
|
+
elif command == "CLEAR":
|
|
328
|
+
# Clear screen (ANSI escape sequence)
|
|
329
|
+
print("\033c", end="")
|
|
330
|
+
return True
|
|
331
|
+
|
|
332
|
+
elif command == "EXIT":
|
|
333
|
+
raise PromptExitError("User requested to exit FastAgent session")
|
|
334
|
+
|
|
335
|
+
elif command == "LIST_AGENTS":
|
|
336
|
+
if available_agents:
|
|
337
|
+
rich_print("\n[bold]Available Agents:[/bold]")
|
|
338
|
+
for agent in sorted(available_agents):
|
|
339
|
+
rich_print(f" @{agent}")
|
|
340
|
+
else:
|
|
341
|
+
rich_print("[yellow]No agents available[/yellow]")
|
|
342
|
+
return True
|
|
343
|
+
|
|
344
|
+
elif isinstance(command, str) and command.startswith("SWITCH:"):
|
|
345
|
+
agent_name = command.split(":", 1)[1]
|
|
346
|
+
if agent_name in available_agents:
|
|
347
|
+
if agent_app:
|
|
348
|
+
rich_print(f"[green]Switching to agent: {agent_name}[/green]")
|
|
349
|
+
return {"switch_agent": agent_name}
|
|
350
|
+
else:
|
|
351
|
+
rich_print(
|
|
352
|
+
"[yellow]Agent switching not available in this context[/yellow]"
|
|
353
|
+
)
|
|
354
|
+
else:
|
|
355
|
+
rich_print(f"[red]Unknown agent: {agent_name}[/red]")
|
|
356
|
+
return True
|
|
357
|
+
|
|
358
|
+
return False
|
|
@@ -45,3 +45,20 @@ class ServerInitializationError(FastAgentError):
|
|
|
45
45
|
|
|
46
46
|
def __init__(self, message: str, details: str = ""):
|
|
47
47
|
super().__init__(message, details)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ModelConfigError(FastAgentError):
|
|
51
|
+
"""Raised when there are issues with LLM model configuration
|
|
52
|
+
Example: Unknown model name in model specification string
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, message: str, details: str = ""):
|
|
56
|
+
super().__init__(message, details)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class PromptExitError(FastAgentError):
|
|
60
|
+
"""Raised from enhanced_prompt when the user requests hard exits"""
|
|
61
|
+
|
|
62
|
+
# TODO an exception for flow control :(
|
|
63
|
+
def __init__(self, message: str, details: str = ""):
|
|
64
|
+
super().__init__(message, details)
|