@@ -22,10 +22,13 @@ import {
2222 gray ,
2323 green ,
2424 magenta ,
25+ red ,
2526 yellow ,
2627} from 'picocolors'
2728
2829import { loadLocalAgents , loadedAgents } from './agents/load-agents'
30+ import { backendUrl } from './config'
31+ import { createAuthHeaders } from './utils/auth-headers'
2932import {
3033 killAllBackgroundProcesses ,
3134 sendKillSignalToAllBackgroundProcesses ,
@@ -146,6 +149,72 @@ function getCachedLocalAgentInfo(): Record<
146149 return cachedLocalAgentInfo
147150}
148151
152+ /**
153+ * Validates an agent name against local and remote agents
154+ * @param agent The agent name to validate
155+ * @param localAgents Optional local agents to check against
156+ * @returns The display name of the agent if valid, undefined otherwise
157+ */
158+ export async function validateAgent (
159+ agent : string ,
160+ localAgents ?: Record < string , any > ,
161+ ) : Promise < string | undefined > {
162+ const agents = localAgents ?? { }
163+
164+ // if local agents are loaded, they're already validated
165+ const localById = agents ?. [ agent ]
166+ const localByDisplay = Object . values ( agents ?? { } ) . find (
167+ ( a : any ) => a ?. displayName === agent ,
168+ )
169+ if ( localById || localByDisplay ) {
170+ // Display the resolved agent name for local agents too
171+ const displayName = ( localById ?. displayName ||
172+ localByDisplay ?. displayName ||
173+ localById ?. id ||
174+ agent ) as string
175+ // Delete the inline console.log to centralize logging in the caller
176+ return displayName
177+ }
178+
179+ Spinner . get ( ) . start ( 'Checking agent...' )
180+ try {
181+ const url = `${ backendUrl } /api/agents/validate-name?agentId=${ encodeURIComponent ( agent ) } `
182+
183+ // Use helper to create headers with x-codebuff-api-key
184+ const headers = createAuthHeaders ( )
185+
186+ const resp = await fetch ( url , {
187+ method : 'GET' ,
188+ headers,
189+ } )
190+ // Include optional fields from backend, notably displayName
191+ const data : {
192+ valid ?: boolean
193+ normalizedId ?: string
194+ displayName ?: string
195+ } = await resp . json ( ) . catch ( ( ) => ( { } ) as any )
196+
197+ if ( resp . ok && data . valid ) {
198+ // Delete inline console logging here to centralize in caller
199+ return data . displayName
200+ }
201+
202+ if ( resp . ok && ! data . valid ) {
203+ console . error ( red ( `\nUnknown agent: ${ bold ( agent ) } . Exiting.` ) )
204+ process . exit ( 1 )
205+ }
206+ } catch {
207+ console . error (
208+ yellow (
209+ `\nCould not validate agent due to a network error. Proceeding...` ,
210+ ) ,
211+ )
212+ } finally {
213+ Spinner . get ( ) . stop ( )
214+ }
215+ return undefined
216+ }
217+
149218const PROMPT_HISTORY_PATH = path . join ( CONFIG_DIR , 'prompt_history.json' )
150219
151220// Paste detection constants
@@ -631,10 +700,16 @@ export class CLI {
631700 } else {
632701 // Normal interactive mode
633702 if ( client . user ) {
634- displayGreeting ( this . costMode , client . user . name )
703+ // Validate agent and display name before greeting if agent is specified
704+ if ( this . agent ) {
705+ const agents = await loadLocalAgents ( { verbose : false } )
706+ const resolvedName = await validateAgent ( this . agent , agents )
707+ if ( resolvedName ) {
708+ console . log ( green ( `\nAgent: ${ bold ( resolvedName ) } ` ) )
709+ }
710+ }
635711
636- // Agent name will be displayed by validateAgent when resolved
637- // No need to display here to avoid race conditions
712+ displayGreeting ( this . costMode , client . user . name )
638713 } else {
639714 console . log (
640715 `Welcome to Codebuff! Give us a sec to get your account set up...` ,
0 commit comments