refactor: migrate Gson serialization to kotlinx.serialization (#475)

* refactor: migrate Gson serialization to kotlinx.serialization

* fix(dto): resolve serializing Any? and Map<String, Any?> with JsonElement

* test(refactor): fix unit test issues under kotlinx.serialization and update nullable DTO defaults

* fix(chat): support flexible numeric and string decoding for message timestamps

* fix(chat): sequentialize cache loading to avoid overwriting network state
This commit is contained in:
M57 authored and GitHub committed 2026-07-05 21:30:44 +03:00
1 parent 1be5ab2f6d
commit 5697405b19
64 files changed
+863 -577

No files matched your search

@@ -1,68 +1,73 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class AchievementsResponse(
val achievements: List<Achievement>? = emptyList(),
@SerializedName("unlocked_count") val unlockedCount: Int = 0,
@SerializedName("discovered_count") val discoveredCount: Int = 0,
@SerializedName("secret_count") val secretCount: Int = 0,
@SerializedName("total_count") val totalCount: Int = 0,
@SerializedName("is_stale") val isStale: Boolean = false,
@SerializedName("generated_at") val generatedAt: Long? = null,
@SerializedName("scan_meta") val scanMeta: ScanMeta? = null,
@SerialName("unlocked_count") val unlockedCount: Int = 0,
@SerialName("discovered_count") val discoveredCount: Int = 0,
@SerialName("secret_count") val secretCount: Int = 0,
@SerialName("total_count") val totalCount: Int = 0,
@SerialName("is_stale") val isStale: Boolean = false,
@SerialName("generated_at") val generatedAt: Long? = null,
@SerialName("scan_meta") val scanMeta: ScanMeta? = null,
val error: String? = null,
)
@Serializable
data class ScanMeta(
val status: ScanStatus? = null,
)
@Serializable
data class ScanStatus(
val state: String = "idle",
@SerializedName("started_at") val startedAt: Long? = null,
@SerializedName("finished_at") val finishedAt: Long? = null,
@SerializedName("last_error") val lastError: String? = null,
@SerializedName("last_duration_ms") val lastDurationMs: Long? = null,
@SerializedName("run_count") val runCount: Int = 0,
@SerialName("started_at") val startedAt: Long? = null,
@SerialName("finished_at") val finishedAt: Long? = null,
@SerialName("last_error") val lastError: String? = null,
@SerialName("last_duration_ms") val lastDurationMs: Long? = null,
@SerialName("run_count") val runCount: Int = 0,
)
@Serializable
data class RecentUnlock(
val id: String,
val name: String,
val description: String?,
val category: String?,
val kind: String?,
val icon: String?,
val description: String? = null,
val category: String? = null,
val kind: String? = null,
val icon: String? = null,
val unlocked: Boolean,
val discovered: Boolean,
val state: String?,
val tier: String?,
val progress: Double?,
@SerializedName("next_tier") val nextTier: String?,
@SerializedName("next_threshold") val nextThreshold: Double?,
@SerializedName("progress_pct") val progressPct: Double?,
@SerializedName("unlocked_at") val unlockedAt: Long?,
val secret: Boolean?,
val criteria: String?,
val state: String? = null,
val tier: String? = null,
val progress: Double? = null,
@SerialName("next_tier") val nextTier: String? = null,
@SerialName("next_threshold") val nextThreshold: Double? = null,
@SerialName("progress_pct") val progressPct: Double? = null,
@SerialName("unlocked_at") val unlockedAt: Long? = null,
val secret: Boolean? = null,
val criteria: String? = null,
)
@Serializable
data class Achievement(
val id: String,
val name: String,
val description: String?,
val category: String?,
val kind: String?,
val icon: String?,
val description: String? = null,
val category: String? = null,
val kind: String? = null,
val icon: String? = null,
val unlocked: Boolean,
val discovered: Boolean,
val state: String?,
val tier: String?,
val progress: Double?,
@SerializedName("next_tier") val nextTier: String?,
@SerializedName("next_threshold") val nextThreshold: Double?,
@SerializedName("progress_pct") val progressPct: Double?,
@SerializedName("unlocked_at") val unlockedAt: Long?,
val secret: Boolean?,
val criteria: String?,
val state: String? = null,
val tier: String? = null,
val progress: Double? = null,
@SerialName("next_tier") val nextTier: String? = null,
@SerialName("next_threshold") val nextThreshold: Double? = null,
@SerialName("progress_pct") val progressPct: Double? = null,
@SerialName("unlocked_at") val unlockedAt: Long? = null,
val secret: Boolean? = null,
val criteria: String? = null,
)
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class ActionResponse(
val archive: String? = null,
val name: String? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class ActionStatusResponse(
val exit_code: Int? = null,
val lines: List<String>? = null,
@@ -1,4 +1,5 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
/**
* Represents a file attached to a chat message.
@@ -9,6 +10,7 @@ package com.m57.hermescontrol.data.model
* @param size File size in bytes
* @param localPath Optional local file system path for direct access
*/
@Serializable
data class Attachment(
val uri: String,
val name: String,
@@ -1,10 +1,13 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class CheckpointsResponse(
val sessions: List<CheckpointSession>? = null,
val total_bytes: Long? = null,
)
@Serializable
data class CheckpointSession(
val session: String? = null,
val files: Int? = null,
@@ -1,22 +1,26 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import com.google.gson.JsonElement
@Serializable
data class RawConfigResponse(
val path: String?,
val yaml: String?,
val path: String? = null,
val yaml: String? = null,
)
@Serializable
data class UpdateRawConfigRequest(
val yaml_text: String,
val profile: String? = null,
)
@Serializable
data class ConfigSchemaResponse(
val fields: Map<String, SchemaField>,
val category_order: List<String>,
)
@Serializable
data class SchemaField(
val type: String,
val description: String? = null,
@@ -24,6 +28,7 @@ data class SchemaField(
val options: List<String>? = null,
)
@Serializable
data class ConfigUpdateRequest(
val config: Map<String, JsonElement>,
val profile: String? = null,
@@ -1,7 +1,8 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
import java.util.UUID
@Serializable
data class ConnectionProfile(
val id: String = UUID.randomUUID().toString(),
val name: String,
@@ -1,14 +1,18 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class CredentialPoolResponse(
val providers: List<CredentialPoolProvider>? = null,
)
@Serializable
data class CredentialPoolProvider(
val provider: String? = null,
val entries: List<CredentialPoolEntry>? = null,
)
@Serializable
data class CredentialPoolEntry(
val index: Int? = null,
val label: String? = null,
@@ -1,17 +1,23 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
@Serializable
data class CronJobRepeat(
val times: Int? = null,
val completed: Int = 0,
)
@Serializable
data class CronJob(
val id: String,
val name: String,
val schedule: Any?,
val state: String?,
val last_run_status: String?,
val next_run: String?,
val schedule: JsonElement? = null,
val state: String? = null,
val last_run_status: String? = null,
val next_run: String? = null,
val schedule_display: String? = null,
val last_status: String? = null,
val next_run_at: String? = null,
@@ -36,8 +42,8 @@ data class CronJob(
val scheduleText: String
get() =
when (schedule) {
is String -> schedule
is Map<*, *> -> (schedule["display"] as? String) ?: schedule_display ?: ""
is JsonPrimitive -> schedule.content
is JsonObject -> (schedule["display"] as? JsonPrimitive)?.content ?: schedule_display ?: ""
else -> schedule_display ?: ""
}
@@ -1,5 +1,8 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@Serializable
data class CreateCronJobRequest(
val name: String = "",
val schedule: String,
@@ -17,6 +20,7 @@ data class CreateCronJobRequest(
val repeat: Int? = null,
)
@Serializable
data class UpdateCronJobRequest(
val updates: Map<String, Any?>,
val updates: Map<String, JsonElement>,
)
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class CuratorResponse(
val enabled: Boolean? = null,
val paused: Boolean? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class DebugShareResponse(
val ok: Boolean? = null,
val urls: Map<String, String>? = null,
@@ -1,7 +1,9 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class DoctorResponse(
val ok: Boolean,
val pid: Int?,
val name: String?,
val pid: Int? = null,
val name: String? = null,
)
@@ -1,32 +1,37 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class EnvVarConfig(
@SerializedName("is_set") val isSet: Boolean,
@SerializedName("redacted_value") val redactedValue: String?,
val description: String?,
val url: String?,
val category: String?,
@SerializedName("is_password") val isPassword: Boolean,
@SerialName("is_set") val isSet: Boolean,
@SerialName("redacted_value") val redactedValue: String? = null,
val description: String? = null,
val url: String? = null,
val category: String? = null,
@SerialName("is_password") val isPassword: Boolean,
)
@Serializable
data class EnvVarRevealRequest(
val key: String,
val profile: String? = null,
)
@Serializable
data class EnvVarRevealResponse(
val key: String,
val value: String,
)
@Serializable
data class EnvVarUpdate(
val key: String,
val value: String,
val profile: String? = null,
)
@Serializable
data class EnvVarDeleteRequest(
val key: String,
val profile: String? = null,
@@ -1,10 +1,13 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class HookResponse(
val hooks: List<HookEntry>? = null,
val valid_events: List<String>? = null,
)
@Serializable
data class HookEntry(
val event: String? = null,
val matcher: String? = null,
@@ -1,37 +1,43 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class KanbanBoard(
@SerializedName("slug") val id: String,
@SerialName("slug") val id: String,
val name: String,
val description: String?,
val description: String? = null,
)
@Serializable
data class KanbanTask(
val id: String,
val title: String,
@SerializedName("body") val description: String?,
@SerialName("body") val description: String? = null,
val status: String,
@SerializedName("assignee") val assignedTo: String?,
@SerialName("assignee") val assignedTo: String? = null,
)
@Serializable
data class CreateTaskBody(
val title: String,
val body: String?,
val body: String? = null,
)
@Serializable
data class KanbanColumn(
val name: String,
val tasks: List<KanbanTask>,
)
@Serializable
data class KanbanBoardResponse(
val columns: List<KanbanColumn>,
val assignees: List<String>?,
val tenants: List<String>?,
val assignees: List<String>? = null,
val tenants: List<String>? = null,
)
@Serializable
data class KanbanBoardsResponse(
val boards: List<KanbanBoard>,
val current: String? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class LogResponse(
val lines: List<String>? = null,
val logs: List<String>? = null,
@@ -1,25 +1,30 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class McpServersResponse(
val servers: List<McpServer>,
)
@Serializable
data class McpServer(
val name: String,
val transport: String?,
val url: String?,
val command: String?,
val args: List<String>?,
val env: Map<String, String>?,
val transport: String? = null,
val url: String? = null,
val command: String? = null,
val args: List<String>? = null,
val env: Map<String, String>? = null,
val enabled: Boolean,
val status: String? = null,
val error: String? = null,
)
@Serializable
data class McpServerToggleRequest(
val enabled: Boolean,
)
@Serializable
data class AddMcpServerRequest(
val name: String,
val url: String? = null,
@@ -28,10 +33,12 @@ data class AddMcpServerRequest(
val env: Map<String, String>? = null,
)
@Serializable
data class McpCatalogResponse(
val entries: List<McpCatalogEntry>,
)
@Serializable
data class McpCatalogEntry(
val name: String,
val description: String? = null,
@@ -42,6 +49,7 @@ data class McpCatalogEntry(
val env: List<McpCatalogEnvVar>? = null,
)
@Serializable
data class McpCatalogEnvVar(
val key: String,
val label: String? = null,
@@ -49,6 +57,7 @@ data class McpCatalogEnvVar(
val required: Boolean = false,
)
@Serializable
data class McpCatalogInstallRequest(
val name: String,
val env: Map<String, String>? = null,
@@ -1,10 +1,13 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class MemoryResponse(
val active: String? = null,
val builtin_files: BuiltinFileSizes? = null,
)
@Serializable
data class BuiltinFileSizes(
val memory: Long? = null,
val user: Long? = null,
@@ -1,57 +1,63 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class MessagingPlatform(
val id: String,
val name: String,
val description: String? = null,
@SerializedName("docs_url") val docsUrl: String? = null,
@SerialName("docs_url") val docsUrl: String? = null,
val enabled: Boolean,
val configured: Boolean,
@SerializedName("gateway_running") val gatewayRunning: Boolean = false,
@SerialName("gateway_running") val gatewayRunning: Boolean = false,
val state: String = "disabled",
@SerializedName("error_code") val errorCode: String? = null,
@SerializedName("error_message") val errorMessage: String? = null,
@SerializedName("env_vars") val envVars: List<EnvVarField>? = null,
@SerializedName("updated_at") val updatedAt: String? = null,
@SerializedName("home_channel") val homeChannel: HomeChannelInfo? = null,
@SerialName("error_code") val errorCode: String? = null,
@SerialName("error_message") val errorMessage: String? = null,
@SerialName("env_vars") val envVars: List<EnvVarField>? = null,
@SerialName("updated_at") val updatedAt: String? = null,
@SerialName("home_channel") val homeChannel: HomeChannelInfo? = null,
)
@Serializable
data class HomeChannelInfo(
val platform: String,
@SerializedName("chat_id") val chatId: String,
@SerialName("chat_id") val chatId: String,
val name: String,
@SerializedName("thread_id") val threadId: String? = null,
@SerialName("thread_id") val threadId: String? = null,
)
@Serializable
data class EnvVarField(
val key: String,
val required: Boolean,
@SerializedName("is_set") val isSet: Boolean,
@SerializedName("redacted_value") val redactedValue: String? = null,
@SerialName("is_set") val isSet: Boolean,
@SerialName("redacted_value") val redactedValue: String? = null,
val description: String? = null,
val prompt: String? = null,
val help: String? = null,
@SerializedName("is_password") val isPassword: Boolean,
@SerialName("is_password") val isPassword: Boolean,
val advanced: Boolean = false,
val url: String? = null,
@SerializedName("expires_at") val expiresAt: String? = null,
@SerialName("expires_at") val expiresAt: String? = null,
)
@Serializable
data class MessagingPlatformResponse(
@SerializedName("env_path") val envPath: String,
@SerializedName("gateway_start_command") val gatewayStartCommand: String,
@SerialName("env_path") val envPath: String,
@SerialName("gateway_start_command") val gatewayStartCommand: String,
val platforms: List<MessagingPlatform>,
)
@Serializable
data class MessagingPlatformUpdate(
val enabled: Boolean? = null,
val env: Map<String, String> = emptyMap(),
@SerializedName("clear_env") val clearEnv: List<String> = emptyList(),
@SerialName("clear_env") val clearEnv: List<String> = emptyList(),
val profile: String? = null,
)
@Serializable
data class MessagingPlatformTestResult(
val ok: Boolean,
val state: String,
@@ -60,37 +66,42 @@ data class MessagingPlatformTestResult(
// ── Telegram onboarding ─────────────────────────────────────────────────
@Serializable
data class TelegramOnboardingStartRequest(
@SerializedName("bot_name") val botName: String = "Hermes Agent",
@SerialName("bot_name") val botName: String = "Hermes Agent",
)
@Serializable
data class TelegramOnboardingStartResponse(
@SerializedName("pairing_id") val pairingId: String,
@SerializedName("suggested_username") val suggestedUsername: String,
@SerializedName("deep_link") val deepLink: String,
@SerializedName("qr_payload") val qrPayload: String,
@SerializedName("expires_at") val expiresAt: String,
@SerialName("pairing_id") val pairingId: String,
@SerialName("suggested_username") val suggestedUsername: String,
@SerialName("deep_link") val deepLink: String,
@SerialName("qr_payload") val qrPayload: String,
@SerialName("expires_at") val expiresAt: String,
)
@Serializable
data class TelegramOnboardingStatusResponse(
val status: String,
@SerializedName("bot_username") val botUsername: String? = null,
@SerializedName("owner_user_id") val ownerUserId: String? = null,
@SerializedName("expires_at") val expiresAt: String? = null,
@SerialName("bot_username") val botUsername: String? = null,
@SerialName("owner_user_id") val ownerUserId: String? = null,
@SerialName("expires_at") val expiresAt: String? = null,
)
@Serializable
data class TelegramOnboardingApplyRequest(
@SerializedName("allowed_user_ids") val allowedUserIds: List<String>,
@SerialName("allowed_user_ids") val allowedUserIds: List<String>,
val profile: String? = null,
)
@Serializable
data class TelegramOnboardingApplyResponse(
val ok: Boolean,
val platform: String,
@SerializedName("bot_username") val botUsername: String? = null,
@SerializedName("needs_restart") val needsRestart: Boolean,
@SerializedName("restart_started") val restartStarted: Boolean? = null,
@SerializedName("restart_action") val restartAction: String? = null,
@SerializedName("restart_pid") val restartPid: Int? = null,
@SerializedName("restart_error") val restartError: String? = null,
@SerialName("bot_username") val botUsername: String? = null,
@SerialName("needs_restart") val needsRestart: Boolean,
@SerialName("restart_started") val restartStarted: Boolean? = null,
@SerialName("restart_action") val restartAction: String? = null,
@SerialName("restart_pid") val restartPid: Int? = null,
@SerialName("restart_error") val restartError: String? = null,
)
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class AuxiliaryTaskAssignment(
val task: String,
val provider: String,
@@ -7,21 +9,25 @@ data class AuxiliaryTaskAssignment(
val base_url: String? = null,
)
@Serializable
data class AuxiliaryModelsResponse(
val tasks: List<AuxiliaryTaskAssignment>,
val main: MainModelAssignment,
)
@Serializable
data class MainModelAssignment(
val provider: String,
val model: String,
)
@Serializable
data class MoaModelSlot(
val provider: String,
val model: String,
)
@Serializable
data class MoaConfigPreset(
val reference_models: List<MoaModelSlot>,
val aggregator: MoaModelSlot,
@@ -31,6 +37,7 @@ data class MoaConfigPreset(
val enabled: Boolean = true,
)
@Serializable
data class MoaConfigResponse(
val default_preset: String = "",
val active_preset: String = "",
@@ -43,6 +50,7 @@ data class MoaConfigResponse(
val enabled: Boolean = true,
)
@Serializable
data class ModelAssignmentRequest(
val confirm_expensive_model: Boolean = false,
val scope: String,
@@ -52,6 +60,7 @@ data class ModelAssignmentRequest(
val task: String? = null,
)
@Serializable
data class ModelAssignmentResponse(
val confirm_message: String? = null,
val confirm_required: Boolean? = null,
@@ -1,22 +1,26 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class ModelOptionsResponse(
val providers: List<ModelProvider>,
)
@Serializable
data class ModelProvider(
val slug: String,
val name: String,
val is_current: Boolean?,
val is_user_defined: Boolean?,
val models: List<String>?,
val total_models: Int?,
val source: String?,
val authenticated: Boolean?,
val auth_type: String?,
val warning: String?,
val is_current: Boolean? = null,
val is_user_defined: Boolean? = null,
val models: List<String>? = null,
val total_models: Int? = null,
val source: String? = null,
val authenticated: Boolean? = null,
val auth_type: String? = null,
val warning: String? = null,
)
@Serializable
data class PinnedModel(
val providerSlug: String,
val modelName: String,
@@ -1,24 +1,29 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class PairingResponse(
val pending: List<PairingItem>,
val approved: List<PairingItem>,
)
@Serializable
data class PairingItem(
val platform: String,
val user_id: String?,
val username: String?,
val display_name: String?,
val code: String?,
val created_at: String?,
val user_id: String? = null,
val username: String? = null,
val display_name: String? = null,
val code: String? = null,
val created_at: String? = null,
)
@Serializable
data class PairingApproveRequest(
val platform: String,
val code: String,
)
@Serializable
data class PairingRevokeRequest(
val platform: String,
val user_id: String,
@@ -1,20 +1,21 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class PluginInfo(
val name: String,
val description: String?,
val version: String?,
val source: String?,
@SerializedName("runtime_status") val runtimeStatus: String?,
@SerializedName("has_dashboard_manifest") val hasDashboardManifest: Boolean = false,
@SerializedName("dashboard_manifest") val dashboardManifest: PluginManifestData? = null,
@SerializedName("can_remove") val canRemove: Boolean = false,
@SerializedName("can_update_git") val canUpdateGit: Boolean = false,
@SerializedName("auth_required") val authRequired: Boolean = false,
@SerializedName("auth_command") val authCommand: String? = null,
@SerializedName("user_hidden") val userHidden: Boolean = false,
val description: String? = null,
val version: String? = null,
val source: String? = null,
@SerialName("runtime_status") val runtimeStatus: String? = null,
@SerialName("has_dashboard_manifest") val hasDashboardManifest: Boolean = false,
@SerialName("dashboard_manifest") val dashboardManifest: PluginManifestData? = null,
@SerialName("can_remove") val canRemove: Boolean = false,
@SerialName("can_update_git") val canUpdateGit: Boolean = false,
@SerialName("auth_required") val authRequired: Boolean = false,
@SerialName("auth_command") val authCommand: String? = null,
@SerialName("user_hidden") val userHidden: Boolean = false,
) {
val enabled: Boolean
get() = runtimeStatus.equals("enabled", ignoreCase = true)
@@ -25,6 +26,7 @@ data class PluginInfo(
runtimeStatus.equals("disabled", ignoreCase = true)
}
@Serializable
data class PluginManifestData(
val name: String? = null,
val label: String? = null,
@@ -35,10 +37,11 @@ data class PluginManifestData(
val slots: List<String>? = null,
val entry: String? = null,
val css: String? = null,
@SerializedName("has_api") val hasApi: Boolean = false,
@SerialName("has_api") val hasApi: Boolean = false,
val source: String? = null,
)
@Serializable
data class PluginTabInfo(
val path: String? = null,
val position: String? = null,
@@ -46,6 +49,7 @@ data class PluginTabInfo(
val hidden: Boolean = false,
)
@Serializable
data class DashboardPluginMeta(
val name: String? = null,
val label: String? = null,
@@ -53,31 +57,36 @@ data class DashboardPluginMeta(
val tab: PluginTabInfo? = null,
)
@Serializable
data class PluginsHubProviders(
@SerializedName("memory_provider") val memoryProvider: String? = null,
@SerializedName("memory_options") val memoryOptions: List<ProviderOption> = emptyList(),
@SerializedName("context_engine") val contextEngine: String? = null,
@SerializedName("context_options") val contextOptions: List<ProviderOption> = emptyList(),
@SerialName("memory_provider") val memoryProvider: String? = null,
@SerialName("memory_options") val memoryOptions: List<ProviderOption> = emptyList(),
@SerialName("context_engine") val contextEngine: String? = null,
@SerialName("context_options") val contextOptions: List<ProviderOption> = emptyList(),
)
@Serializable
data class ProviderOption(
val name: String,
val description: String? = null,
)
@Serializable
data class PluginsHubResponse(
val plugins: List<PluginInfo>,
@SerializedName("orphan_dashboard_plugins") val orphanDashboardPlugins: List<DashboardPluginMeta> = emptyList(),
@SerialName("orphan_dashboard_plugins") val orphanDashboardPlugins: List<DashboardPluginMeta> = emptyList(),
val providers: PluginsHubProviders? = null,
)
@Serializable
data class AgentPluginInstallBody(
val identifier: String,
val force: Boolean = false,
val enable: Boolean = true,
)
@Serializable
data class PluginProvidersPutRequest(
@SerializedName("memory_provider") val memoryProvider: String? = null,
@SerializedName("context_engine") val contextEngine: String? = null,
@SerialName("memory_provider") val memoryProvider: String? = null,
@SerialName("context_engine") val contextEngine: String? = null,
)
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class PortalResponse(
val logged_in: Boolean? = null,
val portal_url: String? = null,
@@ -9,6 +11,7 @@ data class PortalResponse(
val features: List<PortalFeature>? = null,
)
@Serializable
data class PortalFeature(
val label: String? = null,
val state: String? = null,
@@ -1,9 +1,12 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class ProfilesResponse(
val profiles: List<ProfileInfo>,
)
@Serializable
data class ProfileInfo(
val name: String,
val path: String? = null,
@@ -17,46 +20,55 @@ data class ProfileInfo(
val description_auto: Boolean? = null,
)
@Serializable
data class ActiveProfileResponse(
val active: String,
val current: String?,
val current: String? = null,
)
@Serializable
data class SetActiveProfileRequest(
val name: String,
)
@Serializable
data class ProfileSoulResponse(
val content: String,
)
@Serializable
data class UpdateProfileSoulRequest(
val content: String,
)
@Serializable
data class UpdateProfileModelRequest(
val provider: String,
val model: String,
)
@Serializable
data class CloneProfileRequest(
val name: String,
)
@Serializable
data class UpdateProfileDescriptionRequest(
val description: String,
)
@Serializable
data class CreateProfileRequest(
val name: String,
val description: String?,
val provider: String?,
val model: String?,
val mcp_servers: List<McpServerConfigInput>?,
val keep_skills: Boolean?,
val hub_skills: List<String>?,
val description: String? = null,
val provider: String? = null,
val model: String? = null,
val mcp_servers: List<McpServerConfigInput>? = null,
val keep_skills: Boolean? = null,
val hub_skills: List<String>? = null,
)
@Serializable
data class McpServerConfigInput(
val name: String,
val transport: String,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class SaveSkillContentRequest(
val name: String,
val content: String,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class SessionListResponse(
val sessions: List<SessionInfo>,
val total: Int = 0,
@@ -7,35 +9,41 @@ data class SessionListResponse(
val offset: Int = 0,
)
@Serializable
data class SessionInfo(
val id: String,
val title: String?,
val created_at: String?,
val message_count: Int?,
val status: String?,
val title: String? = null,
val created_at: String? = null,
val message_count: Int? = null,
val status: String? = null,
val preview: String? = null,
val started_at: Double? = null,
val source: String? = null,
)
@Serializable
data class SessionStatsResponse(
val total: Int = 0,
val active: Int = 0,
)
@Serializable
data class SessionRenameRequest(
val title: String,
)
@Serializable
data class BulkDeleteRequest(
val ids: List<String>,
val delete_all: Boolean = false,
)
@Serializable
data class PruneRequest(
val days: Int,
)
@Serializable
data class SessionPromptResponse(
val prompt: String? = null,
val id: String? = null,
@@ -1,12 +1,20 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonPrimitive
@Serializable
data class SessionMessagesResponse(
val messages: List<SessionMessage>,
)
@Serializable
data class SessionMessage(
val role: String?,
val content: String?,
val timestamp: String?,
val type: String?,
)
val role: String? = null,
val content: String? = null,
val timestamp: JsonElement? = null,
val type: String? = null,
) {
val timestampText: String?
get() = (timestamp as? JsonPrimitive)?.content
}
@@ -1,11 +1,12 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import com.google.gson.annotations.SerializedName
@Serializable
data class Skill(
val name: String,
val description: String?,
val category: String?,
val description: String? = null,
val category: String? = null,
val enabled: Boolean,
val content: String? = null,
val source: String? = null, // built-in, hub, optional
@@ -13,40 +14,46 @@ data class Skill(
val linked_files: List<String>? = null,
)
@Serializable
data class HubSkill(
val name: String,
val description: String?,
val source: String?,
val description: String? = null,
val source: String? = null,
val category: String? = null,
val identifier: String? = null,
@SerializedName("trust_level") val trustLevel: String? = null,
@SerialName("trust_level") val trustLevel: String? = null,
val repo: String? = null,
val tags: List<String>? = null,
)
@Serializable
data class SkillHubSearchResponse(
val results: List<HubSkill>,
@SerializedName("source_counts") val sourceCounts: Map<String, Int>? = null,
@SerializedName("timed_out") val timedOut: List<String>? = null,
@SerialName("source_counts") val sourceCounts: Map<String, Int>? = null,
@SerialName("timed_out") val timedOut: List<String>? = null,
val installed: Map<String, SkillHubInstalledEntry>? = null,
)
@Serializable
data class SkillHubInstalledEntry(
val name: String? = null,
@SerializedName("trust_level") val trustLevel: String? = null,
@SerializedName("scan_verdict") val scanVerdict: String? = null,
@SerialName("trust_level") val trustLevel: String? = null,
@SerialName("scan_verdict") val scanVerdict: String? = null,
)
@Serializable
data class SkillHubInstallRequest(
val identifier: String,
val profile: String? = null,
)
@Serializable
data class SkillHubUninstallRequest(
val name: String,
val profile: String? = null,
)
@Serializable
data class SkillScanResponse(
val identifier: String,
val passed: Boolean? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class SkillContentResponse(
val name: String,
val content: String,
@@ -1,14 +1,17 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class StatusResponse(
val version: String?,
val gateway_running: Boolean?,
val active_sessions: Int?,
val auth_required: Boolean?,
val gateway_platforms: Map<String, PlatformStatus>?,
val version: String? = null,
val gateway_running: Boolean? = null,
val active_sessions: Int? = null,
val auth_required: Boolean? = null,
val gateway_platforms: Map<String, PlatformStatus?>? = null,
)
@Serializable
data class PlatformStatus(
val state: String?,
val state: String? = null,
val error_code: String? = null,
)
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class SystemStatsResponse(
val os: String? = null,
val os_release: String? = null,
@@ -20,6 +22,7 @@ data class SystemStatsResponse(
val process: ProcessStats? = null,
)
@Serializable
data class MemoryStats(
val total: Long? = null,
val available: Long? = null,
@@ -27,6 +30,7 @@ data class MemoryStats(
val percent: Double? = null,
)
@Serializable
data class DiskStats(
val total: Long? = null,
val used: Long? = null,
@@ -34,6 +38,7 @@ data class DiskStats(
val percent: Double? = null,
)
@Serializable
data class ProcessStats(
val pid: Int? = null,
val rss: Long? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class ToggleSkillRequest(
val name: String,
val enabled: Boolean,
@@ -1,15 +1,18 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class Toolset(
val name: String,
val label: String?,
val description: String?,
val label: String? = null,
val description: String? = null,
val enabled: Boolean,
val available: Boolean?,
val configured: Boolean?,
val tools: List<String>?,
val available: Boolean? = null,
val configured: Boolean? = null,
val tools: List<String>? = null,
)
@Serializable
data class ToolsetToggleRequest(
val enabled: Boolean,
val profile: String? = null,
@@ -1,5 +1,7 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class UpdateCheckResponse(
val install_method: String? = null,
val current_version: String? = null,
@@ -1,25 +1,29 @@
package com.m57.hermescontrol.data.model
import kotlinx.serialization.Serializable
@Serializable
data class WebhooksResponse(
val enabled: Boolean,
val base_url: String?,
val subscriptions: List<WebhookSubscription>?,
val base_url: String? = null,
val subscriptions: List<WebhookSubscription>? = null,
)
@Serializable
data class WebhookSubscription(
val name: String,
val description: String?,
val events: List<String>?,
val deliver: String?,
val deliver_only: Boolean?,
val prompt: String?,
val skills: List<String>?,
val created_at: String?,
val description: String? = null,
val events: List<String>? = null,
val deliver: String? = null,
val deliver_only: Boolean? = null,
val prompt: String? = null,
val skills: List<String>? = null,
val created_at: String? = null,
val url: String,
val secret_set: Boolean?,
val enabled: Boolean?,
val secret_set: Boolean? = null,
val enabled: Boolean? = null,
)
@Serializable
data class CreateWebhookRequest(
val name: String,
val description: String? = null,
@@ -32,14 +36,17 @@ data class CreateWebhookRequest(
val secret: String? = null,
)
@Serializable
data class WebhooksToggleRequest(
val enabled: Boolean,
)
@Serializable
data class WebhookToggleSubscriptionRequest(
val enabled: Boolean,
)
@Serializable
data class DeleteWebhookResponse(
val ok: Boolean,
)