rem styles from tool

This commit is contained in:
Krishav Raj Singh 2025-09-28 01:28:49 +05:30
parent 67cbf529dd
commit d4179c7832
1 changed files with 76 additions and 217 deletions

View File

@ -6,13 +6,12 @@ import json
import os
from datetime import datetime
import re
from .presentation_styles_config import get_style_config, get_all_styles
class SandboxPresentationTool(SandboxToolsBase):
"""
Per-slide HTML presentation tool for creating professional presentations.
Each slide is managed individually with 1920x1080 dimensions.
Supports iterative slide creation, editing, and presentation assembly.
Per-slide HTML presentation tool for creating presentation slides.
Each slide is created as a basic HTML document without predefined CSS styling.
Users can include their own CSS styling inline or in style tags as needed.
"""
def __init__(self, project_id: str, thread_manager: ThreadManager):
@ -20,6 +19,7 @@ class SandboxPresentationTool(SandboxToolsBase):
self.workspace_path = "/workspace"
self.presentations_dir = "presentations"
async def _ensure_presentations_dir(self):
"""Ensure the presentations directory exists"""
full_path = f"{self.workspace_path}/{self.presentations_dir}"
@ -42,15 +42,9 @@ class SandboxPresentationTool(SandboxToolsBase):
"""Convert presentation name to safe filename"""
return "".join(c for c in name if c.isalnum() or c in "-_").lower()
def _get_style_config(self, style_name: str) -> Dict:
"""Get style configuration for a given style name"""
return get_style_config(style_name)
def _create_slide_html(self, slide_content: str, slide_number: int, total_slides: int, presentation_title: str, style: str = "default") -> str:
"""Create a complete HTML document for a single slide with proper 1920x1080 dimensions"""
# Get style configuration
style_config = self._get_style_config(style)
def _create_slide_html(self, slide_content: str, slide_number: int, total_slides: int, presentation_title: str) -> str:
"""Create a basic HTML document without predefined CSS"""
html_template = f"""<!DOCTYPE html>
<html lang="en">
@ -58,146 +52,12 @@ class SandboxPresentationTool(SandboxToolsBase):
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{presentation_title} - Slide {slide_number}</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="{style_config['font_import']}" rel="stylesheet">
<script src="https://d3js.org/d3.v7.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.9.1"></script>
<style>
/* Base styling and 1920x1080 slide container */
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
margin: 0;
padding: 0;
font-family: {style_config['font_family']};
color: {style_config['text_color']};
}}
.slide-container {{
/* CRITICAL: Standard presentation dimensions */
width: 1920px;
height: 1080px;
max-width: 100vw;
max-height: 100vh;
position: relative;
background: {style_config['background']};
color: {style_config['text_color']};
overflow: hidden;
/* Auto-scale to fit viewport while maintaining aspect ratio */
transform-origin: center center;
transform: scale(min(100vw / 1920px, 100vh / 1080px));
}}
/* Slide number indicator */
.slide-number {{
position: absolute;
bottom: 30px;
right: 30px;
font-size: 18px;
color: {style_config['text_color']};
opacity: 0.7;
font-weight: 500;
z-index: 1000;
}}
/* Common presentation elements with style theming */
.slide-title {{
font-size: 48px;
font-weight: bold;
margin-bottom: 30px;
color: {style_config['primary_color']};
}}
.slide-subtitle {{
font-size: 32px;
margin-bottom: 40px;
color: {style_config['text_color']};
}}
.slide-content {{
font-size: 24px;
line-height: 1.6;
color: {style_config['text_color']};
}}
.accent-bar {{
width: 100px;
height: 4px;
background-color: {style_config['accent_color']};
margin: 20px 0;
}}
/* Primary color elements */
.primary-color {{
color: {style_config['primary_color']};
}}
.primary-bg {{
background-color: {style_config['primary_color']};
}}
/* Accent color elements */
.accent-color {{
color: {style_config['accent_color']};
}}
.accent-bg {{
background-color: {style_config['accent_color']};
}}
/* Style-aware text color */
.text-color {{
color: {style_config['text_color']};
}}
/* Responsive images */
img {{
max-width: 100%;
height: auto;
border-radius: 8px;
}}
/* List styling */
ul, ol {{
margin: 20px 0;
padding-left: 30px;
}}
li {{
margin: 10px 0;
font-size: 20px;
line-height: 1.5;
color: {style_config['text_color']};
}}
/* Style-specific enhancements */
.card {{
background: {'rgba(255, 255, 255, 0.1)' if 'gradient' in style_config['background'] or style_config['background'].startswith('#1') or style_config['background'].startswith('#0') else 'rgba(0, 0, 0, 0.05)'};
border-radius: 12px;
padding: 30px;
backdrop-filter: blur(10px);
}}
.highlight {{
background: {style_config['accent_color']};
color: {'#FFFFFF' if style_config['accent_color'].startswith('#') else style_config['text_color']};
padding: 4px 12px;
border-radius: 6px;
font-weight: 600;
}}
</style>
</head>
<body>
<div class="slide-container">
{slide_content}
<div class="slide-number">{slide_number}{f" / {total_slides}" if total_slides > 0 else ""}</div>
</div>
{slide_content}
</body>
</html>"""
return html_template
@ -229,7 +89,7 @@ class SandboxPresentationTool(SandboxToolsBase):
"type": "function",
"function": {
"name": "create_slide",
"description": "Create or update a single slide in a presentation. Each slide is saved as a standalone HTML file with 1920x1080 dimensions (16:9 aspect ratio). Perfect for iterative slide creation and editing. Use 'presentation_styles' tool first to see available styles.",
"description": "Create or update a single slide in a presentation. Each slide is saved as a standalone HTML file with 1920x1080 dimensions (16:9 aspect ratio). Perfect for iterative slide creation and editing.",
"parameters": {
"type": "object",
"properties": {
@ -246,18 +106,13 @@ class SandboxPresentationTool(SandboxToolsBase):
"description": "Title of this specific slide (for reference and navigation)"
},
"content": {
"type": "string",
"description": "HTML content for the slide body. Should include all styling within the content. The content will be placed inside a 1920x1080 slide container with CSS frameworks (Tailwind, FontAwesome, D3, Chart.js) available. Use professional styling with good typography, spacing, and visual hierarchy. You can use style-aware CSS classes: .primary-color, .primary-bg, .accent-color, .accent-bg, .text-color, .card, .highlight"
},
"type": "string",
"description": "Complete HTML content including inline CSS or <style> blocks. Design for 1920x1080 resolution. Include all necessary styling as no external CSS frameworks are automatically loaded."
},
"presentation_title": {
"type": "string",
"description": "Main title of the presentation (used in HTML title and navigation)",
"default": "Presentation"
},
"style": {
"type": "string",
"description": "Visual style theme for the slide. Use 'presentation_styles' tool to see all available options. Examples: 'velvet', 'glacier', 'ember', 'sage', 'obsidian', 'coral', 'platinum', 'aurora', 'midnight', 'citrus', or 'default'",
"default": "default"
}
},
"required": ["presentation_name", "slide_number", "slide_title", "content"]
@ -265,36 +120,69 @@ class SandboxPresentationTool(SandboxToolsBase):
}
})
@usage_example('''
Create individual slides for a presentation about "Modern Web Development":
Create clean, professional presentation slides:
<function_calls>
<invoke name="create_slide">
<parameter name="presentation_name">modern_web_development</parameter>
<parameter name="slide_number">1</parameter>
<parameter name="slide_title">Title Slide</parameter>
<parameter name="presentation_title">Modern Web Development Trends 2024</parameter>
<parameter name="content"><div style='background: linear-gradient(135deg, #005A9C 0%, #FF6B00 100%); height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; color: white; padding: 80px;'><h1 style='font-size: 72px; font-weight: bold; margin-bottom: 30px;'>Modern Web Development</h1><div style='width: 150px; height: 6px; background: white; margin: 30px auto;'></div><h2 style='font-size: 36px; margin-bottom: 40px; opacity: 0.9;'>Trends & Technologies 2024</h2><p style='font-size: 24px; opacity: 0.8;'>Building Tomorrow's Web Today</p></div></parameter>
</invoke>
</function_calls>
# Example 1: Simple Title Slide
<function_calls>
<invoke name="create_slide">
<parameter name="presentation_name">product_launch_2024</parameter>
<parameter name="slide_number">1</parameter>
<parameter name="slide_title">Product Launch Title</parameter>
<parameter name="presentation_title">Product Launch 2024</parameter>
<parameter name="content">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.slide-container {
width: 1920px;
height: 1080px;
background: #ffffff;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Arial', sans-serif;
color: #333333;
}
.content {
text-align: center;
padding: 40px;
}
.main-title {
font-size: 64px;
font-weight: 700;
margin-bottom: 30px;
color: #2563eb;
line-height: 1.2;
}
.subtitle {
font-size: 28px;
margin-bottom: 40px;
color: #666666;
font-weight: 400;
}
.accent-line {
width: 100px;
height: 4px;
background: #2563eb;
margin: 30px auto;
border-radius: 2px;
}
</style>
Then create the next slide:
<function_calls>
<invoke name="create_slide">
<parameter name="presentation_name">modern_web_development</parameter>
<parameter name="slide_number">2</parameter>
<parameter name="slide_title">Frontend Frameworks</parameter>
<parameter name="presentation_title">Modern Web Development Trends 2024</parameter>
<parameter name="content"><div style='display: flex; height: 100%; padding: 0;'><div style='width: 60%; padding: 80px; display: flex; flex-direction: column; justify-content: center;'><h1 style='font-size: 48px; font-weight: bold; color: #005A9C; margin-bottom: 20px;'>Frontend Frameworks</h1><div style='width: 100px; height: 4px; background: #FF6B00; margin-bottom: 40px;'></div><div style='font-size: 22px; line-height: 1.8;'><div style='margin-bottom: 25px; display: flex; align-items: center;'><i class='fab fa-react' style='color: #61DAFB; font-size: 28px; margin-right: 15px;'></i><div><strong>React</strong> - Component-based UI library</div></div><div style='margin-bottom: 25px; display: flex; align-items: center;'><i class='fab fa-vuejs' style='color: #4FC08D; font-size: 28px; margin-right: 15px;'></i><div><strong>Vue.js</strong> - Progressive framework</div></div></div></div><div style='width: 40%; background: #f8f9fa; display: flex; align-items: center; justify-content: center; padding: 40px;'><div style='text-align: center;'><div style='font-size: 64px; margin-bottom: 30px;'>📱</div><h3 style='font-size: 28px; color: #005A9C;'>Modern Tools</h3></div></div></div></parameter>
</invoke>
</function_calls>
This approach allows you to:
- Create slides one at a time
- Edit existing slides by using the same slide number
- Build presentations iteratively
- Mix and match different slide designs
- Each slide is a standalone HTML file with full styling
<div class="slide-container">
<div class="content">
<h1 class="main-title">Product Launch 2024</h1>
<div class="accent-line"></div>
<p class="subtitle">Introducing our latest innovation</p>
</div>
</div>
</parameter>
</invoke>
</function_calls>
''')
async def create_slide(
self,
@ -302,8 +190,7 @@ This approach allows you to:
slide_number: int,
slide_title: str,
content: str,
presentation_title: str = "Presentation",
style: str = "default"
presentation_title: str = "Presentation"
) -> ToolResult:
"""Create or update a single slide in a presentation"""
try:
@ -337,8 +224,7 @@ This approach allows you to:
slide_content=content,
slide_number=slide_number,
total_slides=0, # Will be updated when regenerating navigation
presentation_title=presentation_title,
style=style
presentation_title=presentation_title
)
# Save slide file
@ -355,7 +241,6 @@ This approach allows you to:
"filename": slide_filename,
"file_path": f"{self.presentations_dir}/{safe_name}/{slide_filename}",
"preview_url": f"/workspace/{self.presentations_dir}/{safe_name}/{slide_filename}",
"style": style,
"created_at": datetime.now().isoformat()
}
@ -363,16 +248,15 @@ This approach allows you to:
await self._save_presentation_metadata(presentation_path, metadata)
return self.success_response({
"message": f"Slide {slide_number} '{slide_title}' created/updated successfully with '{style}' style",
"message": f"Slide {slide_number} '{slide_title}' created/updated successfully",
"presentation_name": presentation_name,
"presentation_path": f"{self.presentations_dir}/{safe_name}",
"slide_number": slide_number,
"slide_title": slide_title,
"slide_file": f"{self.presentations_dir}/{safe_name}/{slide_filename}",
"preview_url": f"/workspace/{self.presentations_dir}/{safe_name}/{slide_filename}",
"style": style,
"total_slides": len(metadata["slides"]),
"note": "Slide saved as standalone HTML file with 1920x1080 dimensions"
"note": "Professional slide created with custom styling - designed for 1920x1080 resolution"
})
except Exception as e:
@ -513,31 +397,6 @@ This approach allows you to:
@openapi_schema({
"type": "function",
"function": {
"name": "presentation_styles",
"description": "Get available presentation styles with their descriptions and visual characteristics. Use this to show users different style options before creating slides.",
"parameters": {
"type": "object",
"properties": {},
"required": []
}
}
})
async def presentation_styles(self) -> ToolResult:
"""Get available presentation styles with descriptions and examples"""
try:
styles = get_all_styles()
return self.success_response({
"message": f"Found {len(styles)} presentation styles available",
"styles": styles,
"usage_tip": "Choose a style and use it with the 'style' parameter in create_slide"
})
except Exception as e:
return self.fail_response(f"Failed to get presentation styles: {str(e)}")
@openapi_schema({
"type": "function",