mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-11 22:11:49 +00:00
9115169c03
Replace direct ActivityStore injection with event-driven audit system. Handlers emit audit events via msgBus.Broadcast(), a single subscriber with buffered channel persists to activity_logs table. Coverage expanded from 3 agent CRUD actions to ~65 audit points across all HTTP handlers and WebSocket RPC methods including agents, providers, skills, MCP servers, cron, sessions, teams, pairing, and more.
162 lines
5.1 KiB
Go
162 lines
5.1 KiB
Go
package methods
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"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"
|
|
)
|
|
|
|
// SessionsMethods handles sessions.list, sessions.preview, sessions.patch, sessions.delete, sessions.reset.
|
|
type SessionsMethods struct {
|
|
sessions store.SessionStore
|
|
eventBus bus.EventPublisher
|
|
}
|
|
|
|
func NewSessionsMethods(sess store.SessionStore, eventBus bus.EventPublisher) *SessionsMethods {
|
|
return &SessionsMethods{sessions: sess, eventBus: eventBus}
|
|
}
|
|
|
|
func (m *SessionsMethods) Register(router *gateway.MethodRouter) {
|
|
router.Register(protocol.MethodSessionsList, m.handleList)
|
|
router.Register(protocol.MethodSessionsPreview, m.handlePreview)
|
|
router.Register(protocol.MethodSessionsPatch, m.handlePatch)
|
|
router.Register(protocol.MethodSessionsDelete, m.handleDelete)
|
|
router.Register(protocol.MethodSessionsReset, m.handleReset)
|
|
}
|
|
|
|
type sessionsListParams struct {
|
|
AgentID string `json:"agentId"`
|
|
Limit int `json:"limit"`
|
|
Offset int `json:"offset"`
|
|
}
|
|
|
|
func (m *SessionsMethods) handleList(_ context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
var params sessionsListParams
|
|
if req.Params != nil {
|
|
json.Unmarshal(req.Params, ¶ms)
|
|
}
|
|
|
|
if params.Limit <= 0 {
|
|
params.Limit = 20
|
|
}
|
|
|
|
result := m.sessions.ListPagedRich(store.SessionListOpts{
|
|
AgentID: params.AgentID,
|
|
Limit: params.Limit,
|
|
Offset: params.Offset,
|
|
})
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"sessions": result.Sessions,
|
|
"total": result.Total,
|
|
"limit": params.Limit,
|
|
"offset": params.Offset,
|
|
}))
|
|
}
|
|
|
|
type sessionKeyParams struct {
|
|
Key string `json:"key"`
|
|
}
|
|
|
|
func (m *SessionsMethods) handlePreview(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
locale := store.LocaleFromContext(ctx)
|
|
var params sessionKeyParams
|
|
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgInvalidJSON)))
|
|
return
|
|
}
|
|
|
|
history := m.sessions.GetHistory(params.Key)
|
|
summary := m.sessions.GetSummary(params.Key)
|
|
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"key": params.Key,
|
|
"messages": history,
|
|
"summary": summary,
|
|
}))
|
|
}
|
|
|
|
// handlePatch updates session metadata fields.
|
|
// Matching TS sessions.patch (src/gateway/server-methods/sessions.ts:237-287).
|
|
func (m *SessionsMethods) handlePatch(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
locale := store.LocaleFromContext(ctx)
|
|
var params struct {
|
|
Key string `json:"key"`
|
|
Label *string `json:"label,omitempty"`
|
|
Model *string `json:"model,omitempty"`
|
|
Metadata map[string]string `json:"metadata,omitempty"`
|
|
}
|
|
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgInvalidJSON)))
|
|
return
|
|
}
|
|
|
|
if params.Key == "" {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgRequired, "key")))
|
|
return
|
|
}
|
|
|
|
// Apply label patch
|
|
if params.Label != nil {
|
|
m.sessions.SetLabel(params.Key, *params.Label)
|
|
}
|
|
|
|
// Apply model patch
|
|
if params.Model != nil {
|
|
m.sessions.UpdateMetadata(params.Key, *params.Model, "", "")
|
|
}
|
|
|
|
// Apply metadata patch
|
|
if len(params.Metadata) > 0 {
|
|
m.sessions.SetSessionMetadata(params.Key, params.Metadata)
|
|
}
|
|
|
|
// Save changes to DB
|
|
m.sessions.Save(params.Key)
|
|
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"ok": true,
|
|
"key": params.Key,
|
|
}))
|
|
emitAudit(m.eventBus, client, "session.patched", "session", params.Key)
|
|
}
|
|
|
|
func (m *SessionsMethods) handleDelete(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
locale := store.LocaleFromContext(ctx)
|
|
var params sessionKeyParams
|
|
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgInvalidJSON)))
|
|
return
|
|
}
|
|
|
|
if err := m.sessions.Delete(params.Key); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInternal, err.Error()))
|
|
return
|
|
}
|
|
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"ok": true,
|
|
}))
|
|
emitAudit(m.eventBus, client, "session.deleted", "session", params.Key)
|
|
}
|
|
|
|
func (m *SessionsMethods) handleReset(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
|
locale := store.LocaleFromContext(ctx)
|
|
var params sessionKeyParams
|
|
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
|
|
client.SendResponse(protocol.NewErrorResponse(req.ID, protocol.ErrInvalidRequest, i18n.T(locale, i18n.MsgInvalidJSON)))
|
|
return
|
|
}
|
|
|
|
m.sessions.Reset(params.Key)
|
|
|
|
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
|
"ok": true,
|
|
}))
|
|
emitAudit(m.eventBus, client, "session.reset", "session", params.Key)
|
|
}
|