Skip to content

Commit 06ce767

Browse files
committed
fix(codebuff): shallow watching and CWD filter for Freebuff
1. Shallow watching: Changed codebuffWatchRoots to enumerate project directories and emit shallow watches on <root>/*/chats/ instead of recursive watches on <root>/. Reduces inotify usage from O(N*M) to O(N) where N=projects and M=sessions. 2. CWD filter: Made skippedSourceAllowsCwdFilter query both AgentCodebuff and AgentFreebuff so CWD filtering works for sources containing only Freebuff sessions.
1 parent 58a01a2 commit 06ce767

2 files changed

Lines changed: 47 additions & 18 deletions

File tree

internal/parser/codebuff_provider.go

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,43 @@ func (s codebuffSourceSet) Parse(
6363
return outcome, err
6464
}
6565

66-
// codebuffWatchRoots creates watch plans for recursive watching of
67-
// each root. Since sessions are two levels deep under chats/, we need
68-
// recursive watching.
66+
// codebuffWatchRoots creates shallow watch plans at the chats/ directory
67+
// level for each project under each root. The on-disk layout is
68+
// <root>/<project>/chats/<timestamp>/. Watching each <root>/*/chats/
69+
// directory with Recursive: false creates one watch per project instead
70+
// of one per session, reducing inotify usage from O(N*M) to O(N).
6971
func codebuffWatchRoots(roots []string) []WatchRoot {
70-
out := make([]WatchRoot, 0, len(roots))
72+
var out []WatchRoot
7173
for _, root := range roots {
72-
out = append(out, WatchRoot{
73-
Path: root,
74-
Recursive: true,
75-
IncludeGlobs: []string{"chat-messages.json", "run-state.json", "chat-meta.json"},
76-
DebounceKey: "codebuff:sessions:" + root,
77-
})
74+
projects, err := os.ReadDir(root)
75+
if err != nil {
76+
continue
77+
}
78+
for _, project := range projects {
79+
if !project.IsDir() {
80+
continue
81+
}
82+
chatsDir := filepath.Join(root, project.Name(), "chats")
83+
if !IsDir(chatsDir) {
84+
continue
85+
}
86+
out = append(out, WatchRoot{
87+
Path: chatsDir,
88+
Recursive: false,
89+
IncludeGlobs: []string{"chat-messages.json", "run-state.json", "chat-meta.json"},
90+
DebounceKey: "codebuff:sessions:" + chatsDir,
91+
})
92+
}
7893
}
7994
return out
8095
}
8196

97+
// IsDir reports whether path names an existing directory.
98+
func IsDir(path string) bool {
99+
info, err := os.Stat(path)
100+
return err == nil && info.IsDir()
101+
}
102+
82103
// codebuffClassifyPath maps a changed path back to its source
83104
// chat-messages.json. Paths are shaped like:
84105
// <root>/<project>/chats/<timestamp>/chat-messages.json

internal/sync/engine.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6545,17 +6545,25 @@ func (e *Engine) skippedSourceAllowsCwdFilter(
65456545
return true, nil
65466546
}
65476547
path := e.effectiveSourcePath(job.path)
6548-
ids, err := e.db.ListSessionIDsByFilePath(path, string(job.agent))
6549-
if err != nil {
6550-
return false, err
6551-
}
6552-
for _, id := range ids {
6553-
session, err := e.db.GetSession(ctx, id)
6548+
// Freebuff shares the Codebuff provider. Query both agent types
6549+
// so CWD filtering works for sources containing only Freebuff sessions.
6550+
agentsToQuery := []string{string(job.agent)}
6551+
if job.agent == parser.AgentCodebuff {
6552+
agentsToQuery = append(agentsToQuery, string(parser.AgentFreebuff))
6553+
}
6554+
for _, agentStr := range agentsToQuery {
6555+
ids, err := e.db.ListSessionIDsByFilePath(path, agentStr)
65546556
if err != nil {
65556557
return false, err
65566558
}
6557-
if session != nil && !e.cwdFilter.allows(session.Cwd) {
6558-
return false, nil
6559+
for _, id := range ids {
6560+
session, err := e.db.GetSession(ctx, id)
6561+
if err != nil {
6562+
return false, err
6563+
}
6564+
if session != nil && !e.cwdFilter.allows(session.Cwd) {
6565+
return false, nil
6566+
}
65596567
}
65606568
}
65616569
return true, nil

0 commit comments

Comments
 (0)