From c1d7c82f82d56c87cbfc80ff86611fbd38940a24 Mon Sep 17 00:00:00 2001 From: marko-kraemer Date: Sat, 5 Apr 2025 17:38:55 +0100 Subject: [PATCH] func name & xml_tag_name --- backend/agent/workspace/index.html | 529 ++--------------------- backend/agent/workspace/script.js | 140 ++++++ backend/agent/workspace/styles.css | 150 +++++++ backend/agentpress/response_processor.py | 90 ++-- 4 files changed, 388 insertions(+), 521 deletions(-) create mode 100644 backend/agent/workspace/script.js create mode 100644 backend/agent/workspace/styles.css diff --git a/backend/agent/workspace/index.html b/backend/agent/workspace/index.html index 0d9c663c..53a5f72e 100644 --- a/backend/agent/workspace/index.html +++ b/backend/agent/workspace/index.html @@ -3,493 +3,52 @@ - Minecraft Clone - + AGI Interface + + -
+
-
-
-
+
+
+

AGI Interface

+
+ + System Active +
+
+ +
+
+
+
+
+ + +
+
+
+ +
+
+ +
+
+
+

Processing Power

+
+
+
+
+
+

Learning Rate

+
+
+
+
+
+
+
-
- - - - - + \ No newline at end of file diff --git a/backend/agent/workspace/script.js b/backend/agent/workspace/script.js new file mode 100644 index 00000000..f475a235 --- /dev/null +++ b/backend/agent/workspace/script.js @@ -0,0 +1,140 @@ +class AGIInterface { + constructor() { + this.initializeElements(); + this.bindEvents(); + this.initializeNeuralNetwork(); + this.updateMetrics(); + } + + initializeElements() { + this.chatMessages = document.getElementById('chat-messages'); + this.userInput = document.getElementById('user-input'); + this.sendButton = document.getElementById('send-btn'); + this.canvas = document.getElementById('neural-canvas'); + this.ctx = this.canvas.getContext('2d'); + this.processingPower = document.getElementById('processing-power'); + this.learningRate = document.getElementById('learning-rate'); + } + + bindEvents() { + this.sendButton.addEventListener('click', () => this.handleUserInput()); + this.userInput.addEventListener('keypress', (e) => { + if (e.key === 'Enter') this.handleUserInput(); + }); + window.addEventListener('resize', () => this.resizeCanvas()); + } + + handleUserInput() { + const message = this.userInput.value.trim(); + if (message) { + this.addMessage('user', message); + this.generateResponse(message); + this.userInput.value = ''; + } + } + + addMessage(type, content) { + const messageDiv = document.createElement('div'); + messageDiv.className = `message ${type}-message`; + messageDiv.innerHTML = ` +
+ ${content} + ${new Date().toLocaleTimeString()} +
+ `; + this.chatMessages.appendChild(messageDiv); + this.chatMessages.scrollTop = this.chatMessages.scrollHeight; + } + + generateResponse(userMessage) { + // Simulate AI processing + setTimeout(() => { + const responses = [ + "I understand your query about " + userMessage, + "Processing your request regarding " + userMessage, + "Analyzing the context of " + userMessage, + "Interesting perspective on " + userMessage + ]; + const response = responses[Math.floor(Math.random() * responses.length)]; + this.addMessage('ai', response); + this.updateMetrics(); + }, 1000); + } + + initializeNeuralNetwork() { + this.resizeCanvas(); + this.nodes = []; + this.connections = []; + + // Create nodes + for (let layer = 0; layer < 3; layer++) { + const nodesInLayer = layer === 1 ? 4 : 3; + for (let i = 0; i < nodesInLayer; i++) { + this.nodes.push({ + x: (layer + 1) * this.canvas.width / 4, + y: (i + 1) * this.canvas.height / (nodesInLayer + 1), + layer: layer + }); + } + } + + // Create connections + this.nodes.forEach(node => { + if (node.layer < 2) { + this.nodes.filter(n => n.layer === node.layer + 1).forEach(nextNode => { + this.connections.push({ + start: node, + end: nextNode, + activity: Math.random() + }); + }); + } + }); + + this.animate(); + } + + resizeCanvas() { + this.canvas.width = this.canvas.offsetWidth; + this.canvas.height = this.canvas.offsetHeight; + } + + animate() { + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + + // Draw connections + this.connections.forEach(conn => { + this.ctx.beginPath(); + this.ctx.moveTo(conn.start.x, conn.start.y); + this.ctx.lineTo(conn.end.x, conn.end.y); + this.ctx.strokeStyle = `rgba(52, 152, 219, ${conn.activity})`; + this.ctx.lineWidth = 2; + this.ctx.stroke(); + + conn.activity = Math.max(0.1, Math.min(1, conn.activity + (Math.random() - 0.5) * 0.1)); + }); + + // Draw nodes + this.nodes.forEach(node => { + this.ctx.beginPath(); + this.ctx.arc(node.x, node.y, 10, 0, Math.PI * 2); + this.ctx.fillStyle = '#3498db'; + this.ctx.fill(); + }); + + requestAnimationFrame(() => this.animate()); + } + + updateMetrics() { + const processingPowerValue = Math.random() * 100; + const learningRateValue = Math.random() * 100; + + this.processingPower.style.width = `${processingPowerValue}%`; + this.learningRate.style.width = `${learningRateValue}%`; + } +} + +// Initialize the application +document.addEventListener('DOMContentLoaded', () => { + const agi = new AGIInterface(); +}); \ No newline at end of file diff --git a/backend/agent/workspace/styles.css b/backend/agent/workspace/styles.css new file mode 100644 index 00000000..6a355b13 --- /dev/null +++ b/backend/agent/workspace/styles.css @@ -0,0 +1,150 @@ +:root { + --primary-color: #2c3e50; + --secondary-color: #3498db; + --accent-color: #e74c3c; + --background-color: #f5f6fa; + --text-color: #2c3e50; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Arial', sans-serif; + background-color: var(--background-color); + color: var(--text-color); +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 0; + margin-bottom: 30px; +} + +h1 { + color: var(--primary-color); + font-size: 2.5em; +} + +.status-indicator { + display: flex; + align-items: center; + gap: 10px; +} + +.pulse { + width: 10px; + height: 10px; + background-color: #2ecc71; + border-radius: 50%; + animation: pulse 2s infinite; +} + +@keyframes pulse { + 0% { transform: scale(1); opacity: 1; } + 50% { transform: scale(1.5); opacity: 0.7; } + 100% { transform: scale(1); opacity: 1; } +} + +main { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 30px; +} + +.interaction-panel, .visualization-panel { + background: white; + border-radius: 15px; + padding: 20px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +.chat-interface { + height: 500px; + display: flex; + flex-direction: column; +} + +.messages { + flex-grow: 1; + overflow-y: auto; + padding: 15px; + margin-bottom: 15px; +} + +.input-area { + display: flex; + gap: 10px; +} + +input[type="text"] { + flex-grow: 1; + padding: 12px; + border: 2px solid #e0e0e0; + border-radius: 8px; + font-size: 16px; +} + +button { + padding: 12px 24px; + background-color: var(--secondary-color); + color: white; + border: none; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s; +} + +button:hover { + background-color: #2980b9; +} + +.neural-network { + height: 300px; + margin-bottom: 20px; +} + +canvas { + width: 100%; + height: 100%; +} + +.metrics { + display: grid; + gap: 20px; +} + +.metric h3 { + margin-bottom: 10px; +} + +.progress-bar { + height: 20px; + background-color: #f0f0f0; + border-radius: 10px; + overflow: hidden; +} + +.progress { + height: 100%; + background-color: var(--secondary-color); + width: 0%; + transition: width 0.3s ease; +} + +@media (max-width: 768px) { + main { + grid-template-columns: 1fr; + } +} \ No newline at end of file diff --git a/backend/agentpress/response_processor.py b/backend/agentpress/response_processor.py index 25c5f1ff..b161a857 100644 --- a/backend/agentpress/response_processor.py +++ b/backend/agentpress/response_processor.py @@ -697,16 +697,20 @@ class ResponseProcessor: if not tag_match: logger.error(f"No tag found in XML chunk: {xml_chunk}") return None - - tag_name = tag_match.group(1) - logger.info(f"Found XML tag: {tag_name}") - # Get tool info and schema - tool_info = self.tool_registry.get_xml_tool(tag_name) + # This is the XML tag as it appears in the text (e.g., "create-file") + xml_tag_name = tag_match.group(1) + logger.info(f"Found XML tag: {xml_tag_name}") + + # Get tool info and schema from registry + tool_info = self.tool_registry.get_xml_tool(xml_tag_name) if not tool_info or not tool_info['schema'].xml_schema: - logger.error(f"No tool or schema found for tag: {tag_name}") + logger.error(f"No tool or schema found for tag: {xml_tag_name}") return None - + + # This is the actual function name to call (e.g., "create_file") + function_name = tool_info['method'] + schema = tool_info['schema'].xml_schema params = {} remaining_chunk = xml_chunk @@ -721,26 +725,26 @@ class ResponseProcessor: if value is not None: params[mapping.param_name] = value logger.info(f"Found attribute {mapping.path} -> {mapping.param_name}: {value}") - + elif mapping.node_type == "element": # Extract element content content, remaining_chunk = self._extract_tag_content(remaining_chunk, mapping.path) if content is not None: params[mapping.param_name] = content.strip() logger.info(f"Found element {mapping.path} -> {mapping.param_name}") - + elif mapping.node_type == "text": if mapping.path == ".": # Extract root content - content, _ = self._extract_tag_content(remaining_chunk, tag_name) + content, _ = self._extract_tag_content(remaining_chunk, xml_tag_name) if content is not None: params[mapping.param_name] = content.strip() logger.info(f"Found text content for {mapping.param_name}") - + elif mapping.node_type == "content": if mapping.path == ".": # Extract root content - content, _ = self._extract_tag_content(remaining_chunk, tag_name) + content, _ = self._extract_tag_content(remaining_chunk, xml_tag_name) if content is not None: params[mapping.param_name] = content.strip() logger.info(f"Found root content for {mapping.param_name}") @@ -757,10 +761,11 @@ class ResponseProcessor: logger.error(f"XML chunk: {xml_chunk}") return None - # Create tool call + # Create tool call with clear separation between function_name and xml_tag_name tool_call = { - "name": tool_info['method'], - "arguments": params + "function_name": function_name, # The actual method to call (e.g., create_file) + "xml_tag_name": xml_tag_name, # The original XML tag (e.g., create-file) + "arguments": params # The extracted parameters } logger.info(f"Created tool call: {tool_call}") @@ -792,7 +797,7 @@ class ResponseProcessor: async def _execute_tool(self, tool_call: Dict[str, Any]) -> ToolResult: """Execute a single tool call and return the result.""" try: - function_name = tool_call["name"] + function_name = tool_call["function_name"] arguments = tool_call["arguments"] logger.info(f"Executing tool: {function_name} with arguments: {arguments}") @@ -817,7 +822,7 @@ class ResponseProcessor: logger.info(f"Tool execution complete: {function_name} -> {result}") return result except Exception as e: - logger.error(f"Error executing tool {tool_call['name']}: {str(e)}", exc_info=True) + logger.error(f"Error executing tool {tool_call['function_name']}: {str(e)}", exc_info=True) return ToolResult(success=False, output=f"Error executing tool: {str(e)}") async def _execute_tools( @@ -981,37 +986,43 @@ class ResponseProcessor: def _format_xml_tool_result(self, tool_call: Dict[str, Any], result: ToolResult) -> str: - """Format a tool result as a simple XML tag. + """Format a tool result as an XML tag or plain text. Args: tool_call: The tool call that was executed result: The result of the tool execution Returns: - String containing the XML-formatted result or standard format if not XML + String containing the formatted result """ - xml_tag_name = self._get_tool_display_name(tool_call["name"]) + # Always use xml_tag_name if it exists + if "xml_tag_name" in tool_call: + xml_tag_name = tool_call["xml_tag_name"] + return f"<{xml_tag_name}> {str(result)} " - # If display name is same as method name, it's not an XML tool - if xml_tag_name == tool_call["name"]: - return f"Result for {tool_call['name']}: {str(result)}" - - # Format as simple XML tag without attributes - xml_output = f"<{xml_tag_name}> {str(result)} " - return xml_output + # Non-XML tool, just return the function result + function_name = tool_call["function_name"] + return f"Result for {function_name}: {str(result)}" - def _get_tool_display_name(self, method_name: str) -> str: - """Get the display name for a tool (XML tag name if applicable, or method name).""" - if not hasattr(self.tool_registry, 'xml_tools'): - return method_name + def _get_tool_display_name(self, function_name: str) -> str: + """Get the XML tag name for a function name. + + Args: + function_name: The function name to look up - # Check if this method corresponds to an XML tool + Returns: + The XML tag name if found, otherwise the original function name + """ + if not hasattr(self.tool_registry, 'xml_tools'): + return function_name + + # Check if this function corresponds to an XML tool for tag_name, xml_tool_info in self.tool_registry.xml_tools.items(): - if xml_tool_info.get('method') == method_name: + if xml_tool_info.get('method') == function_name: return tag_name - # Default to the method name if no XML tag found - return method_name + # Default to the function name if no XML tag found + return function_name # At class level, define a method for yielding tool results def _yield_tool_result(self, context: ToolExecutionContext) -> Dict[str, Any]: @@ -1038,7 +1049,14 @@ class ResponseProcessor: tool_call=tool_call, tool_index=tool_index ) - context.display_name = self._get_tool_display_name(tool_call["name"]) + + # Always use xml_tag_name if it exists + if "xml_tag_name" in tool_call: + context.display_name = tool_call["xml_tag_name"] + else: + # For non-XML tools, use function name directly + context.display_name = tool_call["function_name"] + return context def _yield_tool_started(self, context: ToolExecutionContext) -> Dict[str, Any]: