mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat(agent): /clear now clears seahorse DB in addition to JSONL
- Add Clear(ctx, sessionKey) to ContextManager interface - Implement Clear for legacy (JSONL) and seahorse (DB + JSONL) - Add Engine.ClearSession + Store.ClearConversation - Fix FTS5 DELETE trigger syntax in schema (was using wrong external-content FTS5 syntax; now uses standard DELETE FROM) - Fix ClearSession to skip sessions never ingested (was creating blank conversations record via GetOrCreateConversation) - Simplify summary_parents DELETE into single OR statement - Add TestStoreClearConversation unit test
This commit is contained in:
@@ -61,6 +61,16 @@ func (m *legacyContextManager) Ingest(_ context.Context, _ *IngestRequest) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *legacyContextManager) Clear(_ context.Context, sessionKey string) error {
|
||||
agent := m.al.registry.GetDefaultAgent()
|
||||
if agent == nil || agent.Sessions == nil {
|
||||
return fmt.Errorf("sessions not initialized")
|
||||
}
|
||||
agent.Sessions.SetHistory(sessionKey, []providers.Message{})
|
||||
agent.Sessions.SetSummary(sessionKey, "")
|
||||
return agent.Sessions.Save(sessionKey)
|
||||
}
|
||||
|
||||
// maybeSummarize triggers summarization if the session history exceeds thresholds.
|
||||
// It runs asynchronously in a goroutine.
|
||||
func (m *legacyContextManager) maybeSummarize(sessionKey string) {
|
||||
|
||||
@@ -24,6 +24,10 @@ type ContextManager interface {
|
||||
// Ingest records a message into the ContextManager's own storage.
|
||||
// Called after each message is persisted to session JSONL.
|
||||
Ingest(ctx context.Context, req *IngestRequest) error
|
||||
|
||||
// Clear removes all stored context for a session (messages, summaries, etc.).
|
||||
// Called when the user issues /clear or /reset.
|
||||
Clear(ctx context.Context, sessionKey string) error
|
||||
}
|
||||
|
||||
// AssembleRequest is the input to Assemble.
|
||||
|
||||
@@ -690,6 +690,7 @@ func (m *noopContextManager) Assemble(_ context.Context, req *AssembleRequest) (
|
||||
}
|
||||
func (m *noopContextManager) Compact(_ context.Context, _ *CompactRequest) error { return nil }
|
||||
func (m *noopContextManager) Ingest(_ context.Context, _ *IngestRequest) error { return nil }
|
||||
func (m *noopContextManager) Clear(_ context.Context, _ string) error { return nil }
|
||||
|
||||
// trackingContextManager tracks call counts for each method.
|
||||
type trackingContextManager struct {
|
||||
@@ -726,6 +727,8 @@ func (m *trackingContextManager) Ingest(_ context.Context, req *IngestRequest) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *trackingContextManager) Clear(_ context.Context, _ string) error { return nil }
|
||||
|
||||
// resetCMRegistry clears the global factory registry and returns a cleanup
|
||||
// function that restores the original state after the test.
|
||||
func resetCMRegistry() func() {
|
||||
|
||||
@@ -154,6 +154,19 @@ func (m *seahorseContextManager) Ingest(ctx context.Context, req *IngestRequest)
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear removes all stored context for a session (seahorse DB + JSONL).
|
||||
func (m *seahorseContextManager) Clear(ctx context.Context, sessionKey string) error {
|
||||
if err := m.engine.ClearSession(ctx, sessionKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if m.sessions != nil {
|
||||
m.sessions.SetHistory(sessionKey, []providers.Message{})
|
||||
m.sessions.SetSummary(sessionKey, "")
|
||||
return m.sessions.Save(sessionKey)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// bootstrapSession reconciles JSONL session history into seahorse SQLite.
|
||||
func (m *seahorseContextManager) bootstrapSession(ctx context.Context, sessionKey string) {
|
||||
if m.sessions == nil {
|
||||
|
||||
+7
-10
@@ -3368,7 +3368,7 @@ func (al *AgentLoop) handleCommand(
|
||||
return "", false
|
||||
}
|
||||
|
||||
rt := al.buildCommandsRuntime(agent, opts)
|
||||
rt := al.buildCommandsRuntime(ctx, agent, opts)
|
||||
executor := commands.NewExecutor(al.cmdRegistry, rt)
|
||||
|
||||
var commandReply string
|
||||
@@ -3488,7 +3488,11 @@ func (al *AgentLoop) applyExplicitSkillCommand(
|
||||
return true, false, ""
|
||||
}
|
||||
|
||||
func (al *AgentLoop) buildCommandsRuntime(agent *AgentInstance, opts *processOptions) *commands.Runtime {
|
||||
func (al *AgentLoop) buildCommandsRuntime(
|
||||
ctx context.Context,
|
||||
agent *AgentInstance,
|
||||
opts *processOptions,
|
||||
) *commands.Runtime {
|
||||
registry := al.GetRegistry()
|
||||
cfg := al.GetConfig()
|
||||
rt := &commands.Runtime{
|
||||
@@ -3570,14 +3574,7 @@ func (al *AgentLoop) buildCommandsRuntime(agent *AgentInstance, opts *processOpt
|
||||
if opts == nil {
|
||||
return fmt.Errorf("process options not available")
|
||||
}
|
||||
if agent.Sessions == nil {
|
||||
return fmt.Errorf("sessions not initialized for agent")
|
||||
}
|
||||
|
||||
agent.Sessions.SetHistory(opts.SessionKey, make([]providers.Message, 0))
|
||||
agent.Sessions.SetSummary(opts.SessionKey, "")
|
||||
agent.Sessions.Save(opts.SessionKey)
|
||||
return nil
|
||||
return al.contextManager.Clear(ctx, opts.SessionKey)
|
||||
}
|
||||
}
|
||||
return rt
|
||||
|
||||
Reference in New Issue
Block a user