|
15 | 15 |
|
16 | 16 | (def ^:private logger-tag "[CONTEXT]") |
17 | 17 |
|
| 18 | +(defn ^:private extract-at-mentions |
| 19 | + "Extract all @path mentions from content. Supports relative and absolute paths with any extension." |
| 20 | + [content] |
| 21 | + (let [pattern #"@([^\s\)]+\.\w+)" |
| 22 | + matches (re-seq pattern content)] |
| 23 | + (map second matches))) |
| 24 | + |
| 25 | +(defn ^:private parse-agents-file |
| 26 | + ([path] (parse-agents-file path #{})) |
| 27 | + ([path visited] |
| 28 | + (if (contains? visited path) |
| 29 | + [] |
| 30 | + (let [root-content (llm-api/refine-file-context path nil) |
| 31 | + visited' (conj visited path) |
| 32 | + at-mentions (extract-at-mentions root-content) |
| 33 | + parent-dir (str (fs/parent path)) |
| 34 | + resolved-paths (map (fn [mention] |
| 35 | + (cond |
| 36 | + ;; Absolute path |
| 37 | + (string/starts-with? mention "/") |
| 38 | + mention |
| 39 | + |
| 40 | + ;; Relative path (./... or ../...) |
| 41 | + (or (string/starts-with? mention "./") |
| 42 | + (string/starts-with? mention "../")) |
| 43 | + (str (fs/canonicalize (fs/file parent-dir mention))) |
| 44 | + |
| 45 | + ;; Simple filename, relative to current file's directory |
| 46 | + :else |
| 47 | + (str (fs/canonicalize (fs/file parent-dir mention))))) |
| 48 | + at-mentions) |
| 49 | + ;; Deduplicate resolved paths |
| 50 | + unique-paths (distinct resolved-paths) |
| 51 | + ;; Recursively parse all mentioned files |
| 52 | + nested-results (mapcat #(parse-agents-file % visited') unique-paths)] |
| 53 | + (concat [{:type :agents-file |
| 54 | + :path path |
| 55 | + :content root-content}] |
| 56 | + nested-results))))) |
| 57 | + |
18 | 58 | (defn ^:private agents-file-contexts |
19 | | - "Search for AGENTS.md file both in workspaceRoot and global config dir." |
20 | | - [db _config] |
| 59 | + "Search for AGENTS.md file both in workspaceRoot and global config dir. |
| 60 | + Process any found @paths mentions recursively, supporting both relative and absolute paths. |
| 61 | + Deduplicates files to avoid reading the same file multiple times." |
| 62 | + [db] |
21 | 63 | ;; TODO make it customizable by behavior |
22 | 64 | (let [agent-file "AGENTS.md" |
23 | 65 | local-agent-files (keep (fn [{:keys [uri]}] |
|
28 | 70 | global-agent-file (let [agent-file (fs/path (config/global-config-dir) agent-file)] |
29 | 71 | (when (fs/readable? agent-file) |
30 | 72 | (fs/canonicalize agent-file)))] |
31 | | - (mapv (fn [path] |
32 | | - {:type :file |
33 | | - :path (str path) |
34 | | - :partial false |
35 | | - :content (llm-api/refine-file-context (str path) nil)}) |
36 | | - (concat local-agent-files |
37 | | - (when global-agent-file [global-agent-file]))))) |
| 73 | + (->> (concat local-agent-files |
| 74 | + (when global-agent-file [global-agent-file])) |
| 75 | + (mapcat #(parse-agents-file (str %)))))) |
38 | 76 |
|
39 | 77 | (defn ^:private file->refined-context [path lines-range] |
40 | 78 | (let [ext (string/lower-case (fs/extension path))] |
|
52 | 90 | :content (llm-api/refine-file-context path lines-range)} |
53 | 91 | :partial lines-range)))) |
54 | 92 |
|
55 | | -(defn raw-contexts->refined [contexts db config] |
56 | | - (concat (agents-file-contexts db config) |
| 93 | +(defn raw-contexts->refined [contexts db] |
| 94 | + (concat (agents-file-contexts db) |
57 | 95 | (mapcat (fn [{:keys [type path lines-range position uri]}] |
58 | 96 | (case (name type) |
59 | 97 | "file" [(file->refined-context path lines-range)] |
|
0 commit comments