mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-07-13 03:05:12 +00:00
88a5793030
## 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
82 lines
2.4 KiB
Go
82 lines
2.4 KiB
Go
package methods
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/bus"
|
|
"github.com/nextlevelbuilder/goclaw/internal/gateway"
|
|
"github.com/nextlevelbuilder/goclaw/internal/i18n"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
|
)
|
|
|
|
// --- agents.delete ---
|
|
// Matching TS src/gateway/server-methods/agents.ts:347-398
|
|
|
|
func (m *AgentsMethods) handleDelete(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
locale := store.LocaleFromContext(ctx)
|
|
var params struct {
|
|
AgentID string `json:"agentId"`
|
|
DeleteFiles bool `json:"deleteFiles"`
|
|
}
|
|
params.DeleteFiles = true // default
|
|
if req.Params != nil {
|
|
json.Unmarshal(req.Params, ¶ms)
|
|
}
|
|
|
|
if params.AgentID == "" {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgRequired, "agentId")))
|
|
return
|
|
}
|
|
if params.AgentID == "default" {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgCannotDeleteDefault)))
|
|
return
|
|
}
|
|
|
|
var removedBindings int
|
|
|
|
if m.agentStore != nil {
|
|
// --- DB-backed: delete from store ---
|
|
ag, err := m.agentStore.GetByKey(ctx, params.AgentID)
|
|
if err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrNotFound, i18n.T(locale, i18n.MsgAgentNotFound, params.AgentID)))
|
|
return
|
|
}
|
|
|
|
if err := m.agentStore.Delete(ctx, ag.ID); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInternal, i18n.T(locale, i18n.MsgFailedToDelete, "agent", fmt.Sprintf("%v", err))))
|
|
return
|
|
}
|
|
|
|
m.agents.InvalidateAgent(params.AgentID)
|
|
m.agents.Remove(params.AgentID)
|
|
|
|
// Emit agent:deleted event for async cleanup (e.g. orphaned provider removal)
|
|
if m.eventBus != nil {
|
|
m.eventBus.Broadcast(bus.Event{
|
|
Name: bus.TopicAgentDeleted,
|
|
Payload: bus.AgentDeletedPayload{
|
|
AgentKey: params.AgentID,
|
|
Provider: ag.Provider,
|
|
TenantID: store.TenantIDFromContext(ctx),
|
|
},
|
|
})
|
|
}
|
|
|
|
// Best-effort delete workspace
|
|
if params.DeleteFiles && ag.Workspace != "" {
|
|
os.RemoveAll(ag.Workspace)
|
|
}
|
|
}
|
|
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"ok": true,
|
|
"agentId": params.AgentID,
|
|
"removedBindings": removedBindings,
|
|
}))
|
|
emitAudit(m.eventBus, client, "agent.deleted", "agent", params.AgentID)
|
|
}
|