* feat(#530): add SessionSearch models + searchSessions endpoint + contract tests * feat(#530): wire server-backed search into Sessions screen (debounce + render) * style(#530): ktlint import ordering on HermesApiService * fix(#530): ktlint-clean overlap wrap + map search snippet to title * fix(#530): map search snippet to title so results show + highlight * fix(#530): render search hits as honest result cards instead of faking title Backend SessionSearchResult carries no session name (only snippet + metadata), so mapping snippet->title made the card show raw excerpt as the title. Instead, render a dedicated SearchResultCard: 'Match' label + session id, highlighted snippet as body, and source/model/played-at chips. Added SessionInfo.model and a friendly relative-time formatter. ktlint clean, compileDebugKotlin + unit tests pass. * fix(#530): strip JSON from search snippet + tighten result card padding * fix(#530): strip FTS highlight markers from search snippet on client agy's backend change re-wraps matched terms in >>>term<<< markers inside the clean snippet, but the mobile highlights by raw query term and never consumed those markers — so literal '>>>'/'<<<' would render in result text. Strip the markers before passing the snippet to highlightText so the query highlight still works on clean text. * fix(#530): integrate tree-flattening hierarchy with search modes in SessionsScreen * fix(#530): fix test assertion and mock ApiClient in SessionsViewModelTest * fix(#530): resolve compose PaddingValues compile error and fix slash-preservation test path * fix(#530): clean search snippet from JSON payload and add unit test --------- Co-authored-by: M57 <m57@hermes-control.app>
This commit is contained in:
1 parent
71c1bdded9
commit
c543eb6470
8 files changed
+914
-252
No files matched your search
@@ -21,6 +21,7 @@ data class SessionInfo(
|
||||
val source: String? = null,
|
||||
val parent_session_id: String? = null,
|
||||
val display_name: String? = null,
|
||||
val model: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.m57.hermescontrol.data.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SessionSearchResponse(
|
||||
val results: List<SessionSearchResult> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SessionSearchResult(
|
||||
val session_id: String,
|
||||
val snippet: String? = null,
|
||||
val role: String? = null,
|
||||
val source: String? = null,
|
||||
val model: String? = null,
|
||||
val session_started: Double? = null,
|
||||
)
|
||||
@@ -70,6 +70,7 @@ import com.m57.hermescontrol.data.model.SessionListResponse
|
||||
import com.m57.hermescontrol.data.model.SessionMessagesResponse
|
||||
import com.m57.hermescontrol.data.model.SessionPromptResponse
|
||||
import com.m57.hermescontrol.data.model.SessionRenameRequest
|
||||
import com.m57.hermescontrol.data.model.SessionSearchResponse
|
||||
import com.m57.hermescontrol.data.model.SessionStatsResponse
|
||||
import com.m57.hermescontrol.data.model.SetActiveProfileRequest
|
||||
import com.m57.hermescontrol.data.model.Skill
|
||||
@@ -132,6 +133,12 @@ interface HermesApiService {
|
||||
@Query("order") order: String = "recent",
|
||||
): Response<SessionListResponse>
|
||||
|
||||
@GET("api/sessions/search")
|
||||
suspend fun searchSessions(
|
||||
@Query("q") q: String,
|
||||
@Query("profile") profile: String? = null,
|
||||
): Response<SessionSearchResponse>
|
||||
|
||||
@GET("api/sessions/{id}/messages")
|
||||
suspend fun getSessionMessages(
|
||||
// Preserve slashes in session IDs — backend generates IDs containing '/' characters (issue #468).
|
||||
|
||||
Reference in new issue
Block a user