fast-agent-mcp 0.3.14__py3-none-any.whl → 0.3.15__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/agents/llm_agent.py +45 -4
- fast_agent/agents/mcp_agent.py +3 -3
- fast_agent/agents/tool_agent.py +33 -19
- fast_agent/agents/workflow/router_agent.py +2 -1
- fast_agent/cli/commands/check_config.py +5 -2
- fast_agent/config.py +2 -2
- fast_agent/core/fastagent.py +14 -1
- fast_agent/core/validation.py +31 -33
- fast_agent/human_input/form_fields.py +4 -1
- fast_agent/interfaces.py +4 -1
- fast_agent/llm/fastagent_llm.py +31 -0
- fast_agent/llm/model_database.py +2 -2
- fast_agent/llm/model_factory.py +4 -1
- fast_agent/mcp/prompt_message_extended.py +2 -2
- fast_agent/resources/setup/fastagent.config.yaml +5 -4
- fast_agent/ui/console_display.py +654 -69
- fast_agent/ui/elicitation_form.py +23 -1
- fast_agent/ui/enhanced_prompt.py +49 -3
- fast_agent/ui/markdown_truncator.py +942 -0
- fast_agent/ui/mcp_display.py +2 -2
- fast_agent/ui/plain_text_truncator.py +68 -0
- fast_agent/ui/streaming_buffer.py +449 -0
- {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.15.dist-info}/METADATA +4 -3
- {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.15.dist-info}/RECORD +27 -24
- {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.15.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.15.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Simplified, robust elicitation form dialog."""
|
|
2
2
|
|
|
3
|
+
import re
|
|
3
4
|
from datetime import date, datetime
|
|
4
5
|
from typing import Any, Dict, Optional
|
|
5
6
|
|
|
@@ -63,9 +64,15 @@ class SimpleNumberValidator(Validator):
|
|
|
63
64
|
class SimpleStringValidator(Validator):
|
|
64
65
|
"""Simple string validator with real-time feedback."""
|
|
65
66
|
|
|
66
|
-
def __init__(
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
min_length: Optional[int] = None,
|
|
70
|
+
max_length: Optional[int] = None,
|
|
71
|
+
pattern: Optional[str] = None
|
|
72
|
+
):
|
|
67
73
|
self.min_length = min_length
|
|
68
74
|
self.max_length = max_length
|
|
75
|
+
self.pattern = re.compile(pattern, re.DOTALL) if pattern else None
|
|
69
76
|
|
|
70
77
|
def validate(self, document):
|
|
71
78
|
text = document.text
|
|
@@ -83,6 +90,12 @@ class SimpleStringValidator(Validator):
|
|
|
83
90
|
cursor_position=self.max_length,
|
|
84
91
|
)
|
|
85
92
|
|
|
93
|
+
if self.pattern is not None and self.pattern.fullmatch(text) is None:
|
|
94
|
+
# TODO: Wrap or truncate line if too long
|
|
95
|
+
raise ValidationError(
|
|
96
|
+
message=f"Must match pattern '{self.pattern.pattern}'", cursor_position=len(text)
|
|
97
|
+
)
|
|
98
|
+
|
|
86
99
|
|
|
87
100
|
class FormatValidator(Validator):
|
|
88
101
|
"""Format-specific validator using Pydantic validators."""
|
|
@@ -429,6 +442,8 @@ class ElicitationForm:
|
|
|
429
442
|
constraints["minLength"] = field_def["minLength"]
|
|
430
443
|
if field_def.get("maxLength") is not None:
|
|
431
444
|
constraints["maxLength"] = field_def["maxLength"]
|
|
445
|
+
if field_def.get("pattern") is not None:
|
|
446
|
+
constraints["pattern"] = field_def["pattern"]
|
|
432
447
|
|
|
433
448
|
# Check anyOf constraints (for Optional fields)
|
|
434
449
|
if "anyOf" in field_def:
|
|
@@ -438,6 +453,8 @@ class ElicitationForm:
|
|
|
438
453
|
constraints["minLength"] = variant["minLength"]
|
|
439
454
|
if variant.get("maxLength") is not None:
|
|
440
455
|
constraints["maxLength"] = variant["maxLength"]
|
|
456
|
+
if variant.get("pattern") is not None:
|
|
457
|
+
constraints["pattern"] = variant["pattern"]
|
|
441
458
|
break
|
|
442
459
|
|
|
443
460
|
return constraints
|
|
@@ -468,6 +485,10 @@ class ElicitationForm:
|
|
|
468
485
|
if constraints.get("maxLength"):
|
|
469
486
|
hints.append(f"max {constraints['maxLength']} chars")
|
|
470
487
|
|
|
488
|
+
if constraints.get("pattern"):
|
|
489
|
+
# TODO: Wrap or truncate line if too long
|
|
490
|
+
format_hint = f"Pattern: {constraints['pattern']}"
|
|
491
|
+
|
|
471
492
|
# Handle format hints separately (these go on next line)
|
|
472
493
|
format_type = field_def.get("format")
|
|
473
494
|
if format_type:
|
|
@@ -545,6 +566,7 @@ class ElicitationForm:
|
|
|
545
566
|
validator = SimpleStringValidator(
|
|
546
567
|
min_length=constraints.get("minLength"),
|
|
547
568
|
max_length=constraints.get("maxLength"),
|
|
569
|
+
pattern=constraints.get("pattern"),
|
|
548
570
|
)
|
|
549
571
|
else:
|
|
550
572
|
constraints = {}
|
fast_agent/ui/enhanced_prompt.py
CHANGED
|
@@ -684,20 +684,26 @@ async def get_enhanced_input(
|
|
|
684
684
|
if llm:
|
|
685
685
|
model_name = getattr(llm, "model_name", None)
|
|
686
686
|
if not model_name:
|
|
687
|
-
model_name = getattr(
|
|
687
|
+
model_name = getattr(
|
|
688
|
+
getattr(llm, "default_request_params", None), "model", None
|
|
689
|
+
)
|
|
688
690
|
|
|
689
691
|
if not model_name:
|
|
690
692
|
model_name = getattr(agent.config, "model", None)
|
|
691
693
|
if not model_name and getattr(agent.config, "default_request_params", None):
|
|
692
694
|
model_name = getattr(agent.config.default_request_params, "model", None)
|
|
693
695
|
if not model_name:
|
|
694
|
-
context = getattr(agent, "context", None) or getattr(
|
|
696
|
+
context = getattr(agent, "context", None) or getattr(
|
|
697
|
+
agent_provider, "context", None
|
|
698
|
+
)
|
|
695
699
|
config_obj = getattr(context, "config", None) if context else None
|
|
696
700
|
model_name = getattr(config_obj, "default_model", None)
|
|
697
701
|
|
|
698
702
|
if model_name:
|
|
699
703
|
max_len = 25
|
|
700
|
-
model_display =
|
|
704
|
+
model_display = (
|
|
705
|
+
model_name[: max_len - 1] + "…" if len(model_name) > max_len else model_name
|
|
706
|
+
)
|
|
701
707
|
else:
|
|
702
708
|
print(f"[toolbar debug] no model resolved for agent '{agent_name}'")
|
|
703
709
|
model_display = "unknown"
|
|
@@ -876,6 +882,46 @@ async def get_enhanced_input(
|
|
|
876
882
|
# Display info for all available agents with tree structure for workflows
|
|
877
883
|
await _display_all_agents_with_hierarchy(available_agents, agent_provider)
|
|
878
884
|
|
|
885
|
+
# Show streaming status message
|
|
886
|
+
if agent_provider:
|
|
887
|
+
# Get logger settings from the agent's context (not agent_provider)
|
|
888
|
+
logger_settings = None
|
|
889
|
+
try:
|
|
890
|
+
agent = agent_provider._agent(agent_name)
|
|
891
|
+
agent_context = agent._context or agent.context
|
|
892
|
+
logger_settings = agent_context.config.logger
|
|
893
|
+
except Exception:
|
|
894
|
+
# If we can't get the agent or its context, logger_settings stays None
|
|
895
|
+
pass
|
|
896
|
+
|
|
897
|
+
# Only show streaming messages if chat display is enabled AND we have logger_settings
|
|
898
|
+
if logger_settings:
|
|
899
|
+
show_chat = getattr(logger_settings, "show_chat", True)
|
|
900
|
+
|
|
901
|
+
if show_chat:
|
|
902
|
+
# Check for parallel agents
|
|
903
|
+
has_parallel = any(
|
|
904
|
+
agent.agent_type == AgentType.PARALLEL
|
|
905
|
+
for agent in agent_provider._agents.values()
|
|
906
|
+
)
|
|
907
|
+
|
|
908
|
+
# Note: streaming may have been disabled by fastagent.py if parallel agents exist
|
|
909
|
+
# So we check has_parallel first to show the appropriate message
|
|
910
|
+
if has_parallel:
|
|
911
|
+
# Streaming is disabled due to parallel agents
|
|
912
|
+
rich_print(
|
|
913
|
+
"[dim]Markdown Streaming disabled (Parallel Agents configured)[/dim]"
|
|
914
|
+
)
|
|
915
|
+
else:
|
|
916
|
+
# Check if streaming is enabled
|
|
917
|
+
streaming_enabled = getattr(logger_settings, "streaming_display", True)
|
|
918
|
+
streaming_mode = getattr(logger_settings, "streaming", "markdown")
|
|
919
|
+
if streaming_enabled and streaming_mode != "none":
|
|
920
|
+
# Streaming is enabled - notify users since it's experimental
|
|
921
|
+
rich_print(
|
|
922
|
+
f"[dim]Experimental: Streaming Enabled - {streaming_mode} mode[/dim]"
|
|
923
|
+
)
|
|
924
|
+
|
|
879
925
|
rich_print()
|
|
880
926
|
help_message_shown = True
|
|
881
927
|
|