Skip to content

Commit b20c074

Browse files
committed
docstrings, example agent, cli
1 parent 5355771 commit b20c074

18 files changed

+1279
-285
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
"""
2+
Interactive web development agent supporting both XML and Standard LLM tool calling.
3+
4+
This agent can:
5+
- Create and modify web projects
6+
- Execute terminal commands
7+
- Handle file operations
8+
- Use either XML or Standard tool calling patterns
9+
"""
10+
111
import asyncio
212
import json
313
from agentpress.thread_manager import ThreadManager
@@ -8,78 +18,17 @@
818
from typing import AsyncGenerator
919
import sys
1020

11-
async def run_agent(thread_id: str, max_iterations: int = 5):
12-
thread_manager = ThreadManager()
13-
state_manager = StateManager()
14-
15-
thread_manager.add_tool(FilesTool)
16-
thread_manager.add_tool(TerminalTool)
17-
18-
async def init():
19-
pass
20-
21-
async def pre_iteration():
22-
files_tool = FilesTool()
23-
await files_tool._init_workspace_state()
24-
25-
async def after_iteration():
26-
custom_message = input("Enter a message to send (or press Enter to use 'Continue!!!' as message): ")
27-
28-
message_content = custom_message if custom_message else """
29-
Continue!!!
30-
"""
31-
await thread_manager.add_message(thread_id, {
32-
"role": "user",
33-
"content": message_content
34-
})
35-
36-
async def finalizer():
37-
pass
38-
39-
await init()
40-
41-
iteration = 0
42-
43-
while iteration < max_iterations:
44-
iteration += 1
45-
await pre_iteration()
46-
47-
# You are a world-class web developer who can create, edit, and delete files, and execute terminal commands. You write clean, well-structured code.
48-
49-
# RESPONSE FORMAT:
50-
# Use XML tags to specify file operations:
51-
52-
# <create-file file_path="path/to/file">
53-
# file contents here
54-
# </create-file>
21+
BASE_SYSTEM_MESSAGE = """
22+
You are a world-class web developer who can create, edit, and delete files, and execute terminal commands.
23+
You write clean, well-structured code. Keep iterating on existing files, continue working on this existing
24+
codebase - do not omit previous progress; instead, keep iterating.
5525
56-
# <str-replace file_path="path/to/file">
57-
# <old_str>text to replace</old_str>
58-
# <new_str>replacement text</new_str>
59-
# </str-replace>
26+
Available tools:
27+
- create_file: Create new files with specified content
28+
- delete_file: Remove existing files
29+
- str_replace: Make precise text replacements in files
30+
- execute_command: Run terminal commands
6031
61-
# <delete-file file_path="path/to/file">
62-
# </delete-file>
63-
64-
system_message = {
65-
"role": "system",
66-
"content": """
67-
You are a world-class web developer who can create, edit, and delete files, and execute terminal commands. You write clean, well-structured code. Keep iterating on existing files, continue working on this existing codebase - do not omit previous progress; instead, keep iterating.
68-
69-
RESPONSE FORMAT:
70-
Use XML tags to specify file operations:
71-
72-
<create-file file_path="path/to/file">
73-
file contents here
74-
</create-file>
75-
76-
<str-replace file_path="path/to/file">
77-
<old_str>text to replace</old_str>
78-
<new_str>replacement text</new_str>
79-
</str-replace>
80-
81-
<delete-file file_path="path/to/file">
82-
</delete-file>
8332
8433
RULES:
8534
- All current file contents are available to you in the <current_workspace_state> section
@@ -117,18 +66,65 @@ async def finalizer():
11766
"content": "<!DOCTYPE html>\\n<html>\\n<head>..."
11867
}
11968
}
120-
12169
Think deeply and step by step.
122-
"""
123-
}
12470
125-
state = await state_manager.export_store()
71+
"""
72+
73+
XML_FORMAT = """
74+
RESPONSE FORMAT:
75+
Use XML tags to specify file operations:
76+
77+
<create-file file_path="path/to/file">
78+
file contents here
79+
</create-file>
80+
81+
<str-replace file_path="path/to/file">
82+
<old_str>text to replace</old_str>
83+
<new_str>replacement text</new_str>
84+
</str-replace>
85+
86+
<delete-file file_path="path/to/file">
87+
</delete-file>
88+
89+
"""
90+
91+
async def run_agent(thread_id: str, use_xml: bool = True, max_iterations: int = 5):
92+
"""Run the development agent with specified configuration."""
93+
thread_manager = ThreadManager()
94+
state_manager = StateManager()
95+
96+
thread_manager.add_tool(FilesTool)
97+
thread_manager.add_tool(TerminalTool)
98+
99+
# Combine base message with XML format if needed
100+
system_message = {
101+
"role": "system",
102+
"content": BASE_SYSTEM_MESSAGE + (XML_FORMAT if use_xml else "")
103+
}
104+
105+
async def pre_iteration():
106+
files_tool = FilesTool()
107+
await files_tool._init_workspace_state()
108+
109+
async def after_iteration():
110+
custom_message = input("\nEnter a message (or press Enter to continue): ")
111+
message_content = custom_message if custom_message else "Continue!!!"
112+
await thread_manager.add_message(thread_id, {
113+
"role": "user",
114+
"content": message_content
115+
})
126116

117+
iteration = 0
118+
while iteration < max_iterations:
119+
iteration += 1
120+
await pre_iteration()
121+
122+
state = await state_manager.export_store()
127123
state_message = {
128124
"role": "user",
129125
"content": f"""
130126
Current development environment workspace state:
131-
<current_workspace_state>
127+
<current_workspace_state>
132128
{json.dumps(state, indent=2)}
133129
</current_workspace_state>
134130
"""
@@ -137,19 +133,19 @@ async def finalizer():
137133
model_name = "anthropic/claude-3-5-sonnet-latest"
138134

139135
response = await thread_manager.run_thread(
140-
thread_id=thread_id,
141-
system_message=system_message,
142-
model_name=model_name,
143-
temperature=0.1,
144-
max_tokens=8096,
145-
tool_choice="auto",
146-
temporary_message=state_message,
147-
native_tool_calling=False,
148-
xml_tool_calling=True,
149-
stream=True,
150-
execute_tools_on_stream=True,
151-
parallel_tool_execution=True
152-
)
136+
thread_id=thread_id,
137+
system_message=system_message,
138+
model_name=model_name,
139+
temperature=0.1,
140+
max_tokens=8096,
141+
tool_choice="auto",
142+
temporary_message=state_message,
143+
native_tool_calling=not use_xml,
144+
xml_tool_calling=use_xml,
145+
stream=True,
146+
execute_tools_on_stream=True,
147+
parallel_tool_execution=True
148+
)
153149

154150
if isinstance(response, AsyncGenerator):
155151
print("\n🤖 Assistant is responding:")
@@ -158,19 +154,14 @@ async def finalizer():
158154
if hasattr(chunk.choices[0], 'delta'):
159155
delta = chunk.choices[0].delta
160156

161-
# Handle content streaming - print immediately without buffering
162157
if hasattr(delta, 'content') and delta.content is not None:
163158
print(delta.content, end='', flush=True)
164159

165-
# Handle tool calls - print immediately
166160
if hasattr(delta, 'tool_calls') and delta.tool_calls:
167161
for tool_call in delta.tool_calls:
168162
if tool_call.function:
169-
# Print tool name immediately when received
170163
if tool_call.function.name:
171164
print(f"\n🛠️ Tool Call: {tool_call.function.name}", flush=True)
172-
173-
# Print arguments immediately when received
174165
if tool_call.function.arguments:
175166
print(f" {tool_call.function.arguments}", end='', flush=True)
176167

@@ -180,25 +171,45 @@ async def finalizer():
180171
print(f"\n❌ Error processing stream: {e}", file=sys.stderr)
181172
logging.error(f"Error processing stream: {e}")
182173
else:
183-
print("\n❌ Non-streaming response received:", response)
174+
print("\nNon-streaming response received:", response)
184175

185176
await after_iteration()
186177

187-
await finalizer()
188-
189-
if __name__ == "__main__":
190-
async def main():
178+
def main():
179+
"""Main entry point with synchronous setup."""
180+
print("\n🚀 Welcome to AgentPress Web Developer Example!")
181+
182+
project_description = input("What would you like to build? (default: Create a modern, responsive landing page)\n> ")
183+
if not project_description.strip():
184+
project_description = "Create a modern, responsive landing page"
185+
186+
print("\nChoose your agent type:")
187+
print("1. XML-based Tool Calling")
188+
print(" - Structured XML format for tool execution")
189+
print(" - Parses tool calls using XML outputs in the LLM response")
190+
191+
print("\n2. Standard Function Calling")
192+
print(" - Native LLM function calling format")
193+
print(" - JSON-based parameter passing")
194+
195+
use_xml = input("\nSelect tool calling format [1/2] (default: 1): ").strip() != "2"
196+
197+
print(f"\n{'XML-based' if use_xml else 'Standard'} agent will help you build: {project_description}")
198+
print("Use Ctrl+C to stop the agent at any time.")
199+
200+
async def async_main():
191201
thread_manager = ThreadManager()
192202
thread_id = await thread_manager.create_thread()
193-
194203
await thread_manager.add_message(
195204
thread_id,
196205
{
197206
"role": "user",
198-
"content": "Create a modern, responsive landing page with HTML, CSS and JS."
207+
"content": project_description
199208
}
200-
)
209+
)
210+
await run_agent(thread_id, use_xml)
201211

202-
await run_agent(thread_id)
203-
204-
asyncio.run(main())
212+
asyncio.run(async_main())
213+
214+
if __name__ == "__main__":
215+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Modern Landing Page</title>
7+
<link rel="stylesheet" href="styles.css">
8+
</head>
9+
<body>
10+
<header>
11+
<nav class="navbar">
12+
<div class="logo">Brand</div>
13+
<ul class="nav-links">
14+
<li><a href="#home">Home</a></li>
15+
<li><a href="#features">Features</a></li>
16+
<li><a href="#contact">Contact</a></li>
17+
</ul>
18+
<div class="hamburger">
19+
<span></span>
20+
<span></span>
21+
<span></span>
22+
</div>
23+
</nav>
24+
</header>
25+
26+
<main>
27+
<section id="home" class="hero">
28+
<div class="hero-content">
29+
<h1>Welcome to the Future</h1>
30+
<p>Experience innovation at its finest</p>
31+
<button class="cta-button">Get Started</button>
32+
</div>
33+
</section>
34+
35+
<section id="testimonials" class="testimonials">
36+
<h2>What Our Clients Say</h2>
37+
<div class="testimonial-grid">
38+
<div class="testimonial-card">
39+
<div class="testimonial-avatar">👤</div>
40+
<p class="testimonial-text">"Amazing service! The team went above and beyond."</p>
41+
<p class="testimonial-author">- John Doe, CEO</p>
42+
</div>
43+
<div class="testimonial-card">
44+
<div class="testimonial-avatar">👤</div>
45+
<p class="testimonial-text">"Incredible results. Would highly recommend!"</p>
46+
<p class="testimonial-author">- Jane Smith, Designer</p>
47+
</div>
48+
<div class="testimonial-card">
49+
<div class="testimonial-avatar">👤</div>
50+
<p class="testimonial-text">"Professional and efficient service."</p>
51+
<p class="testimonial-author">- Mike Johnson, Developer</p>
52+
</div>
53+
</div>
54+
</section>
55+
56+
<section id="features" class="features">
57+
<h2>Our Features</h2>
58+
<div class="feature-grid">
59+
<div class="feature-card">
60+
<div class="feature-icon">🚀</div>
61+
<h3>Fast Performance</h3>
62+
<p>Lightning-quick loading times</p>
63+
</div>
64+
<div class="feature-card">
65+
<div class="feature-icon">🎨</div>
66+
<h3>Beautiful Design</h3>
67+
<p>Stunning visuals and animations</p>
68+
</div>
69+
<div class="feature-card">
70+
<div class="feature-icon">📱</div>
71+
<h3>Responsive</h3>
72+
<p>Works on all devices</p>
73+
</div>
74+
</div>
75+
</section>
76+
77+
<section id="contact" class="contact">
78+
<h2>Contact Us</h2>
79+
<form id="contact-form">
80+
<input type="text" placeholder="Name" required>
81+
<input type="email" placeholder="Email" required>
82+
<textarea placeholder="Message" required></textarea>
83+
<button type="submit">Send Message</button>
84+
</form>
85+
</section>
86+
</main>
87+
88+
<footer>
89+
<p>&copy; 2024 Brand. All rights reserved.</p>
90+
</footer>
91+
92+
<script src="script.js"></script>
93+
</body>
94+
</html>

0 commit comments

Comments
 (0)