validate ppt

This commit is contained in:
Krishav Raj Singh 2025-10-09 07:13:07 +05:30
parent 98ca19b6c3
commit cf6c6142c5
3 changed files with 193 additions and 13 deletions

View File

@ -5,7 +5,7 @@ You are a **Creative Presentation Virtuoso**, an elite visual storyteller and de
## 🚨 **Core Directives**
1. **Theme Consistency is Paramount**: You MUST maintain a single, consistent visual theme throughout the entire presentation. This includes colors, fonts, and layout patterns. No exceptions.
2. **Content Density is Strictly Controlled**: You MUST ensure that the content on each slide is concise and fits comfortably within the 1080px slide height. You will use a **Content Density Score** to validate this before creating each slide.
2. **Content Density is Strictly Controlled**: You MUST ensure that the content on each slide is concise and fits comfortably within the 1080px slide height. You will use the `validate_slide` tool after creating each slide to ensure proper dimensions.
## 🎨 **Mandatory Workflow**
@ -48,20 +48,16 @@ Follow this simplified, four-step workflow for every presentation. **DO NOT SKIP
For each slide in your outline, you will perform the following steps:
1. **Calculate Content Density Score**: Before creating the slide, you MUST calculate a **Content Density Score**. This score is the sum of the following:
* **Title**: Number of characters / 10
* **Paragraphs**: Total number of characters in all paragraphs / 20
* **Bullet Points**: Number of bullet points * 5
* **Images**: Number of images * 15
1. **Create the Slide**: Create the slide using the `create_slide` tool. All styling MUST be derived from the **Theme Object** defined in Phase 2. Use relative path like `../images/[name]` to link images.
2. **Validate Content Density**: The **Content Density Score MUST NOT exceed 100**. If it does, you must revise the content to be more concise.
2. **Validate Slide Dimensions**: After creating each slide, you MUST use the `validate_slide` tool to verify that the slide height does not exceed 1080px. This tool will:
* Check for explicit height values exceeding 1080px
* Analyze content density and layout
* Provide warnings and recommendations if issues are detected
3. **Declare and Create**: Once the score is validated, announce the score and then create the slide using the `create_slide` tool. All styling MUST be derived from the **Theme Object** defined in Phase 2. Use relative path like `../images/[name]` to link images.
If validation fails or warnings are raised, revise the slide to reduce content or adjust spacing before proceeding to the next slide.
> **Example Slide Creation Announcement:**
> "The Content Density Score for this slide is 85, which is within the acceptable limit. I will now create the slide."
4. **Enforce Theme Consistency**: Ensure that every slide uses the *exact same* colors and fonts from the **Theme Object**. Do not introduce new styles or deviate from the established theme.
3. **Enforce Theme Consistency**: Ensure that every slide uses the *exact same* colors and fonts from the **Theme Object**. Do not introduce new styles or deviate from the established theme.
### **Phase 4: Final Presentation** 🎯

View File

@ -6,6 +6,7 @@ import json
import os
from datetime import datetime
import re
import asyncio
class SandboxPresentationTool(SandboxToolsBase):
"""
@ -427,6 +428,183 @@ class SandboxPresentationTool(SandboxToolsBase):
return self.fail_response(f"Failed to delete presentation: {str(e)}")
@openapi_schema({
"type": "function",
"function": {
"name": "validate_slide",
"description": "Validate a slide by reading its HTML code and checking if the content height exceeds 1080px. Use this tool to ensure slides fit within the standard presentation dimensions before finalizing them. This helps maintain proper slide formatting and prevents content overflow issues.",
"parameters": {
"type": "object",
"properties": {
"presentation_name": {
"type": "string",
"description": "Name of the presentation containing the slide to validate"
},
"slide_number": {
"type": "integer",
"description": "Slide number to validate (1-based)"
}
},
"required": ["presentation_name", "slide_number"]
}
}
})
async def validate_slide(self, presentation_name: str, slide_number: int) -> ToolResult:
"""Validate a slide by rendering it in a browser and measuring actual content height"""
try:
await self._ensure_sandbox()
if not presentation_name:
return self.fail_response("Presentation name is required.")
if slide_number < 1:
return self.fail_response("Slide number must be 1 or greater.")
safe_name = self._sanitize_filename(presentation_name)
presentation_path = f"{self.workspace_path}/{self.presentations_dir}/{safe_name}"
# Load metadata to verify slide exists
metadata = await self._load_presentation_metadata(presentation_path)
if not metadata.get("slides") or str(slide_number) not in metadata["slides"]:
return self.fail_response(f"Slide {slide_number} not found in presentation '{presentation_name}'")
# Get slide info
slide_info = metadata["slides"][str(slide_number)]
slide_filename = slide_info["filename"]
# Create a Python script to measure the actual rendered height using Playwright
measurement_script = f'''
import asyncio
import json
from playwright.async_api import async_playwright
async def measure_slide_height():
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
args=['--no-sandbox', '--disable-setuid-sandbox']
)
page = await browser.new_page(viewport={{"width": 1920, "height": 1080}})
# Load the HTML file
await page.goto('file:///workspace/{self.presentations_dir}/{safe_name}/{slide_filename}')
# Wait for page to load
await page.wait_for_load_state('networkidle')
# Measure the actual content height
dimensions = await page.evaluate("""
() => {{
const body = document.body;
const html = document.documentElement;
// Get the actual scroll height (total content height)
const scrollHeight = Math.max(
body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight
);
// Get viewport height
const viewportHeight = window.innerHeight;
// Check if content overflows
const overflows = scrollHeight > 1080;
return {{
scrollHeight: scrollHeight,
viewportHeight: viewportHeight,
overflows: overflows,
excessHeight: scrollHeight - 1080
}};
}}
""")
await browser.close()
return dimensions
result = asyncio.run(measure_slide_height())
print(json.dumps(result))
'''
# Write the script to a temporary file in the sandbox
script_path = f"{self.workspace_path}/.validate_slide_temp.py"
await self.sandbox.fs.upload_file(measurement_script.encode(), script_path)
# Execute the script
try:
result = await self.sandbox.process.exec(
f"/bin/sh -c 'cd /workspace && python3 .validate_slide_temp.py'",
timeout=30
)
# Parse the result
output = (getattr(result, "result", None) or getattr(result, "output", "") or "").strip()
if not output:
raise Exception("No output from validation script")
dimensions = json.loads(output)
# Clean up the temporary script
try:
await self.sandbox.fs.delete_file(script_path)
except:
pass
except Exception as e:
# Clean up on error
try:
await self.sandbox.fs.delete_file(script_path)
except:
pass
return self.fail_response(f"Failed to measure slide dimensions: {str(e)}")
# Analyze results
validation_results = {
"slide_number": slide_number,
"slide_title": slide_info["title"],
"actual_content_height": dimensions["scrollHeight"],
"target_height": 1080,
"excess_height": dimensions["excessHeight"],
"validation_passed": not dimensions["overflows"],
"warnings": [],
"errors": [],
"recommendations": []
}
# Add errors or success messages based on actual measurements
if dimensions["overflows"]:
validation_results["validation_passed"] = False
validation_results["errors"].append(
f"Content height ({dimensions['scrollHeight']}px) exceeds the 1080px limit by {dimensions['excessHeight']}px"
)
validation_results["recommendations"].append(
f"Reduce content or spacing by at least {dimensions['excessHeight']}px to fit within 1080px height"
)
# Provide warnings for slides close to the limit
elif dimensions["scrollHeight"] > 1000:
margin = 1080 - dimensions["scrollHeight"]
validation_results["warnings"].append(
f"Content height ({dimensions['scrollHeight']}px) is close to the 1080px limit (only {margin}px margin remaining)"
)
validation_results["recommendations"].append(
"Consider reducing content slightly to ensure comfortable fit across different browsers"
)
# Summary message
if validation_results["validation_passed"] and not validation_results["warnings"]:
validation_results["message"] = f"✓ Slide {slide_number} '{slide_info['title']}' validation passed. Content height: {dimensions['scrollHeight']}px (within 1080px limit)"
elif validation_results["validation_passed"] and validation_results["warnings"]:
validation_results["message"] = f"⚠ Slide {slide_number} '{slide_info['title']}' validation passed with {len(validation_results['warnings'])} warning(s)"
else:
validation_results["message"] = f"✗ Slide {slide_number} '{slide_info['title']}' validation failed. Content height: {dimensions['scrollHeight']}px exceeds 1080px by {dimensions['excessHeight']}px"
return self.success_response(validation_results)
except Exception as e:
return self.fail_response(f"Failed to validate slide: {str(e)}")
@openapi_schema({
"type": "function",
"function": {

View File

@ -218,6 +218,12 @@ TOOL_GROUPS: Dict[str, ToolGroup] = {
description="Delete entire presentations",
enabled=True
),
ToolMethod(
name="validate_slide",
display_name="Validate Slide",
description="Validate slide dimensions and content height",
enabled=True
),
ToolMethod(
name="present_presentation",
display_name="Present Presentation",