refactor(#1375): type command dispatch, slash exec and attachment RPC params (#1394)

This commit is contained in:
m57 authored and GitHub committed 2026-09-30 01:09:34 +03:00
1 parent 1456e642e3
commit 26c60a10c0
8 files changed
+263 -65

No files matched your search

@@ -830,6 +830,17 @@ object HermesWsClient {
return deferred
}
/**
* Non-suspending typed twin of [request] for callers that must enqueue inside a
* non-suspending owner check and await the raw result themselves.
*/
fun <P, R> requestTyped(
method: RpcMethod<P, R>,
params: P,
timeoutMs: Long = REQUEST_TIMEOUT_MS,
suppressErrorEvent: Boolean = false,
): CompletableDeferred<Any?> = request(method.name, encodeParams(method, params), timeoutMs, suppressErrorEvent)
/**
* Send a typed JSON-RPC request and await its deserialized result.
*
@@ -844,8 +855,7 @@ object HermesWsClient {
timeoutMs: Long = REQUEST_TIMEOUT_MS,
suppressErrorEvent: Boolean = false,
): R {
val encoded = encodeParams(method, params)
val deferred = request(method.name, encoded, timeoutMs, suppressErrorEvent)
val deferred = requestTyped(method, params, timeoutMs, suppressErrorEvent)
val result =
try {
deferred.await()
@@ -0,0 +1,40 @@
package com.m57.hermescontrol.data.ws.contract
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/** `commands.catalog` is sent without explicit params; the active profile is injected by WsProfileParams. */
@Serializable
data object CommandsCatalogParams
/** `arg` is sent whenever non-null, including an empty string, exactly like the old map payload. */
@Serializable
data class CommandDispatchParams(
@SerialName("name") val name: String,
@SerialName("arg") val arg: String? = null,
@SerialName("session_id") val sessionId: String? = null,
)
@Serializable
data class SlashExecParams(
@SerialName("session_id") val sessionId: String,
@SerialName("command") val command: String,
)
/** `data_url` carries the bytes for an uploaded file; `path` is for gateway-visible files. */
@Serializable
data class FileAttachParams(
@SerialName("session_id") val sessionId: String,
@SerialName("path") val path: String? = null,
@SerialName("data_url") val dataUrl: String? = null,
@SerialName("name") val name: String? = null,
)
/** The mobile client always sends the payload as `content_base64`; the `data` alias is not modelled. */
@Serializable
data class ImageAttachBytesParams(
@SerialName("session_id") val sessionId: String,
@SerialName("content_base64") val contentBase64: String? = null,
@SerialName("filename") val filename: String? = null,
@SerialName("ext") val ext: String? = null,
)
@@ -427,6 +427,46 @@ object RpcMethods {
JsonElement.serializer(),
)
// Passthrough JsonElement results: callers keep their existing legacy decoders.
val COMMANDS_CATALOG: RpcMethod<CommandsCatalogParams, JsonElement> =
RpcMethod(
WsMethods.COMMANDS_CATALOG,
CommandsCatalogParams.serializer(),
JsonElement.serializer(),
)
// Passthrough JsonElement results: callers keep their existing legacy decoders.
val COMMAND_DISPATCH: RpcMethod<CommandDispatchParams, JsonElement> =
RpcMethod(
WsMethods.COMMAND_DISPATCH,
CommandDispatchParams.serializer(),
JsonElement.serializer(),
)
// Passthrough JsonElement results: callers keep their existing legacy decoders.
val SLASH_EXEC: RpcMethod<SlashExecParams, JsonElement> =
RpcMethod(
WsMethods.SLASH_EXEC,
SlashExecParams.serializer(),
JsonElement.serializer(),
)
// Passthrough JsonElement results: callers keep their existing legacy decoders.
val FILE_ATTACH: RpcMethod<FileAttachParams, JsonElement> =
RpcMethod(
WsMethods.FILE_ATTACH,
FileAttachParams.serializer(),
JsonElement.serializer(),
)
// Passthrough JsonElement results: callers keep their existing legacy decoders.
val IMAGE_ATTACH_BYTES: RpcMethod<ImageAttachBytesParams, JsonElement> =
RpcMethod(
WsMethods.IMAGE_ATTACH_BYTES,
ImageAttachBytesParams.serializer(),
JsonElement.serializer(),
)
/** Every typed method. GatewayContractTest iterates this; future migrations append here. */
val all: List<RpcMethod<*, *>> =
listOf(
@@ -482,5 +522,10 @@ object RpcMethods {
CONFIG_GET,
MODEL_OPTIONS,
CLIENT_CAPABILITIES,
COMMANDS_CATALOG,
COMMAND_DISPATCH,
SLASH_EXEC,
FILE_ATTACH,
IMAGE_ATTACH_BYTES,
)
}