Remove deprecated avatar fields, use profile_image_url consistently

Co-authored-by: markokraemer.mail <markokraemer.mail@gmail.com>
This commit is contained in:
Cursor Agent 2025-08-15 01:53:34 +00:00
parent a4519f81ce
commit e4b8d96c30
22 changed files with 49 additions and 128 deletions

View File

@ -74,10 +74,7 @@ class AgentCreateRequest(BaseModel):
custom_mcps: Optional[List[Dict[str, Any]]] = []
agentpress_tools: Optional[Dict[str, Any]] = {}
is_default: Optional[bool] = False
# Deprecated, kept for backward-compat
avatar: Optional[str] = None
avatar_color: Optional[str] = None
# New profile image url (can be external or Supabase storage URL)
# Profile image url (can be external or Supabase storage URL)
profile_image_url: Optional[str] = None
class AgentVersionResponse(BaseModel):
@ -111,10 +108,7 @@ class AgentUpdateRequest(BaseModel):
custom_mcps: Optional[List[Dict[str, Any]]] = None
agentpress_tools: Optional[Dict[str, Any]] = None
is_default: Optional[bool] = None
# Deprecated, kept for backward-compat
avatar: Optional[str] = None
avatar_color: Optional[str] = None
# New profile image url
# Profile image url
profile_image_url: Optional[str] = None
class AgentResponse(BaseModel):
@ -127,10 +121,7 @@ class AgentResponse(BaseModel):
custom_mcps: List[Dict[str, Any]]
agentpress_tools: Dict[str, Any]
is_default: bool
# Deprecated
avatar: Optional[str] = None
avatar_color: Optional[str] = None
# New
# Profile image url
profile_image_url: Optional[str] = None
created_at: str
updated_at: Optional[str] = None
@ -165,10 +156,7 @@ class AgentExportData(BaseModel):
agentpress_tools: Dict[str, Any]
configured_mcps: List[Dict[str, Any]]
custom_mcps: List[Dict[str, Any]]
# Deprecated
avatar: Optional[str] = None
avatar_color: Optional[str] = None
# New
# Profile image url
profile_image_url: Optional[str] = None
tags: Optional[List[str]] = []
metadata: Optional[Dict[str, Any]] = None
@ -700,8 +688,6 @@ async def get_thread_agent(thread_id: str, user_id: str = Depends(get_current_us
is_default=agent_data.get('is_default', False),
is_public=agent_data.get('is_public', False),
tags=agent_data.get('tags', []),
avatar=agent_config.get('avatar'),
avatar_color=agent_config.get('avatar_color'),
profile_image_url=agent_config.get('profile_image_url'),
created_at=agent_data['created_at'],
updated_at=agent_data.get('updated_at', agent_data['created_at']),
@ -1578,8 +1564,6 @@ async def get_agents(
is_default=agent.get('is_default', False),
is_public=agent.get('is_public', False),
tags=agent.get('tags', []),
avatar=agent_config.get('avatar'),
avatar_color=agent_config.get('avatar_color'),
profile_image_url=agent_config.get('profile_image_url'),
created_at=agent['created_at'],
updated_at=agent['updated_at'],
@ -1704,8 +1688,6 @@ async def get_agent(agent_id: str, user_id: str = Depends(get_current_user_id_fr
is_default=agent_data.get('is_default', False),
is_public=agent_data.get('is_public', False),
tags=agent_data.get('tags', []),
avatar=agent_config.get('avatar'),
avatar_color=agent_config.get('avatar_color'),
profile_image_url=agent_config.get('profile_image_url'),
created_at=agent_data['created_at'],
updated_at=agent_data.get('updated_at', agent_data['created_at']),
@ -1757,10 +1739,7 @@ async def export_agent(agent_id: str, user_id: str = Depends(get_current_user_id
'custom_mcp': config.get('custom_mcps', [])
},
'metadata': {
# keep backward compat metadata
'avatar': config.get('avatar'),
'avatar_color': config.get('avatar_color'),
# include profile image url in metadata for completeness
# include profile image url in metadata
'profile_image_url': agent.get('profile_image_url')
}
}
@ -1778,10 +1757,7 @@ async def export_agent(agent_id: str, user_id: str = Depends(get_current_user_id
"system_prompt": sanitized_config['system_prompt'],
"name": config.get('name', ''),
"description": config.get('description', ''),
# Deprecated
"avatar": config.get('avatar'),
"avatar_color": config.get('avatar_color'),
# New
# Profile image url
"profile_image_url": agent.get('profile_image_url'),
"tags": agent.get('tags', []),
"export_metadata": export_metadata,
@ -1947,10 +1923,7 @@ async def create_agent(
"account_id": user_id,
"name": agent_data.name,
"description": agent_data.description,
# Deprecated fields still populated if sent by older clients
"avatar": agent_data.avatar,
"avatar_color": agent_data.avatar_color,
# New profile image url field
# Profile image url field
"profile_image_url": agent_data.profile_image_url,
"is_default": agent_data.is_default or False,
"version_count": 1
@ -2019,8 +1992,6 @@ async def create_agent(
is_default=agent.get('is_default', False),
is_public=agent.get('is_public', False),
tags=agent.get('tags', []),
avatar=agent.get('avatar'),
avatar_color=agent.get('avatar_color'),
profile_image_url=agent.get('profile_image_url'),
created_at=agent['created_at'],
updated_at=agent.get('updated_at', agent['created_at']),
@ -2167,8 +2138,6 @@ async def update_agent(
agentpress_tools=initial_version_data["agentpress_tools"],
configured_mcps=initial_version_data["configured_mcps"],
custom_mcps=initial_version_data["custom_mcps"],
avatar=None,
avatar_color=None,
workflows=workflows
)
initial_version_data["config"] = initial_config
@ -2246,10 +2215,7 @@ async def update_agent(
update_data["is_default"] = agent_data.is_default
if agent_data.is_default:
await client.table('agents').update({"is_default": False}).eq("account_id", user_id).eq("is_default", True).neq("agent_id", agent_id).execute()
if agent_data.avatar is not None:
update_data["avatar"] = agent_data.avatar
if agent_data.avatar_color is not None:
update_data["avatar_color"] = agent_data.avatar_color
if agent_data.profile_image_url is not None:
update_data["profile_image_url"] = agent_data.profile_image_url
@ -2265,8 +2231,6 @@ async def update_agent(
current_custom_mcps = current_version_data.get('custom_mcps', [])
current_agentpress_tools = agent_data.agentpress_tools if agent_data.agentpress_tools is not None else current_version_data.get('agentpress_tools', {})
current_avatar = agent_data.avatar if agent_data.avatar is not None else existing_data.get('avatar')
current_avatar_color = agent_data.avatar_color if agent_data.avatar_color is not None else existing_data.get('avatar_color')
new_version_id = None
if needs_new_version:
try:
@ -2378,8 +2342,6 @@ async def update_agent(
is_default=agent.get('is_default', False),
is_public=agent.get('is_public', False),
tags=agent.get('tags', []),
avatar=agent_config.get('avatar'),
avatar_color=agent_config.get('avatar_color'),
profile_image_url=agent_config.get('profile_image_url'),
created_at=agent['created_at'],
updated_at=agent.get('updated_at', agent['created_at']),

View File

@ -51,8 +51,6 @@ def extract_agent_config(agent_data: Dict[str, Any], version_data: Optional[Dict
'custom_mcps': custom_mcps,
'agentpress_tools': _extract_agentpress_tools_for_run(agentpress_tools),
'workflows': workflows,
'avatar': agent_data.get('avatar'),
'avatar_color': agent_data.get('avatar_color'),
'profile_image_url': agent_data.get('profile_image_url'),
'is_suna_default': is_suna_default,
'centrally_managed': centrally_managed,
@ -89,9 +87,7 @@ def extract_agent_config(agent_data: Dict[str, Any], version_data: Optional[Dict
config['agentpress_tools'] = _extract_agentpress_tools_for_run(tools.get('agentpress', {}))
config['workflows'] = config.get('workflows', [])
# Legacy and new fields
config['avatar'] = agent_data.get('avatar')
config['avatar_color'] = agent_data.get('avatar_color')
# Profile image url field
config['profile_image_url'] = agent_data.get('profile_image_url')
return config
@ -114,8 +110,6 @@ def extract_agent_config(agent_data: Dict[str, Any], version_data: Optional[Dict
'custom_mcps': [],
'agentpress_tools': {},
'workflows': [],
'avatar': agent_data.get('avatar'),
'avatar_color': agent_data.get('avatar_color'),
'profile_image_url': agent_data.get('profile_image_url'),
'is_suna_default': is_suna_default,
'centrally_managed': centrally_managed,
@ -130,8 +124,6 @@ def build_unified_config(
agentpress_tools: Dict[str, Any],
configured_mcps: List[Dict[str, Any]],
custom_mcps: Optional[List[Dict[str, Any]]] = None,
avatar: Optional[str] = None,
avatar_color: Optional[str] = None,
suna_metadata: Optional[Dict[str, Any]] = None,
workflows: Optional[List[Dict[str, Any]]] = None
) -> Dict[str, Any]:
@ -150,10 +142,7 @@ def build_unified_config(
'custom_mcp': custom_mcps or []
},
'workflows': workflows or [],
'metadata': {
'avatar': avatar,
'avatar_color': avatar_color
}
'metadata': {}
}
if suna_metadata:

View File

@ -5,8 +5,7 @@ from agent.prompt import SYSTEM_PROMPT
class SunaConfig:
NAME = "Suna"
DESCRIPTION = "Suna is your AI assistant with access to various tools and integrations to help you with tasks across domains."
AVATAR = "🌞"
AVATAR_COLOR = "#F59E0B"
DEFAULT_MODEL = "anthropic/claude-sonnet-4-20250514"
SYSTEM_PROMPT = SYSTEM_PROMPT
@ -49,8 +48,6 @@ class SunaConfig:
"custom_mcps": cls.DEFAULT_CUSTOM_MCPS,
"agentpress_tools": cls.DEFAULT_TOOLS,
"is_default": True,
"avatar": cls.AVATAR,
"avatar_color": cls.AVATAR_COLOR,
"metadata": {
"is_suna_default": True,
"centrally_managed": True,

View File

@ -48,8 +48,7 @@ class SunaConfigManager:
"description": SunaConfig.DESCRIPTION,
"system_prompt": SunaConfig.get_system_prompt(),
"default_tools": SunaConfig.DEFAULT_TOOLS,
"avatar": SunaConfig.AVATAR,
"avatar_color": SunaConfig.AVATAR_COLOR,
"restrictions": SunaConfig.USER_RESTRICTIONS,
}

View File

@ -184,8 +184,7 @@ class SunaAgentRepository:
"name": SunaConfig.NAME,
"description": SunaConfig.DESCRIPTION,
"is_default": True,
"avatar": SunaConfig.AVATAR,
"avatar_color": SunaConfig.AVATAR_COLOR,
"metadata": {
"is_suna_default": True,
"centrally_managed": True,

View File

@ -0,0 +1,17 @@
-- Remove deprecated avatar columns migration
-- This migration permanently removes avatar and avatar_color columns since we've switched to image URLs
BEGIN;
-- Drop indexes related to avatar columns
DROP INDEX IF EXISTS idx_agents_avatar;
DROP INDEX IF EXISTS idx_agents_avatar_color;
-- Remove avatar columns from agents table
ALTER TABLE agents DROP COLUMN IF EXISTS avatar;
ALTER TABLE agents DROP COLUMN IF EXISTS avatar_color;
-- Add comment to document the change
COMMENT ON TABLE agents IS 'Agents table - avatar/avatar_color columns removed in favor of profile_image_url in config metadata';
COMMIT;

View File

@ -60,8 +60,6 @@ class TemplateResponse(BaseModel):
download_count: int
created_at: str
updated_at: str
avatar: Optional[str]
avatar_color: Optional[str]
profile_image_url: Optional[str] = None
metadata: Dict[str, Any]
creator_name: Optional[str] = None

View File

@ -40,9 +40,7 @@ def build_unified_config(
system_prompt: str,
agentpress_tools: ConfigType,
configured_mcps: List[ConfigType],
custom_mcps: List[ConfigType],
avatar: Optional[str] = None,
avatar_color: Optional[str] = None
custom_mcps: List[ConfigType]
) -> ConfigType:
try:
from agent.config_helper import build_unified_config as build_config
@ -50,9 +48,7 @@ def build_unified_config(
system_prompt=system_prompt,
agentpress_tools=agentpress_tools,
configured_mcps=configured_mcps,
custom_mcps=custom_mcps,
avatar=avatar,
avatar_color=avatar_color
custom_mcps=custom_mcps
)
except ImportError:
return {
@ -62,10 +58,7 @@ def build_unified_config(
'mcp': configured_mcps,
'custom_mcp': custom_mcps
},
'metadata': {
'avatar': avatar,
'avatar_color': avatar_color
}
'metadata': {}
}

View File

@ -419,12 +419,7 @@ export default function AgentsPage() {
}
};
const getItemStyling = (item: MarketplaceTemplate) => {
return {
avatar: '🤖',
color: '#6366f1',
};
};
const handleUnpublish = async (templateId: string, templateName: string) => {
try {
@ -503,12 +498,7 @@ export default function AgentsPage() {
}
};
const getTemplateStyling = (template: any) => {
return {
avatar: '🤖',
color: '#6366f1',
};
};
if (flagLoading) {
return (
@ -573,7 +563,6 @@ export default function AgentsPage() {
templatesActioningId={templatesActioningId}
onPublish={openPublishDialog}
onUnpublish={handleUnpublish}
getTemplateStyling={getTemplateStyling}
onPublishAgent={handleAgentPublish}
publishingAgentId={publishingAgentId}
/>
@ -593,7 +582,6 @@ export default function AgentsPage() {
installingItemId={installingItemId}
onInstallClick={handleInstallClick}
onDeleteTemplate={handleDeleteTemplate}
getItemStyling={getItemStyling}
currentUserId={user?.id}
onAgentPreview={handleAgentPreview}
/>

View File

@ -49,8 +49,7 @@ interface ApiMessageType extends BaseApiMessageType {
agent_id?: string;
agents?: {
name: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
};
}

View File

@ -78,10 +78,7 @@ type AgentCardData = MarketplaceData | TemplateData | AgentData;
interface AgentCardProps {
mode: AgentCardMode;
data: AgentCardData;
styling?: {
avatar: string;
color: string;
};
isActioning?: boolean;
onPrimaryAction?: (data: any, e?: React.MouseEvent) => void;
onSecondaryAction?: (data: any, e?: React.MouseEvent) => void;

View File

@ -22,7 +22,7 @@ interface MarketplaceTabProps {
installingItemId: string | null;
onInstallClick: (item: MarketplaceTemplate, e?: React.MouseEvent) => void;
onDeleteTemplate?: (item: MarketplaceTemplate, e?: React.MouseEvent) => void;
getItemStyling: (item: MarketplaceTemplate) => { avatar: string; color: string };
currentUserId?: string;
onAgentPreview?: (agent: MarketplaceTemplate) => void;
}
@ -40,7 +40,6 @@ export const MarketplaceTab = ({
installingItemId,
onInstallClick,
onDeleteTemplate,
getItemStyling,
currentUserId,
onAgentPreview
}: MarketplaceTabProps) => {
@ -114,7 +113,6 @@ export const MarketplaceTab = ({
key={item.id}
mode="marketplace"
data={item}
styling={getItemStyling(item)}
isActioning={installingItemId === item.id}
onPrimaryAction={onInstallClick}
onDeleteAction={onDeleteTemplate}
@ -138,7 +136,6 @@ export const MarketplaceTab = ({
key={item.id}
mode="marketplace"
data={item}
styling={getItemStyling(item)}
isActioning={installingItemId === item.id}
onPrimaryAction={onInstallClick}
onDeleteAction={onDeleteTemplate}
@ -157,7 +154,6 @@ export const MarketplaceTab = ({
key={item.id}
mode="marketplace"
data={item}
styling={getItemStyling(item)}
isActioning={installingItemId === item.id}
onPrimaryAction={onInstallClick}
onDeleteAction={onDeleteTemplate}

View File

@ -34,7 +34,7 @@ interface MyAgentsTabProps {
templatesActioningId: string | null;
onPublish: (template: any) => void;
onUnpublish: (templateId: string, templateName: string) => void;
getTemplateStyling: (template: any) => { avatar: string; color: string };
onPublishAgent?: (agent: any) => void;
publishingAgentId?: string | null;
@ -66,7 +66,6 @@ export const MyAgentsTab = ({
templatesActioningId,
onPublish,
onUnpublish,
getTemplateStyling,
onPublishAgent,
publishingAgentId
}: MyAgentsTabProps) => {
@ -133,7 +132,6 @@ export const MyAgentsTab = ({
key={template.template_id}
mode="template"
data={template}
styling={getTemplateStyling(template)}
isActioning={isActioning}
onPrimaryAction={
template.is_public

View File

@ -16,7 +16,7 @@ interface MyTemplatesTabProps {
onUnpublish: (templateId: string, templateName: string) => void;
onViewInMarketplace: () => void;
onSwitchToMyAgents: () => void;
getTemplateStyling: (template: any) => { avatar: string; color: string };
}
export const MyTemplatesTab = ({
@ -27,8 +27,7 @@ export const MyTemplatesTab = ({
onPublish,
onUnpublish,
onViewInMarketplace,
onSwitchToMyAgents,
getTemplateStyling
onSwitchToMyAgents
}: MyTemplatesTabProps) => {
return (
<div className="space-y-6 mt-8">
@ -77,7 +76,6 @@ export const MyTemplatesTab = ({
key={template.template_id}
mode="template"
data={template}
styling={getTemplateStyling(template)}
isActioning={isActioning}
onPrimaryAction={
template.is_public

View File

@ -9,8 +9,7 @@ export interface MarketplaceTemplate {
created_at: string;
marketplace_published_at?: string;
profile_image_url?: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
template_id: string;
is_kortix_team?: boolean;
model?: string;

View File

@ -20,8 +20,7 @@ export interface AgentConfiguration {
agent_id: string;
name: string;
description: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
agentpress_tools: Record<string, AgentpressTool>;
configured_mcps: any[];
custom_mcps: CustomMcp[];

View File

@ -19,8 +19,7 @@ export interface AgentExportData {
config: Record<string, any>;
enabledTools: string[];
}>;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
tags?: string[];
metadata?: Record<string, any>;
export_version: string;

View File

@ -27,8 +27,7 @@ interface JsonAnalysisResult {
agent_info: {
name: string;
description?: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
};
}

View File

@ -43,8 +43,7 @@ export interface AgentTemplate {
marketplace_published_at?: string;
created_at: string;
creator_name?: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
profile_image_url?: string;
is_kortix_team?: boolean;
metadata?: {

View File

@ -26,8 +26,7 @@ interface ApiMessageType {
agent_id?: string;
agents?: {
name: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
};
}

View File

@ -131,8 +131,6 @@ export type Message = {
agent_id?: string;
agents?: {
name: string;
avatar?: string;
avatar_color?: string;
profile_image_url?: string;
};
};
@ -633,8 +631,7 @@ export const getMessages = async (threadId: string): Promise<Message[]> => {
*,
agents:agent_id (
name,
avatar,
avatar_color
profile_image_url
)
`)
.eq('thread_id', threadId)

View File

@ -4,7 +4,7 @@ import { persist } from 'zustand/middleware';
interface Agent {
agent_id: string;
name: string;
avatar?: string;
profile_image_url?: string;
metadata?: {
is_suna_default?: boolean;
};