fast-agent-mcp 0.2.43__py3-none-any.whl → 0.2.45__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 (37) hide show
  1. {fast_agent_mcp-0.2.43.dist-info → fast_agent_mcp-0.2.45.dist-info}/METADATA +6 -5
  2. {fast_agent_mcp-0.2.43.dist-info → fast_agent_mcp-0.2.45.dist-info}/RECORD +37 -36
  3. mcp_agent/agents/base_agent.py +60 -22
  4. mcp_agent/agents/workflow/evaluator_optimizer.py +39 -63
  5. mcp_agent/agents/workflow/router_agent.py +46 -21
  6. mcp_agent/config.py +2 -0
  7. mcp_agent/context.py +4 -0
  8. mcp_agent/core/agent_app.py +15 -5
  9. mcp_agent/core/direct_decorators.py +4 -5
  10. mcp_agent/core/enhanced_prompt.py +80 -11
  11. mcp_agent/core/fastagent.py +9 -1
  12. mcp_agent/core/interactive_prompt.py +60 -1
  13. mcp_agent/core/usage_display.py +10 -3
  14. mcp_agent/human_input/elicitation_form.py +16 -13
  15. mcp_agent/llm/augmented_llm.py +5 -7
  16. mcp_agent/llm/augmented_llm_passthrough.py +4 -0
  17. mcp_agent/llm/providers/augmented_llm_anthropic.py +258 -98
  18. mcp_agent/llm/providers/augmented_llm_bedrock.py +3 -3
  19. mcp_agent/llm/providers/augmented_llm_google_native.py +4 -7
  20. mcp_agent/llm/providers/augmented_llm_openai.py +5 -8
  21. mcp_agent/llm/providers/augmented_llm_tensorzero.py +6 -7
  22. mcp_agent/llm/providers/google_converter.py +6 -9
  23. mcp_agent/llm/providers/multipart_converter_anthropic.py +5 -4
  24. mcp_agent/llm/providers/multipart_converter_openai.py +33 -0
  25. mcp_agent/llm/providers/multipart_converter_tensorzero.py +3 -2
  26. mcp_agent/logging/rich_progress.py +6 -2
  27. mcp_agent/logging/transport.py +30 -36
  28. mcp_agent/mcp/helpers/content_helpers.py +26 -11
  29. mcp_agent/mcp/interfaces.py +22 -2
  30. mcp_agent/mcp/prompt_message_multipart.py +2 -3
  31. mcp_agent/resources/examples/workflows/evaluator.py +2 -2
  32. mcp_agent/resources/examples/workflows/router.py +1 -1
  33. mcp_agent/ui/console_display.py +363 -142
  34. mcp_agent/ui/console_display_legacy.py +401 -0
  35. {fast_agent_mcp-0.2.43.dist-info → fast_agent_mcp-0.2.45.dist-info}/WHEEL +0 -0
  36. {fast_agent_mcp-0.2.43.dist-info → fast_agent_mcp-0.2.45.dist-info}/entry_points.txt +0 -0
  37. {fast_agent_mcp-0.2.43.dist-info → fast_agent_mcp-0.2.45.dist-info}/licenses/LICENSE +0 -0
@@ -5,7 +5,7 @@ Direct AgentApp implementation for interacting with agents without proxies.
5
5
  from typing import Dict, List, Optional, Union
6
6
 
7
7
  from deprecated import deprecated
8
- from mcp.types import PromptMessage
8
+ from mcp.types import GetPromptResult, PromptMessage
9
9
  from rich import print as rich_print
10
10
 
11
11
  from mcp_agent.agents.agent import Agent
@@ -108,22 +108,26 @@ class AgentApp:
108
108
 
109
109
  async def apply_prompt(
110
110
  self,
111
- prompt_name: str,
111
+ prompt: Union[str, GetPromptResult],
112
112
  arguments: Dict[str, str] | None = None,
113
113
  agent_name: str | None = None,
114
+ as_template: bool = False,
114
115
  ) -> str:
115
116
  """
116
117
  Apply a prompt template to an agent (default agent if not specified).
117
118
 
118
119
  Args:
119
- prompt_name: Name of the prompt template to apply
120
+ prompt: Name of the prompt template to apply OR a GetPromptResult object
120
121
  arguments: Optional arguments for the prompt template
121
122
  agent_name: Name of the agent to send to
123
+ as_template: If True, store as persistent template (always included in context)
122
124
 
123
125
  Returns:
124
126
  The agent's response as a string
125
127
  """
126
- return await self._agent(agent_name).apply_prompt(prompt_name, arguments)
128
+ return await self._agent(agent_name).apply_prompt(
129
+ prompt, arguments, as_template=as_template
130
+ )
127
131
 
128
132
  async def list_prompts(self, server_name: str | None = None, agent_name: str | None = None):
129
133
  """
@@ -235,7 +239,12 @@ class AgentApp:
235
239
  """
236
240
  return await self.interactive(agent_name=agent_name, default_prompt=default_prompt)
237
241
 
238
- async def interactive(self, agent_name: str | None = None, default_prompt: str = "", pretty_print_parallel: bool = False) -> str:
242
+ async def interactive(
243
+ self,
244
+ agent_name: str | None = None,
245
+ default_prompt: str = "",
246
+ pretty_print_parallel: bool = False,
247
+ ) -> str:
239
248
  """
240
249
  Interactive prompt for sending messages with advanced features.
241
250
 
@@ -283,6 +292,7 @@ class AgentApp:
283
292
  agent = self._agents.get(agent_name)
284
293
  if agent and agent.agent_type == AgentType.PARALLEL:
285
294
  from mcp_agent.ui.console_display import ConsoleDisplay
295
+
286
296
  display = ConsoleDisplay(config=None)
287
297
  display.show_parallel_results(agent)
288
298
 
@@ -23,6 +23,9 @@ from typing import (
23
23
  from mcp.client.session import ElicitationFnT
24
24
 
25
25
  from mcp_agent.agents.agent import AgentConfig
26
+ from mcp_agent.agents.workflow.router_agent import (
27
+ ROUTING_SYSTEM_INSTRUCTION,
28
+ )
26
29
  from mcp_agent.core.agent_types import AgentType
27
30
  from mcp_agent.core.request_params import RequestParams
28
31
 
@@ -397,10 +400,6 @@ def router(
397
400
  Returns:
398
401
  A decorator that registers the router with proper type annotations
399
402
  """
400
- default_instruction = """
401
- You are a router that determines which specialized agent should handle a given query.
402
- Analyze the query and select the most appropriate agent to handle it.
403
- """
404
403
 
405
404
  return cast(
406
405
  "Callable[[AgentCallable[P, R]], DecoratedRouterProtocol[P, R]]",
@@ -408,7 +407,7 @@ def router(
408
407
  self,
409
408
  AgentType.ROUTER,
410
409
  name=name,
411
- instruction=instruction or default_instruction,
410
+ instruction=instruction or ROUTING_SYSTEM_INSTRUCTION,
412
411
  servers=servers,
413
412
  model=model,
414
413
  use_history=use_history,
@@ -106,15 +106,35 @@ async def _display_agent_info_helper(agent_name: str, agent_provider: object) ->
106
106
  else:
107
107
  # For regular agents, only display if they have MCP servers attached
108
108
  if server_count > 0:
109
- # Pluralization helpers
109
+ # Build display parts in order: tools, prompts, resources (omit if count is 0)
110
+ display_parts = []
111
+
112
+ if tool_count > 0:
113
+ tool_word = "tool" if tool_count == 1 else "tools"
114
+ display_parts.append(f"{tool_count:,}[dim] {tool_word}[/dim]")
115
+
116
+ if prompt_count > 0:
117
+ prompt_word = "prompt" if prompt_count == 1 else "prompts"
118
+ display_parts.append(f"{prompt_count:,}[dim] {prompt_word}[/dim]")
119
+
120
+ if resource_count > 0:
121
+ resource_word = "resource" if resource_count == 1 else "resources"
122
+ display_parts.append(f"{resource_count:,}[dim] {resource_word}[/dim]")
123
+
124
+ # Always show server count
110
125
  server_word = "Server" if server_count == 1 else "Servers"
111
- tool_word = "tool" if tool_count == 1 else "tools"
112
- resource_word = "resource" if resource_count == 1 else "resources"
113
- prompt_word = "prompt" if prompt_count == 1 else "prompts"
126
+ server_text = f"{server_count:,}[dim] MCP {server_word}[/dim]"
114
127
 
115
- rich_print(
116
- f"[dim]Agent [/dim][blue]{agent_name}[/blue][dim]:[/dim] {server_count:,}[dim] MCP {server_word}, [/dim]{tool_count:,}[dim] {tool_word}, [/dim]{resource_count:,}[dim] {resource_word}, [/dim]{prompt_count:,}[dim] {prompt_word} available[/dim]"
117
- )
128
+ if display_parts:
129
+ content = (
130
+ f"{server_text}[dim], [/dim]"
131
+ + "[dim], [/dim]".join(display_parts)
132
+ + "[dim] available[/dim]"
133
+ )
134
+ else:
135
+ content = f"{server_text}[dim] available[/dim]"
136
+
137
+ rich_print(f"[dim]Agent [/dim][blue]{agent_name}[/blue][dim]:[/dim] {content}")
118
138
 
119
139
  # Mark as shown
120
140
  _agent_info_shown.add(agent_name)
@@ -274,6 +294,7 @@ class AgentCompleter(Completer):
274
294
  "prompt": "List and select MCP prompts, or apply specific prompt (/prompt <name>)",
275
295
  "agents": "List available agents",
276
296
  "usage": "Show current usage statistics",
297
+ "markdown": "Show last assistant message without markdown formatting",
277
298
  "help": "Show available commands",
278
299
  "clear": "Clear the screen",
279
300
  "STOP": "Stop this prompting session and move to next workflow step",
@@ -398,7 +419,7 @@ def get_text_from_editor(initial_text: str = "") -> str:
398
419
  return edited_text.strip() # Added strip() to remove trailing newlines often added by editors
399
420
 
400
421
 
401
- def create_keybindings(on_toggle_multiline=None, app=None):
422
+ def create_keybindings(on_toggle_multiline=None, app=None, agent_provider=None, agent_name=None):
402
423
  """Create custom key bindings."""
403
424
  kb = KeyBindings()
404
425
 
@@ -463,6 +484,40 @@ def create_keybindings(on_toggle_multiline=None, app=None):
463
484
  if event.app:
464
485
  event.app.invalidate()
465
486
 
487
+ # Store reference to agent provider and agent name for clipboard functionality
488
+ kb.agent_provider = agent_provider
489
+ kb.current_agent_name = agent_name
490
+
491
+ @kb.add("c-y")
492
+ async def _(event) -> None:
493
+ """Ctrl+Y: Copy last assistant response to clipboard."""
494
+ if kb.agent_provider and kb.current_agent_name:
495
+ try:
496
+ # Get the agent
497
+ if hasattr(kb.agent_provider, "_agent"):
498
+ agent = kb.agent_provider._agent(kb.current_agent_name)
499
+ else:
500
+ agent = kb.agent_provider
501
+
502
+ # Get message history
503
+ if hasattr(agent, "_llm") and agent._llm and agent._llm.message_history:
504
+ # Find last assistant message
505
+ for msg in reversed(agent._llm.message_history):
506
+ if msg.role == "assistant":
507
+ content = msg.last_text()
508
+ import pyperclip
509
+
510
+ pyperclip.copy(content)
511
+ rich_print("\n[green]✓ Copied to clipboard[/green]")
512
+ return
513
+
514
+ else:
515
+ pass
516
+ except Exception:
517
+ pass
518
+ else:
519
+ pass
520
+
466
521
  return kb
467
522
 
468
523
 
@@ -527,6 +582,7 @@ async def get_enhanced_input(
527
582
  shortcuts = [
528
583
  ("Ctrl+T", toggle_text),
529
584
  ("Ctrl+E", "External"),
585
+ ("Ctrl+Y", "Copy"),
530
586
  ("Ctrl+L", "Clear"),
531
587
  ("↑/↓", "History"),
532
588
  ]
@@ -569,7 +625,12 @@ async def get_enhanced_input(
569
625
  )
570
626
 
571
627
  # Create key bindings with a reference to the app
572
- bindings = create_keybindings(on_toggle_multiline=on_multiline_toggle, app=session.app)
628
+ bindings = create_keybindings(
629
+ on_toggle_multiline=on_multiline_toggle,
630
+ app=session.app,
631
+ agent_provider=agent_provider,
632
+ agent_name=agent_name,
633
+ )
573
634
  session.app.key_bindings = bindings
574
635
 
575
636
  # Create formatted prompt text
@@ -619,6 +680,8 @@ async def get_enhanced_input(
619
680
  return "LIST_AGENTS"
620
681
  elif cmd == "usage":
621
682
  return "SHOW_USAGE"
683
+ elif cmd == "markdown":
684
+ return "MARKDOWN"
622
685
  elif cmd == "prompt":
623
686
  # Handle /prompt with no arguments as interactive mode
624
687
  if len(cmd_parts) > 1:
@@ -792,16 +855,18 @@ async def handle_special_commands(command, agent_app=None):
792
855
  rich_print(" /help - Show this help")
793
856
  rich_print(" /clear - Clear screen")
794
857
  rich_print(" /agents - List available agents")
795
- rich_print(" /prompts - List and select MCP prompts")
796
858
  rich_print(" /prompt <name> - Apply a specific prompt by name")
797
859
  rich_print(" /usage - Show current usage statistics")
860
+ rich_print(" /markdown - Show last assistant message without markdown formatting")
798
861
  rich_print(" @agent_name - Switch to agent")
799
862
  rich_print(" STOP - Return control back to the workflow")
800
863
  rich_print(" EXIT - Exit fast-agent, terminating any running workflows")
801
864
  rich_print("\n[bold]Keyboard Shortcuts:[/bold]")
802
865
  rich_print(" Enter - Submit (normal mode) / New line (multiline mode)")
803
- rich_print(" Ctrl+Enter - Always submit (in any mode)")
866
+ rich_print(" Ctrl+Enter - Always submit (in any mode)")
804
867
  rich_print(" Ctrl+T - Toggle multiline mode")
868
+ rich_print(" Ctrl+E - Edit in external editor")
869
+ rich_print(" Ctrl+Y - Copy last assistant response to clipboard")
805
870
  rich_print(" Ctrl+L - Clear input")
806
871
  rich_print(" Up/Down - Navigate history")
807
872
  return True
@@ -827,6 +892,10 @@ async def handle_special_commands(command, agent_app=None):
827
892
  # Return a dictionary to signal that usage should be shown
828
893
  return {"show_usage": True}
829
894
 
895
+ elif command == "MARKDOWN":
896
+ # Return a dictionary to signal that markdown display should be shown
897
+ return {"show_markdown": True}
898
+
830
899
  elif command == "SELECT_PROMPT" or (
831
900
  isinstance(command, str) and command.startswith("SELECT_PROMPT:")
832
901
  ):
@@ -314,7 +314,7 @@ class FastAgent:
314
314
  self.agents,
315
315
  model_factory_func,
316
316
  )
317
-
317
+
318
318
  # Validate API keys after agent creation
319
319
  validate_provider_keys_post_creation(active_agents)
320
320
 
@@ -435,6 +435,14 @@ class FastAgent:
435
435
  raise SystemExit(1)
436
436
 
437
437
  finally:
438
+ # Ensure progress display is stopped before showing usage summary
439
+ try:
440
+ from mcp_agent.progress_display import progress_display
441
+
442
+ progress_display.stop()
443
+ except: # noqa: E722
444
+ pass
445
+
438
446
  # Print usage report before cleanup (show for user exits too)
439
447
  if active_agents and not had_error:
440
448
  self._print_usage_report(active_agents)
@@ -30,7 +30,7 @@ from mcp_agent.core.enhanced_prompt import (
30
30
  handle_special_commands,
31
31
  )
32
32
  from mcp_agent.core.usage_display import collect_agents_from_provider, display_usage_report
33
- from mcp_agent.mcp.mcp_aggregator import SEP # Import SEP once at the top
33
+ from mcp_agent.mcp.mcp_aggregator import SEP
34
34
  from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
35
35
  from mcp_agent.progress_display import progress_display
36
36
 
@@ -56,6 +56,7 @@ class PromptProvider(Protocol):
56
56
  prompt_title: Optional[str] = None,
57
57
  arguments: Optional[Dict[str, str]] = None,
58
58
  agent_name: Optional[str] = None,
59
+ as_template: bool = False,
59
60
  **kwargs,
60
61
  ) -> str:
61
62
  """Apply a prompt."""
@@ -188,6 +189,10 @@ class InteractivePrompt:
188
189
  # Handle usage display
189
190
  await self._show_usage(prompt_provider, agent)
190
191
  continue
192
+ elif "show_markdown" in command_result:
193
+ # Handle markdown display
194
+ await self._show_markdown(prompt_provider, agent)
195
+ continue
191
196
 
192
197
  # Skip further processing if:
193
198
  # 1. The command was handled (command_result is truthy)
@@ -713,3 +718,57 @@ class InteractivePrompt:
713
718
 
714
719
  except Exception as e:
715
720
  rich_print(f"[red]Error showing usage: {e}[/red]")
721
+
722
+ async def _show_markdown(self, prompt_provider: PromptProvider, agent_name: str) -> None:
723
+ """
724
+ Show the last assistant message without markdown formatting.
725
+
726
+ Args:
727
+ prompt_provider: Provider that has access to agents
728
+ agent_name: Name of the current agent
729
+ """
730
+ try:
731
+ # Get agent to display from
732
+ if hasattr(prompt_provider, "_agent"):
733
+ # This is an AgentApp - get the specific agent
734
+ agent = prompt_provider._agent(agent_name)
735
+ else:
736
+ # This is a single agent
737
+ agent = prompt_provider
738
+
739
+ # Check if agent has message history
740
+ if not hasattr(agent, "_llm") or not agent._llm:
741
+ rich_print("[yellow]No message history available[/yellow]")
742
+ return
743
+
744
+ message_history = agent._llm.message_history
745
+ if not message_history:
746
+ rich_print("[yellow]No messages in history[/yellow]")
747
+ return
748
+
749
+ # Find the last assistant message
750
+ last_assistant_msg = None
751
+ for msg in reversed(message_history):
752
+ if msg.role == "assistant":
753
+ last_assistant_msg = msg
754
+ break
755
+
756
+ if not last_assistant_msg:
757
+ rich_print("[yellow]No assistant messages found[/yellow]")
758
+ return
759
+
760
+ # Get the text content and display without markdown
761
+ content = last_assistant_msg.last_text()
762
+
763
+ # Display with a simple header
764
+ rich_print("\n[bold blue]Last Assistant Response (Plain Text):[/bold blue]")
765
+ rich_print("─" * 60)
766
+ # Use console.print with markup=False to display raw text
767
+ from mcp_agent import console
768
+
769
+ console.console.print(content, markup=False)
770
+ rich_print("─" * 60)
771
+ rich_print()
772
+
773
+ except Exception as e:
774
+ rich_print(f"[red]Error showing markdown: {e}[/red]")
@@ -91,12 +91,19 @@ def display_usage_report(
91
91
  max_agent_width = min(15, max(len(data["name"]) for data in usage_data) if usage_data else 8)
92
92
  agent_width = max(max_agent_width, 5) # Minimum of 5 for "Agent" header
93
93
 
94
- # Display the table
94
+ # Display the table with new visual style
95
95
  console = Console()
96
+
97
+ # Top separator
98
+ console.print()
99
+ console.print("─" * console.size.width, style="dim")
100
+ console.print()
101
+
102
+ # Header with block character
103
+ console.print("[dim]▎[/dim] [bold dim]Usage Summary[/bold dim]")
96
104
  console.print()
97
- console.print("[dim]Usage Summary (Cumulative)[/dim]")
98
105
 
99
- # Print header with proper spacing
106
+ # Table header with proper spacing
100
107
  console.print(
101
108
  f"[dim]{'Agent':<{agent_width}} {'Input':>9} {'Output':>9} {'Total':>9} {'Turns':>6} {'Tools':>6} {'Context%':>9} {'Model':<25}[/dim]"
102
109
  )
@@ -5,6 +5,7 @@ from typing import Any, Dict, Optional
5
5
 
6
6
  from mcp.types import ElicitRequestedSchema
7
7
  from prompt_toolkit import Application
8
+ from prompt_toolkit.application.current import get_app
8
9
  from prompt_toolkit.buffer import Buffer
9
10
  from prompt_toolkit.filters import Condition
10
11
  from prompt_toolkit.formatted_text import FormattedText
@@ -272,29 +273,32 @@ class ElicitationForm:
272
273
  keep_focused_window_visible=True,
273
274
  )
274
275
 
275
- # Create title bar manually
276
- title_bar = Window(
277
- FormattedTextControl(FormattedText([("class:title", "Elicitation Request")])),
278
- height=1,
279
- style="class:dialog.title",
280
- )
281
-
282
- # Combine title, sticky headers, and scrollable content
276
+ # Combine sticky headers and scrollable content (no separate title bar needed)
283
277
  full_content = HSplit(
284
278
  [
285
- title_bar,
286
- Window(height=1), # Spacing after title
279
+ Window(height=1), # Top spacing
287
280
  sticky_headers, # Headers stay fixed at top
288
281
  scrollable_content, # Form fields can scroll
289
282
  ]
290
283
  )
291
284
 
292
- # Create dialog frame manually to avoid Dialog's internal scrolling
285
+ # Create dialog frame with title
293
286
  dialog = Frame(
294
287
  body=full_content,
288
+ title="Elicitation Request",
295
289
  style="class:dialog",
296
290
  )
297
291
 
292
+ # Apply width constraints by putting Frame in VSplit with flexible spacers
293
+ # This prevents console display interference and constrains the Frame border
294
+ constrained_dialog = VSplit(
295
+ [
296
+ Window(width=10), # Smaller left spacer
297
+ dialog,
298
+ Window(width=10), # Smaller right spacer
299
+ ]
300
+ )
301
+
298
302
  # Key bindings
299
303
  kb = KeyBindings()
300
304
 
@@ -370,7 +374,7 @@ class ElicitationForm:
370
374
  # Add toolbar to the layout
371
375
  root_layout = HSplit(
372
376
  [
373
- dialog, # The main dialog
377
+ constrained_dialog, # The width-constrained dialog
374
378
  self._toolbar_window,
375
379
  ]
376
380
  )
@@ -588,7 +592,6 @@ class ElicitationForm:
588
592
 
589
593
  def _is_in_multiline_field(self) -> bool:
590
594
  """Check if currently focused field is a multiline field."""
591
- from prompt_toolkit.application.current import get_app
592
595
 
593
596
  focused = get_app().layout.current_control
594
597
 
@@ -46,7 +46,6 @@ from mcp_agent.mcp.interfaces import (
46
46
  from mcp_agent.mcp.mcp_aggregator import MCPAggregator
47
47
  from mcp_agent.mcp.prompt_message_multipart import PromptMessageMultipart
48
48
  from mcp_agent.mcp.prompt_render import render_multipart_message
49
- from mcp_agent.ui.console_display import ConsoleDisplay
50
49
 
51
50
  # Define type variables locally
52
51
  MessageParamT = TypeVar("MessageParamT")
@@ -157,6 +156,10 @@ class AugmentedLLM(ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT
157
156
  self._message_history: List[PromptMessageMultipart] = []
158
157
 
159
158
  # Initialize the display component
159
+ if self.context.config and self.context.config.logger.use_legacy_display:
160
+ from mcp_agent.ui.console_display_legacy import ConsoleDisplay
161
+ else:
162
+ from mcp_agent.ui.console_display import ConsoleDisplay
160
163
  self.display = ConsoleDisplay(config=self.context.config)
161
164
 
162
165
  # Tool call counter for current turn
@@ -209,8 +212,6 @@ class AugmentedLLM(ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT
209
212
  # note - check changes here are mirrored in structured(). i've thought hard about
210
213
  # a strategy to reduce duplication etc, but aiming for simple but imperfect for the moment
211
214
 
212
- # We never expect this for structured() calls - this is for interactive use - developers
213
- # can do this programatically
214
215
  # TODO -- create a "fast-agent" control role rather than magic strings
215
216
 
216
217
  if multipart_messages[-1].first_text().startswith("***SAVE_HISTORY"):
@@ -232,6 +233,7 @@ class AugmentedLLM(ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT
232
233
 
233
234
  # add generic error and termination reason handling/rollback
234
235
  self._message_history.append(assistant_response)
236
+
235
237
  return assistant_response
236
238
 
237
239
  @abstractmethod
@@ -448,10 +450,6 @@ class AugmentedLLM(ContextDependent, AugmentedLLMProtocol, Generic[MessageParamT
448
450
  """Display a tool result in a formatted panel."""
449
451
  self.display.show_tool_result(result, name=self.name)
450
452
 
451
- def show_oai_tool_result(self, result: str) -> None:
452
- """Display a tool result in a formatted panel."""
453
- self.display.show_oai_tool_result(result, name=self.name)
454
-
455
453
  def show_tool_call(self, available_tools, tool_name, tool_args) -> None:
456
454
  """Display a tool call in a formatted panel."""
457
455
  self._current_turn_tool_calls += 1
@@ -162,7 +162,11 @@ class PassthroughLLM(AugmentedLLM):
162
162
  self,
163
163
  multipart_messages: List["PromptMessageMultipart"],
164
164
  request_params: RequestParams | None = None,
165
+ is_template: bool = False,
165
166
  ) -> PromptMessageMultipart:
167
+ # Add messages to history with proper is_prompt flag
168
+ self.history.extend(multipart_messages, is_prompt=is_template)
169
+
166
170
  last_message = multipart_messages[-1]
167
171
 
168
172
  if self.is_tool_call(last_message):