11import type { CSSProperties , ReactNode } from "react" ;
22import type { StatusTone } from "./statusTone" ;
3+ import {
4+ getUtilityTaskCandidates ,
5+ getUtilityTaskDefaultsHint ,
6+ resolveUtilityTaskConfig ,
7+ type UtilityTaskCandidateAgent ,
8+ type UtilityTaskConfigAgent ,
9+ type UtilityTaskDefaults ,
10+ } from "./utilityTask" ;
11+
12+ export { AUTO_PROVIDER_PREFERENCE_ORDER , sortByAutoPreference } from "./utilityTask" ;
313
414// --- Icon registry ---
515
@@ -259,35 +269,9 @@ export function getConfigNormalizer(kind: string): ConfigNormalizer | undefined
259269 return CONFIG_NORMALIZER_REGISTRY . get ( kind ) ;
260270}
261271
262- /**
263- * Preference order used by Auto for utility tasks (title gen, commit gen, conflict resolver).
264- * Codex first by user preference; others fall back alphabetically afterwards by registration order.
265- */
266- export const AUTO_PROVIDER_PREFERENCE_ORDER : readonly string [ ] = [
267- "codex" ,
268- "claude" ,
269- "gemini" ,
270- "opencode" ,
271- "cursor" ,
272- "copilot" ,
273- ] ;
274-
275- export function sortByAutoPreference < T extends { kind : string } > ( items : readonly T [ ] ) : T [ ] {
276- const rank = ( kind : string ) => {
277- const idx = AUTO_PROVIDER_PREFERENCE_ORDER . indexOf ( kind ) ;
278- return idx < 0 ? AUTO_PROVIDER_PREFERENCE_ORDER . length : idx ;
279- } ;
280- return [ ...items ] . sort ( ( a , b ) => rank ( a . kind ) - rank ( b . kind ) ) ;
281- }
282-
283272// --- Commit generation defaults registry ---
284273
285- export interface CommitGenDefaults {
286- label ?: string ;
287- hint ?: string ;
288- model : string ;
289- effort : string ;
290- }
274+ export interface CommitGenDefaults extends UtilityTaskDefaults { }
291275
292276const COMMIT_GEN_REGISTRY = new Map < string , CommitGenDefaults > ( ) ;
293277
@@ -300,24 +284,12 @@ export function getCommitGenDefaults(kind: string): CommitGenDefaults | undefine
300284}
301285
302286export function getCommitGenDefaultsHint ( ) : string | undefined {
303- const entries = [ ...COMMIT_GEN_REGISTRY . values ( ) ]
304- . flatMap ( ( defaults ) =>
305- defaults . hint && defaults . label ? [ `${ defaults . label } -> ${ defaults . hint } ` ] : [ ] ,
306- )
307- . sort ( )
308- . join ( ", " ) ;
309-
310- return entries ? `Defaults: ${ entries } ` : undefined ;
287+ return getUtilityTaskDefaultsHint ( COMMIT_GEN_REGISTRY . values ( ) ) ;
311288}
312289
313290// --- Title generation defaults registry ---
314291
315- export interface TitleGenDefaults {
316- label ?: string ;
317- hint ?: string ;
318- model : string ;
319- effort : string ;
320- }
292+ export interface TitleGenDefaults extends UtilityTaskDefaults { }
321293
322294const TITLE_GEN_REGISTRY = new Map < string , TitleGenDefaults > ( ) ;
323295
@@ -330,24 +302,12 @@ export function getTitleGenDefaults(kind: string): TitleGenDefaults | undefined
330302}
331303
332304export function getTitleGenDefaultsHint ( ) : string | undefined {
333- const entries = [ ...TITLE_GEN_REGISTRY . values ( ) ]
334- . flatMap ( ( defaults ) =>
335- defaults . hint && defaults . label ? [ `${ defaults . label } -> ${ defaults . hint } ` ] : [ ] ,
336- )
337- . sort ( )
338- . join ( ", " ) ;
339-
340- return entries ? `Defaults: ${ entries } ` : undefined ;
305+ return getUtilityTaskDefaultsHint ( TITLE_GEN_REGISTRY . values ( ) ) ;
341306}
342307
343308// --- Conflict resolver defaults registry ---
344309
345- export interface ConflictResolverDefaults {
346- label ?: string ;
347- hint ?: string ;
348- model : string ;
349- effort : string ;
350- }
310+ export interface ConflictResolverDefaults extends UtilityTaskDefaults { }
351311
352312const CONFLICT_RESOLVER_REGISTRY = new Map < string , ConflictResolverDefaults > ( ) ;
353313
@@ -360,73 +320,22 @@ export function getConflictResolverDefaults(kind: string): ConflictResolverDefau
360320}
361321
362322export function getConflictResolverDefaultsHint ( ) : string | undefined {
363- const entries = [ ...CONFLICT_RESOLVER_REGISTRY . values ( ) ]
364- . flatMap ( ( defaults ) =>
365- defaults . hint && defaults . label ? [ `${ defaults . label } -> ${ defaults . hint } ` ] : [ ] ,
366- )
367- . sort ( )
368- . join ( ", " ) ;
369-
370- return entries ? `Defaults: ${ entries } ` : undefined ;
323+ return getUtilityTaskDefaultsHint ( CONFLICT_RESOLVER_REGISTRY . values ( ) ) ;
371324}
372325
373- interface ConflictResolverAgentLike {
374- kind : string ;
375- installed ?: boolean ;
376- authState ?: string ;
377- capabilities : { models : { id : string } [ ] } ;
378- }
379-
380- function hasPreferredConflictResolverModel ( agent : ConflictResolverAgentLike ) : boolean {
381- const defaults = getConflictResolverDefaults ( agent . kind ) ;
382- if ( ! defaults ?. model ) return true ;
383- return agent . capabilities . models . some ( ( m ) => m . id === defaults . model ) ;
384- }
326+ type ConflictResolverAgentLike = UtilityTaskCandidateAgent ;
385327
386328export function getConflictResolverCandidates < T extends ConflictResolverAgentLike > (
387329 agentStatuses : readonly T [ ] ,
388330 provider : string ,
389331) : T [ ] {
390- const available = agentStatuses . filter ( ( a ) => a . installed !== false && a . authState !== "missing" ) ;
391- if ( provider === "auto" ) {
392- const withPreferred = available . filter ( hasPreferredConflictResolverModel ) ;
393- return sortByAutoPreference ( withPreferred . length > 0 ? withPreferred : available ) ;
394- }
395- return available . filter ( ( agent ) => agent . kind === provider ) ;
332+ return getUtilityTaskCandidates ( agentStatuses , provider , getConflictResolverDefaults ) ;
396333}
397334
398335export function resolveConflictResolverConfig (
399- agent :
400- | {
401- kind : string ;
402- capabilities : {
403- models : { id : string } [ ] ;
404- efforts : string [ ] ;
405- modelEfforts : Record < string , string [ ] > ;
406- defaultEffort ?: string | undefined ;
407- } ;
408- }
409- | undefined ,
336+ agent : UtilityTaskConfigAgent | undefined ,
410337 model : string ,
411338 effort : string ,
412339) : { model : string ; effort : string ; availableEfforts : string [ ] } {
413- if ( ! agent ) return { model : "" , effort : "" , availableEfforts : [ ] } ;
414-
415- const defaults = getConflictResolverDefaults ( agent . kind ) ;
416- const nextModel = agent . capabilities . models . some ( ( m ) => m . id === model )
417- ? model
418- : defaults ?. model && agent . capabilities . models . some ( ( m ) => m . id === defaults . model )
419- ? defaults . model
420- : ( agent . capabilities . models [ 0 ] ?. id ?? "" ) ;
421-
422- const modelEfforts = agent . capabilities . modelEfforts [ nextModel ] ;
423- const availableEfforts = modelEfforts ?. length ? modelEfforts : agent . capabilities . efforts ;
424- if ( availableEfforts . length === 0 ) return { model : nextModel , effort : "" , availableEfforts } ;
425-
426- if ( availableEfforts . includes ( effort ) ) return { model : nextModel , effort, availableEfforts } ;
427-
428- const fallback = [ defaults ?. effort , agent . capabilities . defaultEffort , availableEfforts [ 0 ] ] . find (
429- ( c ) => c && availableEfforts . includes ( c ! ) ,
430- ) ;
431- return { model : nextModel , effort : fallback ?? "" , availableEfforts } ;
340+ return resolveUtilityTaskConfig ( agent , model , effort , getConflictResolverDefaults ) ;
432341}
0 commit comments