feat(sessions): show project and last activity on history cards (#1133)

This commit is contained in:
Alfredo Ortegón Sepúlveda authored and GitHub committed 2026-09-16 00:14:09 +03:00
1 parent 529b424eb4
commit aed8ba4a6d
25 files changed
+1617 -80

No files matched your search

@@ -0,0 +1,39 @@
package com.m57.hermescontrol.data.ws
import com.m57.hermescontrol.data.model.ProjectInfo
import com.m57.hermescontrol.data.model.ProjectsListResponse
import com.m57.hermescontrol.data.remote.OkHttpProvider
import kotlinx.coroutines.CancellationException
import kotlinx.serialization.json.JsonObject
/** Supplies the profile's named projects so history rows can show which one a chat belongs to. */
interface ProjectsSource {
/** The project list, or null when the backend can't answer (offline, older server). */
suspend fun fetchProjects(): List<ProjectInfo>?
}
/** [ProjectsSource] backed by the gateway's `projects.list` JSON-RPC. */
class HermesProjectsSource(
// Only ask a live socket: an offline request would be queued and force a reconnect on
// every refresh. The view model refetches when the connection comes back.
private val isConnected: () -> Boolean = { HermesWsClient.connectionStatus.value == ConnectionStatus.CONNECTED },
private val rpcRequest: suspend (method: String, params: Map<String, Any>) -> Any? = { method, params ->
HermesWsClient.request(method, params).await()
},
) : ProjectsSource {
override suspend fun fetchProjects(): List<ProjectInfo>? {
if (!isConnected()) return null
return try {
val element = SessionLiveStatusDecoder.anyToJsonElement(rpcRequest(WsMethods.PROJECTS_LIST, emptyMap()))
if (element is JsonObject && element.containsKey("projects")) {
OkHttpProvider.json.decodeFromJsonElement(ProjectsListResponse.serializer(), element).projects
} else {
null
}
} catch (e: CancellationException) {
throw e
} catch (_: Exception) {
null
}
}
}
@@ -29,6 +29,11 @@ object WsMethods {
const val PROFILES_CONFIGURE = "profiles.configure"
const val PROFILES_LIST = "profiles.list"
// ── Projects ──────────────────────────────────────────────────────────
/** Named workspaces (id, name, color, folders) used to label history rows. */
const val PROJECTS_LIST = "projects.list"
// ── Interaction ───────────────────────────────────────────────────────
const val PROMPT_SUBMIT = "prompt.submit"
const val PROMPT_BTW = "prompt.btw"
@@ -159,6 +164,7 @@ object WsMethods {
// Binds HERMES_HOME so config/skills/pets resolve to the
// focused profile.
"verification.status", // line 282
PROJECTS_LIST, // methods_projects.py: @_registry.profile_scoped
"pet.info", // line 1253
"pet.info.meta", // line 1279
"pet.cells", // line 1302