Files
moteva/server/internal/logic/get_agent_starter_config_logic.go
T
root c94b163540 feat(server): add localized agent starter config endpoint
Add a public GET /api/ui/agent-starters endpoint returning localized
empty-state content (title, description, preview images, and starter
prompts) for the canvas Agent panel. Content is server-configurable via
AgentStarter config with built-in zh-CN/en-US fallbacks, and the route is
exempt from authentication so shared canvases render the same content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 22:19:14 +08:00

144 lines
5.3 KiB
Go

// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.1
package logic
import (
"context"
"strings"
"img_infinite_canvas/internal/config"
"img_infinite_canvas/internal/svc"
"img_infinite_canvas/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type GetAgentStarterConfigLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewGetAgentStarterConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetAgentStarterConfigLogic {
return &GetAgentStarterConfigLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *GetAgentStarterConfigLogic) GetAgentStarterConfig(req *types.GetAgentStarterConfigRequest) (resp *types.AgentStarterConfigResponse, err error) {
locale := "zh-CN"
if req != nil && strings.EqualFold(strings.TrimSpace(req.Locale), "en-US") {
locale = "en-US"
}
content := resolveAgentStarterLocale(l.svcCtx.Config.AgentStarter, locale)
return &types.AgentStarterConfigResponse{
Title: content.Title,
Description: content.Description,
PreviewImages: resolveAgentStarterImages(l.svcCtx.Config.AgentStarter.PreviewImages),
Starters: toAgentStarterItems(content.Starters),
}, nil
}
var defaultAgentStarterImages = []string{
"https://static.codia.ai/public/images/f788bdcc/lg.webp",
"https://static.codia.ai/public/images/ec25067a/lg.webp",
"https://static.codia.ai/public/images/d4ccbe39/lg.webp",
}
var defaultAgentStarterPrompts = []config.AgentStarterItemConfig{
{ID: "ecommerce", Label: "电商商品图", Prompt: "Create a premium ecommerce product image for a portable espresso machine, with realistic lighting, clean composition, benefit callouts, and marketplace-ready visual hierarchy"},
{ID: "poster", Label: "海报", Prompt: "Design a bold launch poster for a new skincare product line, with strong typography, product focus, campaign headline, date, and a polished premium layout"},
{ID: "brand-visual", Label: "品牌视觉", Prompt: "Create a brand identity direction for a modern wellness drink brand, including color palette, typography mood, logo usage, packaging accents, and social-ready visual elements"},
{ID: "social-media", Label: "社交媒体", Prompt: "Create a square Instagram promotion for a weekend fashion sale, with product cutouts, discount headline, brand colors, and a layout that works as a paid social ad"},
{ID: "logo", Label: "Logo 设计", Prompt: "Design a clean vector logo for a direct-to-consumer home goods brand named Loom & Line, with a simple mark, balanced wordmark, and clear black-and-white usage"},
}
func resolveAgentStarterLocale(options config.AgentStarterConfig, locale string) config.AgentStarterLocaleConfig {
fallback := config.AgentStarterLocaleConfig{
Title: "今天想创作什么?",
Description: "输入提示词开始——或使用下方的起点",
Starters: defaultAgentStarterPrompts,
}
configured := options.ZhCN
if locale == "en-US" {
fallback.Title = "What would you like to create today?"
fallback.Description = "Enter a prompt to begin, or use one of the starting points below."
fallback.Starters = englishAgentStarterPrompts(defaultAgentStarterPrompts)
configured = options.EnUS
}
if title := strings.TrimSpace(configured.Title); title != "" {
fallback.Title = title
}
if description := strings.TrimSpace(configured.Description); description != "" {
fallback.Description = description
}
if starters := validAgentStarterConfigs(configured.Starters); len(starters) > 0 {
fallback.Starters = starters
}
return fallback
}
func englishAgentStarterPrompts(items []config.AgentStarterItemConfig) []config.AgentStarterItemConfig {
labels := map[string]string{
"ecommerce": "E-commerce product",
"poster": "Poster",
"brand-visual": "Brand visual",
"social-media": "Social media",
"logo": "Logo design",
}
result := make([]config.AgentStarterItemConfig, 0, len(items))
for _, item := range items {
item.Label = labels[item.ID]
result = append(result, item)
}
return result
}
func resolveAgentStarterImages(configured []string) []string {
images := make([]string, 0, len(configured))
for _, image := range configured {
if image = strings.TrimSpace(image); image != "" {
images = append(images, image)
}
if len(images) == 3 {
break
}
}
if len(images) == 0 {
return append([]string(nil), defaultAgentStarterImages...)
}
return images
}
func validAgentStarterConfigs(configured []config.AgentStarterItemConfig) []config.AgentStarterItemConfig {
starters := make([]config.AgentStarterItemConfig, 0, len(configured))
seen := make(map[string]struct{}, len(configured))
for _, item := range configured {
item.ID = strings.TrimSpace(item.ID)
item.Label = strings.TrimSpace(item.Label)
item.Prompt = strings.TrimSpace(item.Prompt)
if item.ID == "" || item.Label == "" || item.Prompt == "" {
continue
}
if _, exists := seen[item.ID]; exists {
continue
}
seen[item.ID] = struct{}{}
starters = append(starters, item)
}
return starters
}
func toAgentStarterItems(configured []config.AgentStarterItemConfig) []types.AgentStarterItem {
items := make([]types.AgentStarterItem, 0, len(configured))
for _, item := range configured {
items = append(items, types.AgentStarterItem{Id: item.ID, Label: item.Label, Prompt: item.Prompt})
}
return items
}