Skip to content

Commit 320dabb

Browse files
committed
cleanup run_thread params
1 parent 8923b86 commit 320dabb

14 files changed

+1150
-631
lines changed

agentpress/base_processors.py

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import logging
2+
from typing import Dict, Any, Callable, List, Optional, Set
3+
from abc import ABC, abstractmethod
4+
5+
# --- Tool Parser Base ---
6+
7+
class ToolParserBase(ABC):
8+
"""Abstract base class defining the interface for parsing tool calls from LLM responses.
9+
10+
This class provides the foundational interface for parsing both complete and streaming
11+
responses from Language Models, specifically focusing on tool call extraction and processing.
12+
13+
Attributes:
14+
None
15+
16+
Methods:
17+
parse_response: Processes complete LLM responses
18+
parse_stream: Handles streaming response chunks
19+
"""
20+
21+
@abstractmethod
22+
async def parse_response(self, response: Any) -> Dict[str, Any]:
23+
"""Parse a complete LLM response and extract tool calls.
24+
25+
Args:
26+
response (Any): The complete response from the LLM
27+
28+
Returns:
29+
Dict[str, Any]: A dictionary containing:
30+
- role: The message role (usually 'assistant')
31+
- content: The text content of the response
32+
- tool_calls: List of extracted tool calls (if present)
33+
"""
34+
pass
35+
36+
@abstractmethod
37+
async def parse_stream(self, response_chunk: Any, tool_calls_buffer: Dict[int, Dict]) -> tuple[Optional[Dict[str, Any]], bool]:
38+
"""Parse a streaming response chunk and manage tool call accumulation.
39+
40+
Args:
41+
response_chunk (Any): A single chunk from the streaming response
42+
tool_calls_buffer (Dict[int, Dict]): Buffer storing incomplete tool calls
43+
44+
Returns:
45+
tuple[Optional[Dict[str, Any]], bool]: A tuple containing:
46+
- The parsed message if complete tool calls are found (or None)
47+
- Boolean indicating if the stream is complete
48+
"""
49+
pass
50+
51+
# --- Tool Executor Base ---
52+
53+
class ToolExecutorBase(ABC):
54+
"""Abstract base class defining the interface for tool execution strategies.
55+
56+
This class provides the foundation for implementing different tool execution
57+
approaches, supporting both parallel and sequential execution patterns.
58+
59+
Attributes:
60+
None
61+
62+
Methods:
63+
execute_tool_calls: Main entry point for tool execution
64+
_execute_parallel: Handles parallel tool execution
65+
_execute_sequential: Handles sequential tool execution
66+
"""
67+
68+
@abstractmethod
69+
async def execute_tool_calls(
70+
self,
71+
tool_calls: List[Dict[str, Any]],
72+
available_functions: Dict[str, Callable],
73+
thread_id: str,
74+
executed_tool_calls: Optional[Set[str]] = None
75+
) -> List[Dict[str, Any]]:
76+
"""Execute a list of tool calls and return their results.
77+
78+
Args:
79+
tool_calls: List of tool calls to execute
80+
available_functions: Dictionary of available tool functions
81+
thread_id: ID of the current conversation thread
82+
executed_tool_calls: Set of already executed tool call IDs
83+
84+
Returns:
85+
List[Dict[str, Any]]: List of tool execution results
86+
"""
87+
pass
88+
89+
@abstractmethod
90+
async def _execute_parallel(
91+
self,
92+
tool_calls: List[Dict[str, Any]],
93+
available_functions: Dict[str, Callable],
94+
thread_id: str,
95+
executed_tool_calls: Set[str]
96+
) -> List[Dict[str, Any]]:
97+
"""Execute tool calls in parallel."""
98+
pass
99+
100+
@abstractmethod
101+
async def _execute_sequential(
102+
self,
103+
tool_calls: List[Dict[str, Any]],
104+
available_functions: Dict[str, Callable],
105+
thread_id: str,
106+
executed_tool_calls: Set[str]
107+
) -> List[Dict[str, Any]]:
108+
"""Execute tool calls sequentially."""
109+
pass
110+
111+
# --- Results Adder Base ---
112+
113+
class ResultsAdderBase(ABC):
114+
"""Abstract base class for handling tool results and message processing."""
115+
116+
def __init__(self, thread_manager):
117+
"""Initialize with a ThreadManager instance.
118+
119+
Args:
120+
thread_manager: The ThreadManager instance to use for message operations
121+
"""
122+
self.add_message = thread_manager.add_message
123+
self.update_message = thread_manager._update_message
124+
self.list_messages = thread_manager.list_messages
125+
self.message_added = False
126+
127+
@abstractmethod
128+
async def add_initial_response(self, thread_id: str, content: str, tool_calls: Optional[List[Dict[str, Any]]] = None):
129+
pass
130+
131+
@abstractmethod
132+
async def update_response(self, thread_id: str, content: str, tool_calls: Optional[List[Dict[str, Any]]] = None):
133+
pass
134+
135+
@abstractmethod
136+
async def add_tool_result(self, thread_id: str, result: Dict[str, Any]):
137+
pass

agentpress/examples/example_agent/agent.py

+9-16
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async def run_agent(thread_id: str, max_iterations: int = 5):
1616
thread_manager = ThreadManager()
1717
state_manager = StateManager()
1818

19-
# Initialize tools with XML schema support
19+
# Initialize tools
2020
thread_manager.add_tool(FilesTool)
2121
thread_manager.add_tool(TerminalTool)
2222

@@ -60,7 +60,9 @@ async def finalizer():
6060
# file contents here
6161
# </create-file>
6262

63-
# <str-replace file_path="path/to/file" old_str="old_str" new_str="new_str">
63+
# <str-replace file_path="path/to/file">
64+
# <old_str>text to replace</old_str>
65+
# <new_str>replacement text</new_str>
6466
# </str-replace>
6567

6668
# <delete-file file_path="path/to/file">
@@ -71,7 +73,7 @@ async def finalizer():
7173
"content": """
7274
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.
7375
74-
FORMAT:
76+
RESPONSE FORMAT:
7577
Use XML tags to specify file operations:
7678
7779
<create-file file_path="path/to/file">
@@ -141,11 +143,6 @@ async def finalizer():
141143

142144
model_name = "anthropic/claude-3-5-sonnet-latest"
143145

144-
registry = thread_manager.tool_registry
145-
tool_parser = XMLToolParser(tool_registry=registry)
146-
tool_executor = XMLToolExecutor(parallel=True, tool_registry=registry)
147-
results_adder = XMLResultsAdder(thread_manager)
148-
149146
response = await thread_manager.run_thread(
150147
thread_id=thread_id,
151148
system_message=system_message,
@@ -154,15 +151,11 @@ async def finalizer():
154151
max_tokens=8096,
155152
tool_choice="auto",
156153
temporary_message=state_message,
157-
use_tools=True,
158-
native_tool_calling=False,
159-
execute_tools=True,
154+
native_tool_calling=True,
155+
xml_tool_calling=False,
160156
stream=True,
161-
immediate_tool_execution=True,
162-
parallel_tool_execution=True,
163-
tool_parser=tool_parser,
164-
tool_executor=tool_executor,
165-
results_adder=results_adder
157+
execute_tools_on_stream=True,
158+
parallel_tool_execution=True
166159
)
167160

168161
if isinstance(response, AsyncGenerator):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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 class="header">
11+
<nav class="nav">
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="#about">About</a></li>
17+
<li><a href="#contact">Contact</a></li>
18+
</ul>
19+
<button class="mobile-nav-toggle" aria-label="Menu">
20+
<span></span>
21+
<span></span>
22+
<span></span>
23+
</button>
24+
</nav>
25+
</header>
26+
27+
<main>
28+
<section id="home" class="hero">
29+
<div class="hero-content">
30+
<h1>Welcome to the Future</h1>
31+
<p>Transform your digital presence with our innovative solutions</p>
32+
<div class="cta-group">
33+
<button class="cta-button primary">Get Started</button>
34+
<button class="cta-button secondary">Learn More</button>
35+
</div>
36+
</div>
37+
<div class="hero-shape"></div>
38+
</section>
39+
40+
<section id="features" class="features">
41+
<h2>Our Features</h2>
42+
<div class="features-grid">
43+
<div class="feature-card">
44+
<div class="feature-icon">🚀</div>
45+
<h3>Fast Performance</h3>
46+
<p>Lightning-quick load times and smooth interactions</p>
47+
</div>
48+
<div class="feature-card">
49+
<div class="feature-icon">🎨</div>
50+
<h3>Beautiful Design</h3>
51+
<p>Stunning visuals that capture attention</p>
52+
</div>
53+
<div class="feature-card">
54+
<div class="feature-icon">📱</div>
55+
<h3>Responsive</h3>
56+
<p>Perfect display on all devices</p>
57+
</div>
58+
</div>
59+
</section>
60+
61+
<section id="about" class="about">
62+
<div class="about-content">
63+
<h2>About Us</h2>
64+
<p>We're dedicated to creating exceptional digital experiences that drive results.</p>
65+
</div>
66+
</section>
67+
68+
<section id="contact" class="contact">
69+
<h2>Get in Touch</h2>
70+
<form class="contact-form">
71+
<input type="text" placeholder="Name" required>
72+
<input type="email" placeholder="Email" required>
73+
<textarea placeholder="Message" required></textarea>
74+
<button type="submit">Send Message</button>
75+
</form>
76+
</section>
77+
</main>
78+
79+
<footer class="footer">
80+
<p>&copy; 2024 Brand. All rights reserved.</p>
81+
</footer>
82+
83+
<script src="script.js"></script>
84+
</body>
85+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const mobileNavToggle = document.querySelector('.mobile-nav-toggle');
3+
const navLinks = document.querySelector('.nav-links');
4+
const header = document.querySelector('.header');
5+
let lastScroll = 0;
6+
7+
mobileNavToggle.addEventListener('click', () => {
8+
navLinks.classList.toggle('active');
9+
const spans = mobileNavToggle.querySelectorAll('span');
10+
spans[0].style.transform = navLinks.classList.contains('active') ? 'rotate(45deg) translate(8px, 8px)' : '';
11+
spans[1].style.opacity = navLinks.classList.contains('active') ? '0' : '1';
12+
spans[2].style.transform = navLinks.classList.contains('active') ? 'rotate(-45deg) translate(7px, -7px)' : '';
13+
});
14+
15+
window.addEventListener('scroll', () => {
16+
const currentScroll = window.pageYOffset;
17+
18+
if (currentScroll <= 0) {
19+
header.style.transform = 'translateY(0)';
20+
return;
21+
}
22+
23+
if (currentScroll > lastScroll && !header.classList.contains('scroll-down')) {
24+
header.style.transform = 'translateY(-100%)';
25+
} else if (currentScroll < lastScroll && header.classList.contains('scroll-down')) {
26+
header.style.transform = 'translateY(0)';
27+
}
28+
29+
lastScroll = currentScroll;
30+
});
31+
32+
const observerOptions = {
33+
threshold: 0.1,
34+
rootMargin: '0px 0px -50px 0px'
35+
};
36+
37+
const observer = new IntersectionObserver((entries) => {
38+
entries.forEach(entry => {
39+
if (entry.isIntersecting) {
40+
entry.target.style.opacity = '1';
41+
entry.target.style.transform = 'translateY(0)';
42+
}
43+
});
44+
}, observerOptions);
45+
46+
document.querySelectorAll('section').forEach(section => {
47+
section.style.opacity = '0';
48+
section.style.transform = 'translateY(20px)';
49+
section.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out';
50+
observer.observe(section);
51+
});
52+
53+
const form = document.querySelector('.contact-form');
54+
form.addEventListener('submit', (e) => {
55+
e.preventDefault();
56+
const formData = new FormData(form);
57+
const data = Object.fromEntries(formData);
58+
console.log('Form submitted:', data);
59+
form.reset();
60+
});
61+
});

0 commit comments

Comments
 (0)