fast-agent-mcp 0.3.14__py3-none-any.whl → 0.3.16__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.

Files changed (49) hide show
  1. fast_agent/__init__.py +2 -0
  2. fast_agent/agents/agent_types.py +5 -0
  3. fast_agent/agents/llm_agent.py +52 -4
  4. fast_agent/agents/llm_decorator.py +6 -0
  5. fast_agent/agents/mcp_agent.py +137 -13
  6. fast_agent/agents/tool_agent.py +33 -19
  7. fast_agent/agents/workflow/router_agent.py +2 -1
  8. fast_agent/cli/__main__.py +35 -0
  9. fast_agent/cli/commands/check_config.py +90 -2
  10. fast_agent/cli/commands/go.py +100 -36
  11. fast_agent/cli/constants.py +13 -1
  12. fast_agent/cli/main.py +1 -0
  13. fast_agent/config.py +41 -12
  14. fast_agent/constants.py +8 -0
  15. fast_agent/context.py +24 -15
  16. fast_agent/core/direct_decorators.py +9 -0
  17. fast_agent/core/fastagent.py +115 -2
  18. fast_agent/core/logging/listeners.py +8 -0
  19. fast_agent/core/validation.py +31 -33
  20. fast_agent/human_input/form_fields.py +4 -1
  21. fast_agent/interfaces.py +12 -1
  22. fast_agent/llm/fastagent_llm.py +76 -0
  23. fast_agent/llm/memory.py +26 -1
  24. fast_agent/llm/model_database.py +2 -2
  25. fast_agent/llm/model_factory.py +4 -1
  26. fast_agent/llm/provider/anthropic/llm_anthropic.py +112 -0
  27. fast_agent/llm/provider/openai/llm_openai.py +184 -18
  28. fast_agent/llm/provider/openai/responses.py +133 -0
  29. fast_agent/mcp/prompt_message_extended.py +2 -2
  30. fast_agent/resources/setup/agent.py +2 -0
  31. fast_agent/resources/setup/fastagent.config.yaml +11 -4
  32. fast_agent/skills/__init__.py +9 -0
  33. fast_agent/skills/registry.py +200 -0
  34. fast_agent/tools/shell_runtime.py +404 -0
  35. fast_agent/ui/console_display.py +925 -73
  36. fast_agent/ui/elicitation_form.py +98 -24
  37. fast_agent/ui/elicitation_style.py +2 -2
  38. fast_agent/ui/enhanced_prompt.py +128 -26
  39. fast_agent/ui/history_display.py +20 -5
  40. fast_agent/ui/interactive_prompt.py +108 -3
  41. fast_agent/ui/markdown_truncator.py +942 -0
  42. fast_agent/ui/mcp_display.py +2 -2
  43. fast_agent/ui/plain_text_truncator.py +68 -0
  44. fast_agent/ui/streaming_buffer.py +449 -0
  45. {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.16.dist-info}/METADATA +9 -7
  46. {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.16.dist-info}/RECORD +49 -42
  47. {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.16.dist-info}/WHEEL +0 -0
  48. {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.16.dist-info}/entry_points.txt +0 -0
  49. {fast_agent_mcp-0.3.14.dist-info → fast_agent_mcp-0.3.16.dist-info}/licenses/LICENSE +0 -0
@@ -14,6 +14,7 @@ Usage:
14
14
  )
15
15
  """
16
16
 
17
+ from pathlib import Path
17
18
  from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Union, cast
18
19
 
19
20
  if TYPE_CHECKING:
@@ -169,6 +170,9 @@ class InteractivePrompt:
169
170
  # Handle tools list display
170
171
  await self._list_tools(prompt_provider, agent)
171
172
  continue
173
+ elif "list_skills" in command_dict:
174
+ await self._list_skills(prompt_provider, agent)
175
+ continue
172
176
  elif "show_usage" in command_dict:
173
177
  # Handle usage display
174
178
  await self._show_usage(prompt_provider, agent)
@@ -189,6 +193,41 @@ class InteractivePrompt:
189
193
  usage = getattr(agent_obj, "usage_accumulator", None)
190
194
  display_history_overview(target_agent, history, usage)
191
195
  continue
196
+ elif "clear_last" in command_dict:
197
+ clear_info = command_dict.get("clear_last")
198
+ clear_agent = (
199
+ clear_info.get("agent") if isinstance(clear_info, dict) else None
200
+ )
201
+ target_agent = clear_agent or agent
202
+ try:
203
+ agent_obj = prompt_provider._agent(target_agent)
204
+ except Exception:
205
+ rich_print(f"[red]Unable to load agent '{target_agent}'[/red]")
206
+ continue
207
+
208
+ removed_message = None
209
+ pop_callable = getattr(agent_obj, "pop_last_message", None)
210
+ if callable(pop_callable):
211
+ removed_message = pop_callable()
212
+ else:
213
+ history = getattr(agent_obj, "message_history", [])
214
+ if history:
215
+ try:
216
+ removed_message = history.pop()
217
+ except Exception:
218
+ removed_message = None
219
+
220
+ if removed_message:
221
+ role = getattr(removed_message, "role", "message")
222
+ role_display = role.capitalize() if isinstance(role, str) else "Message"
223
+ rich_print(
224
+ f"[green]Removed last {role_display} for agent '{target_agent}'.[/green]"
225
+ )
226
+ else:
227
+ rich_print(
228
+ f"[yellow]No messages to remove for agent '{target_agent}'.[/yellow]"
229
+ )
230
+ continue
192
231
  elif "clear_history" in command_dict:
193
232
  clear_info = command_dict.get("clear_history")
194
233
  clear_agent = (
@@ -857,19 +896,21 @@ class InteractivePrompt:
857
896
  rich_print()
858
897
 
859
898
  # Display tools using clean compact format
860
- for i, tool in enumerate(tools_result.tools, 1):
899
+ index = 1
900
+ for tool in tools_result.tools:
861
901
  # Main line: [ 1] tool_name Title
862
902
  from rich.text import Text
863
903
 
904
+ meta = getattr(tool, "meta", {}) or {}
905
+
864
906
  tool_line = Text()
865
- tool_line.append(f"[{i:2}] ", style="dim cyan")
907
+ tool_line.append(f"[{index:2}] ", style="dim cyan")
866
908
  tool_line.append(tool.name, style="bright_blue bold")
867
909
 
868
910
  # Add title if available
869
911
  if tool.title and tool.title.strip():
870
912
  tool_line.append(f" {tool.title}", style="default")
871
913
 
872
- meta = getattr(tool, "meta", {}) or {}
873
914
  if meta.get("openai/skybridgeEnabled"):
874
915
  tool_line.append(" (skybridge)", style="cyan")
875
916
 
@@ -932,13 +973,77 @@ class InteractivePrompt:
932
973
  rich_print(f" [dim magenta]template:[/dim magenta] {template}")
933
974
 
934
975
  rich_print() # Space between tools
976
+ index += 1
935
977
 
978
+ if index == 1:
979
+ rich_print("[yellow]No MCP tools available for this agent[/yellow]")
936
980
  except Exception as e:
937
981
  import traceback
938
982
 
939
983
  rich_print(f"[red]Error listing tools: {e}[/red]")
940
984
  rich_print(f"[dim]{traceback.format_exc()}[/dim]")
941
985
 
986
+ async def _list_skills(self, prompt_provider: "AgentApp", agent_name: str) -> None:
987
+ """List available local skills for an agent."""
988
+
989
+ try:
990
+ assert hasattr(prompt_provider, "_agent"), (
991
+ "Interactive prompt expects an AgentApp with _agent()"
992
+ )
993
+ agent = prompt_provider._agent(agent_name)
994
+
995
+ rich_print(f"\n[bold]Skills for agent [cyan]{agent_name}[/cyan]:[/bold]")
996
+
997
+ skill_manifests = getattr(agent, "_skill_manifests", None)
998
+ manifests = list(skill_manifests) if skill_manifests else []
999
+
1000
+ if not manifests:
1001
+ rich_print("[yellow]No skills available for this agent[/yellow]")
1002
+ return
1003
+
1004
+ rich_print()
1005
+
1006
+ for index, manifest in enumerate(manifests, 1):
1007
+ from rich.text import Text
1008
+
1009
+ name = getattr(manifest, "name", "")
1010
+ description = getattr(manifest, "description", "")
1011
+ path = Path(getattr(manifest, "path", Path()))
1012
+
1013
+ tool_line = Text()
1014
+ tool_line.append(f"[{index:2}] ", style="dim cyan")
1015
+ tool_line.append(name, style="bright_blue bold")
1016
+ rich_print(tool_line)
1017
+
1018
+ if description:
1019
+ import textwrap
1020
+
1021
+ wrapped_lines = textwrap.wrap(
1022
+ description.strip(), width=72, subsequent_indent=" "
1023
+ )
1024
+ for line in wrapped_lines:
1025
+ if line.startswith(" "):
1026
+ rich_print(f" [white]{line[5:]}[/white]")
1027
+ else:
1028
+ rich_print(f" [white]{line}[/white]")
1029
+
1030
+ source_path = path if path else Path(".")
1031
+ if source_path.is_file():
1032
+ source_path = source_path.parent
1033
+ try:
1034
+ display_path = source_path.relative_to(Path.cwd())
1035
+ except ValueError:
1036
+ display_path = source_path
1037
+
1038
+ rich_print(f" [dim green]source:[/dim green] {display_path}")
1039
+ rich_print()
1040
+
1041
+ except Exception as exc: # noqa: BLE001
1042
+ import traceback
1043
+
1044
+ rich_print(f"[red]Error listing skills: {exc}[/red]")
1045
+ rich_print(f"[dim]{traceback.format_exc()}[/dim]")
1046
+
942
1047
  async def _show_usage(self, prompt_provider: "AgentApp", agent_name: str) -> None:
943
1048
  """
944
1049
  Show usage statistics for the current agent(s) in a colorful table format.