mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-06-10 06:10:46 +00:00
39bb90bd60
- Remove auto-add logic that granted file_writer permission to the first group/guild member who chatted with the bot - Add ConfigTypeFileWriter and ConfigTypeHeartbeat constants, replace all hardcoded config_type strings across callers - Add bootstrap exception: /addwriter and !addwriter allow first writer to be added when no writers exist yet - Optimize writer commands: reuse cached ListFileWriters result for both permission check and last-writer guard, reducing DB queries per command - Add freshness directive to file writer system prompt so bot prioritizes current list over stale references in conversation history
67 lines
2.7 KiB
Go
67 lines
2.7 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/agent"
|
|
"github.com/nextlevelbuilder/goclaw/internal/bootstrap"
|
|
"github.com/nextlevelbuilder/goclaw/internal/store"
|
|
"github.com/nextlevelbuilder/goclaw/internal/tools"
|
|
)
|
|
|
|
// buildEnsureUserProfile creates the user profile resolution callback.
|
|
// Creates/resolves user profile and returns effective workspace.
|
|
// Separated from seeding to allow independent lifecycle management.
|
|
func buildEnsureUserProfile(as store.AgentStore) agent.EnsureUserProfileFunc {
|
|
return func(ctx context.Context, agentID uuid.UUID, userID, workspace, channel string) (string, bool, error) {
|
|
isNew, effectiveWs, err := as.GetOrCreateUserProfile(ctx, agentID, userID, workspace, channel)
|
|
if err != nil {
|
|
return effectiveWs, false, err
|
|
}
|
|
|
|
return effectiveWs, isNew, nil
|
|
}
|
|
}
|
|
|
|
// buildSeedUserFiles creates the context file seeding callback.
|
|
// Seeds BOOTSTRAP.md, USER.md, etc. into user_context_files.
|
|
// isNew=true seeds all files; isNew=false only seeds if user has zero files
|
|
// (avoids re-seeding BOOTSTRAP.md after auto-cleanup on server restart).
|
|
func buildSeedUserFiles(as store.AgentStore) agent.SeedUserFilesFunc {
|
|
return func(ctx context.Context, agentID uuid.UUID, userID, agentType string, isNew bool) error {
|
|
_, err := bootstrap.SeedUserFiles(ctx, as, agentID, userID, agentType, !isNew)
|
|
return err
|
|
}
|
|
}
|
|
|
|
// buildBootstrapCleanup creates a callback that removes BOOTSTRAP.md for a user.
|
|
// Used as a safety net after enough conversation turns, in case the LLM
|
|
// didn't clear BOOTSTRAP.md itself. Idempotent — no-op if already cleared.
|
|
func buildBootstrapCleanup(as store.AgentStore) agent.BootstrapCleanupFunc {
|
|
return func(ctx context.Context, agentID uuid.UUID, userID string) error {
|
|
return as.DeleteUserContextFile(ctx, agentID, userID, bootstrap.BootstrapFile)
|
|
}
|
|
}
|
|
|
|
// buildCacheInvalidate creates a callback that invalidates the context file cache
|
|
// for a user after SeedUserFiles writes via raw agentStore. Without this,
|
|
// LoadContextFiles may return stale (empty) cached results on the first turn.
|
|
func buildCacheInvalidate(intc *tools.ContextFileInterceptor) agent.CacheInvalidateFunc {
|
|
if intc == nil {
|
|
return nil
|
|
}
|
|
return func(agentID uuid.UUID, userID string) {
|
|
intc.InvalidateUser(agentID, userID)
|
|
}
|
|
}
|
|
|
|
// buildContextFileLoader creates the per-request context file loader callback.
|
|
// Delegates to the ContextFileInterceptor for type-aware routing.
|
|
func buildContextFileLoader(intc *tools.ContextFileInterceptor) agent.ContextFileLoaderFunc {
|
|
return func(ctx context.Context, agentID uuid.UUID, userID, agentType string) []bootstrap.ContextFile {
|
|
return intc.LoadContextFiles(ctx, agentID, userID, agentType)
|
|
}
|
|
}
|