Skip to content

Commit 154f141

Browse files
authored
Merge pull request #11 from tanevanwifferen/master
no-intermediates feature
2 parents e917409 + cfe7b4a commit 154f141

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,15 @@ To bypass tool confirmation requirements, use the `--no-confirmations` flag:
101101
$ llm --no-confirmations "What is the top article on hackernews today?"
102102
```
103103
104+
To use in bash scripts, add the --no-intermediates, so it doesn't print intermediate messages, only the concluding end message.
105+
```bash
106+
$ llm --no-intermediates "What is the time in Tokyo right now?"
107+
```
108+
109+
```bash
110+
$ llm --no-confirmations "What is the top article on hackernews today?"
111+
```
112+
104113
### Continuation
105114

106115
Add a `c ` prefix to your message to continue the last conversation.

src/mcp_client_cli/cli.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class AgentState(TypedDict):
4646
today_datetime: str
4747
# The user's memories.
4848
memories: str = "no memories"
49+
remaining_steps: int = 5
4950

5051
async def run() -> None:
5152
"""Run the LLM agent."""
@@ -100,6 +101,8 @@ def setup_argument_parser() -> argparse.Namespace:
100101
help='Print output as raw text instead of parsing markdown')
101102
parser.add_argument('--no-tools', action='store_true',
102103
help='Do not add any tools')
104+
parser.add_argument('--no-intermediates', action='store_true',
105+
help='Only print the final message')
103106
parser.add_argument('--show-memories', action='store_true',
104107
help='Show user memories')
105108
return parser.parse_args()
@@ -234,9 +237,10 @@ async def handle_conversation(args: argparse.Namespace, query: HumanMessage,
234237
messages=[query],
235238
today_datetime=datetime.now().isoformat(),
236239
memories=formatted_memories,
240+
remaining_steps=3
237241
)
238242

239-
output = OutputHandler(text_only=args.text_only)
243+
output = OutputHandler(text_only=args.text_only, only_last_message=args.no_intermediates)
240244
output.start()
241245
try:
242246
async for chunk in agent_executor.astream(

src/mcp_client_cli/output.py

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1+
import json
12
from langchain_core.messages import BaseMessage, AIMessage, AIMessageChunk, ToolMessage
23
from rich.console import Console, ConsoleDimensions
34
from rich.live import Live
45
from rich.markdown import Markdown
56
from rich.prompt import Confirm
67

78
class OutputHandler:
8-
def __init__(self, text_only: bool = False):
9+
def __init__(self, text_only: bool = False, only_last_message: bool = False):
910
self.console = Console()
1011
self.text_only = text_only
12+
self.only_last_message = only_last_message
13+
self.last_message = ""
1114
if self.text_only:
1215
self.md = ""
1316
else:
@@ -26,6 +29,9 @@ def start(self):
2629

2730
def update(self, chunk: any):
2831
self.md = self._parse_chunk(chunk, self.md)
32+
if(self.only_last_message and self.text_only):
33+
# when only_last_message, we print in finish()
34+
return
2935
if self.text_only:
3036
self.console.print(self._parse_chunk(chunk), end="")
3137
else:
@@ -36,9 +42,13 @@ def update(self, chunk: any):
3642

3743
def update_error(self, error: Exception):
3844
import traceback
39-
self.md += f"Error: {error}\n\nStack trace:\n```\n{traceback.format_exc()}```"
45+
error = f"Error: {error}\n\nStack trace:\n```\n{traceback.format_exc()}```"
46+
self.md += error;
47+
if(self.only_last_message):
48+
self.console.print(error)
49+
return;
4050
if self.text_only:
41-
self.console.print(self.md)
51+
self.console.print_exception(self.md)
4252
else:
4353
partial_md = self._truncate_md_to_fit(self.md, self.console.size)
4454
self._live.update(Markdown(partial_md), refresh=True)
@@ -63,9 +73,12 @@ def confirm_tool_call(self, config: dict, chunk: any) -> bool:
6373

6474
def finish(self):
6575
self.stop()
66-
if not self.text_only:
76+
to_print = self.last_message if self.only_last_message else Markdown(self.md)
77+
if not self.text_only and not self.only_last_message:
6778
self.console.clear()
6879
self.console.print(Markdown(self.md))
80+
if self.only_last_message:
81+
self.console.print(to_print)
6982

7083
def _parse_chunk(self, chunk: any, md: str = "") -> str:
7184
"""
@@ -77,6 +90,7 @@ def _parse_chunk(self, chunk: any, md: str = "") -> str:
7790
message_chunk = chunk[1][0] # Get the message content
7891
if isinstance(message_chunk, AIMessageChunk):
7992
content = message_chunk.content
93+
self.last_message += content
8094
if isinstance(content, str):
8195
md += content
8296
elif isinstance(content, list) and len(content) > 0 and isinstance(content[0], dict) and "text" in content[0]:
@@ -85,6 +99,7 @@ def _parse_chunk(self, chunk: any, md: str = "") -> str:
8599
elif isinstance(chunk, dict) and "messages" in chunk:
86100
# Print a newline after the complete message
87101
md += "\n"
102+
self.last_message = ""
88103
elif isinstance(chunk, tuple) and chunk[0] == "values":
89104
message: BaseMessage = chunk[1]['messages'][-1]
90105
if isinstance(message, AIMessage) and message.tool_calls:
@@ -108,6 +123,7 @@ def _parse_chunk(self, chunk: any, md: str = "") -> str:
108123
lines.append(f"{arg}: {value}")
109124
lines.append("```\n")
110125
md += "\n".join(lines)
126+
self.last_message = ""
111127
elif isinstance(message, ToolMessage) and message.status != "success":
112128
md += "Failed call with error:"
113129
md += f"\n\n{message.content}"

0 commit comments

Comments
 (0)