"""Platform Adaptation Tool Adapts content from one platform to multiple other platforms while preserving core message and optimizing for each platform's unique characteristics. """ from typing import Optional from pydantic import Field from config import TEMPERATURE_CREATIVE from systemprompts import PLATFORMADAPT_PROMPT from tools.models import ToolModelCategory from tools.shared.base_models import ToolRequest from tools.simple.base import SimpleTool class PlatformAdaptRequest(ToolRequest): """Request model for Platform Adaptation""" source_content: str = Field( ..., description="The original content to adapt. Can be a social post, blog intro, email, or any marketing content.", ) source_platform: Optional[str] = Field( default=None, description="Where this content originated: 'twitter', 'linkedin', 'blog', 'email', 'instagram', 'facebook', 'bluesky'. Optional but helps inform adaptations.", ) target_platforms: list[str] = Field( ..., description="Platforms to adapt to. Options: 'twitter', 'bluesky', 'linkedin', 'instagram', 'facebook', 'email_subject', 'blog_title'. Specify at least one.", ) preserve_urls: bool = Field( default=True, description="Keep links intact across platforms (True) or adapt/remove them (False). Default True.", ) brand_voice: Optional[str] = Field( default=None, description="Brand voice guidelines to maintain: tone, style, personality traits, terminology preferences.", ) include_hashtags: bool = Field( default=True, description="Include platform-appropriate hashtags in adaptations. Default True.", ) adaptation_notes: Optional[str] = Field( default=None, description="Special adaptation requirements: CTAs to include, key messages to emphasize, phrases to avoid.", ) class PlatformAdaptTool(SimpleTool): """Adapt content across multiple social media platforms""" def get_name(self) -> str: return "platformadapt" def get_description(self) -> str: return ( "Adapt content from one platform to multiple others while preserving core message. " "Automatically respects character limits, adjusts tone, optimizes formatting, and applies " "platform-specific best practices (hashtags, CTAs, threading). " "Ideal for multi-channel campaigns and content repurposing." ) def get_system_prompt(self) -> str: return PLATFORMADAPT_PROMPT def get_default_temperature(self) -> float: return TEMPERATURE_CREATIVE def get_model_category(self) -> ToolModelCategory: return ToolModelCategory.FAST_RESPONSE def get_request_model(self): return PlatformAdaptRequest def get_tool_fields(self) -> dict: """Tool-specific field definitions for PlatformAdapt""" return { "source_content": { "type": "string", "description": "The original content to adapt", }, "target_platforms": { "type": "array", "items": {"type": "string"}, "description": "Platforms to adapt content for", }, } async def prepare_prompt(self, request: PlatformAdaptRequest) -> str: """Prepare the platform adaptation prompt""" prompt_parts = [ "Adapt the following content across multiple platforms while preserving the core message:" ] prompt_parts.append(f"\n**Source Content:**\n{request.source_content}") if request.source_platform: prompt_parts.append(f"\n**Original Platform:** {request.source_platform}") prompt_parts.append( f"\n**Target Platforms:** {', '.join(request.target_platforms)}" ) if request.brand_voice: prompt_parts.append( f"\n**Brand Voice Guidelines:** {request.brand_voice}" ) if request.adaptation_notes: prompt_parts.append( f"\n**Special Requirements:** {request.adaptation_notes}" ) prompt_parts.append(f"\n**URL Handling:** {'Preserve links' if request.preserve_urls else 'Adapt or remove links as needed'}") prompt_parts.append(f"**Hashtags:** {'Include platform-appropriate hashtags' if request.include_hashtags else 'Skip hashtags'}") prompt_parts.append( "\n\nFor each platform, provide the adapted content with character counts, " "adaptation rationale, and platform-specific optimizations applied." ) # Return the complete prompt return "\n".join(prompt_parts) def get_input_schema(self) -> dict: """Return the JSON schema for this tool's input""" return { "type": "object", "properties": { "source_content": { "type": "string", "description": "The original content to adapt across platforms", }, "source_platform": { "type": "string", "description": "Original platform: 'twitter', 'linkedin', 'blog', 'email', 'instagram', 'facebook', 'bluesky'", }, "target_platforms": { "type": "array", "items": {"type": "string"}, "description": "Platforms to adapt to: 'twitter', 'bluesky', 'linkedin', 'instagram', 'facebook', 'email_subject', 'blog_title'", }, "preserve_urls": { "type": "boolean", "description": "Keep links intact (true) or adapt/remove (false)", "default": True, }, "brand_voice": { "type": "string", "description": "Brand voice guidelines: tone, style, personality, terminology", }, "include_hashtags": { "type": "boolean", "description": "Include platform-appropriate hashtags", "default": True, }, "adaptation_notes": { "type": "string", "description": "Special requirements: CTAs, key messages, phrases to avoid", }, "files": { "type": "array", "items": {"type": "string"}, "description": "Optional brand guidelines or style references", }, "images": { "type": "array", "items": {"type": "string"}, "description": "Optional visual assets for context", }, "continuation_id": { "type": "string", "description": "Thread ID to continue previous conversation", }, "model": { "type": "string", "description": "AI model to use (leave empty for default creative model)", }, "temperature": { "type": "number", "description": "Creativity level 0.0-1.0 (default 0.7 for creative adaptation)", "minimum": 0.0, "maximum": 1.0, }, "thinking_mode": { "type": "string", "description": "Thinking depth: minimal, low, medium, high, max", "enum": ["minimal", "low", "medium", "high", "max"], }, "use_websearch": { "type": "boolean", "description": "Enable web search for current platform best practices", "default": False, }, }, "required": ["source_content", "target_platforms"], }