## Problem All 4 marketing tools (contentvariant, subjectlines, platformadapt, factcheck) were calling prepare_chat_style_prompt() which expects request.prompt field. This caused "object has no field 'prompt'" errors in Claude Desktop. ## Root Cause The prepare_prompt() methods were: 1. Building prompt_text string 2. Creating a copy of request 3. Setting request_copy.prompt = prompt_text 4. Calling prepare_chat_style_prompt(request_copy) But ToolRequest (and subclasses) don't have a 'prompt' field, causing AttributeError when prepare_chat_style_prompt tries to access it. ## Solution Changed all prepare_prompt() methods to return the prompt string directly instead of calling prepare_chat_style_prompt(). This is the correct pattern for SimpleTool implementations. ## Files Changed - tools/contentvariant.py: Removed copy() and prepare_chat_style_prompt() call - tools/subjectlines.py: Removed copy() and prepare_chat_style_prompt() call - tools/platformadapt.py: Removed copy() and prepare_chat_style_prompt() call - tools/factcheck.py: Removed copy() and prepare_chat_style_prompt() call ## Testing - Server startup: ✅ All 7 tools load successfully - Tool instantiation: ✅ All tools initialize without errors ## Impact This fixes the schema errors preventing users from using the new Phase 2 tools in Claude Desktop. All tools should now work correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
198 lines
7.8 KiB
Python
198 lines
7.8 KiB
Python
"""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"],
|
|
}
|