@@ -42,40 +42,114 @@ const ENGINE_TO_WIRE_BY_PROFILE: Record<
4242 gpt : { ...DEFAULT_ENGINE_TO_WIRE , ...GPT_OVERRIDES } ,
4343} ;
4444
45- /** Registry engines the gpt profile folds into apply_patch, in advertise order. */
46- export const GPT_PATCH_ENGINES = [
47- "write_file" ,
48- "edit_file" ,
49- "delete_file" ,
50- ] as const ;
45+ /**
46+ * Engines one advertised wire replaces. A profile without an entry keeps
47+ * the 1:1 wire table. Adding a family is a new ToolProfile plus a row here
48+ * and in ENGINE_TO_WIRE_BY_PROFILE — not a new director package.
49+ */
50+ const PROFILE_FOLDS : Record <
51+ ToolProfile ,
52+ { wire : string ; engines : readonly string [ ] } | undefined
53+ > = {
54+ default : undefined ,
55+ gpt : {
56+ wire : "apply_patch" ,
57+ engines : [ "write_file" , "edit_file" , "delete_file" ] ,
58+ } ,
59+ } ;
60+
61+ function buildAdvertisedWireEngines (
62+ profile : ToolProfile ,
63+ ) : ReadonlyMap < string , readonly string [ ] > {
64+ const fold = PROFILE_FOLDS [ profile ] ;
65+ const folded = new Set ( fold ?. engines ?? [ ] ) ;
66+ const map = new Map < string , string [ ] > ( ) ;
67+ for ( const [ engine , wire ] of Object . entries (
68+ ENGINE_TO_WIRE_BY_PROFILE [ profile ] ,
69+ ) ) {
70+ if ( folded . has ( engine ) ) continue ;
71+ const existing = map . get ( wire ) ;
72+ if ( existing === undefined ) map . set ( wire , [ engine ] ) ;
73+ else existing . push ( engine ) ;
74+ }
75+ if ( fold !== undefined ) map . set ( fold . wire , [ ...fold . engines ] ) ;
76+ return map ;
77+ }
78+
79+ const ADVERTISED_WIRE_ENGINES = Object . fromEntries (
80+ ( Object . keys ( ENGINE_TO_WIRE_BY_PROFILE ) as ToolProfile [ ] ) . map ( ( profile ) => [
81+ profile ,
82+ buildAdvertisedWireEngines ( profile ) ,
83+ ] ) ,
84+ ) as Record < ToolProfile , ReadonlyMap < string , readonly string [ ] > > ;
85+
86+ export function toolProfiles ( ) : readonly ToolProfile [ ] {
87+ return Object . keys ( ENGINE_TO_WIRE_BY_PROFILE ) as ToolProfile [ ] ;
88+ }
89+
90+ /** Wire name → engine ids this profile advertises. Folded wires map to every engine they replace. */
91+ export function advertisedWireEngines (
92+ profile : ToolProfile ,
93+ ) : ReadonlyMap < string , readonly string [ ] > {
94+ return ADVERTISED_WIRE_ENGINES [ profile ] ;
95+ }
96+
97+ /**
98+ * Engines `wire` stands for on `profile`. Undefined when this profile does
99+ * not advertise that name (a later family follows the same table).
100+ */
101+ export function enginesForAdvertisedWire (
102+ wire : string ,
103+ profile : ToolProfile ,
104+ ) : readonly string [ ] | undefined {
105+ const table = ADVERTISED_WIRE_ENGINES [ profile ] ;
106+ return table . get ( wire ) ?? table . get ( wire . toLowerCase ( ) ) ;
107+ }
51108
52- /** Tools the gpt profile folds into the single apply_patch envelope tool. */
53- const PATCH_FOLDED_ENGINES : ReadonlySet < string > = new Set ( GPT_PATCH_ENGINES ) ;
109+ /** Every wire any profile advertises for `engine`, including fold wires. */
110+ export function advertisedNamesForEngine ( engine : string ) : readonly string [ ] {
111+ const names : string [ ] = [ ] ;
112+ const seen = new Set < string > ( ) ;
113+ for ( const profile of toolProfiles ( ) ) {
114+ const fold = PROFILE_FOLDS [ profile ] ;
115+ const wire =
116+ fold !== undefined && fold . engines . includes ( engine )
117+ ? fold . wire
118+ : advertisedToolName ( engine , profile ) ;
119+ if ( seen . has ( wire ) ) continue ;
120+ seen . add ( wire ) ;
121+ names . push ( wire ) ;
122+ }
123+ return names ;
124+ }
54125
55126/** gpt models are trained on apply_patch, not write/edit/delete. Other
56- * profiles and lists without a file-mutation tool pass through unchanged. */
127+ * profiles and lists without a folded tool pass through unchanged. */
57128export function foldFileToolNames (
58129 names : readonly string [ ] ,
59130 profile : ToolProfile ,
60131) : readonly string [ ] {
61- if ( profile !== "gpt" ) return names ;
132+ const fold = PROFILE_FOLDS [ profile ] ;
133+ if ( fold === undefined ) return names ;
62134 const folded = ( name : string ) : boolean =>
63- PATCH_FOLDED_ENGINES . has ( engineToolName ( name ) ) ;
135+ fold . engines . includes ( engineToolName ( name ) ) ;
64136 if ( ! names . some ( folded ) ) return names ;
65137 const first = names . findIndex ( folded ) ;
66138 return names . flatMap ( ( name , i ) =>
67- i === first ? [ "apply_patch" ] : folded ( name ) ? [ ] : [ name ] ,
139+ i === first ? [ fold . wire ] : folded ( name ) ? [ ] : [ name ] ,
68140 ) ;
69141}
70142
71143export function foldFileToolDefinitions (
72144 defs : readonly ToolDefinition [ ] ,
73145 profile : ToolProfile ,
74146) : ToolDefinition [ ] {
75- if ( profile !== "gpt" || ! defs . some ( ( d ) => d . name === "apply_patch" ) ) {
147+ const fold = PROFILE_FOLDS [ profile ] ;
148+ if ( fold === undefined || ! defs . some ( ( d ) => d . name === fold . wire ) ) {
76149 return [ ...defs ] ;
77150 }
78- return defs . filter ( ( d ) => ! PATCH_FOLDED_ENGINES . has ( engineToolName ( d . name ) ) ) ;
151+ const folded = new Set ( fold . engines ) ;
152+ return defs . filter ( ( d ) => ! folded . has ( engineToolName ( d . name ) ) ) ;
79153}
80154
81155export function toolProfileForFamily ( family : ModelFamily ) : ToolProfile {
0 commit comments