74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
// SPDX-Licence-Identifier: EUPL-1.2
|
|
package session
|
|
|
|
import (
|
|
"iter"
|
|
"path"
|
|
"slices"
|
|
"time"
|
|
|
|
core "dappco.re/go/core"
|
|
)
|
|
|
|
// SearchResult represents a match found in a session transcript.
|
|
//
|
|
// Example:
|
|
// result := session.SearchResult{SessionID: "abc123", Tool: "Bash"}
|
|
type SearchResult struct {
|
|
SessionID string
|
|
Timestamp time.Time
|
|
Tool string
|
|
Match string
|
|
}
|
|
|
|
// Search finds events matching the query across all sessions in the directory.
|
|
//
|
|
// Example:
|
|
// results, err := session.Search("/tmp/projects", "go test")
|
|
func Search(projectsDir, query string) ([]SearchResult, error) {
|
|
return slices.Collect(SearchSeq(projectsDir, query)), nil
|
|
}
|
|
|
|
// SearchSeq returns an iterator over search results matching the query across all sessions.
|
|
//
|
|
// Example:
|
|
//
|
|
// for result := range session.SearchSeq("/tmp/projects", "go test") {
|
|
// _ = result
|
|
// }
|
|
func SearchSeq(projectsDir, query string) iter.Seq[SearchResult] {
|
|
return func(yield func(SearchResult) bool) {
|
|
matches := core.PathGlob(path.Join(projectsDir, "*.jsonl"))
|
|
|
|
query = core.Lower(query)
|
|
|
|
for _, filePath := range matches {
|
|
sess, _, err := ParseTranscript(filePath)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for evt := range sess.EventsSeq() {
|
|
if evt.Type != "tool_use" {
|
|
continue
|
|
}
|
|
text := core.Lower(core.Concat(evt.Input, " ", evt.Output))
|
|
if core.Contains(text, query) {
|
|
matchCtx := evt.Input
|
|
if matchCtx == "" {
|
|
matchCtx = truncate(evt.Output, 120)
|
|
}
|
|
res := SearchResult{
|
|
SessionID: sess.ID,
|
|
Timestamp: evt.Timestamp,
|
|
Tool: evt.Tool,
|
|
Match: matchCtx,
|
|
}
|
|
if !yield(res) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|