fast-agent-mcp 0.2.58__py3-none-any.whl → 0.3.0__py3-none-any.whl
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/__init__.py +127 -0
- fast_agent/agents/__init__.py +36 -0
- {mcp_agent/core → fast_agent/agents}/agent_types.py +2 -1
- fast_agent/agents/llm_agent.py +217 -0
- fast_agent/agents/llm_decorator.py +486 -0
- mcp_agent/agents/base_agent.py → fast_agent/agents/mcp_agent.py +377 -385
- fast_agent/agents/tool_agent.py +168 -0
- {mcp_agent → fast_agent}/agents/workflow/chain_agent.py +43 -33
- {mcp_agent → fast_agent}/agents/workflow/evaluator_optimizer.py +31 -35
- {mcp_agent → fast_agent}/agents/workflow/iterative_planner.py +56 -47
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_models.py +4 -4
- {mcp_agent → fast_agent}/agents/workflow/parallel_agent.py +34 -41
- {mcp_agent → fast_agent}/agents/workflow/router_agent.py +54 -39
- {mcp_agent → fast_agent}/cli/__main__.py +5 -3
- {mcp_agent → fast_agent}/cli/commands/check_config.py +95 -66
- {mcp_agent → fast_agent}/cli/commands/go.py +20 -11
- {mcp_agent → fast_agent}/cli/commands/quickstart.py +4 -4
- {mcp_agent → fast_agent}/cli/commands/server_helpers.py +1 -1
- {mcp_agent → fast_agent}/cli/commands/setup.py +64 -134
- {mcp_agent → fast_agent}/cli/commands/url_parser.py +9 -8
- {mcp_agent → fast_agent}/cli/main.py +36 -16
- {mcp_agent → fast_agent}/cli/terminal.py +2 -2
- {mcp_agent → fast_agent}/config.py +10 -2
- fast_agent/constants.py +8 -0
- {mcp_agent → fast_agent}/context.py +24 -19
- {mcp_agent → fast_agent}/context_dependent.py +9 -5
- fast_agent/core/__init__.py +17 -0
- {mcp_agent → fast_agent}/core/agent_app.py +39 -36
- fast_agent/core/core_app.py +135 -0
- {mcp_agent → fast_agent}/core/direct_decorators.py +12 -26
- {mcp_agent → fast_agent}/core/direct_factory.py +95 -73
- {mcp_agent → fast_agent/core}/executor/executor.py +4 -5
- {mcp_agent → fast_agent}/core/fastagent.py +32 -32
- fast_agent/core/logging/__init__.py +5 -0
- {mcp_agent → fast_agent/core}/logging/events.py +3 -3
- {mcp_agent → fast_agent/core}/logging/json_serializer.py +1 -1
- {mcp_agent → fast_agent/core}/logging/listeners.py +85 -7
- {mcp_agent → fast_agent/core}/logging/logger.py +7 -7
- {mcp_agent → fast_agent/core}/logging/transport.py +10 -11
- fast_agent/core/prompt.py +9 -0
- {mcp_agent → fast_agent}/core/validation.py +4 -4
- fast_agent/event_progress.py +61 -0
- fast_agent/history/history_exporter.py +44 -0
- {mcp_agent → fast_agent}/human_input/__init__.py +9 -12
- {mcp_agent → fast_agent}/human_input/elicitation_handler.py +26 -8
- {mcp_agent → fast_agent}/human_input/elicitation_state.py +7 -7
- {mcp_agent → fast_agent}/human_input/simple_form.py +6 -4
- {mcp_agent → fast_agent}/human_input/types.py +1 -18
- fast_agent/interfaces.py +228 -0
- fast_agent/llm/__init__.py +9 -0
- mcp_agent/llm/augmented_llm.py → fast_agent/llm/fastagent_llm.py +127 -218
- fast_agent/llm/internal/passthrough.py +137 -0
- mcp_agent/llm/augmented_llm_playback.py → fast_agent/llm/internal/playback.py +29 -25
- mcp_agent/llm/augmented_llm_silent.py → fast_agent/llm/internal/silent.py +10 -17
- fast_agent/llm/internal/slow.py +38 -0
- {mcp_agent → fast_agent}/llm/memory.py +40 -30
- {mcp_agent → fast_agent}/llm/model_database.py +35 -2
- {mcp_agent → fast_agent}/llm/model_factory.py +103 -77
- fast_agent/llm/model_info.py +126 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/anthropic_utils.py +7 -7
- fast_agent/llm/provider/anthropic/llm_anthropic.py +603 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/multipart_converter_anthropic.py +79 -86
- {mcp_agent/llm/providers → fast_agent/llm/provider/bedrock}/bedrock_utils.py +3 -1
- mcp_agent/llm/providers/augmented_llm_bedrock.py → fast_agent/llm/provider/bedrock/llm_bedrock.py +833 -717
- {mcp_agent/llm/providers → fast_agent/llm/provider/google}/google_converter.py +66 -14
- fast_agent/llm/provider/google/llm_google_native.py +431 -0
- mcp_agent/llm/providers/augmented_llm_aliyun.py → fast_agent/llm/provider/openai/llm_aliyun.py +6 -7
- mcp_agent/llm/providers/augmented_llm_azure.py → fast_agent/llm/provider/openai/llm_azure.py +4 -4
- mcp_agent/llm/providers/augmented_llm_deepseek.py → fast_agent/llm/provider/openai/llm_deepseek.py +10 -11
- mcp_agent/llm/providers/augmented_llm_generic.py → fast_agent/llm/provider/openai/llm_generic.py +4 -4
- mcp_agent/llm/providers/augmented_llm_google_oai.py → fast_agent/llm/provider/openai/llm_google_oai.py +4 -4
- mcp_agent/llm/providers/augmented_llm_groq.py → fast_agent/llm/provider/openai/llm_groq.py +14 -16
- mcp_agent/llm/providers/augmented_llm_openai.py → fast_agent/llm/provider/openai/llm_openai.py +133 -207
- mcp_agent/llm/providers/augmented_llm_openrouter.py → fast_agent/llm/provider/openai/llm_openrouter.py +6 -6
- mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py → fast_agent/llm/provider/openai/llm_tensorzero_openai.py +17 -16
- mcp_agent/llm/providers/augmented_llm_xai.py → fast_agent/llm/provider/openai/llm_xai.py +6 -6
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/multipart_converter_openai.py +125 -63
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_multipart.py +12 -12
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_utils.py +18 -16
- {mcp_agent → fast_agent}/llm/provider_key_manager.py +2 -2
- {mcp_agent → fast_agent}/llm/provider_types.py +2 -0
- {mcp_agent → fast_agent}/llm/sampling_converter.py +15 -12
- {mcp_agent → fast_agent}/llm/usage_tracking.py +23 -5
- fast_agent/mcp/__init__.py +43 -0
- {mcp_agent → fast_agent}/mcp/elicitation_factory.py +3 -3
- {mcp_agent → fast_agent}/mcp/elicitation_handlers.py +19 -10
- {mcp_agent → fast_agent}/mcp/gen_client.py +3 -3
- fast_agent/mcp/helpers/__init__.py +36 -0
- fast_agent/mcp/helpers/content_helpers.py +183 -0
- {mcp_agent → fast_agent}/mcp/helpers/server_config_helpers.py +8 -8
- {mcp_agent → fast_agent}/mcp/hf_auth.py +25 -23
- fast_agent/mcp/interfaces.py +93 -0
- {mcp_agent → fast_agent}/mcp/logger_textio.py +4 -4
- {mcp_agent → fast_agent}/mcp/mcp_agent_client_session.py +49 -44
- {mcp_agent → fast_agent}/mcp/mcp_aggregator.py +66 -115
- {mcp_agent → fast_agent}/mcp/mcp_connection_manager.py +16 -23
- {mcp_agent/core → fast_agent/mcp}/mcp_content.py +23 -15
- {mcp_agent → fast_agent}/mcp/mime_utils.py +39 -0
- fast_agent/mcp/prompt.py +159 -0
- mcp_agent/mcp/prompt_message_multipart.py → fast_agent/mcp/prompt_message_extended.py +27 -20
- {mcp_agent → fast_agent}/mcp/prompt_render.py +21 -19
- {mcp_agent → fast_agent}/mcp/prompt_serialization.py +46 -46
- fast_agent/mcp/prompts/__main__.py +7 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_helpers.py +31 -30
- {mcp_agent → fast_agent}/mcp/prompts/prompt_load.py +8 -8
- {mcp_agent → fast_agent}/mcp/prompts/prompt_server.py +11 -19
- {mcp_agent → fast_agent}/mcp/prompts/prompt_template.py +18 -18
- {mcp_agent → fast_agent}/mcp/resource_utils.py +1 -1
- {mcp_agent → fast_agent}/mcp/sampling.py +31 -26
- {mcp_agent/mcp_server → fast_agent/mcp/server}/__init__.py +1 -1
- {mcp_agent/mcp_server → fast_agent/mcp/server}/agent_server.py +5 -6
- fast_agent/mcp/ui_agent.py +48 -0
- fast_agent/mcp/ui_mixin.py +209 -0
- fast_agent/mcp_server_registry.py +90 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis-campaign.py +5 -4
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/forms_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character_handler.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/tool_call.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_one.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_two.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-eval.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-imp.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/tensorzero/agent.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/tensorzero/image_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/tensorzero/simple_agent.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/chaining.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/evaluator.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/human_input.py +5 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/orchestrator.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/parallel.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/workflows/router.py +5 -2
- fast_agent/resources/setup/.gitignore +24 -0
- fast_agent/resources/setup/agent.py +18 -0
- fast_agent/resources/setup/fastagent.config.yaml +44 -0
- fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
- fast_agent/tools/elicitation.py +369 -0
- fast_agent/types/__init__.py +32 -0
- fast_agent/types/llm_stop_reason.py +77 -0
- fast_agent/ui/__init__.py +38 -0
- fast_agent/ui/console_display.py +1005 -0
- {mcp_agent/human_input → fast_agent/ui}/elicitation_form.py +17 -12
- mcp_agent/human_input/elicitation_forms.py → fast_agent/ui/elicitation_style.py +1 -1
- {mcp_agent/core → fast_agent/ui}/enhanced_prompt.py +96 -25
- {mcp_agent/core → fast_agent/ui}/interactive_prompt.py +330 -125
- fast_agent/ui/mcp_ui_utils.py +224 -0
- {mcp_agent → fast_agent/ui}/progress_display.py +2 -2
- {mcp_agent/logging → fast_agent/ui}/rich_progress.py +4 -4
- {mcp_agent/core → fast_agent/ui}/usage_display.py +3 -8
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.0.dist-info}/METADATA +7 -7
- fast_agent_mcp-0.3.0.dist-info/RECORD +202 -0
- fast_agent_mcp-0.3.0.dist-info/entry_points.txt +5 -0
- fast_agent_mcp-0.2.58.dist-info/RECORD +0 -193
- fast_agent_mcp-0.2.58.dist-info/entry_points.txt +0 -6
- mcp_agent/__init__.py +0 -114
- mcp_agent/agents/agent.py +0 -92
- mcp_agent/agents/workflow/__init__.py +0 -1
- mcp_agent/agents/workflow/orchestrator_agent.py +0 -597
- mcp_agent/app.py +0 -175
- mcp_agent/core/__init__.py +0 -26
- mcp_agent/core/prompt.py +0 -191
- mcp_agent/event_progress.py +0 -134
- mcp_agent/human_input/handler.py +0 -81
- mcp_agent/llm/__init__.py +0 -2
- mcp_agent/llm/augmented_llm_passthrough.py +0 -232
- mcp_agent/llm/augmented_llm_slow.py +0 -53
- mcp_agent/llm/providers/__init__.py +0 -8
- mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -718
- mcp_agent/llm/providers/augmented_llm_google_native.py +0 -496
- mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -57
- mcp_agent/llm/providers/sampling_converter_openai.py +0 -26
- mcp_agent/llm/sampling_format_converter.py +0 -37
- mcp_agent/logging/__init__.py +0 -0
- mcp_agent/mcp/__init__.py +0 -50
- mcp_agent/mcp/helpers/__init__.py +0 -25
- mcp_agent/mcp/helpers/content_helpers.py +0 -187
- mcp_agent/mcp/interfaces.py +0 -266
- mcp_agent/mcp/prompts/__init__.py +0 -0
- mcp_agent/mcp/prompts/__main__.py +0 -10
- mcp_agent/mcp_server_registry.py +0 -343
- mcp_agent/tools/tool_definition.py +0 -14
- mcp_agent/ui/console_display.py +0 -790
- mcp_agent/ui/console_display_legacy.py +0 -401
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_prompts.py +0 -0
- {mcp_agent/agents → fast_agent/cli}/__init__.py +0 -0
- {mcp_agent → fast_agent}/cli/constants.py +0 -0
- {mcp_agent → fast_agent}/core/error_handling.py +0 -0
- {mcp_agent → fast_agent}/core/exceptions.py +0 -0
- {mcp_agent/cli → fast_agent/core/executor}/__init__.py +0 -0
- {mcp_agent → fast_agent/core}/executor/task_registry.py +0 -0
- {mcp_agent → fast_agent/core}/executor/workflow_signal.py +0 -0
- {mcp_agent → fast_agent}/human_input/form_fields.py +0 -0
- {mcp_agent → fast_agent}/llm/prompt_utils.py +0 -0
- {mcp_agent/core → fast_agent/llm}/request_params.py +0 -0
- {mcp_agent → fast_agent}/mcp/common.py +0 -0
- {mcp_agent/executor → fast_agent/mcp/prompts}/__init__.py +0 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_constants.py +0 -0
- {mcp_agent → fast_agent}/py.typed +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_account_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_forms_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_game_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/researcher/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/.env.sample +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/Makefile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/README.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/crab.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/docker-compose.yml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/Dockerfile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/entrypoint.sh +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/mcp_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/pyproject.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_schema.json +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/graded_report.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.txt +0 -0
- {mcp_agent → fast_agent/ui}/console.py +0 -0
- {mcp_agent/core → fast_agent/ui}/mermaid_utils.py +0 -0
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,10 +6,88 @@ import asyncio
|
|
|
6
6
|
import logging
|
|
7
7
|
import time
|
|
8
8
|
from abc import ABC, abstractmethod
|
|
9
|
-
from typing import Dict, List
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
from
|
|
9
|
+
from typing import TYPE_CHECKING, Dict, List
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from fast_agent.event_progress import ProgressEvent
|
|
13
|
+
|
|
14
|
+
from fast_agent.core.logging.events import Event, EventFilter, EventType
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def convert_log_event(event: Event) -> "ProgressEvent | None":
|
|
18
|
+
"""Convert a log event to a progress event if applicable."""
|
|
19
|
+
|
|
20
|
+
# Import at runtime to avoid circular imports
|
|
21
|
+
from fast_agent.event_progress import ProgressAction, ProgressEvent
|
|
22
|
+
|
|
23
|
+
# Check to see if there is any additional data
|
|
24
|
+
if not event.data:
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
event_data = event.data.get("data")
|
|
28
|
+
if not isinstance(event_data, dict):
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
progress_action = event_data.get("progress_action")
|
|
32
|
+
if not progress_action:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
# Build target string based on the event type.
|
|
36
|
+
# Progress display is currently [time] [event] --- [target] [details]
|
|
37
|
+
namespace = event.namespace
|
|
38
|
+
agent_name = event_data.get("agent_name")
|
|
39
|
+
target = agent_name
|
|
40
|
+
details = ""
|
|
41
|
+
if progress_action == ProgressAction.FATAL_ERROR:
|
|
42
|
+
details = event_data.get("error_message", "An error occurred")
|
|
43
|
+
elif "mcp_aggregator" in namespace:
|
|
44
|
+
server_name = event_data.get("server_name", "")
|
|
45
|
+
tool_name = event_data.get("tool_name")
|
|
46
|
+
if tool_name:
|
|
47
|
+
# fetch(fetch)
|
|
48
|
+
details = f"{server_name} ({tool_name})"
|
|
49
|
+
else:
|
|
50
|
+
details = f"{server_name}"
|
|
51
|
+
|
|
52
|
+
# For TOOL_PROGRESS, use progress message if available, otherwise keep default
|
|
53
|
+
if progress_action == ProgressAction.TOOL_PROGRESS:
|
|
54
|
+
progress_message = event_data.get("details", "")
|
|
55
|
+
if progress_message: # Only override if message is non-empty
|
|
56
|
+
details = progress_message
|
|
57
|
+
|
|
58
|
+
elif "augmented_llm" in namespace:
|
|
59
|
+
model = event_data.get("model", "")
|
|
60
|
+
|
|
61
|
+
# For all augmented_llm events, put model info in details column
|
|
62
|
+
details = f"{model}"
|
|
63
|
+
chat_turn = event_data.get("chat_turn")
|
|
64
|
+
if chat_turn is not None:
|
|
65
|
+
details = f"{model} turn {chat_turn}"
|
|
66
|
+
else:
|
|
67
|
+
if not target:
|
|
68
|
+
target = event_data.get("target", "unknown")
|
|
69
|
+
|
|
70
|
+
# Extract streaming token count for STREAMING actions
|
|
71
|
+
streaming_tokens = None
|
|
72
|
+
if progress_action == ProgressAction.STREAMING:
|
|
73
|
+
streaming_tokens = event_data.get("details", "")
|
|
74
|
+
|
|
75
|
+
# Extract progress data for TOOL_PROGRESS actions
|
|
76
|
+
progress = None
|
|
77
|
+
total = None
|
|
78
|
+
if progress_action == ProgressAction.TOOL_PROGRESS:
|
|
79
|
+
progress = event_data.get("progress")
|
|
80
|
+
total = event_data.get("total")
|
|
81
|
+
|
|
82
|
+
return ProgressEvent(
|
|
83
|
+
action=ProgressAction(progress_action),
|
|
84
|
+
target=target or "unknown",
|
|
85
|
+
details=details,
|
|
86
|
+
agent_name=event_data.get("agent_name"),
|
|
87
|
+
streaming_tokens=streaming_tokens,
|
|
88
|
+
progress=progress,
|
|
89
|
+
total=total,
|
|
90
|
+
)
|
|
13
91
|
|
|
14
92
|
|
|
15
93
|
class EventListener(ABC):
|
|
@@ -71,10 +149,10 @@ class LoggingListener(FilteredListener):
|
|
|
71
149
|
"""
|
|
72
150
|
Initialize the listener.
|
|
73
151
|
Args:
|
|
74
|
-
logger: Logger to use for event processing. Defaults to '
|
|
152
|
+
logger: Logger to use for event processing. Defaults to 'fast_agent'.
|
|
75
153
|
"""
|
|
76
154
|
super().__init__(event_filter=event_filter)
|
|
77
|
-
self.logger = logger or logging.getLogger("
|
|
155
|
+
self.logger = logger or logging.getLogger("fast_agent")
|
|
78
156
|
|
|
79
157
|
async def handle_matched_event(self, event) -> None:
|
|
80
158
|
level_map: Dict[EventType, int] = {
|
|
@@ -117,7 +195,7 @@ class ProgressListener(LifecycleAwareListener):
|
|
|
117
195
|
Args:
|
|
118
196
|
display: Optional display handler. If None, the shared progress_display will be used.
|
|
119
197
|
"""
|
|
120
|
-
from
|
|
198
|
+
from fast_agent.ui.progress_display import progress_display
|
|
121
199
|
|
|
122
200
|
self.display = display or progress_display
|
|
123
201
|
|
|
@@ -14,13 +14,13 @@ import time
|
|
|
14
14
|
from contextlib import asynccontextmanager, contextmanager
|
|
15
15
|
from typing import Any, Dict
|
|
16
16
|
|
|
17
|
-
from
|
|
18
|
-
from
|
|
17
|
+
from fast_agent.core.logging.events import Event, EventContext, EventFilter, EventType
|
|
18
|
+
from fast_agent.core.logging.listeners import (
|
|
19
19
|
BatchingListener,
|
|
20
20
|
LoggingListener,
|
|
21
21
|
ProgressListener,
|
|
22
22
|
)
|
|
23
|
-
from
|
|
23
|
+
from fast_agent.core.logging.transport import AsyncEventBus, EventTransport
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class Logger:
|
|
@@ -208,10 +208,10 @@ class LoggingConfig:
|
|
|
208
208
|
return
|
|
209
209
|
|
|
210
210
|
# Suppress boto3/botocore logging to prevent flooding
|
|
211
|
-
logging.getLogger(
|
|
212
|
-
logging.getLogger(
|
|
213
|
-
logging.getLogger(
|
|
214
|
-
logging.getLogger(
|
|
211
|
+
logging.getLogger("boto3").setLevel(logging.WARNING)
|
|
212
|
+
logging.getLogger("botocore").setLevel(logging.WARNING)
|
|
213
|
+
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
214
|
+
logging.getLogger("s3transfer").setLevel(logging.WARNING)
|
|
215
215
|
|
|
216
216
|
bus = AsyncEventBus.get(transport=transport)
|
|
217
217
|
|
|
@@ -17,11 +17,11 @@ from rich import print
|
|
|
17
17
|
from rich.json import JSON
|
|
18
18
|
from rich.text import Text
|
|
19
19
|
|
|
20
|
-
from
|
|
21
|
-
from
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
20
|
+
from fast_agent.config import LoggerSettings
|
|
21
|
+
from fast_agent.core.logging.events import Event, EventFilter
|
|
22
|
+
from fast_agent.core.logging.json_serializer import JSONSerializer
|
|
23
|
+
from fast_agent.core.logging.listeners import EventListener, LifecycleAwareListener
|
|
24
|
+
from fast_agent.ui.console import console
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class EventTransport(Protocol):
|
|
@@ -424,15 +424,14 @@ class AsyncEventBus:
|
|
|
424
424
|
)
|
|
425
425
|
|
|
426
426
|
except asyncio.CancelledError:
|
|
427
|
-
#
|
|
428
|
-
if event is not None:
|
|
427
|
+
# TODO -- added _queue assertion; is that necessary?
|
|
428
|
+
if event is not None and self._queue is not None:
|
|
429
429
|
self._queue.task_done()
|
|
430
|
-
|
|
430
|
+
raise
|
|
431
431
|
except Exception as e:
|
|
432
432
|
print(f"Error in event processing loop: {e}")
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if event is not None:
|
|
433
|
+
# Mark task done for this event
|
|
434
|
+
if event is not None and self._queue is not None:
|
|
436
435
|
self._queue.task_done()
|
|
437
436
|
|
|
438
437
|
# Process remaining events in queue
|
|
@@ -4,13 +4,13 @@ Validation utilities for FastAgent configuration and dependencies.
|
|
|
4
4
|
|
|
5
5
|
from typing import Any, Dict, List
|
|
6
6
|
|
|
7
|
-
from
|
|
8
|
-
from
|
|
7
|
+
from fast_agent.agents.agent_types import AgentType
|
|
8
|
+
from fast_agent.core.exceptions import (
|
|
9
9
|
AgentConfigError,
|
|
10
10
|
CircularDependencyError,
|
|
11
11
|
ServerConfigError,
|
|
12
12
|
)
|
|
13
|
-
from
|
|
13
|
+
from fast_agent.llm.fastagent_llm import FastAgentLLM
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def validate_server_references(context, agents: Dict[str, Dict[str, Any]]) -> None:
|
|
@@ -96,7 +96,7 @@ def validate_workflow_references(agents: Dict[str, Dict[str, Any]]) -> None:
|
|
|
96
96
|
]
|
|
97
97
|
|
|
98
98
|
if not (
|
|
99
|
-
isinstance(func,
|
|
99
|
+
isinstance(func, FastAgentLLM)
|
|
100
100
|
or child_data["type"] in workflow_types
|
|
101
101
|
or (hasattr(func, "_llm") and func._llm is not None)
|
|
102
102
|
):
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Module for converting log events to progress events."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ProgressAction(str, Enum):
|
|
10
|
+
"""Progress actions available in the system."""
|
|
11
|
+
|
|
12
|
+
STARTING = "Starting"
|
|
13
|
+
LOADED = "Loaded"
|
|
14
|
+
INITIALIZED = "Initialized"
|
|
15
|
+
CHATTING = "Chatting"
|
|
16
|
+
STREAMING = "Streaming" # Special action for real-time streaming updates
|
|
17
|
+
ROUTING = "Routing"
|
|
18
|
+
PLANNING = "Planning"
|
|
19
|
+
READY = "Ready"
|
|
20
|
+
CALLING_TOOL = "Calling Tool"
|
|
21
|
+
TOOL_PROGRESS = "Tool Progress"
|
|
22
|
+
UPDATED = "Updated"
|
|
23
|
+
FINISHED = "Finished"
|
|
24
|
+
SHUTDOWN = "Shutdown"
|
|
25
|
+
AGGREGATOR_INITIALIZED = "Running"
|
|
26
|
+
SERVER_OFFLINE = "Offline"
|
|
27
|
+
SERVER_RECONNECTING = "Reconnecting"
|
|
28
|
+
SERVER_ONLINE = "Online"
|
|
29
|
+
FATAL_ERROR = "Error"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ProgressEvent(BaseModel):
|
|
33
|
+
"""Represents a progress event converted from a log event."""
|
|
34
|
+
|
|
35
|
+
action: ProgressAction
|
|
36
|
+
target: str
|
|
37
|
+
details: Optional[str] = None
|
|
38
|
+
agent_name: Optional[str] = None
|
|
39
|
+
streaming_tokens: Optional[str] = None # Special field for streaming token count
|
|
40
|
+
progress: Optional[float] = None # Current progress value
|
|
41
|
+
total: Optional[float] = None # Total value for progress calculation
|
|
42
|
+
|
|
43
|
+
def __str__(self) -> str:
|
|
44
|
+
"""Format the progress event for display."""
|
|
45
|
+
# Special handling for streaming - show token count in action position
|
|
46
|
+
if self.action == ProgressAction.STREAMING and self.streaming_tokens:
|
|
47
|
+
# For streaming, show just the token count instead of "Streaming"
|
|
48
|
+
action_display = self.streaming_tokens.ljust(11)
|
|
49
|
+
base = f"{action_display}. {self.target}"
|
|
50
|
+
if self.details:
|
|
51
|
+
base += f" - {self.details}"
|
|
52
|
+
else:
|
|
53
|
+
base = f"{self.action.ljust(11)}. {self.target}"
|
|
54
|
+
if self.details:
|
|
55
|
+
base += f" - {self.details}"
|
|
56
|
+
|
|
57
|
+
if self.agent_name:
|
|
58
|
+
base = f"[{self.agent_name}] {base}"
|
|
59
|
+
return base
|
|
60
|
+
|
|
61
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
History export utilities for agents.
|
|
3
|
+
|
|
4
|
+
Provides a minimal, type-friendly way to save an agent's message history
|
|
5
|
+
without using control strings. Uses the existing serialization helpers
|
|
6
|
+
to choose JSON (for .json files) or Markdown-like delimited text otherwise.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING, Optional
|
|
12
|
+
|
|
13
|
+
from fast_agent.mcp.prompt_serialization import save_messages_to_file
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from fast_agent.interfaces import AgentProtocol
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class HistoryExporter:
|
|
20
|
+
"""Utility for exporting agent history to a file."""
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
async def save(agent: AgentProtocol, filename: Optional[str] = None) -> str:
|
|
24
|
+
"""
|
|
25
|
+
Save the given agent's message history to a file.
|
|
26
|
+
|
|
27
|
+
If filename ends with ".json", the history is saved in MCP JSON format.
|
|
28
|
+
Otherwise, it is saved in a human-readable Markdown-style format.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
agent: The agent whose history will be saved.
|
|
32
|
+
filename: Optional filename. If None, a default name is chosen.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The path that was written to.
|
|
36
|
+
"""
|
|
37
|
+
# Determine a default filename when not provided
|
|
38
|
+
target = filename or f"{getattr(agent, 'name', 'assistant')}_prompts.txt"
|
|
39
|
+
|
|
40
|
+
messages = agent.message_history
|
|
41
|
+
save_messages_to_file(messages, target)
|
|
42
|
+
|
|
43
|
+
# Return and optionally print a small confirmation
|
|
44
|
+
return target
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
"""Human input modules for forms and elicitation.
|
|
1
|
+
"""Human input modules for forms and elicitation.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Keep __init__ lightweight to avoid circular imports during submodule import.
|
|
4
|
+
Exports schema builders directly and defers simple form API imports.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from fast_agent.human_input.form_fields import (
|
|
6
8
|
BooleanField,
|
|
7
9
|
EnumField,
|
|
8
10
|
FormSchema,
|
|
9
11
|
IntegerField,
|
|
10
12
|
NumberField,
|
|
11
|
-
# Field classes
|
|
12
13
|
StringField,
|
|
13
14
|
boolean,
|
|
14
15
|
choice,
|
|
@@ -17,18 +18,11 @@ from mcp_agent.human_input.form_fields import (
|
|
|
17
18
|
email,
|
|
18
19
|
integer,
|
|
19
20
|
number,
|
|
20
|
-
# Convenience functions
|
|
21
21
|
string,
|
|
22
22
|
url,
|
|
23
23
|
)
|
|
24
|
-
from mcp_agent.human_input.simple_form import ask, ask_sync, form, form_sync
|
|
25
24
|
|
|
26
25
|
__all__ = [
|
|
27
|
-
# Form functions
|
|
28
|
-
"form",
|
|
29
|
-
"form_sync",
|
|
30
|
-
"ask",
|
|
31
|
-
"ask_sync",
|
|
32
26
|
# Schema builder
|
|
33
27
|
"FormSchema",
|
|
34
28
|
# Field classes
|
|
@@ -48,3 +42,6 @@ __all__ = [
|
|
|
48
42
|
"boolean",
|
|
49
43
|
"choice",
|
|
50
44
|
]
|
|
45
|
+
|
|
46
|
+
# Note: form(), ask() helpers are available via fast_agent.human_input.simple_form;
|
|
47
|
+
# intentionally not imported here to avoid import-time cycles.
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
from typing import Any, Dict, Optional
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from fast_agent.human_input.elicitation_state import elicitation_state
|
|
4
|
+
from fast_agent.human_input.types import (
|
|
5
|
+
HumanInputRequest,
|
|
6
|
+
HumanInputResponse,
|
|
7
|
+
)
|
|
8
|
+
from fast_agent.tools.elicitation import set_elicitation_input_callback
|
|
9
|
+
from fast_agent.ui.elicitation_form import (
|
|
4
10
|
show_simple_elicitation_form,
|
|
5
11
|
)
|
|
6
|
-
from
|
|
12
|
+
from fast_agent.ui.elicitation_style import (
|
|
7
13
|
ELICITATION_STYLE,
|
|
8
14
|
)
|
|
9
|
-
from
|
|
10
|
-
from mcp_agent.human_input.types import (
|
|
11
|
-
HumanInputRequest,
|
|
12
|
-
HumanInputResponse,
|
|
13
|
-
)
|
|
14
|
-
from mcp_agent.progress_display import progress_display
|
|
15
|
+
from fast_agent.ui.progress_display import progress_display
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
async def elicitation_input_callback(
|
|
@@ -86,3 +87,20 @@ async def elicitation_input_callback(
|
|
|
86
87
|
response=response.strip() if isinstance(response, str) else response,
|
|
87
88
|
metadata={"has_schema": schema is not None},
|
|
88
89
|
)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# Register adapter with fast_agent tools so they can invoke this UI handler without importing types
|
|
93
|
+
async def _elicitation_adapter(
|
|
94
|
+
request_payload: dict,
|
|
95
|
+
agent_name: str | None = None,
|
|
96
|
+
server_name: str | None = None,
|
|
97
|
+
server_info: dict[str, Any] | None = None,
|
|
98
|
+
) -> str:
|
|
99
|
+
req = HumanInputRequest(**request_payload)
|
|
100
|
+
resp = await elicitation_input_callback(
|
|
101
|
+
request=req, agent_name=agent_name, server_name=server_name, server_info=server_info
|
|
102
|
+
)
|
|
103
|
+
return resp.response if isinstance(resp.response, str) else str(resp.response)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
set_elicitation_input_callback(_elicitation_adapter)
|
|
@@ -5,30 +5,30 @@ from typing import Set
|
|
|
5
5
|
|
|
6
6
|
class ElicitationState:
|
|
7
7
|
"""Manages global state for elicitation requests, including disabled servers."""
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
def __init__(self):
|
|
10
10
|
self.disabled_servers: Set[str] = set()
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def disable_server(self, server_name: str) -> None:
|
|
13
13
|
"""Disable elicitation requests for a specific server."""
|
|
14
14
|
self.disabled_servers.add(server_name)
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def is_disabled(self, server_name: str) -> bool:
|
|
17
17
|
"""Check if elicitation is disabled for a server."""
|
|
18
18
|
return server_name in self.disabled_servers
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def enable_server(self, server_name: str) -> None:
|
|
21
21
|
"""Re-enable elicitation requests for a specific server."""
|
|
22
22
|
self.disabled_servers.discard(server_name)
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
def clear_all(self) -> None:
|
|
25
25
|
"""Clear all disabled servers."""
|
|
26
26
|
self.disabled_servers.clear()
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
def get_disabled_servers(self) -> Set[str]:
|
|
29
29
|
"""Get a copy of all disabled servers."""
|
|
30
30
|
return self.disabled_servers.copy()
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
# Global instance for session-scoped Cancel All functionality
|
|
34
|
-
elicitation_state = ElicitationState()
|
|
34
|
+
elicitation_state = ElicitationState()
|
|
@@ -5,8 +5,7 @@ from typing import Any, Dict, Optional, Union
|
|
|
5
5
|
|
|
6
6
|
from mcp.types import ElicitRequestedSchema
|
|
7
7
|
|
|
8
|
-
from
|
|
9
|
-
from mcp_agent.human_input.form_fields import FormSchema
|
|
8
|
+
from fast_agent.human_input.form_fields import FormSchema
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
async def form(
|
|
@@ -26,7 +25,7 @@ async def form(
|
|
|
26
25
|
Dict with form data if accepted, None if cancelled/declined
|
|
27
26
|
|
|
28
27
|
Example:
|
|
29
|
-
from
|
|
28
|
+
from fast_agent.human_input.form_fields import FormSchema, string, email, integer
|
|
30
29
|
|
|
31
30
|
schema = FormSchema(
|
|
32
31
|
name=string("Name", "Your full name", min_length=2),
|
|
@@ -46,6 +45,9 @@ async def form(
|
|
|
46
45
|
else:
|
|
47
46
|
elicit_schema = schema
|
|
48
47
|
|
|
48
|
+
# Import here to avoid import-time cycles via package __init__
|
|
49
|
+
from fast_agent.ui.elicitation_form import show_simple_elicitation_form
|
|
50
|
+
|
|
49
51
|
# Show the form
|
|
50
52
|
action, result = await show_simple_elicitation_form(
|
|
51
53
|
schema=elicit_schema, message=message, agent_name=title, server_name="SimpleForm"
|
|
@@ -86,7 +88,7 @@ async def ask(
|
|
|
86
88
|
Short alias for form() function.
|
|
87
89
|
|
|
88
90
|
Example:
|
|
89
|
-
from
|
|
91
|
+
from fast_agent.human_input.form_fields import FormSchema, string, email
|
|
90
92
|
|
|
91
93
|
schema = FormSchema(
|
|
92
94
|
name=string("Name", "Your name"),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Any
|
|
1
|
+
from typing import Any
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
4
|
|
|
@@ -38,20 +38,3 @@ class HumanInputResponse(BaseModel):
|
|
|
38
38
|
|
|
39
39
|
metadata: dict[str, Any] | None = None
|
|
40
40
|
"""Additional response payload"""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class HumanInputCallback(Protocol):
|
|
44
|
-
"""Protocol for callbacks that handle human input requests."""
|
|
45
|
-
|
|
46
|
-
async def __call__(self, request: HumanInputRequest) -> AsyncIterator[HumanInputResponse]:
|
|
47
|
-
"""
|
|
48
|
-
Handle a human input request.
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
request: The input request to handle
|
|
52
|
-
|
|
53
|
-
Returns:
|
|
54
|
-
AsyncIterator yielding responses as they come in
|
|
55
|
-
TODO: saqadri - Keep it simple and just return HumanInputResponse?
|
|
56
|
-
"""
|
|
57
|
-
...
|