mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-08-12 20:22:27 +00:00
## Summary - Agent rename now updates Name field in IDENTITY.md (agent-level + per-user copies for open agents) via both HTTP and WS paths - Fixes lossy identity rebuild: previous logic reconstructed IDENTITY.md from only Name/Emoji/Avatar, silently dropping LLM-written fields (Creature, Purpose, Vibe, etc.) - Uses targeted field replacement (bootstrap.UpdateIdentityField) preserving original formatting - Adds ListUserContextFilesByName to AgentContextStore (PG + SQLite) - Fixes LastIndex bug in UpdateIdentityField where values containing colons (e.g. Avatar URLs) would break field replacement - Removes ~335 lines of dead config.json fallback code (agentStore is always set) - Adds 9 unit tests for UpdateIdentityField covering plain/markdown formats, URLs, edge cases
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
package bootstrap
|
|
|
|
import "testing"
|
|
|
|
func TestUpdateIdentityField(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
content string
|
|
fieldName string
|
|
newValue string
|
|
want string
|
|
}{
|
|
{
|
|
name: "plain format",
|
|
content: "# Identity\nName: OldName\nEmoji: 🤖",
|
|
fieldName: "Name",
|
|
newValue: "NewName",
|
|
want: "# Identity\nName: NewName\nEmoji: 🤖",
|
|
},
|
|
{
|
|
name: "LLM markdown format",
|
|
content: "# Identity\n- **Name:** OldName\n- **Creature:** Fox",
|
|
fieldName: "Name",
|
|
newValue: "NewName",
|
|
want: "# Identity\n- **Name:** NewName\n- **Creature:** Fox",
|
|
},
|
|
{
|
|
name: "field not found inserts after heading",
|
|
content: "# Identity\nEmoji: 🤖",
|
|
fieldName: "Name",
|
|
newValue: "NewName",
|
|
want: "# Identity\nName: NewName\nEmoji: 🤖",
|
|
},
|
|
{
|
|
name: "empty content inserts at top",
|
|
content: "",
|
|
fieldName: "Name",
|
|
newValue: "NewName",
|
|
want: "Name: NewName\n",
|
|
},
|
|
{
|
|
name: "empty newValue returns unchanged",
|
|
content: "# Identity\nName: OldName",
|
|
fieldName: "Name",
|
|
newValue: "",
|
|
want: "# Identity\nName: OldName",
|
|
},
|
|
{
|
|
name: "value with colon (URL) preserved on other fields",
|
|
content: "# Identity\nName: Bot\nAvatar: https://example.com/avatar.png",
|
|
fieldName: "Name",
|
|
newValue: "NewBot",
|
|
want: "# Identity\nName: NewBot\nAvatar: https://example.com/avatar.png",
|
|
},
|
|
{
|
|
name: "update avatar URL field correctly",
|
|
content: "# Identity\nName: Bot\nAvatar: https://old.com/img.png",
|
|
fieldName: "Avatar",
|
|
newValue: "https://new.com/img.png",
|
|
want: "# Identity\nName: Bot\nAvatar: https://new.com/img.png",
|
|
},
|
|
{
|
|
name: "LLM markdown avatar with URL",
|
|
content: "# Identity\n- **Name:** Bot\n- **Avatar:** https://old.com/img.png",
|
|
fieldName: "Avatar",
|
|
newValue: "https://new.com/img.png",
|
|
want: "# Identity\n- **Name:** Bot\n- **Avatar:** https://new.com/img.png",
|
|
},
|
|
{
|
|
name: "preserves other LLM fields",
|
|
content: "# Identity\n- **Name:** Bot\n- **Creature:** Fox\n- **Purpose:** Help users\n- **Vibe:** Friendly",
|
|
fieldName: "Name",
|
|
newValue: "NewBot",
|
|
want: "# Identity\n- **Name:** NewBot\n- **Creature:** Fox\n- **Purpose:** Help users\n- **Vibe:** Friendly",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := UpdateIdentityField(tt.content, tt.fieldName, tt.newValue)
|
|
if got != tt.want {
|
|
t.Errorf("UpdateIdentityField() =\n%q\nwant:\n%q", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|