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
|
@@ -18,24 +18,24 @@ from typing import Awaitable, Callable, Dict, List, Mapping, Optional, Protocol,
|
|
|
18
18
|
|
|
19
19
|
from mcp.types import Prompt, PromptMessage
|
|
20
20
|
from rich import print as rich_print
|
|
21
|
-
from rich.console import Console
|
|
22
|
-
from rich.table import Table
|
|
23
21
|
|
|
24
|
-
from
|
|
25
|
-
from
|
|
22
|
+
from fast_agent.agents.agent_types import AgentType
|
|
23
|
+
from fast_agent.history.history_exporter import HistoryExporter
|
|
24
|
+
from fast_agent.interfaces import AgentProtocol
|
|
25
|
+
from fast_agent.mcp.mcp_aggregator import SEP
|
|
26
|
+
from fast_agent.types import PromptMessageExtended
|
|
27
|
+
from fast_agent.ui.enhanced_prompt import (
|
|
26
28
|
_display_agent_info_helper,
|
|
27
29
|
get_argument_input,
|
|
28
30
|
get_enhanced_input,
|
|
29
31
|
get_selection_input,
|
|
30
32
|
handle_special_commands,
|
|
31
33
|
)
|
|
32
|
-
from
|
|
33
|
-
from
|
|
34
|
-
from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
|
|
35
|
-
from mcp_agent.progress_display import progress_display
|
|
34
|
+
from fast_agent.ui.progress_display import progress_display
|
|
35
|
+
from fast_agent.ui.usage_display import collect_agents_from_provider, display_usage_report
|
|
36
36
|
|
|
37
37
|
# Type alias for the send function
|
|
38
|
-
SendFunc = Callable[[Union[str, PromptMessage,
|
|
38
|
+
SendFunc = Callable[[Union[str, PromptMessage, PromptMessageExtended], str], Awaitable[str]]
|
|
39
39
|
|
|
40
40
|
# Type alias for the agent getter function
|
|
41
41
|
AgentGetter = Callable[[str], Optional[object]]
|
|
@@ -45,7 +45,7 @@ class PromptProvider(Protocol):
|
|
|
45
45
|
"""Protocol for objects that can provide prompt functionality."""
|
|
46
46
|
|
|
47
47
|
async def list_prompts(
|
|
48
|
-
self,
|
|
48
|
+
self, namespace: Optional[str] = None, agent_name: Optional[str] = None
|
|
49
49
|
) -> Mapping[str, List[Prompt]]:
|
|
50
50
|
"""List available prompts."""
|
|
51
51
|
...
|
|
@@ -62,6 +62,14 @@ class PromptProvider(Protocol):
|
|
|
62
62
|
"""Apply a prompt."""
|
|
63
63
|
...
|
|
64
64
|
|
|
65
|
+
def _agent(self, agent_name: str) -> AgentProtocol:
|
|
66
|
+
"""Return the concrete agent by name (AgentApp provides this)."""
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
def _show_turn_usage(self, agent_name: str) -> None:
|
|
70
|
+
"""Display usage for a given agent after a turn."""
|
|
71
|
+
...
|
|
72
|
+
|
|
65
73
|
|
|
66
74
|
class InteractivePrompt:
|
|
67
75
|
"""
|
|
@@ -83,7 +91,7 @@ class InteractivePrompt:
|
|
|
83
91
|
send_func: SendFunc,
|
|
84
92
|
default_agent: str,
|
|
85
93
|
available_agents: List[str],
|
|
86
|
-
prompt_provider:
|
|
94
|
+
prompt_provider: PromptProvider,
|
|
87
95
|
default: str = "",
|
|
88
96
|
) -> str:
|
|
89
97
|
"""
|
|
@@ -144,11 +152,11 @@ class InteractivePrompt:
|
|
|
144
152
|
rich_print(f"[red]Agent '{new_agent}' not found[/red]")
|
|
145
153
|
continue
|
|
146
154
|
# Keep the existing list_prompts handler for backward compatibility
|
|
147
|
-
elif "list_prompts" in command_result
|
|
155
|
+
elif "list_prompts" in command_result:
|
|
148
156
|
# Use the prompt_provider directly
|
|
149
157
|
await self._list_prompts(prompt_provider, agent)
|
|
150
158
|
continue
|
|
151
|
-
elif "select_prompt" in command_result
|
|
159
|
+
elif "select_prompt" in command_result:
|
|
152
160
|
# Handle prompt selection, using both list_prompts and apply_prompt
|
|
153
161
|
prompt_name = command_result.get("prompt_name")
|
|
154
162
|
prompt_index = command_result.get("prompt_index")
|
|
@@ -181,7 +189,7 @@ class InteractivePrompt:
|
|
|
181
189
|
# Use the name-based selection
|
|
182
190
|
await self._select_prompt(prompt_provider, agent, prompt_name)
|
|
183
191
|
continue
|
|
184
|
-
elif "list_tools" in command_result
|
|
192
|
+
elif "list_tools" in command_result:
|
|
185
193
|
# Handle tools list display
|
|
186
194
|
await self._list_tools(prompt_provider, agent)
|
|
187
195
|
continue
|
|
@@ -193,6 +201,22 @@ class InteractivePrompt:
|
|
|
193
201
|
# Handle markdown display
|
|
194
202
|
await self._show_markdown(prompt_provider, agent)
|
|
195
203
|
continue
|
|
204
|
+
elif "save_history" in command_result:
|
|
205
|
+
# Save history for the current agent
|
|
206
|
+
filename = command_result.get("filename")
|
|
207
|
+
try:
|
|
208
|
+
agent_obj = prompt_provider._agent(agent)
|
|
209
|
+
|
|
210
|
+
# Prefer type-safe exporter over magic string
|
|
211
|
+
saved_path = await HistoryExporter.save(agent_obj, filename)
|
|
212
|
+
rich_print(f"[green]History saved to {saved_path}[/green]")
|
|
213
|
+
except Exception:
|
|
214
|
+
# Fallback to magic string path for maximum compatibility
|
|
215
|
+
control = "***SAVE_HISTORY" + (f" {filename}" if filename else "")
|
|
216
|
+
result = await send_func(control, agent)
|
|
217
|
+
if result:
|
|
218
|
+
rich_print(f"[green]{result}[/green]")
|
|
219
|
+
continue
|
|
196
220
|
|
|
197
221
|
# Skip further processing if:
|
|
198
222
|
# 1. The command was handled (command_result is truthy)
|
|
@@ -216,6 +240,51 @@ class InteractivePrompt:
|
|
|
216
240
|
|
|
217
241
|
return result
|
|
218
242
|
|
|
243
|
+
def _create_combined_separator_status(
|
|
244
|
+
self, left_content: str, right_info: str, console
|
|
245
|
+
) -> None:
|
|
246
|
+
"""
|
|
247
|
+
Create a combined separator and status line using the new visual style.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
left_content: The main content (block, arrow, name) - left justified with color
|
|
251
|
+
right_info: Supplementary information to show in brackets - right aligned
|
|
252
|
+
console: Rich console instance to use
|
|
253
|
+
"""
|
|
254
|
+
from rich.text import Text
|
|
255
|
+
|
|
256
|
+
width = console.size.width
|
|
257
|
+
|
|
258
|
+
# Create left text
|
|
259
|
+
left_text = Text.from_markup(left_content)
|
|
260
|
+
|
|
261
|
+
# Create right text if we have info
|
|
262
|
+
if right_info and right_info.strip():
|
|
263
|
+
# Add dim brackets around the right info
|
|
264
|
+
right_text = Text()
|
|
265
|
+
right_text.append("[", style="dim")
|
|
266
|
+
right_text.append_text(Text.from_markup(right_info))
|
|
267
|
+
right_text.append("]", style="dim")
|
|
268
|
+
# Calculate separator count
|
|
269
|
+
separator_count = width - left_text.cell_len - right_text.cell_len
|
|
270
|
+
if separator_count < 1:
|
|
271
|
+
separator_count = 1 # Always at least 1 separator
|
|
272
|
+
else:
|
|
273
|
+
right_text = Text("")
|
|
274
|
+
separator_count = width - left_text.cell_len
|
|
275
|
+
|
|
276
|
+
# Build the combined line
|
|
277
|
+
combined = Text()
|
|
278
|
+
combined.append_text(left_text)
|
|
279
|
+
combined.append(" ", style="default")
|
|
280
|
+
combined.append("─" * (separator_count - 1), style="dim")
|
|
281
|
+
combined.append_text(right_text)
|
|
282
|
+
|
|
283
|
+
# Print with empty line before
|
|
284
|
+
rich_print()
|
|
285
|
+
console.print(combined)
|
|
286
|
+
rich_print()
|
|
287
|
+
|
|
219
288
|
async def _get_all_prompts(
|
|
220
289
|
self, prompt_provider: PromptProvider, agent_name: Optional[str] = None
|
|
221
290
|
):
|
|
@@ -232,7 +301,7 @@ class InteractivePrompt:
|
|
|
232
301
|
try:
|
|
233
302
|
# Call list_prompts on the provider
|
|
234
303
|
prompt_servers = await prompt_provider.list_prompts(
|
|
235
|
-
|
|
304
|
+
namespace=None, agent_name=agent_name
|
|
236
305
|
)
|
|
237
306
|
|
|
238
307
|
all_prompts = []
|
|
@@ -305,44 +374,94 @@ class InteractivePrompt:
|
|
|
305
374
|
prompt_provider: Provider that implements list_prompts
|
|
306
375
|
agent_name: Name of the agent
|
|
307
376
|
"""
|
|
308
|
-
console = Console()
|
|
309
|
-
|
|
310
377
|
try:
|
|
311
|
-
# Directly call the list_prompts function for this agent
|
|
312
|
-
rich_print(f"\n[bold]Fetching prompts for agent [cyan]{agent_name}[/cyan]...[/bold]")
|
|
313
|
-
|
|
314
378
|
# Get all prompts using the helper function
|
|
315
379
|
all_prompts = await self._get_all_prompts(prompt_provider, agent_name)
|
|
316
380
|
|
|
317
|
-
|
|
318
|
-
# Create a table for better display
|
|
319
|
-
table = Table(title="Available MCP Prompts")
|
|
320
|
-
table.add_column("#", justify="right", style="cyan")
|
|
321
|
-
table.add_column("Server", style="green")
|
|
322
|
-
table.add_column("Prompt Name", style="bright_blue")
|
|
323
|
-
table.add_column("Title")
|
|
324
|
-
table.add_column("Description")
|
|
325
|
-
table.add_column("Args", justify="center")
|
|
326
|
-
|
|
327
|
-
# Add prompts to table
|
|
328
|
-
for i, prompt in enumerate(all_prompts):
|
|
329
|
-
table.add_row(
|
|
330
|
-
str(i + 1),
|
|
331
|
-
prompt["server"],
|
|
332
|
-
prompt["name"],
|
|
333
|
-
prompt["title"],
|
|
334
|
-
prompt["description"],
|
|
335
|
-
str(prompt["arg_count"]),
|
|
336
|
-
)
|
|
381
|
+
rich_print(f"\n[bold]Prompts for agent [cyan]{agent_name}[/cyan]:[/bold]")
|
|
337
382
|
|
|
338
|
-
|
|
383
|
+
if not all_prompts:
|
|
384
|
+
rich_print("[yellow]No prompts available for this agent[/yellow]")
|
|
385
|
+
return
|
|
386
|
+
|
|
387
|
+
rich_print()
|
|
388
|
+
|
|
389
|
+
# Display prompts using clean compact format
|
|
390
|
+
for i, prompt in enumerate(all_prompts, 1):
|
|
391
|
+
# Main line: [ 1] server•prompt_name Title
|
|
392
|
+
from rich.text import Text
|
|
393
|
+
|
|
394
|
+
prompt_line = Text()
|
|
395
|
+
prompt_line.append(f"[{i:2}] ", style="dim cyan")
|
|
396
|
+
prompt_line.append(f"{prompt['server']}•", style="dim green")
|
|
397
|
+
prompt_line.append(prompt["name"], style="bright_blue bold")
|
|
398
|
+
|
|
399
|
+
# Add title if available
|
|
400
|
+
if prompt["title"] and prompt["title"].strip():
|
|
401
|
+
prompt_line.append(f" {prompt['title']}", style="default")
|
|
402
|
+
|
|
403
|
+
rich_print(prompt_line)
|
|
404
|
+
|
|
405
|
+
# Description lines - show 2-3 rows if needed
|
|
406
|
+
if prompt["description"] and prompt["description"].strip():
|
|
407
|
+
description = prompt["description"].strip()
|
|
408
|
+
# Calculate rough character limit for 2-3 lines (assuming ~80 chars per line with indent)
|
|
409
|
+
char_limit = 240 # About 3 lines worth
|
|
410
|
+
|
|
411
|
+
if len(description) > char_limit:
|
|
412
|
+
# Find a good break point near the limit (prefer sentence/word boundaries)
|
|
413
|
+
truncate_pos = char_limit
|
|
414
|
+
# Look back for sentence end
|
|
415
|
+
sentence_break = description.rfind(". ", 0, char_limit + 20)
|
|
416
|
+
if sentence_break > char_limit - 50: # If we found a nearby sentence break
|
|
417
|
+
truncate_pos = sentence_break + 1
|
|
418
|
+
else:
|
|
419
|
+
# Look for word boundary
|
|
420
|
+
word_break = description.rfind(" ", 0, char_limit + 10)
|
|
421
|
+
if word_break > char_limit - 30: # If we found a nearby word break
|
|
422
|
+
truncate_pos = word_break
|
|
423
|
+
|
|
424
|
+
description = description[:truncate_pos].rstrip() + "..."
|
|
425
|
+
|
|
426
|
+
# Split into lines and wrap
|
|
427
|
+
import textwrap
|
|
428
|
+
|
|
429
|
+
wrapped_lines = textwrap.wrap(description, width=72, subsequent_indent=" ")
|
|
430
|
+
for line in wrapped_lines:
|
|
431
|
+
if line.startswith(" "): # Already indented continuation line
|
|
432
|
+
rich_print(f" [white]{line[5:]}[/white]")
|
|
433
|
+
else: # First line needs indent
|
|
434
|
+
rich_print(f" [white]{line}[/white]")
|
|
435
|
+
|
|
436
|
+
# Arguments line - show argument names if available
|
|
437
|
+
if prompt["arg_count"] > 0:
|
|
438
|
+
arg_names = prompt.get("arg_names", [])
|
|
439
|
+
required_args = prompt.get("required_args", [])
|
|
440
|
+
|
|
441
|
+
if arg_names:
|
|
442
|
+
arg_list = []
|
|
443
|
+
for arg_name in arg_names:
|
|
444
|
+
if arg_name in required_args:
|
|
445
|
+
arg_list.append(f"{arg_name}*")
|
|
446
|
+
else:
|
|
447
|
+
arg_list.append(arg_name)
|
|
448
|
+
|
|
449
|
+
args_text = ", ".join(arg_list)
|
|
450
|
+
if len(args_text) > 80:
|
|
451
|
+
args_text = args_text[:77] + "..."
|
|
452
|
+
rich_print(f" [dim magenta]args: {args_text}[/dim magenta]")
|
|
453
|
+
else:
|
|
454
|
+
rich_print(
|
|
455
|
+
f" [dim magenta]args: {prompt['arg_count']} parameter{'s' if prompt['arg_count'] != 1 else ''}[/dim magenta]"
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
rich_print() # Space between prompts
|
|
459
|
+
|
|
460
|
+
# Add usage instructions
|
|
461
|
+
rich_print(
|
|
462
|
+
"[dim]Usage: /prompt <number> to select by number, or /prompts for interactive selection[/dim]"
|
|
463
|
+
)
|
|
339
464
|
|
|
340
|
-
# Add usage instructions
|
|
341
|
-
rich_print("\n[bold]Usage:[/bold]")
|
|
342
|
-
rich_print(" • Use [cyan]/prompt <number>[/cyan] to select a prompt by number")
|
|
343
|
-
rich_print(" • Or use [cyan]/prompts[/cyan] to open the prompt selection UI")
|
|
344
|
-
else:
|
|
345
|
-
rich_print("[yellow]No prompts available[/yellow]")
|
|
346
465
|
except Exception as e:
|
|
347
466
|
import traceback
|
|
348
467
|
|
|
@@ -364,15 +483,13 @@ class InteractivePrompt:
|
|
|
364
483
|
agent_name: Name of the agent
|
|
365
484
|
requested_name: Optional name of the prompt to apply
|
|
366
485
|
"""
|
|
367
|
-
console = Console()
|
|
368
|
-
|
|
369
486
|
try:
|
|
370
487
|
# Get all available prompts directly from the prompt provider
|
|
371
488
|
rich_print(f"\n[bold]Fetching prompts for agent [cyan]{agent_name}[/cyan]...[/bold]")
|
|
372
489
|
|
|
373
490
|
# Call list_prompts on the provider
|
|
374
491
|
prompt_servers = await prompt_provider.list_prompts(
|
|
375
|
-
|
|
492
|
+
namespace=None, agent_name=agent_name
|
|
376
493
|
)
|
|
377
494
|
|
|
378
495
|
if not prompt_servers:
|
|
@@ -487,40 +604,85 @@ class InteractivePrompt:
|
|
|
487
604
|
rich_print("[red]Invalid input, please enter a number[/red]")
|
|
488
605
|
return
|
|
489
606
|
else:
|
|
490
|
-
# Show prompt selection UI
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
#
|
|
505
|
-
if
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
607
|
+
# Show prompt selection UI using clean compact format
|
|
608
|
+
rich_print(f"\n[bold]Select a prompt for agent [cyan]{agent_name}[/cyan]:[/bold]")
|
|
609
|
+
rich_print()
|
|
610
|
+
|
|
611
|
+
# Display prompts using the same format as _list_prompts
|
|
612
|
+
for i, prompt in enumerate(all_prompts, 1):
|
|
613
|
+
# Main line: [ 1] server•prompt_name Title
|
|
614
|
+
from rich.text import Text
|
|
615
|
+
|
|
616
|
+
prompt_line = Text()
|
|
617
|
+
prompt_line.append(f"[{i:2}] ", style="dim cyan")
|
|
618
|
+
prompt_line.append(f"{prompt['server']}•", style="dim green")
|
|
619
|
+
prompt_line.append(prompt["name"], style="bright_blue bold")
|
|
620
|
+
|
|
621
|
+
# Add title if available
|
|
622
|
+
if prompt["title"] and prompt["title"].strip():
|
|
623
|
+
prompt_line.append(f" {prompt['title']}", style="default")
|
|
624
|
+
|
|
625
|
+
rich_print(prompt_line)
|
|
626
|
+
|
|
627
|
+
# Description lines - show 2-3 rows if needed
|
|
628
|
+
if prompt["description"] and prompt["description"].strip():
|
|
629
|
+
description = prompt["description"].strip()
|
|
630
|
+
# Calculate rough character limit for 2-3 lines (assuming ~80 chars per line with indent)
|
|
631
|
+
char_limit = 240 # About 3 lines worth
|
|
632
|
+
|
|
633
|
+
if len(description) > char_limit:
|
|
634
|
+
# Find a good break point near the limit (prefer sentence/word boundaries)
|
|
635
|
+
truncate_pos = char_limit
|
|
636
|
+
# Look back for sentence end
|
|
637
|
+
sentence_break = description.rfind(". ", 0, char_limit + 20)
|
|
638
|
+
if (
|
|
639
|
+
sentence_break > char_limit - 50
|
|
640
|
+
): # If we found a nearby sentence break
|
|
641
|
+
truncate_pos = sentence_break + 1
|
|
642
|
+
else:
|
|
643
|
+
# Look for word boundary
|
|
644
|
+
word_break = description.rfind(" ", 0, char_limit + 10)
|
|
645
|
+
if word_break > char_limit - 30: # If we found a nearby word break
|
|
646
|
+
truncate_pos = word_break
|
|
647
|
+
|
|
648
|
+
description = description[:truncate_pos].rstrip() + "..."
|
|
649
|
+
|
|
650
|
+
# Split into lines and wrap
|
|
651
|
+
import textwrap
|
|
652
|
+
|
|
653
|
+
wrapped_lines = textwrap.wrap(
|
|
654
|
+
description, width=72, subsequent_indent=" "
|
|
655
|
+
)
|
|
656
|
+
for line in wrapped_lines:
|
|
657
|
+
if line.startswith(" "): # Already indented continuation line
|
|
658
|
+
rich_print(f" [white]{line[5:]}[/white]")
|
|
659
|
+
else: # First line needs indent
|
|
660
|
+
rich_print(f" [white]{line}[/white]")
|
|
661
|
+
|
|
662
|
+
# Arguments line - show argument names if available
|
|
663
|
+
if prompt["arg_count"] > 0:
|
|
664
|
+
arg_names = prompt.get("arg_names", [])
|
|
665
|
+
required_args = prompt.get("required_args", [])
|
|
666
|
+
|
|
667
|
+
if arg_names:
|
|
668
|
+
arg_list = []
|
|
669
|
+
for arg_name in arg_names:
|
|
670
|
+
if arg_name in required_args:
|
|
671
|
+
arg_list.append(f"{arg_name}*")
|
|
672
|
+
else:
|
|
673
|
+
arg_list.append(arg_name)
|
|
674
|
+
|
|
675
|
+
args_text = ", ".join(arg_list)
|
|
676
|
+
if len(args_text) > 80:
|
|
677
|
+
args_text = args_text[:77] + "..."
|
|
678
|
+
rich_print(f" [dim magenta]args: {args_text}[/dim magenta]")
|
|
679
|
+
else:
|
|
680
|
+
rich_print(
|
|
681
|
+
f" [dim magenta]args: {prompt['arg_count']} parameter{'s' if prompt['arg_count'] != 1 else ''}[/dim magenta]"
|
|
682
|
+
)
|
|
683
|
+
|
|
684
|
+
rich_print() # Space between prompts
|
|
522
685
|
|
|
523
|
-
console.print(table)
|
|
524
686
|
prompt_names = [str(i + 1) for i in range(len(all_prompts))]
|
|
525
687
|
|
|
526
688
|
# Get user selection
|
|
@@ -595,12 +757,10 @@ class InteractivePrompt:
|
|
|
595
757
|
rich_print(f"\n[bold]Applying prompt [cyan]{namespaced_name}[/cyan]...[/bold]")
|
|
596
758
|
|
|
597
759
|
# Get the agent directly for generate() call
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
# This is a single agent
|
|
603
|
-
agent = prompt_provider
|
|
760
|
+
assert hasattr(prompt_provider, "_agent"), (
|
|
761
|
+
"Interactive prompt expects an AgentApp with _agent()"
|
|
762
|
+
)
|
|
763
|
+
agent = prompt_provider._agent(agent_name)
|
|
604
764
|
|
|
605
765
|
try:
|
|
606
766
|
# Use agent.apply_prompt() which handles everything properly:
|
|
@@ -620,9 +780,9 @@ class InteractivePrompt:
|
|
|
620
780
|
return
|
|
621
781
|
|
|
622
782
|
# Convert to multipart format
|
|
623
|
-
from
|
|
783
|
+
from fast_agent.types import PromptMessageExtended
|
|
624
784
|
|
|
625
|
-
multipart_messages =
|
|
785
|
+
multipart_messages = PromptMessageExtended.from_get_prompt_result(prompt_result)
|
|
626
786
|
|
|
627
787
|
# Now start progress display for the actual generation
|
|
628
788
|
progress_display.resume()
|
|
@@ -633,8 +793,7 @@ class InteractivePrompt:
|
|
|
633
793
|
progress_display.pause()
|
|
634
794
|
|
|
635
795
|
# Show usage info after the turn (same as send_wrapper does)
|
|
636
|
-
|
|
637
|
-
prompt_provider._show_turn_usage(agent_name)
|
|
796
|
+
prompt_provider._show_turn_usage(agent_name)
|
|
638
797
|
|
|
639
798
|
except Exception as e:
|
|
640
799
|
rich_print(f"[red]Error applying prompt: {e}[/red]")
|
|
@@ -653,18 +812,14 @@ class InteractivePrompt:
|
|
|
653
812
|
prompt_provider: Provider that implements list_tools
|
|
654
813
|
agent_name: Name of the agent
|
|
655
814
|
"""
|
|
656
|
-
console = Console()
|
|
657
|
-
|
|
658
815
|
try:
|
|
659
816
|
# Get agent to list tools from
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
# This is a single agent
|
|
665
|
-
agent = prompt_provider
|
|
817
|
+
assert hasattr(prompt_provider, "_agent"), (
|
|
818
|
+
"Interactive prompt expects an AgentApp with _agent()"
|
|
819
|
+
)
|
|
820
|
+
agent = prompt_provider._agent(agent_name)
|
|
666
821
|
|
|
667
|
-
rich_print(f"\n[bold]
|
|
822
|
+
rich_print(f"\n[bold]Tools for agent [cyan]{agent_name}[/cyan]:[/bold]")
|
|
668
823
|
|
|
669
824
|
# Get tools using list_tools
|
|
670
825
|
tools_result = await agent.list_tools()
|
|
@@ -673,23 +828,75 @@ class InteractivePrompt:
|
|
|
673
828
|
rich_print("[yellow]No tools available for this agent[/yellow]")
|
|
674
829
|
return
|
|
675
830
|
|
|
676
|
-
|
|
677
|
-
table = Table(title="Available MCP Tools")
|
|
678
|
-
table.add_column("#", justify="right", style="cyan")
|
|
679
|
-
table.add_column("Tool Name", style="bright_blue")
|
|
680
|
-
table.add_column("Title")
|
|
681
|
-
table.add_column("Description")
|
|
682
|
-
|
|
683
|
-
# Add tools to table
|
|
684
|
-
for i, tool in enumerate(tools_result.tools):
|
|
685
|
-
table.add_row(
|
|
686
|
-
str(i + 1),
|
|
687
|
-
tool.name,
|
|
688
|
-
tool.title or "No title",
|
|
689
|
-
tool.description or "No description",
|
|
690
|
-
)
|
|
831
|
+
rich_print()
|
|
691
832
|
|
|
692
|
-
|
|
833
|
+
# Display tools using clean compact format
|
|
834
|
+
for i, tool in enumerate(tools_result.tools, 1):
|
|
835
|
+
# Main line: [ 1] tool_name Title
|
|
836
|
+
from rich.text import Text
|
|
837
|
+
|
|
838
|
+
tool_line = Text()
|
|
839
|
+
tool_line.append(f"[{i:2}] ", style="dim cyan")
|
|
840
|
+
tool_line.append(tool.name, style="bright_blue bold")
|
|
841
|
+
|
|
842
|
+
# Add title if available
|
|
843
|
+
if tool.title and tool.title.strip():
|
|
844
|
+
tool_line.append(f" {tool.title}", style="default")
|
|
845
|
+
|
|
846
|
+
rich_print(tool_line)
|
|
847
|
+
|
|
848
|
+
# Description lines - show 2-3 rows if needed
|
|
849
|
+
if tool.description and tool.description.strip():
|
|
850
|
+
description = tool.description.strip()
|
|
851
|
+
# Calculate rough character limit for 2-3 lines (assuming ~80 chars per line with indent)
|
|
852
|
+
char_limit = 240 # About 3 lines worth
|
|
853
|
+
|
|
854
|
+
if len(description) > char_limit:
|
|
855
|
+
# Find a good break point near the limit (prefer sentence/word boundaries)
|
|
856
|
+
truncate_pos = char_limit
|
|
857
|
+
# Look back for sentence end
|
|
858
|
+
sentence_break = description.rfind(". ", 0, char_limit + 20)
|
|
859
|
+
if sentence_break > char_limit - 50: # If we found a nearby sentence break
|
|
860
|
+
truncate_pos = sentence_break + 1
|
|
861
|
+
else:
|
|
862
|
+
# Look for word boundary
|
|
863
|
+
word_break = description.rfind(" ", 0, char_limit + 10)
|
|
864
|
+
if word_break > char_limit - 30: # If we found a nearby word break
|
|
865
|
+
truncate_pos = word_break
|
|
866
|
+
|
|
867
|
+
description = description[:truncate_pos].rstrip() + "..."
|
|
868
|
+
|
|
869
|
+
# Split into lines and wrap
|
|
870
|
+
import textwrap
|
|
871
|
+
|
|
872
|
+
wrapped_lines = textwrap.wrap(description, width=72, subsequent_indent=" ")
|
|
873
|
+
for line in wrapped_lines:
|
|
874
|
+
if line.startswith(" "): # Already indented continuation line
|
|
875
|
+
rich_print(f" [white]{line[5:]}[/white]")
|
|
876
|
+
else: # First line needs indent
|
|
877
|
+
rich_print(f" [white]{line}[/white]")
|
|
878
|
+
|
|
879
|
+
# Arguments line - show schema info if available
|
|
880
|
+
if hasattr(tool, "inputSchema") and tool.inputSchema:
|
|
881
|
+
schema = tool.inputSchema
|
|
882
|
+
if "properties" in schema:
|
|
883
|
+
properties = schema["properties"]
|
|
884
|
+
required = schema.get("required", [])
|
|
885
|
+
|
|
886
|
+
arg_list = []
|
|
887
|
+
for prop_name, prop_info in properties.items():
|
|
888
|
+
if prop_name in required:
|
|
889
|
+
arg_list.append(f"{prop_name}*")
|
|
890
|
+
else:
|
|
891
|
+
arg_list.append(prop_name)
|
|
892
|
+
|
|
893
|
+
if arg_list:
|
|
894
|
+
args_text = ", ".join(arg_list)
|
|
895
|
+
if len(args_text) > 80:
|
|
896
|
+
args_text = args_text[:77] + "..."
|
|
897
|
+
rich_print(f" [dim magenta]args: {args_text}[/dim magenta]")
|
|
898
|
+
|
|
899
|
+
rich_print() # Space between tools
|
|
693
900
|
|
|
694
901
|
except Exception as e:
|
|
695
902
|
import traceback
|
|
@@ -729,12 +936,10 @@ class InteractivePrompt:
|
|
|
729
936
|
"""
|
|
730
937
|
try:
|
|
731
938
|
# Get agent to display from
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
# This is a single agent
|
|
737
|
-
agent = prompt_provider
|
|
939
|
+
assert hasattr(prompt_provider, "_agent"), (
|
|
940
|
+
"Interactive prompt expects an AgentApp with _agent()"
|
|
941
|
+
)
|
|
942
|
+
agent = prompt_provider._agent(agent_name)
|
|
738
943
|
|
|
739
944
|
# Check if agent has message history
|
|
740
945
|
if not hasattr(agent, "_llm") or not agent._llm:
|
|
@@ -764,7 +969,7 @@ class InteractivePrompt:
|
|
|
764
969
|
rich_print("\n[bold blue]Last Assistant Response (Plain Text):[/bold blue]")
|
|
765
970
|
rich_print("─" * 60)
|
|
766
971
|
# Use console.print with markup=False to display raw text
|
|
767
|
-
from
|
|
972
|
+
from fast_agent.ui import console
|
|
768
973
|
|
|
769
974
|
console.console.print(content, markup=False)
|
|
770
975
|
rich_print("─" * 60)
|