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:
2026-07-10 22:19:14 +08:00
parent 2df9ae6581
commit c94b163540
11 changed files with 373 additions and 1 deletions
@@ -0,0 +1,31 @@
// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.1
package handler
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"img_infinite_canvas/internal/logic"
"img_infinite_canvas/internal/svc"
"img_infinite_canvas/internal/types"
)
func getAgentStarterConfigHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.GetAgentStarterConfigRequest
if err := httpx.Parse(r, &req); err != nil {
httpx.ErrorCtx(r.Context(), w, err)
return
}
l := logic.NewGetAgentStarterConfigLogic(r.Context(), svcCtx)
resp, err := l.GetAgentStarterConfig(&req)
if err != nil {
httpx.ErrorCtx(r.Context(), w, err)
} else {
httpx.OkJsonCtx(r.Context(), w, resp)
}
}
}
+5
View File
@@ -329,6 +329,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/shares/:shareId",
Handler: resolveShareHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/ui/agent-starters",
Handler: getAgentStarterConfigHandler(serverCtx),
},
},
rest.WithPrefix("/api"),
)
@@ -107,7 +107,8 @@ func requiresAuthenticatedUser(r *http.Request) bool {
strings.HasPrefix(path, "/api/shares/") ||
path == "/api/auth/options" ||
path == "/api/health" ||
path == "/api/dashboard" {
path == "/api/dashboard" ||
path == "/api/ui/agent-starters" {
return false
}
return true
@@ -86,6 +86,24 @@ func TestUserContextMiddlewareIgnoresSpoofedUserIDOnPublicRoute(t *testing.T) {
}
}
func TestUserContextMiddlewareAllowsPublicAgentStarterConfig(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "/api/ui/agent-starters?locale=en-US", nil)
rec := httptest.NewRecorder()
called := false
UserContextMiddleware(fakeBearerAuthenticator{})(func(w http.ResponseWriter, _ *http.Request) {
called = true
w.WriteHeader(http.StatusNoContent)
})(rec, req)
if !called {
t.Fatal("expected public agent starter config route to continue")
}
if rec.Code != http.StatusNoContent {
t.Fatalf("expected status %d, got %d", http.StatusNoContent, rec.Code)
}
}
func TestUserContextMiddlewareAuthorizesAnonymousCanvasShare(t *testing.T) {
ownerID := "d1d2fbbb-97bb-4406-8d0b-ec814cc65092"
authorizer := fakeShareAuthorizer{access: sharingmodule.Access{