Setting the file. One moment.
Dedup Recs · Vercel Optimize · vercel-labs/agent-skills · Skills Docs
ContentsBack to the top of the page This file
Number 7.83
Position 83 of 155
Type JavaScript
Size 10 KB
Lines 325 lib/ dedup-recs.mjs
JavaScript · 325 lines · 10 KB
9 const order = [];
10 for ( const rec of recommendations) {
11 if ( ! rec || typeof rec !== 'object' || rec.abstain === true ) {
12 order. push (rec);
13 continue ;
14 }
15
16 const key = recommendationKey (rec);
17 if ( ! byKey. has (key)) {
18 const normalized = withDedupMetadata (rec);
19 byKey. set (key, normalized);
20 order. push ({ __dedupKey: key });
21 continue ;
22 }
23
24 const current = byKey. get (key);
25 const merged = mergeDuplicateRecs (current, rec);
26 byKey. set (key, merged);
27 }
28
29 return order. map (( entry ) => entry?.__dedupKey ? byKey. get (entry.__dedupKey) : entry);
30 }
31
32 export function recommendationKey ( rec ) {
33 const intent = dedupIntent (rec);
34 const bucket = intent === 'cache-control:s-maxage'
35 ? NO_VALUE
36 : String (rec?.bucket ?? NO_VALUE );
37 return JSON . stringify ([
38 bucket,
39 dedupEditTarget (rec),
40 primarySkillRule (rec),
41 intent,
42 ]);
43 }
44
45 export function normalizePath ( path ) {
46 if ( typeof path !== 'string' || path. trim () === '' ) return NO_VALUE ;
47 return path
48 . trim ()
49 . replace ( / \\ / g , '/' )
50 . replace ( / ^ \.\/ / , '' )
51 . replace ( / \/ + / g , '/' )
52 . replace ( /:( \d + )(?:: \d + ) ?$ / , '' );
53 }
54
55 export function primarySkillRule ( rec ) {
56 const citations = Array. isArray (rec?.citations) ? rec.citations : [];
57 return citations. find (( c ) => typeof c === 'string' && / ^ [A-Za-z][\w-] * : [A-Za-z][\w-] *$ / . test (c)) ?? NO_VALUE ;
58 }
59
60 export function fixShape ( rec ) {
61 if ( typeof rec?.fixShape === 'string' && rec.fixShape. trim ()) {
62 return normalizeFixText (rec.fixShape);
63 }
64 const primaryText = [rec?.fix, rec?.desiredBehavior]
65 . filter (( v ) => typeof v === 'string' && v. trim ())
66 . join ( ' \n ' );
67 const text = primaryText || rec?.what;
68 return normalizeFixText (text);
69 }
70
71 export function dedupIntent ( rec ) {
72 if ( isSMaxageCacheHeaderRec (rec)) return 'cache-control:s-maxage' ;
73 if ( isCacheLifeRec (rec)) return cacheLifeIntent (rec);
74 const sharedFunction = sharedFunctionTarget (rec);
75 if (sharedFunction) return `parallel-shared-helper:${ sharedFunction }` ;
76 return fixShape (rec);
77 }
78
79 export function dedupEditTarget ( rec ) {
80 return sharedFunctionTarget (rec) ?? normalizePath ( firstAffectedFile (rec));
81 }
82
83 function firstAffectedFile ( rec ) {
84 const direct = affectedFiles (rec);
85 const editTarget = referencedCodeFiles (rec, [ 'fix' , 'desiredBehavior' , 'currentBehavior' ])[ 0 ];
86 if (editTarget) return editTarget;
87 const referenced = referencedCodeFiles (rec)
88 . find (( file ) => direct. includes (file));
89 if (referenced) return referenced;
90 return Array. isArray (rec?.affectedFiles) ? rec.affectedFiles[ 0 ] : null ;
91 }
92
93 function affectedFiles ( rec ) {
94 return Array. isArray (rec?.affectedFiles)
95 ? rec.affectedFiles. map (normalizePath). filter (( file ) => file !== NO_VALUE )
96 : [];
97 }
98
99 function referencedCodeFiles ( rec , fields = [ 'what' , 'why' , 'fix' , 'currentBehavior' , 'desiredBehavior' , 'verify' ]) {
100 const text = fields
101 . map (( field ) => rec?.[field])
102 . filter (( v ) => typeof v === 'string' && v. trim ())
103 . join ( ' \n ' );
104 const matches = text. match ( /(?: ^| [\s`'"(] )((?: \. {1,2} \/ | [A-Za-z0-9_.@-] + \/ ) [A-Za-z0-9_./@[ \] ()-] + \. (?:mjs | cjs | js | jsx | ts | tsx))/ g ) ?? [];
105 return unique (matches. map (( m ) =>
106 normalizePath (m. replace ( / ^ [\s`'"(] + / , '' ))
107 ). filter (( file ) => file !== NO_VALUE ));
108 }
109
110 function isSMaxageCacheHeaderRec ( rec ) {
111 const text = [
112 rec?.what,
113 rec?.why,
114 rec?.fix,
115 rec?.desiredBehavior,
116 ... (Array. isArray (rec?.citations) ? rec.citations : []),
117 ]. filter (Boolean). join ( ' \n ' );
118 return / \b s-maxage \b / i . test (text) &&
119 / \b (?:Cache-Control | CDN cache | cdn-cache | caching \/ cdn-cache) \b / i . test (text);
120 }
121
122 function isCacheLifeRec ( rec ) {
123 const text = [
124 rec?.candidateRef,
125 rec?.what,
126 rec?.why,
127 rec?.fix,
128 rec?.desiredBehavior,
129 ... (Array. isArray (rec?.citations) ? rec.citations : []),
130 ]. filter (Boolean). join ( ' \n ' );
131 return / ^ isr_overrevalidation:/ . test ( String (rec?.candidateRef ?? '' )) &&
132 / \b cacheLife \s * \( |\b cacheLife \b / i . test (text);
133 }
134
135 function sharedFunctionTarget ( rec ) {
136 const rule = primarySkillRule (rec);
137 if ( ! /(?: ^| :)async-parallel $| (?: ^| :)server-parallel-fetching $| (?: ^| :)async-suspense-boundaries $ / . test (rule)) {
138 return null ;
139 }
140 const text = [
141 rec?.what,
142 rec?.why,
143 rec?.fix,
144 rec?.currentBehavior,
145 rec?.desiredBehavior,
146 ]. filter (( v ) => typeof v === 'string' && v. trim ()). join ( ' \n ' );
147 const names = [
148 ... text. matchAll ( / \b (?:get | fetch | load | read | render | create | generate | filter | resolve) [A-Z][A-Za-z0-9_] *\b / g ),
149 ]. map (( m ) => m[ 0 ]);
150 const stop = new Set ([
151 'getPayload' ,
152 'draftMode' ,
153 'notFound' ,
154 'redirect' ,
155 'Promise' ,
156 'Response' ,
157 'NextResponse' ,
158 ]);
159 const candidates = names. filter (( name ) => ! stop. has (name));
160 if (candidates. length === 0 ) return null ;
161 const score = new Map ();
162 for ( const name of candidates) {
163 score. set (name, (score. get (name) ?? 0 ) + 1 );
164 }
165 return [ ... score. entries ()]
166 . sort (( a , b ) => b[ 1 ] - a[ 1 ] || text. indexOf (a[ 0 ]) - text. indexOf (b[ 0 ]))
167 . map (([ name ]) => `function:${ name }` )[ 0 ] ?? null ;
168 }
169
170 function cacheLifeIntent ( rec ) {
171 const text = [
172 rec?.what,
173 rec?.why,
174 rec?.fix,
175 rec?.desiredBehavior,
176 rec?.verify,
177 ]. filter (Boolean). join ( ' \n ' );
178 const profiles = unique (
179 [ ... text. matchAll ( / \b cacheLife \s * \( \s * ['"`] ( [ ^ '"`] + ) ['"`] / g )]
180 . map (( m ) => m[ 1 ])
181 );
182 const tags = unique ([
183 ... [ ... text. matchAll ( / \b cacheTag \s * \( ( [ ^ )] * ) \) / gs )]. flatMap (( m ) => {
184 const args = m[ 1 ] ?? '' ;
185 return [
186 ... [ ... args. matchAll ( / ['"] ( [ ^ '"] + ) ['"] / g )]. map (( x ) => x[ 1 ]),
187 ... [ ... args. matchAll ( /`( [ ^ `] + )`/ g )]. map (( x ) => x[ 1 ]. includes ( '${' ) ? `${ x [ 1 ]. split ( '${' )[ 0 ] }*` : x[ 1 ]),
188 ];
189 }),
190 ]);
191 const invalidation = / \b (?:revalidateTag | updateTag) \s * \( / . test (text) ? 'with-invalidation-api' : 'no-invalidation-api' ;
192 return [
193 'next-cache:cache-life' ,
194 profiles. join ( '|' ) || NO_VALUE ,
195 tags. join ( '|' ) || NO_VALUE ,
196 invalidation,
197 ]. join ( ':' );
198 }
199
200 function unique ( values ) {
201 return Array. from ( new Set (values. filter (( v ) => typeof v === 'string' && v. trim ()). map (( v ) => v. trim ()))). sort ();
202 }
203
204 function normalizeFixText ( text ) {
205 if ( typeof text !== 'string' || text. trim () === '' ) return NO_VALUE ;
206 return text
207 . toLowerCase ()
208 . replace ( /``` [\s\S] *? ```/ g , ' codeblock ' )
209 . replace ( /` [ ^ `] * `/ g , ' code ' )
210 . replace ( / \b \d + (?: \. \d + ) ? (?:ms | s | % | kb | mb | gb | k | m) ?\b / g , '#' )
211 . replace ( / [ ^ a-z0-9#] + / g , ' ' )
212 . trim ()
213 . split ( / \s + / )
214 . slice ( 0 , 80 )
215 . join ( ' ' ) || NO_VALUE ;
216 }
217
218 function withDedupMetadata ( rec ) {
219 const existing = normalizedAppliesAlsoTo (rec.appliesAlsoTo);
220 const count = Math. max (
221 numericCount (rec.corroborationCount),
222 1 + existing. length ,
223 );
224 return existing. length > 0 || count > 1
225 ? { ... rec, appliesAlsoTo: existing, corroborationCount: count }
226 : { ... rec };
227 }
228
229 function mergeDuplicateRecs ( a , b ) {
230 const aScore = recScore (a);
231 const bScore = recScore (b);
232 const winner = bScore > aScore ? b : a;
233 const loser = winner === a ? b : a;
234 const winnerExisting = normalizedAppliesAlsoTo (winner.appliesAlsoTo);
235 const loserExisting = normalizedAppliesAlsoTo (loser.appliesAlsoTo);
236 const appliesAlsoTo = uniqueAppliesAlsoTo ([
237 ... winnerExisting,
238 appliesAlsoEntry (loser),
239 ... loserExisting,
240 ]);
241 const corroborationCount =
242 numericCount (winner.corroborationCount) + numericCount (loser.corroborationCount);
243 return {
244 ... winner,
245 appliesAlsoTo,
246 corroborationCount: Math. max (corroborationCount, 1 + appliesAlsoTo. length ),
247 };
248 }
249
250 function recScore ( rec ) {
251 const priority = typeof rec?.priority === 'number' ? rec.priority : 0 ;
252 const quality = typeof rec?.quality?.overall === 'number' ? rec.quality.overall : 0 ;
253 return (priority * 1_000_000_000_000 ) + signalMagnitude (rec) + quality;
254 }
255
256 function signalMagnitude ( rec ) {
257 const text = [
258 rec?.o11ySignal,
259 rec?.why,
260 rec?.what,
261 rec?.impact,
262 ]. filter (( v ) => typeof v === 'string' && v. trim ()). join ( ' \n ' );
263 const inv = parseNumber (text, /(?:inv | invocations ?| function invocations ?| requests ? ) [:=]\s * ( [\d,] + )/ i );
264 const p95 = parseNumber (text, /(?:p95 | 95th percentile(?: duration) ? ) [:=] ? \s * ( [\d,] + ) \s * ms/ i );
265 const errors = parseNumber (text, /(?:errs | errors ? ) [:=]\s * ( [\d,] + )/ i );
266 const writes = parseNumber (text, /writes [:=]\s * ( [\d,] + )/ i );
267 const reads = parseNumber (text, /reads [:=]\s * ( [\d,] + )/ i );
268 if (inv != null && p95 != null ) return inv * p95;
269 if (errors != null ) return errors;
270 if (writes != null && reads != null ) return writes + reads;
271 if (inv != null ) return inv;
272 return 0 ;
273 }
274
275 function parseNumber ( text , re ) {
276 const match = re. exec (text);
277 if ( ! match) return null ;
278 const value = Number ( String (match[ 1 ]). replace ( /,/ g , '' ));
279 return Number. isFinite (value) ? value : null ;
280 }
281
282 function numericCount ( value ) {
283 return Number. isFinite (value) && value > 0 ? value : 1 ;
284 }
285
286 function appliesAlsoEntry ( rec ) {
287 return {
288 candidateRef: rec?.candidateRef ?? null ,
289 affectedFiles: Array. isArray (rec?.affectedFiles)
290 ? rec.affectedFiles. map (normalizePath). filter (( p ) => p !== NO_VALUE )
291 : [],
292 o11ySignal: rec?.o11ySignal ?? null ,
293 what: rec?.what ?? null ,
294 };
295 }
296
297 function normalizedAppliesAlsoTo ( entries ) {
298 if ( ! Array. isArray (entries)) return [];
299 return entries
300 . filter (( e ) => e && typeof e === 'object' )
301 . map (( e ) => ({
302 candidateRef: e.candidateRef ?? null ,
303 affectedFiles: Array. isArray (e.affectedFiles)
304 ? e.affectedFiles. map (normalizePath). filter (( p ) => p !== NO_VALUE )
305 : [],
306 o11ySignal: e.o11ySignal ?? null ,
307 what: e.what ?? null ,
308 }));
309 }
310
311 function uniqueAppliesAlsoTo ( entries ) {
312 const seen = new Set ();
313 const out = [];
314 for ( const entry of entries) {
315 const key = JSON . stringify ([
316 entry.candidateRef ?? NO_VALUE ,
317 entry.affectedFiles?. join ( ',' ) ?? NO_VALUE ,
318 entry.what ?? NO_VALUE ,
319 ]);
320 if (seen. has (key)) continue ;
321 seen. add (key);
322 out. push (entry);
323 }
324 return out;
325 }