Setting the file. One moment.
Repo Root · Vercel Optimize · vercel-labs/agent-skills · Skills Docs
ContentsBack to the top of the page lib/ repo-root.mjs
JavaScript · 86 lines · 3 KB
[])) {
10 if (r?.abstain) continue ;
11 const af = Array. isArray (r?.affectedFiles) ? r.affectedFiles[ 0 ] : null ;
12 if ( typeof af === 'string' && af. length > 0 ) return af;
13 const ref = Array. isArray (r?.findingRefs) ? r.findingRefs[ 0 ] : null ;
14 if ( typeof ref === 'string' && ref. length > 0 ) {
15 const m = ref. match ( / ^ ( . +? ): \d +$ / );
16 if (m) return m[ 1 ];
17 }
18 }
19 return null ;
20 }
21
22 export async function fileResolvesAt ( root , file ) {
23 try {
24 await access ( join (root, file));
25 return true ;
26 } catch {
27 return false ;
28 }
29 }
30
31 export async function detectRepoRoot ( probeFile , startDir , maxDepth = 10 ) {
32 let dir = resolve (startDir);
33 for ( let depth = 0 ; depth < maxDepth; depth ++ ) {
34 if ( await fileResolvesAt (dir, probeFile)) return dir;
35 const parent = dirname (dir);
36 if (parent === dir) return null ;
37 dir = parent;
38 }
39 return null ;
40 }
41
42 // rootDirectory "apps/fixture-site" + cwd .../monorepo/apps/fixture-site → repo root .../monorepo.
43 export function deriveRootFromSignals ( signals , cwd = process. cwd ()) {
44 const dir = signals?.project?.rootDirectory;
45 if ( ! dir || typeof dir !== 'string' ) return null ;
46 const offset = normalize (dir). replace ( / ^ \.\/ ? / , '' ). replace ( / \/ $ / , '' );
47 if ( ! offset) return null ;
48 const cwdAbs = resolve (cwd);
49 // Match `<root>/<offset>` OR `<root>/<offset>/<more>` — orchestrator may run from a subdir.
50 const parts = cwdAbs. split ( '/' );
51 const offsetParts = offset. split ( '/' );
52 for ( let start = parts. length - offsetParts. length ; start >= 0 ; start -- ) {
53 const slice = parts. slice (start, start + offsetParts. length ). join ( '/' );
54 if (slice === offset) {
55 const root = parts. slice ( 0 , start). join ( '/' );
56 return root || '/' ;
57 }
58 }
59 return null ;
60 }
61
62 export async function resolveRepoRoot ( recs , suppliedRoot , cwd = process. cwd (), signals = null ) {
63 if (signals) {
64 const apiRoot = deriveRootFromSignals (signals, cwd);
65 if (apiRoot) {
66 return { root: apiRoot, source: 'api' , probe: null , apiOffset: signals?.project?.rootDirectory ?? null };
67 }
68 }
69
70 const probe = pickProbeFile (recs);
71 if ( ! probe) {
72 return { root: suppliedRoot ?? '.' , source: suppliedRoot ? 'supplied' : 'default' , probe: null };
73 }
74 if (suppliedRoot && await fileResolvesAt (suppliedRoot, probe)) {
75 return { root: suppliedRoot, source: 'supplied' , probe };
76 }
77 const detected = await detectRepoRoot (probe, suppliedRoot ?? cwd);
78 if (detected) {
79 return {
80 root: detected,
81 source: suppliedRoot ? 'corrected' : 'auto-detected' ,
82 probe,
83 };
84 }
85 return { root: suppliedRoot ?? '.' , source: suppliedRoot ? 'supplied' : 'default' , probe };
86 }