mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-14 22:17:36 +00:00
fix(context): share agent scoped context data
This commit is contained in:
1 parent
536ab4ac6c
commit
2fa715ba4e
5 files changed
+84
-6
No files matched your search
@@ -156,6 +156,9 @@ func (l *Loop) injectContext(ctx context.Context, req *RunRequest) (contextSetup
|
||||
}
|
||||
// Apply user isolation layer via pipeline.
|
||||
shared := l.shouldShareWorkspace(req.UserID, req.PeerKind)
|
||||
if shared {
|
||||
ctx = store.WithSharedContext(ctx)
|
||||
}
|
||||
effectiveWorkspace := tools.ResolveWorkspace(ws,
|
||||
tools.UserChatLayer(tools.SanitizePathSegment(req.UserID), shared),
|
||||
)
|
||||
@@ -359,6 +362,7 @@ func (l *Loop) injectContext(ctx context.Context, req *RunRequest) (contextSetup
|
||||
SharedMemory: store.IsSharedMemory(ctx),
|
||||
SharedKG: store.IsSharedKG(ctx),
|
||||
SharedSessions: store.IsSharedSessions(ctx),
|
||||
SharedContext: store.IsSharedContext(ctx),
|
||||
RestrictToWorkspace: l.restrictToWs != nil && *l.restrictToWs,
|
||||
BuiltinToolSettings: l.builtinToolSettings,
|
||||
ChannelType: req.ChannelType,
|
||||
|
||||
@@ -31,6 +31,8 @@ const (
|
||||
SharedKGKey contextKey = "goclaw_shared_kg"
|
||||
// SharedSessionsKey indicates sessions should be shared across all users (no per-group scoping).
|
||||
SharedSessionsKey contextKey = "goclaw_shared_sessions"
|
||||
// SharedContextKey indicates context files should be read/written at agent scope.
|
||||
SharedContextKey contextKey = "goclaw_shared_context"
|
||||
// ShellDenyGroupsKey holds per-agent shell deny group overrides.
|
||||
ShellDenyGroupsKey contextKey = "goclaw_shell_deny_groups"
|
||||
// AgentKeyKey is the context key for the agent key/name (string identifier, e.g. "default").
|
||||
@@ -282,6 +284,32 @@ func MemoryUserID(ctx context.Context) string {
|
||||
return UserIDFromContext(ctx)
|
||||
}
|
||||
|
||||
// WithSharedContext returns a context flagged for shared context files.
|
||||
func WithSharedContext(ctx context.Context) context.Context {
|
||||
return context.WithValue(ctx, SharedContextKey, true)
|
||||
}
|
||||
|
||||
// IsSharedContext returns true if context files should use agent-level scope.
|
||||
func IsSharedContext(ctx context.Context) bool {
|
||||
if v, ok := ctx.Value(SharedContextKey).(bool); ok {
|
||||
return v
|
||||
}
|
||||
if rc := RunContextFromCtx(ctx); rc != nil {
|
||||
return rc.SharedContext
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContextUserID returns the userID to use for context-file operations.
|
||||
// Shared workspace mode maps virtual context files to the agent-level store so
|
||||
// read_file/write_file behavior matches the visible shared workspace path.
|
||||
func ContextUserID(ctx context.Context) string {
|
||||
if IsSharedContext(ctx) {
|
||||
return ""
|
||||
}
|
||||
return UserIDFromContext(ctx)
|
||||
}
|
||||
|
||||
// KGUserID returns the userID to use for knowledge graph operations.
|
||||
// Returns "" (agent-level scope) when shared KG is active, otherwise the per-user ID.
|
||||
func KGUserID(ctx context.Context) string {
|
||||
|
||||
@@ -34,6 +34,7 @@ type RunContext struct {
|
||||
SharedMemory bool
|
||||
SharedKG bool
|
||||
SharedSessions bool
|
||||
SharedContext bool
|
||||
RestrictToWorkspace bool
|
||||
|
||||
// Tool configuration
|
||||
@@ -52,7 +53,7 @@ type RunContext struct {
|
||||
TeamID string
|
||||
WorkspaceChannel string
|
||||
WorkspaceChatID string
|
||||
TeamIsolated bool // true when team.workspace_scope != "shared" — drives chat_id filtering in vault search
|
||||
TeamIsolated bool // true when team.workspace_scope != "shared" — drives chat_id filtering in vault search
|
||||
TeamTaskID string
|
||||
DelegationID string // delegation identifier for vault auto-linking (empty when not in delegation)
|
||||
LeaderAgentID string // leader's agent UUID for member memory read fallback
|
||||
|
||||
@@ -20,7 +20,15 @@ func (s *SQLiteMemoryStore) GetDocument(ctx context.Context, agentID, userID, pa
|
||||
var content string
|
||||
var err error
|
||||
|
||||
if userID == "" {
|
||||
if store.IsSharedMemory(ctx) {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return "", tcErr
|
||||
}
|
||||
err = s.db.QueryRowContext(ctx,
|
||||
"SELECT content FROM memory_documents WHERE agent_id = ? AND path = ?"+tc+" ORDER BY updated_at DESC LIMIT 1",
|
||||
append([]any{aid, path}, tcArgs...)...).Scan(&content)
|
||||
} else if userID == "" {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return "", tcErr
|
||||
@@ -69,7 +77,15 @@ func (s *SQLiteMemoryStore) DeleteDocument(ctx context.Context, agentID, userID,
|
||||
var res sql.Result
|
||||
var err error
|
||||
|
||||
if userID == "" {
|
||||
if store.IsSharedMemory(ctx) {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return tcErr
|
||||
}
|
||||
res, err = s.db.ExecContext(ctx,
|
||||
"DELETE FROM memory_documents WHERE agent_id = ? AND path = ?"+tc,
|
||||
append([]any{agentID, path}, tcArgs...)...)
|
||||
} else if userID == "" {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return tcErr
|
||||
@@ -100,7 +116,15 @@ func (s *SQLiteMemoryStore) ListDocuments(ctx context.Context, agentID, userID s
|
||||
var rows *sql.Rows
|
||||
var err error
|
||||
|
||||
if userID == "" {
|
||||
if store.IsSharedMemory(ctx) {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return nil, tcErr
|
||||
}
|
||||
rows, err = s.db.QueryContext(ctx,
|
||||
"SELECT path, hash, user_id, updated_at FROM memory_documents WHERE agent_id = ?"+tc,
|
||||
append([]any{agentID}, tcArgs...)...)
|
||||
} else if userID == "" {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return nil, tcErr
|
||||
@@ -147,7 +171,15 @@ func (s *SQLiteMemoryStore) IndexDocument(ctx context.Context, agentID, userID,
|
||||
|
||||
// Get document ID
|
||||
var docID string
|
||||
if userID == "" {
|
||||
if store.IsSharedMemory(ctx) {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return tcErr
|
||||
}
|
||||
err = s.db.QueryRowContext(ctx,
|
||||
"SELECT id FROM memory_documents WHERE agent_id = ? AND path = ?"+tc+" ORDER BY updated_at DESC LIMIT 1",
|
||||
append([]any{agentID, path}, tcArgs...)...).Scan(&docID)
|
||||
} else if userID == "" {
|
||||
tc, tcArgs, tcErr := scopeClause(ctx)
|
||||
if tcErr != nil {
|
||||
return tcErr
|
||||
|
||||
@@ -48,7 +48,20 @@ func (s *SQLiteMemoryStore) likeSearch(ctx context.Context, query, agentID, user
|
||||
var q string
|
||||
var args []any
|
||||
|
||||
if userID != "" {
|
||||
if store.IsSharedMemory(ctx) {
|
||||
tc, tcArgs, err := scopeClause(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = `SELECT path, start_line, end_line, text, user_id
|
||||
FROM memory_chunks
|
||||
WHERE agent_id = ?
|
||||
AND text LIKE ? ESCAPE '\'` + tc + `
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT ?`
|
||||
args = append([]any{agentID, pattern}, tcArgs...)
|
||||
args = append(args, limit)
|
||||
} else if userID != "" {
|
||||
tc, tcArgs, err := scopeClause(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in new issue
Block a user