shipdeck
Version:
Ship MVPs in 48 hours. Fix bugs in 30 seconds. The command deck for developers who ship.
768 lines (654 loc) • 26.2 kB
JavaScript
/**
* Whimsy Injector Agent for Shipdeck Ultimate
* Specializes in adding delightful touches, micro-interactions, and memorable moments to user experiences
*/
const { BaseAgent } = require('./base-agent');
class WhimsyInjector extends BaseAgent {
constructor(options = {}) {
super({
name: 'WhimsyInjector',
description: 'Specialized agent for adding joy, surprise, and memorable moments to user experiences through delightful UI enhancements',
version: '1.0.0',
...options
});
// Whimsy-specific configuration
this.whimsyConfig = {
animationDuration: 'medium', // 'fast', 'medium', 'slow'
respectsReducedMotion: true,
colorScheme: 'playful', // 'playful', 'elegant', 'vibrant'
interactionLevel: 'moderate', // 'subtle', 'moderate', 'bold'
accessibility: true,
performance: 'optimized',
...options.whimsyConfig
};
// Delightful patterns library
this.delightPatterns = this.initializeDelightPatterns();
this.animationLibrary = this.initializeAnimationLibrary();
this.personalityTemplates = this.initializePersonalityTemplates();
}
/**
* Get whimsy injector capabilities
* @returns {Array<string>} Array of whimsy capabilities
*/
getCapabilities() {
return ['delight', 'animation', 'micro-interactions', 'easter-eggs', 'personality'];
}
/**
* Initialize library of delightful patterns
* @returns {Object} Delight patterns object
*/
initializeDelightPatterns() {
return {
confetti: {
trigger: 'success',
performance: 'gpu-accelerated',
accessibility: 'respects-reduced-motion'
},
sparkles: {
trigger: 'hover',
performance: 'lightweight',
accessibility: 'decorative'
},
smoothTransitions: {
trigger: 'state-change',
performance: 'css-based',
accessibility: 'enhances-ux'
},
bouncyButtons: {
trigger: 'click',
performance: 'transform-based',
accessibility: 'tactile-feedback'
},
progressCelebration: {
trigger: 'milestone',
performance: 'requestAnimationFrame',
accessibility: 'optional-enhancement'
}
};
}
/**
* Initialize animation library
* @returns {Object} Animation library object
*/
initializeAnimationLibrary() {
return {
entrances: ['fadeIn', 'slideUp', 'scaleIn', 'bounceIn'],
exits: ['fadeOut', 'slideDown', 'scaleOut', 'bounceOut'],
hovers: ['lift', 'glow', 'wobble', 'pulse'],
loading: ['spin', 'bounce', 'dots', 'skeleton'],
success: ['checkmark', 'confetti', 'celebration', 'tada'],
error: ['shake', 'highlight', 'gentle-bounce'],
transitions: ['smooth', 'elastic', 'spring', 'ease-out']
};
}
/**
* Initialize personality templates for messages
* @returns {Object} Personality templates
*/
initializePersonalityTemplates() {
return {
errors: {
friendly: [
"Oops! Something didn't go as planned, but we're on it!",
"Well, that's embarrassing. Let's try that again!",
"Houston, we have a small problem. But nothing we can't fix!",
"Looks like something went sideways. Give us a moment to sort this out!"
],
encouraging: [
"Don't worry, everyone makes mistakes! Let's fix this together.",
"No biggie! Even the best of us trip sometimes.",
"That's okay! We learn from every stumble.",
"Close! Just a tiny adjustment needed."
],
playful: [
"Whoopsie-daisy! Time for plan B.",
"Plot twist! That wasn't supposed to happen.",
"Well, that was unexpected! Let's pivot.",
"Surprise! That's not how it usually goes."
]
},
loading: {
patient: [
"Taking our time to get this just right...",
"Good things come to those who wait...",
"Brewing something special for you...",
"Almost there, just adding the finishing touches..."
],
playful: [
"Doing some digital magic behind the scenes...",
"Teaching the pixels to dance...",
"Convincing the servers to work faster...",
"Summoning data from the cloud realm..."
],
progress: [
"Step 1 of 3: Gathering ingredients...",
"Halfway there! Building your masterpiece...",
"Final touches being applied...",
"Ready in 3... 2... 1..."
]
},
success: {
celebration: [
"Boom! Mission accomplished!",
"Victory dance time!",
"And that's how it's done!",
"Nailed it! High five!"
],
grateful: [
"Thank you for your patience!",
"We appreciate you sticking with us!",
"Thanks for being awesome!",
"You're the best!"
],
motivational: [
"Look what you've accomplished!",
"You're crushing it!",
"Another milestone reached!",
"Keep up the amazing work!"
]
}
};
}
/**
* Execute whimsy injection task
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Generated whimsy enhancements
*/
async execute(task, context = {}) {
this.log('info', `Executing whimsy task: ${task.type}`, { task: task.type });
try {
switch (task.type) {
case 'add-micro-interactions':
return await this.addMicroInteractions(task, context);
case 'create-loading-states':
return await this.createDelightfulLoading(task, context);
case 'add-easter-eggs':
return await this.addEasterEggs(task, context);
case 'inject-personality':
return await this.injectPersonality(task, context);
case 'create-animations':
return await this.createAnimations(task, context);
case 'enhance-hover-effects':
return await this.enhanceHoverEffects(task, context);
case 'add-success-celebrations':
return await this.addSuccessCelebrations(task, context);
case 'create-smooth-transitions':
return await this.createSmoothTransitions(task, context);
case 'full-whimsy-injection':
return await this.fullWhimsyInjection(task, context);
default:
return await this.customWhimsyTask(task, context);
}
} catch (error) {
this.log('error', `Whimsy task execution failed: ${error.message}`, { error: error.stack });
throw error;
}
}
/**
* Add micro-interactions to UI components
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Micro-interaction enhancements
*/
async addMicroInteractions(task, context) {
const prompt = this.createPrompt({
...task,
systemContext: `You are a UI/UX specialist focused on creating delightful micro-interactions.
Key principles:
- Respect reduced motion preferences
- Use CSS transforms for performance
- Provide clear visual feedback
- Keep animations under 300ms for interactions
- Ensure accessibility compliance
Available interaction types: ${Object.keys(this.delightPatterns).join(', ')}
Animation library: ${Object.keys(this.animationLibrary).join(', ')}
Generate React/Next.js components with Tailwind CSS classes and modern CSS animations.
Include proper error handling and accessibility considerations.`
}, context);
const response = await this.sendMessage(prompt, {
temperature: 0.8 // More creative for delightful touches
});
if (!response.success) {
throw new Error(`Failed to generate micro-interactions: ${response.error}`);
}
return this.processMicroInteractionResponse(response.content, task);
}
/**
* Create delightful loading states
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Loading state components
*/
async createDelightfulLoading(task, context) {
const loadingTypes = task.loadingTypes || ['skeleton', 'spinner', 'progress', 'entertainment'];
const prompt = this.createPrompt({
...task,
systemContext: `Create engaging and delightful loading states that keep users entertained.
Loading types to implement: ${loadingTypes.join(', ')}
Personality style: ${this.whimsyConfig.colorScheme}
Animation duration: ${this.whimsyConfig.animationDuration}
Requirements:
- Respect prefers-reduced-motion
- Use semantic loading messages
- Include progress indicators where appropriate
- Add personality to waiting times
- Optimize for performance (CSS transforms, GPU acceleration)
- Ensure screen reader compatibility
Generate complete React components with TypeScript support and comprehensive error handling.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.9 });
if (!response.success) {
throw new Error(`Failed to create loading states: ${response.error}`);
}
return this.processLoadingResponse(response.content, task, loadingTypes);
}
/**
* Add Easter eggs and surprises
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Easter egg implementations
*/
async addEasterEggs(task, context) {
const easterEggTypes = task.easterEggTypes || ['konami-code', 'click-sequence', 'time-based', 'user-milestone'];
const prompt = this.createPrompt({
...task,
systemContext: `Create delightful Easter eggs that surprise and delight users without compromising the main experience.
Easter egg types: ${easterEggTypes.join(', ')}
Interaction level: ${this.whimsyConfig.interactionLevel}
Guidelines:
- Should not interfere with primary user tasks
- Include way to disable for accessibility
- Use local storage for persistence
- Add telemetry for engagement tracking
- Make them discoverable but not obvious
- Ensure they work across different screen sizes
Create React hooks and components that can be easily integrated into existing applications.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.95 });
if (!response.success) {
throw new Error(`Failed to create Easter eggs: ${response.error}`);
}
return this.processEasterEggResponse(response.content, task, easterEggTypes);
}
/**
* Inject personality into error messages and UI text
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Personality-enhanced content
*/
async injectPersonality(task, context) {
const personalityStyle = task.personalityStyle || 'friendly';
const messageTypes = task.messageTypes || ['errors', 'loading', 'success', 'empty-states'];
const availablePersonalities = Object.keys(this.personalityTemplates.errors);
const prompt = this.createPrompt({
...task,
systemContext: `Transform bland UI messages into personality-rich content that creates emotional connection.
Personality style: ${personalityStyle}
Available styles: ${availablePersonalities.join(', ')}
Message types: ${messageTypes.join(', ')}
Requirements:
- Maintain professionalism while adding character
- Ensure messages are still informative
- Consider international audiences
- Include fallbacks for serious contexts
- Respect user preferences for tone
- Maintain accessibility standards
Generate a comprehensive content system with multiple variations for each message type.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.85 });
if (!response.success) {
throw new Error(`Failed to inject personality: ${response.error}`);
}
return this.processPersonalityResponse(response.content, task, personalityStyle, messageTypes);
}
/**
* Create smooth animations and transitions
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Animation implementations
*/
async createAnimations(task, context) {
const animationTypes = task.animationTypes || ['page-transitions', 'component-mounts', 'state-changes', 'scroll-triggered'];
const prompt = this.createPrompt({
...task,
systemContext: `Create buttery-smooth animations that enhance user experience without causing motion sickness.
Animation types: ${animationTypes.join(', ')}
Available animations: ${Object.keys(this.animationLibrary).join(', ')}
Duration preference: ${this.whimsyConfig.animationDuration}
Technical requirements:
- Use CSS transforms and opacity for performance
- Implement will-change property appropriately
- Respect prefers-reduced-motion media query
- Use requestAnimationFrame for JS animations
- Optimize for 60fps performance
- Include loading states for heavy animations
Generate production-ready animation utilities and components with TypeScript support.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.7 });
if (!response.success) {
throw new Error(`Failed to create animations: ${response.error}`);
}
return this.processAnimationResponse(response.content, task, animationTypes);
}
/**
* Enhance hover effects for better interactivity
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Enhanced hover effects
*/
async enhanceHoverEffects(task, context) {
const elementTypes = task.elementTypes || ['buttons', 'cards', 'links', 'images', 'icons'];
const prompt = this.createPrompt({
...task,
systemContext: `Create engaging hover effects that provide clear visual feedback and enhance interactivity.
Element types: ${elementTypes.join(', ')}
Hover effects available: ${this.animationLibrary.hovers.join(', ')}
Requirements:
- Work well on both desktop and touch devices
- Provide immediate visual feedback
- Use hardware acceleration when possible
- Include focus states for keyboard navigation
- Maintain accessibility contrast ratios
- Consider hover intent detection
- Optimize for performance on lower-end devices
Generate CSS classes and React components with comprehensive hover state management.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.8 });
if (!response.success) {
throw new Error(`Failed to enhance hover effects: ${response.error}`);
}
return this.processHoverEffectResponse(response.content, task, elementTypes);
}
/**
* Add success celebration animations
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Success celebration implementations
*/
async addSuccessCelebrations(task, context) {
const celebrationTypes = task.celebrationTypes || ['form-submission', 'milestone-reached', 'task-completed', 'level-up'];
const prompt = this.createPrompt({
...task,
systemContext: `Create celebratory animations that make users feel accomplished and encourage continued engagement.
Celebration types: ${celebrationTypes.join(', ')}
Success animations: ${this.animationLibrary.success.join(', ')}
Design principles:
- Make achievements feel meaningful
- Use progressive enhancement
- Include sound effects considerations
- Scale celebration intensity with achievement importance
- Provide subtle alternatives for reduced motion
- Consider cultural sensitivity in celebration styles
- Include proper timing and sequencing
Generate celebration components with customizable intensity and trigger conditions.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.9 });
if (!response.success) {
throw new Error(`Failed to create success celebrations: ${response.error}`);
}
return this.processCelebrationResponse(response.content, task, celebrationTypes);
}
/**
* Create smooth transitions between states and pages
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Transition implementations
*/
async createSmoothTransitions(task, context) {
const transitionTypes = task.transitionTypes || ['page-navigation', 'modal-open-close', 'tab-switching', 'accordion-expand'];
const prompt = this.createPrompt({
...task,
systemContext: `Create seamless transitions that provide visual continuity and enhance perceived performance.
Transition types: ${transitionTypes.join(', ')}
Transition styles: ${this.animationLibrary.transitions.join(', ')}
Technical considerations:
- Maintain layout stability during transitions
- Use transform and opacity for smoothest performance
- Implement proper z-index management
- Handle interrupted transitions gracefully
- Optimize for different screen sizes
- Consider reduced motion preferences
- Implement proper enter/exit timing
Generate transition utilities compatible with React Router and Next.js page transitions.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.75 });
if (!response.success) {
throw new Error(`Failed to create transitions: ${response.error}`);
}
return this.processTransitionResponse(response.content, task, transitionTypes);
}
/**
* Full whimsy injection across entire application
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Complete whimsy overhaul
*/
async fullWhimsyInjection(task, context) {
const components = task.components || ['buttons', 'forms', 'navigation', 'cards', 'modals', 'loading', 'errors'];
const prompt = this.createPrompt({
...task,
systemContext: `Perform a comprehensive whimsy injection across the entire application, creating a cohesive delightful experience.
Components to enhance: ${components.join(', ')}
All capabilities: ${this.getCapabilities().join(', ')}
Config: ${JSON.stringify(this.whimsyConfig, null, 2)}
Create a complete design system that includes:
- Unified animation language
- Consistent micro-interactions
- Cohesive personality voice
- Performance-optimized implementations
- Accessibility-compliant enhancements
- Cross-component harmony
- Progressive enhancement strategy
Generate a production-ready whimsy design system with documentation and implementation guide.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.85 });
if (!response.success) {
throw new Error(`Failed to perform full whimsy injection: ${response.error}`);
}
return this.processFullWhimsyResponse(response.content, task, components);
}
/**
* Handle custom whimsy tasks
* @param {Object} task - Task configuration
* @param {Object} context - Execution context
* @returns {Promise<Object>} Custom whimsy implementation
*/
async customWhimsyTask(task, context) {
const prompt = this.createPrompt({
...task,
systemContext: `Handle a custom whimsy request with creative problem-solving and delightful solutions.
Available patterns: ${Object.keys(this.delightPatterns).join(', ')}
Animation library: ${Object.keys(this.animationLibrary).join(', ')}
Capabilities: ${this.getCapabilities().join(', ')}
Apply whimsy principles:
- Surprise and delight
- Accessibility first
- Performance optimized
- Contextually appropriate
- User-centered design
- Technical excellence
Create a custom solution that exceeds expectations while maintaining professional standards.`
}, context);
const response = await this.sendMessage(prompt, { temperature: 0.9 });
if (!response.success) {
throw new Error(`Failed to execute custom whimsy task: ${response.error}`);
}
return this.processCustomWhimsyResponse(response.content, task);
}
// Response processing methods
processMicroInteractionResponse(content, task) {
return {
type: 'micro-interactions',
task: task.type,
enhancements: this.parseResponse(content),
patterns: Object.keys(this.delightPatterns),
accessibility: this.whimsyConfig.accessibility,
performance: 'optimized',
implementation: 'ready'
};
}
processLoadingResponse(content, task, loadingTypes) {
return {
type: 'loading-states',
task: task.type,
loadingTypes,
components: this.parseResponse(content),
personality: this.personalityTemplates.loading,
accessibility: 'screen-reader-friendly',
performance: 'gpu-accelerated'
};
}
processEasterEggResponse(content, task, easterEggTypes) {
return {
type: 'easter-eggs',
task: task.type,
easterEggTypes,
implementations: this.parseResponse(content),
discoverability: 'hidden-but-findable',
accessibility: 'optional-enhancement'
};
}
processPersonalityResponse(content, task, personalityStyle, messageTypes) {
return {
type: 'personality-injection',
task: task.type,
personalityStyle,
messageTypes,
content: this.parseResponse(content),
fallbacks: 'professional-tone',
localization: 'consideration-included'
};
}
processAnimationResponse(content, task, animationTypes) {
return {
type: 'animations',
task: task.type,
animationTypes,
implementations: this.parseResponse(content),
performance: '60fps-optimized',
accessibility: 'reduced-motion-compliant'
};
}
processHoverEffectResponse(content, task, elementTypes) {
return {
type: 'hover-effects',
task: task.type,
elementTypes,
effects: this.parseResponse(content),
touchDevice: 'compatible',
keyboard: 'focus-state-included'
};
}
processCelebrationResponse(content, task, celebrationTypes) {
return {
type: 'success-celebrations',
task: task.type,
celebrationTypes,
celebrations: this.parseResponse(content),
intensity: 'customizable',
timing: 'contextual'
};
}
processTransitionResponse(content, task, transitionTypes) {
return {
type: 'smooth-transitions',
task: task.type,
transitionTypes,
transitions: this.parseResponse(content),
continuity: 'visual-maintained',
performance: 'layout-stable'
};
}
processFullWhimsyResponse(content, task, components) {
return {
type: 'full-whimsy-injection',
task: task.type,
components,
designSystem: this.parseResponse(content),
cohesion: 'unified-experience',
implementation: 'production-ready',
documentation: 'comprehensive'
};
}
processCustomWhimsyResponse(content, task) {
return {
type: 'custom-whimsy',
task: task.type,
solution: this.parseResponse(content),
creativity: 'high',
standards: 'professional',
uniqueness: 'custom-crafted'
};
}
/**
* Get system prompt for whimsy injection
* @returns {string} System prompt
*/
getSystemPrompt() {
return `You are WhimsyInjector, a specialized AI agent focused on creating delightful user experiences through carefully crafted micro-interactions, animations, and personality touches.
Your mission: Transform mundane interfaces into memorable experiences that surprise, delight, and create emotional connections with users.
Capabilities: ${this.getCapabilities().join(', ')}
Core Principles:
1. Accessibility First - Always respect reduced motion preferences and ensure screen reader compatibility
2. Performance Optimized - Use CSS transforms, GPU acceleration, and efficient animation techniques
3. Contextually Appropriate - Match the level of whimsy to the application's purpose and audience
4. Progressive Enhancement - Core functionality should work without animations
5. User-Centered Design - Every animation should serve a purpose and improve usability
Technical Standards:
- Generate production-ready React/Next.js components with TypeScript
- Use Tailwind CSS classes for styling and animations
- Include comprehensive error handling and loading states
- Implement proper accessibility attributes and ARIA labels
- Follow modern CSS animation best practices
- Ensure cross-browser compatibility
Personality: Enthusiastic but professional, creative but practical, delightful but never distracting.
Remember: The best whimsy feels natural and enhances the user experience rather than calling attention to itself.`;
}
/**
* Get whimsy-specific configuration for external integrations
* @returns {Object} Configuration object
*/
getWhimsyConfig() {
return {
...this.whimsyConfig,
delightPatterns: Object.keys(this.delightPatterns),
animationLibrary: Object.keys(this.animationLibrary),
personalityStyles: Object.keys(this.personalityTemplates),
capabilities: this.getCapabilities()
};
}
/**
* Validate whimsy task specific requirements
* @param {Object} task - Task to validate
* @returns {boolean} True if valid
*/
validateWhimsyTask(task) {
// Call parent validation first
super.validateTask(task);
// Whimsy-specific validations
const validTypes = [
'add-micro-interactions',
'create-loading-states',
'add-easter-eggs',
'inject-personality',
'create-animations',
'enhance-hover-effects',
'add-success-celebrations',
'create-smooth-transitions',
'full-whimsy-injection'
];
if (!validTypes.includes(task.type) && !task.type.startsWith('custom-')) {
throw new Error(`Invalid whimsy task type: ${task.type}. Valid types: ${validTypes.join(', ')}`);
}
return true;
}
/**
* Override execute to include whimsy-specific validation
*/
async execute(task, context = {}) {
this.validateWhimsyTask(task);
return super.execute.call(this, task, context);
}
}
module.exports = { WhimsyInjector };