diff --git a/agent/store/CHAT_STORAGE_DESIGN.md b/agent/store/CHAT_STORAGE_DESIGN.md index 4e7248a1..603831c1 100644 --- a/agent/store/CHAT_STORAGE_DESIGN.md +++ b/agent/store/CHAT_STORAGE_DESIGN.md @@ -1673,6 +1673,11 @@ GET /v1/chat/sessions/chat_123/messages?limit=100&offset=0&role=assistant&type=t | `type` | string | - | Filter by message type | | `limit` | int | 100 | Max messages to return (max 1000) | | `offset` | int | 0 | Offset for pagination | +| `locale` | string | - | Locale for assistant info (e.g., `zh-cn`, `en-us`). Falls back to `Accept-Language` header | + +**Locale Resolution Priority:** +1. Query parameter `locale` +2. HTTP header `Accept-Language` **Response:** @@ -1708,10 +1713,20 @@ GET /v1/chat/sessions/chat_123/messages?limit=100&offset=0&role=assistant&type=t "created_at": "2024-01-15T10:00:05Z" } ], - "count": 2 + "count": 2, + "assistants": { + "weather_assistant": { + "assistant_id": "weather_assistant", + "name": "Weather Assistant", + "avatar": "https://example.com/weather-avatar.png", + "description": "Get weather information for any location" + } + } } ``` +**Note:** The `assistants` field contains localized assistant information (name, avatar, description) for all unique `assistant_id` values found in the messages. This allows the frontend to display assistant details without additional API calls. The locale is determined by the `locale` query parameter or `Accept-Language` header. + ### Permission Filtering All endpoints respect Yao's permission system: diff --git a/openapi/chat/session.go b/openapi/chat/session.go index e61088d9..e80d29c6 100644 --- a/openapi/chat/session.go +++ b/openapi/chat/session.go @@ -49,15 +49,24 @@ func ListChats(c *gin.Context) { return } - // Return result - response.RespondWithSuccess(c, response.StatusOK, gin.H{ - "data": result.Data, - "groups": result.Groups, + // Build response based on grouping mode + // When group_by is set, data should be nil to avoid duplication + resp := gin.H{ "page": result.Page, "pagesize": result.PageSize, "pagecount": result.PageCount, "total": result.Total, - }) + } + + if len(result.Groups) > 0 { + // Grouped response: only include groups + resp["groups"] = result.Groups + } else { + // Flat response: only include data + resp["data"] = result.Data + } + + response.RespondWithSuccess(c, response.StatusOK, resp) } // GetChat retrieves a single chat session by ID diff --git a/openapi/tests/chat/session_test.go b/openapi/tests/chat/session_test.go index dbfe6441..177c7be5 100644 --- a/openapi/tests/chat/session_test.go +++ b/openapi/tests/chat/session_test.go @@ -300,9 +300,11 @@ func TestListChatSessions(t *testing.T) { err = json.NewDecoder(resp.Body).Decode(&response) assert.NoError(t, err) - // Check for groups in response + // Check for groups in response (when group_by=time, only groups is returned, not data) _, hasGroups := response["groups"] + _, hasData := response["data"] assert.True(t, hasGroups, "Response should contain groups when group_by=time") + assert.False(t, hasData, "Response should NOT contain data when group_by=time (to avoid duplication)") t.Logf("Successfully retrieved chat sessions with time grouping") })