feat(chat/activity): Self-improvement event badges for memory & skill updates (#744)

* feat(chat/activity): Self-improvement event badges for memory & skill updates (#737)

* feat(chat): Handle background review.summary WS events for self-improvement notices

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-07-29 21:43:08 +03:00
1 parent 2cf41ead06
commit 1b596746af
12 files changed
+381 -1

No files matched your search

@@ -0,0 +1,42 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Data structures for the Hermes agent self-improvement / learning graph endpoint
* GET /api/learning/graph
*/
@Serializable
data class LearningGraphNode(
val id: String,
val label: String,
val kind: String, // "skill" | "memory"
val timestamp: Long? = null,
val category: String? = null,
@SerialName("useCount") val useCount: Int = 0,
val state: String? = null,
@SerialName("createdBy") val createdBy: String? = null,
val pinned: Boolean = false,
)
@Serializable
data class LearningGraphEdge(
val source: String,
val target: String,
)
@Serializable
data class LearningGraphMemoryCard(
val source: String,
val timestamp: Long? = null,
val title: String,
val body: String,
)
@Serializable
data class LearningGraphResponse(
val nodes: List<LearningGraphNode> = emptyList(),
val edges: List<LearningGraphEdge> = emptyList(),
val memory: List<LearningGraphMemoryCard> = emptyList(),
)
@@ -34,6 +34,7 @@ import com.m57.hermescontrol.data.model.HookResponse
import com.m57.hermescontrol.data.model.KanbanBoardResponse
import com.m57.hermescontrol.data.model.KanbanBoardsResponse
import com.m57.hermescontrol.data.model.KanbanTask
import com.m57.hermescontrol.data.model.LearningGraphResponse
import com.m57.hermescontrol.data.model.LogResponse
import com.m57.hermescontrol.data.model.ManagedDirectoryCreate
import com.m57.hermescontrol.data.model.ManagedFileActionResponse
@@ -667,6 +668,11 @@ interface HermesApiService {
suspend fun getPortal(): Response<PortalResponse>
// ── Admin: Curator ────────────────────────────────────────────────
@GET("api/learning/graph")
suspend fun getLearningGraph(
@Query("profile") profile: String? = null,
): Response<LearningGraphResponse>
@GET("api/curator")
suspend fun getCurator(): Response<CuratorResponse>
@@ -149,6 +149,11 @@ object EventParser {
WsEvent.BackgroundComplete(payload)
}
"review.summary" -> {
val text = (payload?.get("text") as? String)?.trim() ?: ""
WsEvent.ReviewSummary(text, sessionId)
}
"session.updated" -> {
WsEvent.SessionUpdated(payload)
}
@@ -123,6 +123,16 @@ sealed class WsEvent {
val sessionId: String? = null,
) : WsEvent()
/**
* Self-improvement background review summary event.
* Emitted when background review patches a skill or saves a memory.
* Payload: `{ text: "💾 Self-improvement review: ..." }`
*/
data class ReviewSummary(
val text: String,
val sessionId: String? = null,
) : WsEvent()
// ── Status ───────────────────────────────────────────────────────────
data class StatusUpdate(