turbo-editors/turbo-corepublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

agent_files.go · 71 lines · 2.4 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 20h ago1// The project's files as an agent window offers them: what "@" lists in the
2// box, and what a mention is resolved against when a prompt is sent.
3
4package app
5
6import (
7 "io/fs"
8 "path/filepath"
9
📦 Turbo Core f3ade8d k33g 12h ago10 "rickub.com/turbo-editors/turbo-core/acp"
🛟 Updated. 28d5985 k33g 20h ago11)
12
13// projectFileLimit caps how many files an agent window is offered.
14//
15// Past this the picker is a list to scroll rather than a list to choose from,
16// and a walk of a monorepo on every "@" would make the box stutter. Typing one
17// more letter after the "@" is the answer for a project this size, exactly as
18// it is for the Open File dialog.
19const projectFileLimit = 5000
20
21// projectFiles lists the project for the agent windows.
22//
23// It walks on each call rather than caching: the picker asks once when "@" is
24// typed and keeps the answer while it is open, and a list that never noticed a
25// file the agent just created would be wrong at the moment it mattered.
26func (a *App) projectFiles() []acp.Mention {
27 return listProjectFiles(a.projectRoot(), projectFileLimit)
28}
29
30// listProjectFiles walks root and returns its regular files, relative to root
31// with forward slashes, in the order the walk finds them. The .git directory
32// is skipped for the reason the file tree skips it: nothing in it is meant to
33// be read by hand, and it is large enough to bury everything else. The walk
34// stops at limit files.
35//
36// listProjectFiles("/src/p", 5000) // [{app/menus.go /src/p/app/menus.go} …]
37func listProjectFiles(root string, limit int) []acp.Mention {
38 var out []acp.Mention
39 _ = filepath.WalkDir(root, func(path string, entry fs.DirEntry, err error) error {
40 if err != nil || entry.IsDir() {
41 return skipGit(entry, err)
42 }
43 if entry.Type().IsRegular() {
44 out = appendFile(out, root, path)
45 }
46 if len(out) >= limit {
47 return filepath.SkipAll
48 }
49 return nil
50 })
51 return out
52}
53
54// skipGit tells the walk to leave .git alone, and to carry on past a directory
55// it could not read rather than stop the whole listing for it.
56func skipGit(entry fs.DirEntry, err error) error {
57 if err == nil && entry.Name() == ".git" {
58 return filepath.SkipDir
59 }
60 return nil
61}
62
63// appendFile adds one file to the list, named relative to the project with
64// forward slashes whatever the platform, because that is how it is typed.
65func appendFile(files []acp.Mention, root, path string) []acp.Mention {
66 relative, err := filepath.Rel(root, path)
67 if err != nil {
68 return files
69 }
70 return append(files, acp.Mention{Name: filepath.ToSlash(relative), Path: path})
71}