feat(team): share leader memory with team members (read-only)

Team members dispatched via team tasks can now read the leader's memory
files (MEMORY.md, memory/*.md) as a fallback when they have no own
memory. Memory writes are blocked for members — only the leader can
save memory files. This follows the existing team_workspace context
propagation pattern: dispatch metadata → RunRequest → context → tools.

Affected tools: read_file (interceptor), memory_get, memory_search,
list_files (interceptor). All include leader fallback with per-user →
global scope cascade.
This commit is contained in:
viettranx committed 2026-03-27 22:45:40 +07:00
1 parent e9342533e0
commit ee9f5b8aaf
10 files changed
+523 -7

No files matched your search

+23 -4
View File
@@ -98,10 +98,19 @@ func (t *MemorySearchTool) Execute(ctx context.Context, args map[string]any) *Re
searchOpts.MinScore = mc.MinScore
}
}
results, err := t.memStore.Search(ctx, query, agentID.String(), userID, searchOpts)
agentStr := agentID.String()
results, err := t.memStore.Search(ctx, query, agentStr, userID, searchOpts)
if err != nil {
return ErrorResult(fmt.Sprintf("memory search failed: %v", err))
}
// Fallback: also search leader's memory for team members and merge results.
if leaderID := LeaderAgentIDFromCtx(ctx); leaderID != "" && leaderID != agentStr {
leaderResults, lerr := t.memStore.Search(ctx, query, leaderID, userID, searchOpts)
if lerr != nil && userID != "" {
leaderResults, _ = t.memStore.Search(ctx, query, leaderID, "", searchOpts)
}
results = append(results, leaderResults...)
}
if len(results) == 0 {
return NewResult("No memory results found for query: " + query)
}
@@ -179,11 +188,21 @@ func (t *MemoryGetTool) Execute(ctx context.Context, args map[string]any) *Resul
userID := store.MemoryUserID(ctx)
agentStr := agentID.String()
// Try per-user first, then global
content, err := t.memStore.GetDocument(ctx, agentID.String(), userID, path)
content, err := t.memStore.GetDocument(ctx, agentStr, userID, path)
if err != nil && userID != "" {
// Fallback to global
content, err = t.memStore.GetDocument(ctx, agentID.String(), "", path)
content, err = t.memStore.GetDocument(ctx, agentStr, "", path)
}
// Fallback: try leader's memory for team members.
if err != nil {
if leaderID := LeaderAgentIDFromCtx(ctx); leaderID != "" && leaderID != agentStr {
content, err = t.memStore.GetDocument(ctx, leaderID, userID, path)
if err != nil && userID != "" {
content, err = t.memStore.GetDocument(ctx, leaderID, "", path)
}
}
}
if err != nil {
return ErrorResult(fmt.Sprintf("failed to read %s: %v", path, err))