mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-15 00:17:27 +00:00
fix(gateway): clear claude-cli session on sessions.reset RPC (#1232)
The sessions.reset RPC only reset the native session store, leaving the Claude CLI-backed history (.jsonl + CLAUDE.md) in place. The /reset chat command already clears it via providers.ResetCLISession, so RPC callers got an incomplete reset for claude-cli agents — stale history was resumed on the next turn. Mirror the chat path by calling ResetCLISession from handleReset. It is a no-op when the CLI provider is unused. The call is wired through an overridable package var so the behavior can be regression-tested.
This commit is contained in:
1 parent
2bf0f9e172
commit
cedd6673c4
2 files changed
+52
No files matched your search
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/nextlevelbuilder/goclaw/internal/gateway"
|
||||
httpapi "github.com/nextlevelbuilder/goclaw/internal/http"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/i18n"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/providers"
|
||||
"github.com/nextlevelbuilder/goclaw/internal/store"
|
||||
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
||||
)
|
||||
@@ -204,6 +205,10 @@ func (m *SessionsMethods) handleDelete(ctx context.Context, client *gateway.Clie
|
||||
emitAudit(m.eventBus, client, "session.deleted", "session", params.Key)
|
||||
}
|
||||
|
||||
// cliSessionReset clears the Claude CLI-backed session for a key. It is a
|
||||
// package var so tests can stub it; defaults to the real provider helper.
|
||||
var cliSessionReset = providers.ResetCLISession
|
||||
|
||||
func (m *SessionsMethods) handleReset(ctx context.Context, client *gateway.Client, req *protocol.RequestFrame) {
|
||||
locale := store.LocaleFromContext(ctx)
|
||||
var params sessionKeyParams
|
||||
@@ -225,6 +230,10 @@ func (m *SessionsMethods) handleReset(ctx context.Context, client *gateway.Clien
|
||||
}
|
||||
|
||||
m.sessions.Reset(ctx, params.Key)
|
||||
// Also clear the Claude CLI session (.jsonl + CLAUDE.md) so the RPC reset
|
||||
// matches the /reset chat command for claude-cli-backed agents (no-op when
|
||||
// the CLI provider is unused).
|
||||
cliSessionReset("", params.Key)
|
||||
|
||||
client.SendResponse(protocol.NewOKResponse(req.ID, map[string]any{
|
||||
"ok": true,
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package methods
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/nextlevelbuilder/goclaw/pkg/protocol"
|
||||
)
|
||||
|
||||
// TestSessionsReset_ClearsCLISession is a regression guard ensuring the
|
||||
// sessions.reset RPC also clears the Claude CLI-backed session, matching the
|
||||
// /reset chat command. Previously the RPC only reset the native session store,
|
||||
// leaving claude-cli history (.jsonl + CLAUDE.md) in place.
|
||||
func TestSessionsReset_ClearsCLISession(t *testing.T) {
|
||||
sess := newStubSessionStore()
|
||||
// Empty userID matches nullClient()'s empty UserID, so the ownership
|
||||
// check in handleReset passes and we reach the reset path.
|
||||
sess.addSession("reset-key", "")
|
||||
m := buildSessionMethods(t, sess)
|
||||
client := nullClient()
|
||||
|
||||
var called bool
|
||||
var gotKey string
|
||||
orig := cliSessionReset
|
||||
cliSessionReset = func(_, sessionKey string) {
|
||||
called = true
|
||||
gotKey = sessionKey
|
||||
}
|
||||
t.Cleanup(func() { cliSessionReset = orig })
|
||||
|
||||
req := sessionReqFrame(t, protocol.MethodSessionsReset, map[string]any{"key": "reset-key"})
|
||||
m.handleReset(context.Background(), client, req)
|
||||
|
||||
if !called {
|
||||
t.Fatal("sessions.reset did not clear the Claude CLI session")
|
||||
}
|
||||
if gotKey != "reset-key" {
|
||||
t.Errorf("CLI reset key = %q, want %q", gotKey, "reset-key")
|
||||
}
|
||||
if len(sess.resetCalled) != 1 || sess.resetCalled[0] != "reset-key" {
|
||||
t.Errorf("native store.Reset calls = %v, want [reset-key]", sess.resetCalled)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user