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>
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
// 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
|
||||
}
|
||||
Reference in New Issue
Block a user