Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions internal/parser/directory_jsonl_source_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package parser

import (
"path/filepath"
"strings"
)

// DirectoryJSONLSourceSet constrains JSONL sources to the common
// <root>/<project>/<session>.<ext> shape while keeping JSONLSourceSet's source
// methods available through embedding.
type DirectoryJSONLSourceSet struct {
JSONLSourceSet
}

// newDirectoryJSONLSourceSet returns a JSONL source helper for providers whose
// transcripts live one project directory below each configured root. The
// returned helper is always recursive enough to classify watched project files,
// but it rejects root-level and deeper nested files through IncludePath.
func newDirectoryJSONLSourceSet(
provider AgentType,
roots []string,
opts ...jsonlOption,
) DirectoryJSONLSourceSet {
var options JSONLSourceSetOptions
for _, opt := range opts {
opt(&options)
}
userIncludePath := options.IncludePath
options.Recursive = true
options.IncludePath = func(root, path string) bool {
if !isDirectoryJSONLPath(root, path) {
return false
}
return userIncludePath == nil || userIncludePath(root, path)
}
if options.ProjectHint == nil {
options.ProjectHint = func(root, path string) string {
return directoryJSONLProjectFromPath(path)
}
}
return DirectoryJSONLSourceSet{
JSONLSourceSet: jsonlSourceSetFromOptions(provider, roots, options),
}
}

func isDirectoryJSONLPath(root, path string) bool {
rel, err := filepath.Rel(root, path)
if err != nil {
return false
}
parts := strings.Split(rel, string(filepath.Separator))
return len(parts) == 2 &&
parts[0] != "" && parts[0] != "." && parts[0] != ".." &&
parts[1] != "" && parts[1] != "." && parts[1] != ".."
}

func directoryJSONLProjectFromPath(path string) string {
return filepath.Base(filepath.Dir(path))
}
15 changes: 15 additions & 0 deletions internal/parser/file_identity_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//go:build unix

package parser

import (
"os"
"syscall"
)

func sourceFileIdentity(info os.FileInfo) (inode, device uint64) {
if stat, ok := info.Sys().(*syscall.Stat_t); ok {
return uint64(stat.Ino), uint64(stat.Dev)
}
return 0, 0
}
9 changes: 9 additions & 0 deletions internal/parser/file_identity_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build windows

package parser

import "os"

func sourceFileIdentity(info os.FileInfo) (inode, device uint64) {
return 0, 0
}
Loading