fast-agent-mcp 0.2.58__py3-none-any.whl → 0.3.1__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 +75 -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 +52 -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 +54 -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/resources/setup/pyproject.toml.tmpl +17 -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.1.dist-info}/METADATA +7 -7
- fast_agent_mcp-0.3.1.dist-info/RECORD +203 -0
- fast_agent_mcp-0.3.1.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.1.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.58.dist-info → fast_agent_mcp-0.3.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,8 +22,7 @@ from prompt_toolkit.widgets import (
|
|
|
22
22
|
from pydantic import AnyUrl, EmailStr
|
|
23
23
|
from pydantic import ValidationError as PydanticValidationError
|
|
24
24
|
|
|
25
|
-
from
|
|
26
|
-
from mcp_agent.human_input.elicitation_state import elicitation_state
|
|
25
|
+
from fast_agent.ui.elicitation_style import ELICITATION_STYLE
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
class SimpleNumberValidator(Validator):
|
|
@@ -280,10 +279,15 @@ class ElicitationForm:
|
|
|
280
279
|
]
|
|
281
280
|
)
|
|
282
281
|
|
|
283
|
-
#
|
|
282
|
+
# Choose dialog title: prefer schema.title if provided
|
|
283
|
+
dialog_title = self.schema.get("title") if isinstance(self.schema, dict) else None
|
|
284
|
+
if not dialog_title or not isinstance(dialog_title, str):
|
|
285
|
+
dialog_title = "Elicitation Request"
|
|
286
|
+
|
|
287
|
+
# Create dialog frame with dynamic title
|
|
284
288
|
dialog = Frame(
|
|
285
289
|
body=full_content,
|
|
286
|
-
title=
|
|
290
|
+
title=dialog_title,
|
|
287
291
|
style="class:dialog",
|
|
288
292
|
)
|
|
289
293
|
|
|
@@ -334,7 +338,7 @@ class ElicitationForm:
|
|
|
334
338
|
@kb.add("c-j")
|
|
335
339
|
def insert_newline(event):
|
|
336
340
|
# Insert a newline at the cursor position
|
|
337
|
-
event.current_buffer.insert_text(
|
|
341
|
+
event.current_buffer.insert_text("\n")
|
|
338
342
|
# Mark this field as multiline when user adds a newline
|
|
339
343
|
for field_name, widget in self.field_widgets.items():
|
|
340
344
|
if isinstance(widget, Buffer) and widget == event.current_buffer:
|
|
@@ -438,7 +442,6 @@ class ElicitationForm:
|
|
|
438
442
|
|
|
439
443
|
return constraints
|
|
440
444
|
|
|
441
|
-
|
|
442
445
|
def _create_field(self, field_name: str, field_def: Dict[str, Any]):
|
|
443
446
|
"""Create a field widget."""
|
|
444
447
|
|
|
@@ -558,11 +561,11 @@ class ElicitationForm:
|
|
|
558
561
|
max_length = None
|
|
559
562
|
|
|
560
563
|
# Check if default value contains newlines
|
|
561
|
-
if field_type == "string" and default_value is not None and
|
|
564
|
+
if field_type == "string" and default_value is not None and "\n" in str(default_value):
|
|
562
565
|
multiline = True
|
|
563
566
|
self.multiline_fields.add(field_name) # Track multiline fields
|
|
564
567
|
# Set height to actual line count for fields with newlines in default
|
|
565
|
-
initial_height = str(default_value).count(
|
|
568
|
+
initial_height = str(default_value).count("\n") + 1
|
|
566
569
|
elif max_length and max_length > 100:
|
|
567
570
|
# Use multiline for longer fields
|
|
568
571
|
multiline = True
|
|
@@ -605,10 +608,10 @@ class ElicitationForm:
|
|
|
605
608
|
if not buffer.text:
|
|
606
609
|
return initial_height
|
|
607
610
|
# Calculate height based on number of newlines in buffer
|
|
608
|
-
line_count = buffer.text.count(
|
|
611
|
+
line_count = buffer.text.count("\n") + 1
|
|
609
612
|
# Use initial height as minimum, grow up to 20 lines
|
|
610
613
|
return min(max(line_count, initial_height), 20)
|
|
611
|
-
|
|
614
|
+
|
|
612
615
|
text_input = Window(
|
|
613
616
|
BufferControl(buffer=buffer),
|
|
614
617
|
height=get_dynamic_height, # Use dynamic height function
|
|
@@ -727,8 +730,10 @@ class ElicitationForm:
|
|
|
727
730
|
self.app.exit()
|
|
728
731
|
|
|
729
732
|
def _cancel_all(self):
|
|
730
|
-
"""Handle cancel all
|
|
731
|
-
|
|
733
|
+
"""Handle cancel all: signal disable; no side effects here.
|
|
734
|
+
|
|
735
|
+
UI emits an action; handler/orchestration is responsible for updating state.
|
|
736
|
+
"""
|
|
732
737
|
self.action = "disable"
|
|
733
738
|
self._clear_status_bar()
|
|
734
739
|
self.app.exit()
|
|
@@ -19,8 +19,9 @@ from prompt_toolkit.key_binding import KeyBindings
|
|
|
19
19
|
from prompt_toolkit.styles import Style
|
|
20
20
|
from rich import print as rich_print
|
|
21
21
|
|
|
22
|
-
from
|
|
23
|
-
from
|
|
22
|
+
from fast_agent.agents.agent_types import AgentType
|
|
23
|
+
from fast_agent.core.exceptions import PromptExitError
|
|
24
|
+
from fast_agent.llm.model_info import get_model_info
|
|
24
25
|
|
|
25
26
|
# Get the application version
|
|
26
27
|
try:
|
|
@@ -59,9 +60,12 @@ async def _display_agent_info_helper(agent_name: str, agent_provider: object) ->
|
|
|
59
60
|
# This is a single agent
|
|
60
61
|
agent = agent_provider
|
|
61
62
|
|
|
62
|
-
# Get counts
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
# Get counts TODO -- add this to the type library or adjust the way aggregator/reporting works
|
|
64
|
+
server_count = 0
|
|
65
|
+
if hasattr(agent, "_aggregator") and hasattr(agent._aggregator, "server_names"):
|
|
66
|
+
server_count = (
|
|
67
|
+
len(agent._aggregator.server_names) if agent._aggregator.server_names else 0
|
|
68
|
+
)
|
|
65
69
|
|
|
66
70
|
tools_result = await agent.list_tools()
|
|
67
71
|
tool_count = (
|
|
@@ -290,12 +294,13 @@ class AgentCompleter(Completer):
|
|
|
290
294
|
self.agents = agents
|
|
291
295
|
# Map commands to their descriptions for better completion hints
|
|
292
296
|
self.commands = {
|
|
293
|
-
"tools": "List
|
|
294
|
-
"prompt": "List and
|
|
297
|
+
"tools": "List available MCP tools",
|
|
298
|
+
"prompt": "List and choose MCP prompts, or apply specific prompt (/prompt <name>)",
|
|
295
299
|
"agents": "List available agents",
|
|
296
300
|
"usage": "Show current usage statistics",
|
|
297
301
|
"markdown": "Show last assistant message without markdown formatting",
|
|
298
|
-
"
|
|
302
|
+
"save_history": "Save history; .json = MCP JSON, others = Markdown",
|
|
303
|
+
"help": "Show commands and shortcuts",
|
|
299
304
|
"clear": "Clear the screen",
|
|
300
305
|
"STOP": "Stop this prompting session and move to next workflow step",
|
|
301
306
|
"EXIT": "Exit fast-agent, terminating any running workflows",
|
|
@@ -578,32 +583,91 @@ async def get_enhanced_input(
|
|
|
578
583
|
if in_multiline_mode:
|
|
579
584
|
mode_style = "ansired" # More noticeable for multiline mode
|
|
580
585
|
mode_text = "MULTILINE"
|
|
581
|
-
|
|
586
|
+
# toggle_text = "Normal"
|
|
582
587
|
else:
|
|
583
588
|
mode_style = "ansigreen"
|
|
584
589
|
mode_text = "NORMAL"
|
|
585
|
-
toggle_text = "Multiline"
|
|
590
|
+
# toggle_text = "Multiline"
|
|
586
591
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
("Ctrl+J", "Newline" if not in_multiline_mode else None),
|
|
590
|
-
("Ctrl+E", "External"),
|
|
591
|
-
("Ctrl+Y", "Copy"),
|
|
592
|
-
("Ctrl+L", "Clear"),
|
|
593
|
-
("↑/↓", "History"),
|
|
594
|
-
("EXIT", "Exit")
|
|
595
|
-
]
|
|
596
|
-
|
|
597
|
-
newline = "Ctrl+J:Submit" if in_multiline_mode else "<Enter>:Submit"
|
|
592
|
+
# No shortcut hints in the toolbar for now
|
|
593
|
+
shortcuts = []
|
|
598
594
|
|
|
599
595
|
# Only show relevant shortcuts based on mode
|
|
600
596
|
shortcuts = [(k, v) for k, v in shortcuts if v]
|
|
601
597
|
|
|
602
598
|
shortcut_text = " | ".join(f"{key}:{action}" for key, action in shortcuts)
|
|
603
599
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
600
|
+
# Resolve model name and TDV from the current agent if available
|
|
601
|
+
model_display = None
|
|
602
|
+
tdv_segment = None
|
|
603
|
+
try:
|
|
604
|
+
agent_obj = (
|
|
605
|
+
agent_provider._agent(agent_name)
|
|
606
|
+
if agent_provider and hasattr(agent_provider, "_agent")
|
|
607
|
+
else agent_provider
|
|
608
|
+
)
|
|
609
|
+
if agent_obj and hasattr(agent_obj, "llm") and agent_obj.llm:
|
|
610
|
+
model_name = getattr(agent_obj.llm, "model_name", None)
|
|
611
|
+
if model_name:
|
|
612
|
+
# Truncate model name to max 25 characters with ellipsis
|
|
613
|
+
max_len = 25
|
|
614
|
+
if len(model_name) > max_len:
|
|
615
|
+
# Keep total length at max_len including ellipsis
|
|
616
|
+
model_display = model_name[: max_len - 1] + "…"
|
|
617
|
+
else:
|
|
618
|
+
model_display = model_name
|
|
619
|
+
|
|
620
|
+
# Build TDV capability segment based on model database
|
|
621
|
+
info = get_model_info(agent_obj)
|
|
622
|
+
# Default to text-only if info resolution fails for any reason
|
|
623
|
+
t, d, v = (True, False, False)
|
|
624
|
+
if info:
|
|
625
|
+
t, d, v = info.tdv_flags
|
|
626
|
+
|
|
627
|
+
def _style_flag(letter: str, supported: bool) -> str:
|
|
628
|
+
# Enabled uses the same color as NORMAL mode (ansigreen), disabled is dim
|
|
629
|
+
enabled_color = "ansigreen"
|
|
630
|
+
return (
|
|
631
|
+
f"<style fg='{enabled_color}' bg='ansiblack'>{letter}</style>"
|
|
632
|
+
if supported
|
|
633
|
+
else f"<style fg='ansiblack' bg='ansiwhite'>{letter}</style>"
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
tdv_segment = f"{_style_flag('T', t)}{_style_flag('D', d)}{_style_flag('V', v)}"
|
|
637
|
+
except Exception:
|
|
638
|
+
# If anything goes wrong determining the model, omit it gracefully
|
|
639
|
+
model_display = None
|
|
640
|
+
tdv_segment = None
|
|
641
|
+
|
|
642
|
+
# Build dynamic middle segments: model (in green) and optional shortcuts
|
|
643
|
+
middle_segments = []
|
|
644
|
+
if model_display:
|
|
645
|
+
# Model chip + inline TDV flags
|
|
646
|
+
if tdv_segment:
|
|
647
|
+
middle_segments.append(
|
|
648
|
+
f"{tdv_segment} <style bg='ansigreen'>{model_display}</style>"
|
|
649
|
+
)
|
|
650
|
+
else:
|
|
651
|
+
middle_segments.append(f"<style bg='ansigreen'>{model_display}</style>")
|
|
652
|
+
if shortcut_text:
|
|
653
|
+
middle_segments.append(shortcut_text)
|
|
654
|
+
middle = " | ".join(middle_segments)
|
|
655
|
+
|
|
656
|
+
# Version/app label in green (dynamic version)
|
|
657
|
+
version_segment = f"fast-agent {app_version}"
|
|
658
|
+
|
|
659
|
+
if middle:
|
|
660
|
+
return HTML(
|
|
661
|
+
f" <style fg='{toolbar_color}' bg='ansiblack'> {agent_name} </style> "
|
|
662
|
+
f" {middle} | <style fg='{mode_style}' bg='ansiblack'> {mode_text} </style> | "
|
|
663
|
+
f"{version_segment}"
|
|
664
|
+
)
|
|
665
|
+
else:
|
|
666
|
+
return HTML(
|
|
667
|
+
f" <style fg='{toolbar_color}' bg='ansiblack'> {agent_name} </style> "
|
|
668
|
+
f"Mode: <style fg='{mode_style}' bg='ansiblack'> {mode_text} </style> | "
|
|
669
|
+
f"{version_segment}"
|
|
670
|
+
)
|
|
607
671
|
|
|
608
672
|
# A more terminal-agnostic style that should work across themes
|
|
609
673
|
custom_style = Style.from_dict(
|
|
@@ -676,7 +740,7 @@ async def get_enhanced_input(
|
|
|
676
740
|
def pre_process_input(text):
|
|
677
741
|
# Command processing
|
|
678
742
|
if text and text.startswith("/"):
|
|
679
|
-
if text == "/":
|
|
743
|
+
if text == "/":
|
|
680
744
|
return ""
|
|
681
745
|
cmd_parts = text[1:].strip().split(maxsplit=1)
|
|
682
746
|
cmd = cmd_parts[0].lower()
|
|
@@ -691,6 +755,11 @@ async def get_enhanced_input(
|
|
|
691
755
|
return "SHOW_USAGE"
|
|
692
756
|
elif cmd == "markdown":
|
|
693
757
|
return "MARKDOWN"
|
|
758
|
+
elif cmd in ("save_history", "save"):
|
|
759
|
+
# Return a structured action for the interactive loop to handle
|
|
760
|
+
# Prefer programmatic saving via HistoryExporter; fall back to magic-string there if needed
|
|
761
|
+
filename = cmd_parts[1].strip() if len(cmd_parts) > 1 and cmd_parts[1].strip() else None
|
|
762
|
+
return {"save_history": True, "filename": filename}
|
|
694
763
|
elif cmd == "prompt":
|
|
695
764
|
# Handle /prompt with no arguments as interactive mode
|
|
696
765
|
if len(cmd_parts) > 1:
|
|
@@ -867,6 +936,8 @@ async def handle_special_commands(command, agent_app=None):
|
|
|
867
936
|
rich_print(" /prompt <name> - Apply a specific prompt by name")
|
|
868
937
|
rich_print(" /usage - Show current usage statistics")
|
|
869
938
|
rich_print(" /markdown - Show last assistant message without markdown formatting")
|
|
939
|
+
rich_print(" /save_history <filename> - Save current chat history to a file")
|
|
940
|
+
rich_print(" [dim]Tip: Use a .json extension for MCP-compatible JSON; any other extension saves Markdown.[/dim]")
|
|
870
941
|
rich_print(" @agent_name - Switch to agent")
|
|
871
942
|
rich_print(" STOP - Return control back to the workflow")
|
|
872
943
|
rich_print(" EXIT - Exit fast-agent, terminating any running workflows")
|