Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb7edb2e

Browse files
committed
feat(cli): add interactive chat mode with flexible configuration
- Add interactive chat loop that continues until 'exit' or Ctrl-C- Support separate --mcp-config and --model-config flags- Add --config-dir flag for specifying config directory- Implement automatic config discovery (config.json -> separate configs)- Add default checkpointer for persistent chat history- Refactor checkpointer path as constant- Update README with English documentation and new flags
1 parenta78e29a commitb7edb2e

File tree

1 file changed

+90
-23
lines changed

1 file changed

+90
-23
lines changed

‎dive_mcp_host/cli/cli.py‎

Lines changed: 90 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
importargparse
44
importjson
5+
importsys
56
frompathlibimportPath
67

78
fromlangchain_core.messagesimportAIMessage,HumanMessage
@@ -11,6 +12,10 @@
1112
fromdive_mcp_host.host.confimportHostConfig
1213
fromdive_mcp_host.host.hostimportDiveMcpHost
1314

15+
# Default paths for CLI
16+
CLI_DATA_DIR=Path.home()/".dive_mcp_host"
17+
CHECKPOINTER_PATH=CLI_DATA_DIR/"checkpoints.db"
18+
1419

1520
defparse_query(args:type[CLIArgs])->HumanMessage:
1621
"""Parse the query from the command line arguments."""
@@ -75,7 +80,16 @@ def setup_argument_parser() -> type[CLIArgs]:
7580
defload_config(config_path:str)->HostConfig:
7681
"""Load the configuration."""
7782
withPath(config_path).open("r")asf:
78-
returnHostConfig.model_validate_json(f.read())
83+
config_data=json.load(f)
84+
85+
# Add default checkpointer if not present
86+
if"checkpointer"notinconfig_data:
87+
CHECKPOINTER_PATH.parent.mkdir(parents=True,exist_ok=True)
88+
config_data["checkpointer"]= {
89+
"uri":f"sqlite:///{CHECKPOINTER_PATH}"
90+
}
91+
92+
returnHostConfig.model_validate(config_data)
7993

8094

8195
defload_merged_config(mcp_config_path:str,model_config_path:str)->HostConfig:
@@ -105,10 +119,16 @@ def load_merged_config(mcp_config_path: str, model_config_path: str) -> HostConf
105119
server_config_with_name= {**server_config,"name":server_name}
106120
mcp_servers[server_name]=server_config_with_name
107121

122+
# Setup default checkpointer for CLI (use sqlite in home directory)
123+
CHECKPOINTER_PATH.parent.mkdir(parents=True,exist_ok=True)
124+
108125
# Merge configs
109126
merged_config= {
110127
"llm":active_config,
111-
"mcp_servers":mcp_servers
128+
"mcp_servers":mcp_servers,
129+
"checkpointer": {
130+
"uri":f"sqlite:///{CHECKPOINTER_PATH}"
131+
}
112132
}
113133

114134
returnHostConfig.model_validate(merged_config)
@@ -117,7 +137,11 @@ def load_merged_config(mcp_config_path: str, model_config_path: str) -> HostConf
117137
asyncdefrun()->None:
118138
"""dive_mcp_host CLI entrypoint."""
119139
args=setup_argument_parser()
120-
query=parse_query(args)
140+
141+
# Get initial query if provided
142+
initial_query=None
143+
ifargs.query:
144+
initial_query=parse_query(args)
121145

122146
# Load config based on provided arguments
123147
ifargs.config_path:
@@ -151,23 +175,66 @@ async def run() -> None:
151175
system_prompt=f.read()
152176

153177
output_parser=StrOutputParser()
154-
asyncwithDiveMcpHost(config)asmcp_host:
155-
print("Waiting for tools to initialize...")
156-
awaitmcp_host.tools_initialized_event.wait()
157-
print("Tools initialized")
158-
chat=mcp_host.chat(chat_id=current_chat_id,system_prompt=system_prompt)
159-
current_chat_id=chat.chat_id
160-
asyncwithchat:
161-
asyncforresponseinchat.query(query,stream_mode="messages"):
162-
assertisinstance(response,tuple)
163-
msg=response[0]
164-
ifisinstance(msg,AIMessage):
165-
content=output_parser.invoke(msg)
166-
print(content,end="")
167-
continue
168-
print(f"\n\n==== Start Of{type(msg)} ===")
169-
print(msg)
170-
print(f"==== End Of{type(msg)} ===\n")
171-
172-
print()
173-
print(f"Chat ID:{current_chat_id}")
178+
179+
try:
180+
asyncwithDiveMcpHost(config)asmcp_host:
181+
print("Waiting for tools to initialize...")
182+
awaitmcp_host.tools_initialized_event.wait()
183+
print("Tools initialized")
184+
print("="*60)
185+
186+
chat=mcp_host.chat(chat_id=current_chat_id,system_prompt=system_prompt)
187+
current_chat_id=chat.chat_id
188+
189+
asyncwithchat:
190+
# Process initial query if provided
191+
ifinitial_query:
192+
awaitprocess_query(chat,initial_query,output_parser)
193+
194+
# Start interactive chat loop
195+
print("\nChat started. Type 'exit' or press Ctrl-C to quit.")
196+
print(f"Chat ID:{current_chat_id}")
197+
print("="*60)
198+
199+
whileTrue:
200+
try:
201+
# Read user input
202+
user_input=input("\nYou: ").strip()
203+
204+
ifnotuser_input:
205+
continue
206+
207+
# Check for exit commands
208+
ifuser_input.lower()in ["exit","quit"]:
209+
print("\nGoodbye!")
210+
break
211+
212+
# Process the query
213+
query=HumanMessage(content=user_input)
214+
print("\nAssistant: ",end="")
215+
awaitprocess_query(chat,query,output_parser)
216+
217+
exceptEOFError:
218+
# Handle Ctrl-D
219+
print("\n\nGoodbye!")
220+
break
221+
222+
exceptKeyboardInterrupt:
223+
# Handle Ctrl-C
224+
print("\n\nGoodbye!")
225+
sys.exit(0)
226+
227+
228+
asyncdefprocess_query(chat,query:HumanMessage,output_parser:StrOutputParser)->None:
229+
"""Process a single query and print the response."""
230+
asyncforresponseinchat.query(query,stream_mode="messages"):
231+
assertisinstance(response,tuple)
232+
msg=response[0]
233+
ifisinstance(msg,AIMessage):
234+
content=output_parser.invoke(msg)
235+
print(content,end="")
236+
continue
237+
print(f"\n\n==== Start Of{type(msg)} ===")
238+
print(msg)
239+
print(f"==== End Of{type(msg)} ===\n")
240+
print()# Add newline after response

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp