minion-code 0.1.0__py3-none-any.whl → 0.1.2__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.
- examples/cli_entrypoint.py +60 -0
- examples/{agent_with_todos.py → components/agent_with_todos.py} +58 -47
- examples/{message_response_children_demo.py → components/message_response_children_demo.py} +61 -55
- examples/components/messages_component.py +199 -0
- examples/file_freshness_example.py +22 -22
- examples/file_watching_example.py +32 -26
- examples/interruptible_tui.py +921 -3
- examples/repl_tui.py +129 -0
- examples/skills/example_usage.py +57 -0
- examples/start.py +173 -0
- minion_code/__init__.py +1 -1
- minion_code/acp_server/__init__.py +34 -0
- minion_code/acp_server/agent.py +539 -0
- minion_code/acp_server/hooks.py +354 -0
- minion_code/acp_server/main.py +194 -0
- minion_code/acp_server/permissions.py +142 -0
- minion_code/acp_server/test_client.py +104 -0
- minion_code/adapters/__init__.py +22 -0
- minion_code/adapters/output_adapter.py +207 -0
- minion_code/adapters/rich_adapter.py +169 -0
- minion_code/adapters/textual_adapter.py +254 -0
- minion_code/agents/__init__.py +2 -2
- minion_code/agents/code_agent.py +517 -104
- minion_code/agents/hooks.py +378 -0
- minion_code/cli.py +538 -429
- minion_code/cli_simple.py +665 -0
- minion_code/commands/__init__.py +136 -29
- minion_code/commands/clear_command.py +19 -46
- minion_code/commands/help_command.py +33 -49
- minion_code/commands/history_command.py +37 -55
- minion_code/commands/model_command.py +194 -0
- minion_code/commands/quit_command.py +9 -12
- minion_code/commands/resume_command.py +181 -0
- minion_code/commands/skill_command.py +89 -0
- minion_code/commands/status_command.py +48 -73
- minion_code/commands/tools_command.py +54 -52
- minion_code/commands/version_command.py +34 -69
- minion_code/components/ConfirmDialog.py +430 -0
- minion_code/components/Message.py +318 -97
- minion_code/components/MessageResponse.py +30 -29
- minion_code/components/Messages.py +351 -0
- minion_code/components/PromptInput.py +499 -245
- minion_code/components/__init__.py +24 -17
- minion_code/const.py +7 -0
- minion_code/screens/REPL.py +1453 -469
- minion_code/screens/__init__.py +1 -1
- minion_code/services/__init__.py +20 -20
- minion_code/services/event_system.py +19 -14
- minion_code/services/file_freshness_service.py +223 -170
- minion_code/skills/__init__.py +25 -0
- minion_code/skills/skill.py +128 -0
- minion_code/skills/skill_loader.py +198 -0
- minion_code/skills/skill_registry.py +177 -0
- minion_code/subagents/__init__.py +31 -0
- minion_code/subagents/builtin/__init__.py +30 -0
- minion_code/subagents/builtin/claude_code_guide.py +32 -0
- minion_code/subagents/builtin/explore.py +36 -0
- minion_code/subagents/builtin/general_purpose.py +19 -0
- minion_code/subagents/builtin/plan.py +61 -0
- minion_code/subagents/subagent.py +116 -0
- minion_code/subagents/subagent_loader.py +147 -0
- minion_code/subagents/subagent_registry.py +151 -0
- minion_code/tools/__init__.py +8 -2
- minion_code/tools/bash_tool.py +16 -3
- minion_code/tools/file_edit_tool.py +201 -104
- minion_code/tools/file_read_tool.py +183 -26
- minion_code/tools/file_write_tool.py +17 -3
- minion_code/tools/glob_tool.py +23 -2
- minion_code/tools/grep_tool.py +229 -21
- minion_code/tools/ls_tool.py +28 -3
- minion_code/tools/multi_edit_tool.py +89 -84
- minion_code/tools/python_interpreter_tool.py +9 -1
- minion_code/tools/skill_tool.py +210 -0
- minion_code/tools/task_tool.py +287 -0
- minion_code/tools/todo_read_tool.py +28 -24
- minion_code/tools/todo_write_tool.py +82 -65
- minion_code/{types.py → type_defs.py} +15 -2
- minion_code/utils/__init__.py +45 -17
- minion_code/utils/config.py +610 -0
- minion_code/utils/history.py +114 -0
- minion_code/utils/logs.py +53 -0
- minion_code/utils/mcp_loader.py +153 -55
- minion_code/utils/output_truncator.py +233 -0
- minion_code/utils/session_storage.py +369 -0
- minion_code/utils/todo_file_utils.py +26 -22
- minion_code/utils/todo_storage.py +43 -33
- minion_code/web/__init__.py +9 -0
- minion_code/web/adapters/__init__.py +5 -0
- minion_code/web/adapters/web_adapter.py +524 -0
- minion_code/web/api/__init__.py +7 -0
- minion_code/web/api/chat.py +277 -0
- minion_code/web/api/interactions.py +136 -0
- minion_code/web/api/sessions.py +135 -0
- minion_code/web/server.py +149 -0
- minion_code/web/services/__init__.py +5 -0
- minion_code/web/services/session_manager.py +420 -0
- minion_code-0.1.2.dist-info/METADATA +476 -0
- minion_code-0.1.2.dist-info/RECORD +111 -0
- {minion_code-0.1.0.dist-info → minion_code-0.1.2.dist-info}/WHEEL +1 -1
- minion_code-0.1.2.dist-info/entry_points.txt +6 -0
- tests/test_adapter.py +67 -0
- tests/test_adapter_simple.py +79 -0
- tests/test_file_read_tool.py +144 -0
- tests/test_readonly_tools.py +0 -2
- tests/test_skills.py +441 -0
- examples/advance_tui.py +0 -508
- examples/rich_example.py +0 -4
- examples/simple_file_watching.py +0 -57
- examples/simple_tui.py +0 -267
- examples/simple_usage.py +0 -69
- minion_code-0.1.0.dist-info/METADATA +0 -350
- minion_code-0.1.0.dist-info/RECORD +0 -59
- minion_code-0.1.0.dist-info/entry_points.txt +0 -4
- {minion_code-0.1.0.dist-info → minion_code-0.1.2.dist-info}/licenses/LICENSE +0 -0
- {minion_code-0.1.0.dist-info → minion_code-0.1.2.dist-info}/top_level.txt +0 -0
examples/simple_tui.py
DELETED
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# -*- coding: utf-8 -*-
|
|
3
|
-
"""
|
|
4
|
-
Simple TUI using MinionCodeAgent
|
|
5
|
-
|
|
6
|
-
This example shows how the new MinionCodeAgent class simplifies
|
|
7
|
-
the TUI implementation by handling all the tool setup internally.
|
|
8
|
-
|
|
9
|
-
Compare this with minion_agent_tui.py to see the reduction in boilerplate code.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import asyncio
|
|
13
|
-
import sys
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
|
|
16
|
-
# Add project root to path
|
|
17
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
18
|
-
|
|
19
|
-
from minion_code import MinionCodeAgent
|
|
20
|
-
from minion_code.commands import command_registry
|
|
21
|
-
from rich.console import Console
|
|
22
|
-
from rich.panel import Panel
|
|
23
|
-
from rich.text import Text
|
|
24
|
-
from rich.markdown import Markdown
|
|
25
|
-
from rich.table import Table
|
|
26
|
-
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
27
|
-
from rich.prompt import Prompt
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class SimpleTUI:
|
|
31
|
-
"""Simplified TUI using MinionCodeAgent."""
|
|
32
|
-
|
|
33
|
-
def __init__(self):
|
|
34
|
-
self.agent = None
|
|
35
|
-
self.running = True
|
|
36
|
-
self.console = Console()
|
|
37
|
-
|
|
38
|
-
async def setup(self):
|
|
39
|
-
"""Setup the agent."""
|
|
40
|
-
with Progress(
|
|
41
|
-
SpinnerColumn(),
|
|
42
|
-
TextColumn("[progress.description]{task.description}"),
|
|
43
|
-
console=self.console,
|
|
44
|
-
) as progress:
|
|
45
|
-
task = progress.add_task("🔧 Setting up MinionCodeAgent...", total=None)
|
|
46
|
-
|
|
47
|
-
# Much simpler setup - no manual tool configuration needed
|
|
48
|
-
self.agent = await MinionCodeAgent.create(
|
|
49
|
-
name="Simple TUI Assistant",
|
|
50
|
-
llm="gpt-4o-mini",
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
progress.update(task, completed=True)
|
|
54
|
-
|
|
55
|
-
success_panel = Panel(
|
|
56
|
-
f"✅ Agent ready with [bold green]{len(self.agent.tools)}[/bold green] tools!",
|
|
57
|
-
title="[bold green]Setup Complete[/bold green]",
|
|
58
|
-
border_style="green"
|
|
59
|
-
)
|
|
60
|
-
self.console.print(success_panel)
|
|
61
|
-
|
|
62
|
-
def show_help(self):
|
|
63
|
-
"""Show help information."""
|
|
64
|
-
help_table = Table(title="📚 Simple TUI Help", show_header=True, header_style="bold blue")
|
|
65
|
-
help_table.add_column("Command", style="cyan", no_wrap=True)
|
|
66
|
-
help_table.add_column("Description", style="white")
|
|
67
|
-
|
|
68
|
-
help_table.add_row("help", "Show this help")
|
|
69
|
-
help_table.add_row("tools", "List available tools")
|
|
70
|
-
help_table.add_row("history", "Show conversation history")
|
|
71
|
-
help_table.add_row("clear", "Clear history")
|
|
72
|
-
help_table.add_row("quit", "Exit")
|
|
73
|
-
|
|
74
|
-
self.console.print(help_table)
|
|
75
|
-
self.console.print("\n💡 [italic]Just type your message to chat with the AI agent![/italic]")
|
|
76
|
-
|
|
77
|
-
async def process_input(self, user_input: str):
|
|
78
|
-
"""Process user input."""
|
|
79
|
-
user_input = user_input.strip()
|
|
80
|
-
|
|
81
|
-
# Check if it's a command (starts with /)
|
|
82
|
-
if user_input.startswith('/'):
|
|
83
|
-
await self.process_command(user_input)
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
# Process with agent
|
|
87
|
-
try:
|
|
88
|
-
with Progress(
|
|
89
|
-
SpinnerColumn(),
|
|
90
|
-
TextColumn("[progress.description]{task.description}"),
|
|
91
|
-
console=self.console,
|
|
92
|
-
) as progress:
|
|
93
|
-
task = progress.add_task("🤖 Processing...", total=None)
|
|
94
|
-
response = await self.agent.run_async(user_input)
|
|
95
|
-
progress.update(task, completed=True)
|
|
96
|
-
|
|
97
|
-
# Display agent response with rich formatting
|
|
98
|
-
if "```" in response.answer:
|
|
99
|
-
# If response contains code blocks, render as markdown
|
|
100
|
-
agent_content = Markdown(response.answer)
|
|
101
|
-
else:
|
|
102
|
-
agent_content = response.answer
|
|
103
|
-
|
|
104
|
-
response_panel = Panel(
|
|
105
|
-
agent_content,
|
|
106
|
-
title="🤖 [bold green]Agent Response[/bold green]",
|
|
107
|
-
border_style="green"
|
|
108
|
-
)
|
|
109
|
-
self.console.print(response_panel)
|
|
110
|
-
|
|
111
|
-
except Exception as e:
|
|
112
|
-
error_panel = Panel(
|
|
113
|
-
f"❌ [bold red]Error: {e}[/bold red]",
|
|
114
|
-
title="[bold red]Error[/bold red]",
|
|
115
|
-
border_style="red"
|
|
116
|
-
)
|
|
117
|
-
self.console.print(error_panel)
|
|
118
|
-
|
|
119
|
-
async def process_command(self, command_input: str):
|
|
120
|
-
"""Process a command input."""
|
|
121
|
-
# Remove the leading /
|
|
122
|
-
command_input = command_input[1:] if command_input.startswith('/') else command_input
|
|
123
|
-
|
|
124
|
-
# Split command and arguments
|
|
125
|
-
parts = command_input.split(' ', 1)
|
|
126
|
-
command_name = parts[0].lower()
|
|
127
|
-
args = parts[1] if len(parts) > 1 else ""
|
|
128
|
-
|
|
129
|
-
# Get command class
|
|
130
|
-
command_class = command_registry.get_command(command_name)
|
|
131
|
-
if not command_class:
|
|
132
|
-
error_panel = Panel(
|
|
133
|
-
f"❌ [bold red]Unknown command: /{command_name}[/bold red]\n"
|
|
134
|
-
f"💡 [italic]Use '/help' to see available commands[/italic]",
|
|
135
|
-
title="[bold red]Error[/bold red]",
|
|
136
|
-
border_style="red"
|
|
137
|
-
)
|
|
138
|
-
self.console.print(error_panel)
|
|
139
|
-
return
|
|
140
|
-
|
|
141
|
-
# Create and execute command
|
|
142
|
-
try:
|
|
143
|
-
command_instance = command_class(self.console, self.agent)
|
|
144
|
-
|
|
145
|
-
# Special handling for quit command
|
|
146
|
-
if command_name in ["quit", "exit", "q", "bye"]:
|
|
147
|
-
command_instance._tui_instance = self
|
|
148
|
-
|
|
149
|
-
await command_instance.execute(args)
|
|
150
|
-
|
|
151
|
-
except Exception as e:
|
|
152
|
-
error_panel = Panel(
|
|
153
|
-
f"❌ [bold red]Error executing command /{command_name}: {e}[/bold red]",
|
|
154
|
-
title="[bold red]Command Error[/bold red]",
|
|
155
|
-
border_style="red"
|
|
156
|
-
)
|
|
157
|
-
self.console.print(error_panel)
|
|
158
|
-
|
|
159
|
-
def show_tools(self):
|
|
160
|
-
"""Show available tools in a beautiful table."""
|
|
161
|
-
if not self.agent or not self.agent.tools:
|
|
162
|
-
self.console.print("❌ No tools available")
|
|
163
|
-
return
|
|
164
|
-
|
|
165
|
-
tools_table = Table(title="🛠️ Available Tools", show_header=True, header_style="bold magenta")
|
|
166
|
-
tools_table.add_column("Tool Name", style="cyan", no_wrap=True)
|
|
167
|
-
tools_table.add_column("Description", style="white")
|
|
168
|
-
tools_table.add_column("Type", style="yellow")
|
|
169
|
-
|
|
170
|
-
for tool in self.agent.tools:
|
|
171
|
-
tool_type = "Read-only" if getattr(tool, 'readonly', False) else "Read-write"
|
|
172
|
-
tools_table.add_row(
|
|
173
|
-
tool.name,
|
|
174
|
-
tool.description[:60] + "..." if len(tool.description) > 60 else tool.description,
|
|
175
|
-
tool_type
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
self.console.print(tools_table)
|
|
179
|
-
|
|
180
|
-
def show_history(self):
|
|
181
|
-
"""Show conversation history in a beautiful format."""
|
|
182
|
-
if not self.agent:
|
|
183
|
-
return
|
|
184
|
-
|
|
185
|
-
history = self.agent.get_conversation_history()
|
|
186
|
-
if not history:
|
|
187
|
-
no_history_panel = Panel(
|
|
188
|
-
"📝 [italic]No conversation history yet.[/italic]",
|
|
189
|
-
title="[bold blue]History[/bold blue]",
|
|
190
|
-
border_style="blue"
|
|
191
|
-
)
|
|
192
|
-
self.console.print(no_history_panel)
|
|
193
|
-
return
|
|
194
|
-
|
|
195
|
-
history_panel = Panel(
|
|
196
|
-
f"📝 [bold blue]Conversation History ({len(history)} messages)[/bold blue]",
|
|
197
|
-
border_style="blue"
|
|
198
|
-
)
|
|
199
|
-
self.console.print(history_panel)
|
|
200
|
-
|
|
201
|
-
for i, entry in enumerate(history[-5:], 1): # Show last 5 messages
|
|
202
|
-
# User message
|
|
203
|
-
user_panel = Panel(
|
|
204
|
-
entry['user_message'][:200] + "..." if len(entry['user_message']) > 200 else entry['user_message'],
|
|
205
|
-
title=f"👤 [bold cyan]You (Message {len(history)-5+i})[/bold cyan]",
|
|
206
|
-
border_style="cyan"
|
|
207
|
-
)
|
|
208
|
-
self.console.print(user_panel)
|
|
209
|
-
|
|
210
|
-
# Agent response
|
|
211
|
-
agent_response = entry['agent_response'][:200] + "..." if len(entry['agent_response']) > 200 else entry['agent_response']
|
|
212
|
-
agent_panel = Panel(
|
|
213
|
-
agent_response,
|
|
214
|
-
title="🤖 [bold green]Agent[/bold green]",
|
|
215
|
-
border_style="green"
|
|
216
|
-
)
|
|
217
|
-
self.console.print(agent_panel)
|
|
218
|
-
self.console.print() # Add spacing
|
|
219
|
-
|
|
220
|
-
async def run(self):
|
|
221
|
-
"""Run the TUI."""
|
|
222
|
-
# Welcome banner
|
|
223
|
-
welcome_panel = Panel(
|
|
224
|
-
"🚀 [bold blue]Simple MinionCodeAgent TUI[/bold blue]\n"
|
|
225
|
-
"💡 [italic]Use '/help' for commands or just chat with the agent![/italic]\n"
|
|
226
|
-
"🛑 [italic]Type '/quit' to exit[/italic]",
|
|
227
|
-
title="[bold magenta]Welcome[/bold magenta]",
|
|
228
|
-
border_style="magenta"
|
|
229
|
-
)
|
|
230
|
-
self.console.print(welcome_panel)
|
|
231
|
-
|
|
232
|
-
await self.setup()
|
|
233
|
-
|
|
234
|
-
while self.running:
|
|
235
|
-
try:
|
|
236
|
-
# Use rich prompt for better input experience
|
|
237
|
-
user_input = Prompt.ask(
|
|
238
|
-
"\n[bold cyan]👤 You[/bold cyan]",
|
|
239
|
-
console=self.console
|
|
240
|
-
).strip()
|
|
241
|
-
|
|
242
|
-
if user_input:
|
|
243
|
-
await self.process_input(user_input)
|
|
244
|
-
|
|
245
|
-
except (EOFError, KeyboardInterrupt):
|
|
246
|
-
goodbye_panel = Panel(
|
|
247
|
-
"\n👋 [bold yellow]Goodbye![/bold yellow]",
|
|
248
|
-
title="[bold red]Exit[/bold red]",
|
|
249
|
-
border_style="red"
|
|
250
|
-
)
|
|
251
|
-
self.console.print(goodbye_panel)
|
|
252
|
-
break
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
async def main():
|
|
256
|
-
"""Main function."""
|
|
257
|
-
tui = SimpleTUI()
|
|
258
|
-
await tui.run()
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
def run():
|
|
262
|
-
"""Synchronous entry point."""
|
|
263
|
-
asyncio.run(main())
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if __name__ == "__main__":
|
|
267
|
-
run()
|
examples/simple_usage.py
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""Simple usage example of FileFreshnessService."""
|
|
3
|
-
|
|
4
|
-
import os
|
|
5
|
-
import sys
|
|
6
|
-
|
|
7
|
-
# Add parent directory to path for imports
|
|
8
|
-
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
9
|
-
|
|
10
|
-
from minion_code.services import (
|
|
11
|
-
record_file_read,
|
|
12
|
-
record_file_edit,
|
|
13
|
-
check_file_freshness,
|
|
14
|
-
generate_file_modification_reminder,
|
|
15
|
-
add_event_listener,
|
|
16
|
-
emit_event,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def main():
|
|
21
|
-
"""Simple usage demonstration."""
|
|
22
|
-
|
|
23
|
-
# Set up a simple event listener
|
|
24
|
-
def on_conflict(context):
|
|
25
|
-
print(f"⚠️ Conflict: {context.data['file_path']}")
|
|
26
|
-
|
|
27
|
-
add_event_listener('file:conflict', on_conflict)
|
|
28
|
-
|
|
29
|
-
# Create test file
|
|
30
|
-
test_file = "example.py"
|
|
31
|
-
with open(test_file, "w") as f:
|
|
32
|
-
f.write("print('Hello, World!')")
|
|
33
|
-
|
|
34
|
-
# Record reading the file
|
|
35
|
-
record_file_read(test_file)
|
|
36
|
-
print(f"✅ Recorded reading {test_file}")
|
|
37
|
-
|
|
38
|
-
# Check freshness (should be fresh)
|
|
39
|
-
result = check_file_freshness(test_file)
|
|
40
|
-
print(f"📊 File is fresh: {result.is_fresh}")
|
|
41
|
-
|
|
42
|
-
# Simulate external modification
|
|
43
|
-
with open(test_file, "w") as f:
|
|
44
|
-
f.write("print('Modified externally!')")
|
|
45
|
-
|
|
46
|
-
# Check freshness again (should detect conflict)
|
|
47
|
-
result = check_file_freshness(test_file)
|
|
48
|
-
print(f"📊 After external change - Fresh: {result.is_fresh}, Conflict: {result.conflict}")
|
|
49
|
-
|
|
50
|
-
# Generate reminder for external modification
|
|
51
|
-
reminder = generate_file_modification_reminder(test_file)
|
|
52
|
-
if reminder:
|
|
53
|
-
print(f"💡 Reminder: {reminder}")
|
|
54
|
-
|
|
55
|
-
# Record agent edit (resolves conflict)
|
|
56
|
-
record_file_edit(test_file, "print('Agent fixed this!')")
|
|
57
|
-
print(f"✅ Agent edited {test_file}")
|
|
58
|
-
|
|
59
|
-
# Check freshness after agent edit
|
|
60
|
-
result = check_file_freshness(test_file)
|
|
61
|
-
print(f"📊 After agent edit - Fresh: {result.is_fresh}, Conflict: {result.conflict}")
|
|
62
|
-
|
|
63
|
-
# Cleanup
|
|
64
|
-
os.remove(test_file)
|
|
65
|
-
print("🧹 Cleaned up test file")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if __name__ == "__main__":
|
|
69
|
-
main()
|
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: minion-code
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: A Python project depending on minion
|
|
5
|
-
Author-email: User <user@example.com>
|
|
6
|
-
Requires-Python: >=3.8
|
|
7
|
-
Description-Content-Type: text/markdown
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Requires-Dist: minionx
|
|
10
|
-
Requires-Dist: typer>=0.9.0
|
|
11
|
-
Provides-Extra: dev
|
|
12
|
-
Requires-Dist: pytest; extra == "dev"
|
|
13
|
-
Requires-Dist: black; extra == "dev"
|
|
14
|
-
Requires-Dist: flake8; extra == "dev"
|
|
15
|
-
Requires-Dist: mypy; extra == "dev"
|
|
16
|
-
Provides-Extra: tui
|
|
17
|
-
Requires-Dist: textual>=0.40.0; extra == "tui"
|
|
18
|
-
Requires-Dist: rich>=13.0.0; extra == "tui"
|
|
19
|
-
Provides-Extra: agent
|
|
20
|
-
Requires-Dist: openai>=1.0.0; extra == "agent"
|
|
21
|
-
Dynamic: license-file
|
|
22
|
-
|
|
23
|
-
# MinionCodeAgent
|
|
24
|
-
|
|
25
|
-
一个增强的AI代码助手,基于Minion框架构建,预配置了丰富的开发工具,专为代码开发任务优化。
|
|
26
|
-
|
|
27
|
-
## 特性
|
|
28
|
-
|
|
29
|
-
- 🤖 **智能代码助手**:预配置的AI agent,专为编程任务设计
|
|
30
|
-
- 🔧 **丰富的工具集**:自动包含文件操作、命令执行、网络搜索等12+个工具
|
|
31
|
-
- ⚡ **即开即用**:一行代码创建,无需复杂配置
|
|
32
|
-
- 📝 **对话历史**:内置对话历史跟踪和管理
|
|
33
|
-
- 🎯 **优化提示**:专为代码开发任务优化的系统提示
|
|
34
|
-
- 🛡️ **安全设计**:内置安全检查,防止危险操作
|
|
35
|
-
|
|
36
|
-
## 安装
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# 克隆仓库
|
|
40
|
-
git clone <repository-url>
|
|
41
|
-
cd minion-code
|
|
42
|
-
pip install -e .
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## 快速开始
|
|
46
|
-
|
|
47
|
-
### CLI使用
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# 基本使用
|
|
51
|
-
mcode
|
|
52
|
-
|
|
53
|
-
# 指定工作目录
|
|
54
|
-
mcode --dir /path/to/project
|
|
55
|
-
|
|
56
|
-
# 启用详细输出
|
|
57
|
-
mcode --verbose
|
|
58
|
-
|
|
59
|
-
# 使用MCP配置文件加载额外工具
|
|
60
|
-
mcode --config mcp.json
|
|
61
|
-
|
|
62
|
-
# 组合使用
|
|
63
|
-
mcode --dir /path/to/project --config mcp.json --verbose
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 编程接口
|
|
67
|
-
|
|
68
|
-
```python
|
|
69
|
-
import asyncio
|
|
70
|
-
from minion_code import MinionCodeAgent
|
|
71
|
-
|
|
72
|
-
async def main():
|
|
73
|
-
# 创建AI代码助手,自动配置所有工具
|
|
74
|
-
agent = await MinionCodeAgent.create(
|
|
75
|
-
name="My Code Assistant",
|
|
76
|
-
llm="gpt-4.1"
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
# 与AI助手对话
|
|
80
|
-
response = await agent.run_async("List files in current directory")
|
|
81
|
-
print(response.answer)
|
|
82
|
-
|
|
83
|
-
response = await agent.run_async("Read the README.md file")
|
|
84
|
-
print(response.answer)
|
|
85
|
-
|
|
86
|
-
asyncio.run(main())
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### 自定义配置
|
|
90
|
-
|
|
91
|
-
```python
|
|
92
|
-
# 自定义系统提示和工作目录
|
|
93
|
-
agent = await MinionCodeAgent.create(
|
|
94
|
-
name="Python Expert",
|
|
95
|
-
llm="gpt-4.1",
|
|
96
|
-
system_prompt="You are a specialized Python developer assistant.",
|
|
97
|
-
workdir="/path/to/project",
|
|
98
|
-
additional_tools=[MyCustomTool()]
|
|
99
|
-
)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### 查看可用工具
|
|
103
|
-
|
|
104
|
-
```python
|
|
105
|
-
# 打印工具摘要
|
|
106
|
-
agent.print_tools_summary()
|
|
107
|
-
|
|
108
|
-
# 获取工具信息
|
|
109
|
-
tools_info = agent.get_tools_info()
|
|
110
|
-
for tool in tools_info:
|
|
111
|
-
print(f"{tool['name']}: {tool['description']}")
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## 内置工具
|
|
115
|
-
|
|
116
|
-
MinionCodeAgent自动包含以下工具类别:
|
|
117
|
-
|
|
118
|
-
### 📁 文件和目录工具
|
|
119
|
-
- **FileReadTool**: 读取文件内容
|
|
120
|
-
- **FileWriteTool**: 写入文件
|
|
121
|
-
- **GrepTool**: 在文件中搜索文本
|
|
122
|
-
- **GlobTool**: 文件模式匹配
|
|
123
|
-
- **LsTool**: 列出目录内容
|
|
124
|
-
|
|
125
|
-
### 💻 系统和执行工具
|
|
126
|
-
- **BashTool**: 执行shell命令
|
|
127
|
-
- **PythonInterpreterTool**: 执行Python代码
|
|
128
|
-
|
|
129
|
-
### 🌐 网络和搜索工具
|
|
130
|
-
- **WebSearchTool**: 网络搜索
|
|
131
|
-
- **WikipediaSearchTool**: Wikipedia搜索
|
|
132
|
-
- **VisitWebpageTool**: 访问网页
|
|
133
|
-
|
|
134
|
-
### 🔧 其他工具
|
|
135
|
-
- **UserInputTool**: 用户输入
|
|
136
|
-
- **TodoWriteTool**: 任务管理写入
|
|
137
|
-
- **TodoReadTool**: 任务管理读取
|
|
138
|
-
|
|
139
|
-
## MCP工具集成
|
|
140
|
-
|
|
141
|
-
MinionCodeAgent支持通过MCP (Model Context Protocol) 配置文件加载额外的工具。
|
|
142
|
-
|
|
143
|
-
### MCP配置文件格式
|
|
144
|
-
|
|
145
|
-
创建一个JSON配置文件(如`mcp.json`):
|
|
146
|
-
|
|
147
|
-
```json
|
|
148
|
-
{
|
|
149
|
-
"mcpServers": {
|
|
150
|
-
"chrome-devtools": {
|
|
151
|
-
"command": "npx",
|
|
152
|
-
"args": ["-y", "chrome-devtools-mcp@latest"],
|
|
153
|
-
"env": {
|
|
154
|
-
"FASTMCP_LOG_LEVEL": "ERROR"
|
|
155
|
-
},
|
|
156
|
-
"disabled": false,
|
|
157
|
-
"autoApprove": []
|
|
158
|
-
},
|
|
159
|
-
"filesystem": {
|
|
160
|
-
"command": "uvx",
|
|
161
|
-
"args": ["mcp-server-filesystem", "/tmp"],
|
|
162
|
-
"disabled": true,
|
|
163
|
-
"autoApprove": ["read_file", "list_directory"]
|
|
164
|
-
},
|
|
165
|
-
"git": {
|
|
166
|
-
"command": "uvx",
|
|
167
|
-
"args": ["mcp-server-git"],
|
|
168
|
-
"disabled": false,
|
|
169
|
-
"autoApprove": ["git_status", "git_log"]
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### 配置选项说明
|
|
176
|
-
|
|
177
|
-
- `command`: 启动MCP服务器的命令
|
|
178
|
-
- `args`: 命令参数列表
|
|
179
|
-
- `env`: 环境变量(可选)
|
|
180
|
-
- `disabled`: 是否禁用此服务器(默认false)
|
|
181
|
-
- `autoApprove`: 自动批准的工具名称列表(可选)
|
|
182
|
-
|
|
183
|
-
### 使用MCP配置
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
# 使用MCP配置文件
|
|
187
|
-
minion-code --config examples/mcp_config.json
|
|
188
|
-
|
|
189
|
-
# 查看加载的工具(包括MCP工具)
|
|
190
|
-
# 在CLI中输入: tools
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### 编程接口中使用MCP工具
|
|
194
|
-
|
|
195
|
-
```python
|
|
196
|
-
from minion_code.utils.mcp_loader import load_mcp_tools
|
|
197
|
-
from pathlib import Path
|
|
198
|
-
|
|
199
|
-
async def main():
|
|
200
|
-
# 加载MCP工具
|
|
201
|
-
mcp_tools = await load_mcp_tools(Path("mcp.json"))
|
|
202
|
-
|
|
203
|
-
# 创建包含MCP工具的agent
|
|
204
|
-
agent = await MinionCodeAgent.create(
|
|
205
|
-
name="Enhanced Assistant",
|
|
206
|
-
llm="gpt-4o-mini",
|
|
207
|
-
additional_tools=mcp_tools
|
|
208
|
-
)
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
## 对话历史管理
|
|
212
|
-
|
|
213
|
-
```python
|
|
214
|
-
# 获取对话历史
|
|
215
|
-
history = agent.get_conversation_history()
|
|
216
|
-
for entry in history:
|
|
217
|
-
print(f"User: {entry['user_message']}")
|
|
218
|
-
print(f"Agent: {entry['agent_response']}")
|
|
219
|
-
|
|
220
|
-
# 清除历史
|
|
221
|
-
agent.clear_conversation_history()
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## 与原始实现的对比
|
|
225
|
-
|
|
226
|
-
### 之前 (复杂的手动配置)
|
|
227
|
-
```python
|
|
228
|
-
# 需要手动导入和配置所有工具
|
|
229
|
-
from minion_code.tools import (
|
|
230
|
-
FileReadTool, FileWriteTool, BashTool,
|
|
231
|
-
GrepTool, GlobTool, LsTool,
|
|
232
|
-
PythonInterpreterTool, WebSearchTool,
|
|
233
|
-
# ... 更多工具
|
|
234
|
-
)
|
|
235
|
-
|
|
236
|
-
# 手动创建工具实例
|
|
237
|
-
custom_tools = [
|
|
238
|
-
FileReadTool(),
|
|
239
|
-
FileWriteTool(),
|
|
240
|
-
BashTool(),
|
|
241
|
-
# ... 更多工具配置
|
|
242
|
-
]
|
|
243
|
-
|
|
244
|
-
# 手动设置系统提示
|
|
245
|
-
SYSTEM_PROMPT = "You are a coding agent..."
|
|
246
|
-
|
|
247
|
-
# 创建agent (约50行代码)
|
|
248
|
-
agent = await CodeAgent.create(
|
|
249
|
-
name="Minion Code Assistant",
|
|
250
|
-
llm="gpt-4o-mini",
|
|
251
|
-
system_prompt=SYSTEM_PROMPT,
|
|
252
|
-
tools=custom_tools,
|
|
253
|
-
)
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
### 现在 (使用MinionCodeAgent)
|
|
257
|
-
```python
|
|
258
|
-
# 一行代码完成所有设置
|
|
259
|
-
agent = await MinionCodeAgent.create(
|
|
260
|
-
name="Minion Code Assistant",
|
|
261
|
-
llm="gpt-4o-mini"
|
|
262
|
-
)
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
## API参考
|
|
266
|
-
|
|
267
|
-
### MinionCodeAgent.create()
|
|
268
|
-
|
|
269
|
-
```python
|
|
270
|
-
async def create(
|
|
271
|
-
name: str = "Minion Code Assistant",
|
|
272
|
-
llm: str = "gpt-4o-mini",
|
|
273
|
-
system_prompt: Optional[str] = None,
|
|
274
|
-
workdir: Optional[Union[str, Path]] = None,
|
|
275
|
-
additional_tools: Optional[List[Any]] = None,
|
|
276
|
-
**kwargs
|
|
277
|
-
) -> MinionCodeAgent
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
**参数:**
|
|
281
|
-
- `name`: Agent名称
|
|
282
|
-
- `llm`: 使用的LLM模型
|
|
283
|
-
- `system_prompt`: 自定义系统提示(可选)
|
|
284
|
-
- `workdir`: 工作目录(可选,默认当前目录)
|
|
285
|
-
- `additional_tools`: 额外工具列表(可选)
|
|
286
|
-
- `**kwargs`: 传递给CodeAgent.create()的其他参数
|
|
287
|
-
|
|
288
|
-
### 实例方法
|
|
289
|
-
|
|
290
|
-
- `run_async(message: str)`: 异步运行agent
|
|
291
|
-
- `run(message: str)`: 同步运行agent
|
|
292
|
-
- `get_conversation_history()`: 获取对话历史
|
|
293
|
-
- `clear_conversation_history()`: 清除对话历史
|
|
294
|
-
- `get_tools_info()`: 获取工具信息
|
|
295
|
-
- `print_tools_summary()`: 打印工具摘要
|
|
296
|
-
|
|
297
|
-
### 属性
|
|
298
|
-
|
|
299
|
-
- `agent`: 访问底层CodeAgent实例
|
|
300
|
-
- `tools`: 获取可用工具列表
|
|
301
|
-
- `name`: 获取agent名称
|
|
302
|
-
|
|
303
|
-
## 安全特性
|
|
304
|
-
|
|
305
|
-
- **命令执行安全**:BashTool禁止执行危险命令(如`rm -rf`、`sudo`等)
|
|
306
|
-
- **Python执行限制**:PythonInterpreterTool在受限环境中执行,只允许安全的内置函数和指定模块
|
|
307
|
-
- **文件访问控制**:所有文件操作都有路径验证和错误处理
|
|
308
|
-
|
|
309
|
-
## 示例
|
|
310
|
-
|
|
311
|
-
查看 `examples/` 目录中的完整示例:
|
|
312
|
-
|
|
313
|
-
- `simple_code_agent.py`: 基本MinionCodeAgent使用示例
|
|
314
|
-
- `simple_tui.py`: 简化的TUI实现
|
|
315
|
-
- `advanced_textual_tui.py`: 高级TUI界面(使用Textual库)
|
|
316
|
-
- `minion_agent_tui.py`: 原始复杂实现(对比参考)
|
|
317
|
-
- `mcp_config.json`: MCP配置文件示例
|
|
318
|
-
- `test_mcp_config.py`: MCP配置加载测试
|
|
319
|
-
- `demo_mcp_cli.py`: MCP CLI功能演示
|
|
320
|
-
|
|
321
|
-
运行示例:
|
|
322
|
-
|
|
323
|
-
```bash
|
|
324
|
-
# 基本使用示例
|
|
325
|
-
python examples/simple_code_agent.py
|
|
326
|
-
|
|
327
|
-
# 简单TUI
|
|
328
|
-
python examples/simple_tui.py
|
|
329
|
-
|
|
330
|
-
# 高级TUI (需要安装 textual: pip install textual rich)
|
|
331
|
-
python examples/advanced_textual_tui.py
|
|
332
|
-
|
|
333
|
-
# 测试MCP配置加载
|
|
334
|
-
python examples/test_mcp_config.py
|
|
335
|
-
|
|
336
|
-
# MCP CLI功能演示
|
|
337
|
-
python examples/demo_mcp_cli.py
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
## 文档
|
|
341
|
-
|
|
342
|
-
- [MCP工具集成指南](docs/MCP_GUIDE.md) - 详细的MCP配置和使用指南
|
|
343
|
-
|
|
344
|
-
## 贡献
|
|
345
|
-
|
|
346
|
-
欢迎提交Issue和Pull Request来改进这个项目!
|
|
347
|
-
|
|
348
|
-
## 许可证
|
|
349
|
-
|
|
350
|
-
MIT License
|