mirror of https://github.com/kortix-ai/suna.git
ui: validate slide
This commit is contained in:
parent
cf6c6142c5
commit
5ea69c1980
|
@ -16,7 +16,7 @@ Follow this simplified, four-step workflow for every presentation. **DO NOT SKIP
|
||||||
1. **Understand the User’s Needs**: Ask the user about the presentation’s **audience, context, and goals**.
|
1. **Understand the User’s Needs**: Ask the user about the presentation’s **audience, context, and goals**.
|
||||||
2. **Gather Information**: Use `web_search` and `web_scape` to research the topic thoroughly.
|
2. **Gather Information**: Use `web_search` and `web_scape` to research the topic thoroughly.
|
||||||
3. **Create a Content Outline**: Develop a structured outline that maps out the content for each slide. Focus on one main idea per slide. Also decide if a slide need any images or not, if yes what all. images will it need based on content.
|
3. **Create a Content Outline**: Develop a structured outline that maps out the content for each slide. Focus on one main idea per slide. Also decide if a slide need any images or not, if yes what all. images will it need based on content.
|
||||||
4. **Search Images**: Use `image_search` to batch search all images that are required, set num_results based on the number of images needed.
|
4. **Search Images**: Use `image_search` to batch search all images that are required. **IMPORTANT**: Search for only 2 images per topic (set `num_results=2`) to avoid confusion and keep results focused.
|
||||||
5. **Download Images**: Use `wget` command to batch download all images in `presentations/images` folder.
|
5. **Download Images**: Use `wget` command to batch download all images in `presentations/images` folder.
|
||||||
|
|
||||||
### **Phase 2: Theme Definition** 🎨
|
### **Phase 2: Theme Definition** 🎨
|
||||||
|
@ -50,14 +50,18 @@ For each slide in your outline, you will perform the following steps:
|
||||||
|
|
||||||
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.
|
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 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:
|
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. The validation is simple pass/fail:
|
||||||
* Check for explicit height values exceeding 1080px
|
* **Pass**: Content height ≤ 1080px
|
||||||
* Analyze content density and layout
|
* **Fail**: Content height > 1080px
|
||||||
* Provide warnings and recommendations if issues are detected
|
|
||||||
|
|
||||||
If validation fails or warnings are raised, revise the slide to reduce content or adjust spacing before proceeding to the next slide.
|
If validation fails, you must edit the slide to reduce content or adjust spacing before proceeding to the next slide.
|
||||||
|
|
||||||
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.
|
3. **Edit Slides When Needed**: When you need to modify existing slides (e.g., after validation failures or to update content), use the appropriate file editing tools:
|
||||||
|
* **`edit_file`** (PREFERRED): AI-powered editing tool for quick, precise edits. Specify only the lines you want to change using `// ... existing code ...` for unchanged sections. This is the fastest and most efficient option.
|
||||||
|
* **`str_replace`**: For simple exact text replacements (titles, colors, specific strings). Only use when `edit_file` is not suitable and the string appears exactly once.
|
||||||
|
* **`full_file_rewrite`**: Complete file rewrite. Use as last resort when other tools fail or when replacing entire slide content.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
### **Phase 4: Final Presentation** 🎯
|
### **Phase 4: Final Presentation** 🎯
|
||||||
|
|
||||||
|
|
|
@ -493,29 +493,21 @@ async def measure_slide_height():
|
||||||
# Wait for page to load
|
# Wait for page to load
|
||||||
await page.wait_for_load_state('networkidle')
|
await page.wait_for_load_state('networkidle')
|
||||||
|
|
||||||
# Measure the actual content height
|
# Measure the actual rendered height of the content
|
||||||
dimensions = await page.evaluate("""
|
dimensions = await page.evaluate("""
|
||||||
() => {{
|
() => {{
|
||||||
const body = document.body;
|
// Get the actual bounding box height of the body content
|
||||||
const html = document.documentElement;
|
const bodyRect = document.body.getBoundingClientRect();
|
||||||
|
const actualHeight = Math.ceil(bodyRect.height);
|
||||||
|
|
||||||
// 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;
|
const viewportHeight = window.innerHeight;
|
||||||
|
const overflows = actualHeight > 1080;
|
||||||
// Check if content overflows
|
|
||||||
const overflows = scrollHeight > 1080;
|
|
||||||
|
|
||||||
return {{
|
return {{
|
||||||
scrollHeight: scrollHeight,
|
scrollHeight: actualHeight,
|
||||||
viewportHeight: viewportHeight,
|
viewportHeight: viewportHeight,
|
||||||
overflows: overflows,
|
overflows: overflows,
|
||||||
excessHeight: scrollHeight - 1080
|
excessHeight: Math.max(0, actualHeight - 1080)
|
||||||
}};
|
}};
|
||||||
}}
|
}}
|
||||||
""")
|
""")
|
||||||
|
@ -559,46 +551,25 @@ print(json.dumps(result))
|
||||||
pass
|
pass
|
||||||
return self.fail_response(f"Failed to measure slide dimensions: {str(e)}")
|
return self.fail_response(f"Failed to measure slide dimensions: {str(e)}")
|
||||||
|
|
||||||
# Analyze results
|
# Analyze results - simple pass/fail
|
||||||
|
validation_passed = not dimensions["overflows"]
|
||||||
|
|
||||||
validation_results = {
|
validation_results = {
|
||||||
|
"presentation_name": presentation_name,
|
||||||
|
"presentation_path": presentation_path,
|
||||||
"slide_number": slide_number,
|
"slide_number": slide_number,
|
||||||
"slide_title": slide_info["title"],
|
"slide_title": slide_info["title"],
|
||||||
"actual_content_height": dimensions["scrollHeight"],
|
"actual_content_height": dimensions["scrollHeight"],
|
||||||
"target_height": 1080,
|
"target_height": 1080,
|
||||||
"excess_height": dimensions["excessHeight"],
|
"validation_passed": validation_passed
|
||||||
"validation_passed": not dimensions["overflows"],
|
|
||||||
"warnings": [],
|
|
||||||
"errors": [],
|
|
||||||
"recommendations": []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add errors or success messages based on actual measurements
|
# Add pass/fail message
|
||||||
if dimensions["overflows"]:
|
if validation_passed:
|
||||||
validation_results["validation_passed"] = False
|
validation_results["message"] = f"✓ Slide {slide_number} '{slide_info['title']}' validation passed. Content height: {dimensions['scrollHeight']}px"
|
||||||
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:
|
else:
|
||||||
validation_results["message"] = f"✗ Slide {slide_number} '{slide_info['title']}' validation failed. Content height: {dimensions['scrollHeight']}px exceeds 1080px by {dimensions['excessHeight']}px"
|
validation_results["message"] = f"✗ Slide {slide_number} '{slide_info['title']}' validation failed. Content height: {dimensions['scrollHeight']}px exceeds 1080px limit by {dimensions['excessHeight']}px"
|
||||||
|
validation_results["excess_height"] = dimensions["excessHeight"]
|
||||||
|
|
||||||
return self.success_response(validation_results)
|
return self.success_response(validation_results)
|
||||||
|
|
||||||
|
|
|
@ -484,6 +484,12 @@ export const TOOL_GROUPS: Record<string, ToolGroup> = {
|
||||||
description: 'Delete entire presentations',
|
description: 'Delete entire presentations',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'validate_slide',
|
||||||
|
displayName: 'Validate Slide',
|
||||||
|
description: 'Validate slide dimensions and content height',
|
||||||
|
enabled: true,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ const defaultRegistry: ToolViewRegistryType = {
|
||||||
'list-presentations': ListPresentationsToolView,
|
'list-presentations': ListPresentationsToolView,
|
||||||
'delete-slide': DeleteSlideToolView,
|
'delete-slide': DeleteSlideToolView,
|
||||||
'delete-presentation': DeletePresentationToolView,
|
'delete-presentation': DeletePresentationToolView,
|
||||||
|
'validate-slide': PresentationViewer,
|
||||||
// 'presentation-styles': PresentationStylesToolView,
|
// 'presentation-styles': PresentationStylesToolView,
|
||||||
'present-presentation': PresentPresentationToolView,
|
'present-presentation': PresentPresentationToolView,
|
||||||
|
|
||||||
|
@ -263,6 +264,7 @@ export function ToolView({ name = 'default', assistantContent, toolContent, ...p
|
||||||
'list-slides',
|
'list-slides',
|
||||||
'delete-slide',
|
'delete-slide',
|
||||||
'delete-presentation',
|
'delete-presentation',
|
||||||
|
'validate-slide',
|
||||||
// 'presentation-styles',
|
// 'presentation-styles',
|
||||||
'present-presentation',
|
'present-presentation',
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue