Skip to content

Commit e7d513b

Browse files
ryx2claude
andauthored
Add message_history parameter to agent.to_cli() (#2674)
Co-authored-by: Claude <[email protected]>
1 parent e467c9e commit e7d513b

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed

pydantic_ai_slim/pydantic_ai/_cli.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,15 @@ async def run_chat(
228228
prog_name: str,
229229
config_dir: Path | None = None,
230230
deps: AgentDepsT = None,
231+
message_history: list[ModelMessage] | None = None,
231232
) -> int:
232233
prompt_history_path = (config_dir or PYDANTIC_AI_HOME) / PROMPT_HISTORY_FILENAME
233234
prompt_history_path.parent.mkdir(parents=True, exist_ok=True)
234235
prompt_history_path.touch(exist_ok=True)
235236
session: PromptSession[Any] = PromptSession(history=FileHistory(str(prompt_history_path)))
236237

237238
multiline = False
238-
messages: list[ModelMessage] = []
239+
messages: list[ModelMessage] = message_history[:] if message_history else []
239240

240241
while True:
241242
try:

pydantic_ai_slim/pydantic_ai/agent/abstract.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -899,12 +899,18 @@ def to_a2a(
899899
lifespan=lifespan,
900900
)
901901

902-
async def to_cli(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
902+
async def to_cli(
903+
self: Self,
904+
deps: AgentDepsT = None,
905+
prog_name: str = 'pydantic-ai',
906+
message_history: list[_messages.ModelMessage] | None = None,
907+
) -> None:
903908
"""Run the agent in a CLI chat interface.
904909
905910
Args:
906911
deps: The dependencies to pass to the agent.
907912
prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
913+
message_history: History of the conversation so far.
908914
909915
Example:
910916
```python {title="agent_to_cli.py" test="skip"}
@@ -920,14 +926,28 @@ async def main():
920926

921927
from pydantic_ai._cli import run_chat
922928

923-
await run_chat(stream=True, agent=self, deps=deps, console=Console(), code_theme='monokai', prog_name=prog_name)
929+
await run_chat(
930+
stream=True,
931+
agent=self,
932+
deps=deps,
933+
console=Console(),
934+
code_theme='monokai',
935+
prog_name=prog_name,
936+
message_history=message_history,
937+
)
924938

925-
def to_cli_sync(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-ai') -> None:
939+
def to_cli_sync(
940+
self: Self,
941+
deps: AgentDepsT = None,
942+
prog_name: str = 'pydantic-ai',
943+
message_history: list[_messages.ModelMessage] | None = None,
944+
) -> None:
926945
"""Run the agent in a CLI chat interface with the non-async interface.
927946
928947
Args:
929948
deps: The dependencies to pass to the agent.
930949
prog_name: The name of the program to use for the CLI. Defaults to 'pydantic-ai'.
950+
message_history: History of the conversation so far.
931951
932952
```python {title="agent_to_cli_sync.py" test="skip"}
933953
from pydantic_ai import Agent
@@ -937,4 +957,6 @@ def to_cli_sync(self: Self, deps: AgentDepsT = None, prog_name: str = 'pydantic-
937957
agent.to_cli_sync(prog_name='assistant')
938958
```
939959
"""
940-
return get_event_loop().run_until_complete(self.to_cli(deps=deps, prog_name=prog_name))
960+
return get_event_loop().run_until_complete(
961+
self.to_cli(deps=deps, prog_name=prog_name, message_history=message_history)
962+
)

tests/test_cli.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ def test_agent_to_cli_sync(mocker: MockerFixture, env: TestEnv):
292292
code_theme='monokai',
293293
prog_name='pydantic-ai',
294294
deps=None,
295+
message_history=None,
295296
)
296297

297298

@@ -307,4 +308,44 @@ async def test_agent_to_cli_async(mocker: MockerFixture, env: TestEnv):
307308
code_theme='monokai',
308309
prog_name='pydantic-ai',
309310
deps=None,
311+
message_history=None,
312+
)
313+
314+
315+
@pytest.mark.anyio
316+
async def test_agent_to_cli_with_message_history(mocker: MockerFixture, env: TestEnv):
317+
env.set('OPENAI_API_KEY', 'test')
318+
mock_run_chat = mocker.patch('pydantic_ai._cli.run_chat')
319+
320+
# Create some test message history - cast to the proper base type
321+
test_messages: list[ModelMessage] = [ModelResponse(parts=[TextPart('Hello!')])]
322+
323+
await cli_agent.to_cli(message_history=test_messages)
324+
mock_run_chat.assert_awaited_once_with(
325+
stream=True,
326+
agent=IsInstance(Agent),
327+
console=IsInstance(Console),
328+
code_theme='monokai',
329+
prog_name='pydantic-ai',
330+
deps=None,
331+
message_history=test_messages,
332+
)
333+
334+
335+
def test_agent_to_cli_sync_with_message_history(mocker: MockerFixture, env: TestEnv):
336+
env.set('OPENAI_API_KEY', 'test')
337+
mock_run_chat = mocker.patch('pydantic_ai._cli.run_chat')
338+
339+
# Create some test message history - cast to the proper base type
340+
test_messages: list[ModelMessage] = [ModelResponse(parts=[TextPart('Hello!')])]
341+
342+
cli_agent.to_cli_sync(message_history=test_messages)
343+
mock_run_chat.assert_awaited_once_with(
344+
stream=True,
345+
agent=IsInstance(Agent),
346+
console=IsInstance(Console),
347+
code_theme='monokai',
348+
prog_name='pydantic-ai',
349+
deps=None,
350+
message_history=test_messages,
310351
)

0 commit comments

Comments
 (0)