fix(bots): create clean profile without cloning default soul and custom skills (#997)
This commit is contained in:
2 files changed
+43
-12
No files matched your search
@@ -238,11 +238,11 @@ class BotsViewModel(
|
|||||||
CreateProfileRequest(
|
CreateProfileRequest(
|
||||||
name = name,
|
name = name,
|
||||||
description = description.ifBlank { null },
|
description = description.ifBlank { null },
|
||||||
clone_from_default = true,
|
clone_from_default = false,
|
||||||
)
|
)
|
||||||
val result = safeApiCall { ApiClient.hermesApi.createProfile(req) }
|
val result = safeApiCall { ApiClient.hermesApi.createProfile(req) }
|
||||||
if (result is NetworkResult.Success) {
|
if (result is NetworkResult.Success) {
|
||||||
// Configure UI metadata (avatar, custom title) via RPC
|
// Configure UI metadata (avatar, custom title) and bot SOUL via RPC
|
||||||
val botMeta =
|
val botMeta =
|
||||||
BotRosterMeta(
|
BotRosterMeta(
|
||||||
title = title.ifBlank { null },
|
title = title.ifBlank { null },
|
||||||
@@ -253,7 +253,8 @@ class BotsViewModel(
|
|||||||
color = color,
|
color = color,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
wsClientConfigureBot(name, botMeta)
|
val botSoul = composeBotSoul(name, title, description)
|
||||||
|
wsClientConfigureBot(name, botMeta, soul = botSoul)
|
||||||
loadBots()
|
loadBots()
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} else {
|
} else {
|
||||||
@@ -363,18 +364,36 @@ class BotsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun composeBotSoul(
|
||||||
|
name: String,
|
||||||
|
title: String,
|
||||||
|
description: String,
|
||||||
|
): String {
|
||||||
|
val displayName = title.ifBlank { name }
|
||||||
|
val lines = mutableListOf<String>()
|
||||||
|
lines.add("# $displayName")
|
||||||
|
lines.add("")
|
||||||
|
if (title.isNotBlank()) lines.add("**Role:** $title")
|
||||||
|
if (description.isNotBlank()) lines.add("**Mission:** $description")
|
||||||
|
lines.add("")
|
||||||
|
lines.add("You are $displayName, a persistent named agent (profile `$name`) on this machine.")
|
||||||
|
lines.add("You keep your own memory, skills, and conversation history across sessions.")
|
||||||
|
return lines.joinToString("\n")
|
||||||
|
}
|
||||||
|
|
||||||
private fun wsClientConfigureBot(
|
private fun wsClientConfigureBot(
|
||||||
name: String,
|
name: String,
|
||||||
meta: BotRosterMeta,
|
meta: BotRosterMeta,
|
||||||
|
soul: String? = null,
|
||||||
): kotlinx.coroutines.CompletableDeferred<Any?> {
|
): kotlinx.coroutines.CompletableDeferred<Any?> {
|
||||||
val metaMap =
|
val metaMap =
|
||||||
buildMap<String, Any?> {
|
buildMap<String, Any> {
|
||||||
put("title", meta.title)
|
meta.title?.let { put("title", it) }
|
||||||
put("description", meta.description)
|
meta.description?.let { put("description", it) }
|
||||||
meta.avatar?.let { av ->
|
meta.avatar?.let { av ->
|
||||||
put(
|
put(
|
||||||
"avatar",
|
"avatar",
|
||||||
buildMap<String, Any?> {
|
buildMap<String, Any> {
|
||||||
av.shape?.let { put("shape", it) }
|
av.shape?.let { put("shape", it) }
|
||||||
av.color?.let { put("color", it) }
|
av.color?.let { put("color", it) }
|
||||||
av.icon?.let { put("icon", it) }
|
av.icon?.let { put("icon", it) }
|
||||||
@@ -386,12 +405,16 @@ class BotsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val params =
|
||||||
|
buildMap<String, Any> {
|
||||||
|
put("name", name)
|
||||||
|
put("ui_meta", mapOf("hermes-bots" to metaMap))
|
||||||
|
soul?.let { put("soul", it) }
|
||||||
|
}
|
||||||
|
|
||||||
return HermesWsClient.request(
|
return HermesWsClient.request(
|
||||||
WsMethods.PROFILES_CONFIGURE,
|
WsMethods.PROFILES_CONFIGURE,
|
||||||
mapOf(
|
params,
|
||||||
"name" to name,
|
|
||||||
"ui_meta" to mapOf("hermes-bots" to metaMap),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,15 @@ class BotsViewModelTest {
|
|||||||
advanceUntilIdle()
|
advanceUntilIdle()
|
||||||
|
|
||||||
assertTrue(successCalled)
|
assertTrue(successCalled)
|
||||||
coVerify(exactly = 1) { mockApi.createProfile(match { it.name == "researcher" }) }
|
coVerify(exactly = 1) {
|
||||||
|
mockApi.createProfile(
|
||||||
|
match {
|
||||||
|
it.name == "researcher" &&
|
||||||
|
it.clone_from_default == false &&
|
||||||
|
it.description == "Deep research agent"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in new issue
Block a user