11import os from 'os'
22import path from 'path'
33
4+ import { pluralize } from '@codebuff/common/util/string'
45import { useMemo , useRef , useState } from 'react'
56import { useShallow } from 'zustand/react/shallow'
67
@@ -12,10 +13,10 @@ import { useAuthState } from './hooks/use-auth-state'
1213import { useLogo } from './hooks/use-logo'
1314import { useTerminalDimensions } from './hooks/use-terminal-dimensions'
1415import { useTheme } from './hooks/use-theme'
16+ import { getProjectRoot } from './project-files'
1517import { useChatStore } from './state/chat-store'
1618import { createValidationErrorBlocks } from './utils/create-validation-error-blocks'
1719import { openFileAtPath } from './utils/open-file'
18- import { pluralize } from '@codebuff/common/util/string'
1920
2021import type { MultilineInputHandle } from './components/multiline-input'
2122import type { FileTreeNode } from '@codebuff/common/util/file'
@@ -51,13 +52,12 @@ export const App = ({
5152 const { textBlock : logoBlock } = useLogo ( { availableWidth : contentMaxWidth } )
5253
5354 const [ isAgentListCollapsed , setIsAgentListCollapsed ] = useState ( true )
54-
5555 const inputRef = useRef < MultilineInputHandle | null > ( null )
5656 const { setInputFocused, resetChatStore } = useChatStore (
5757 useShallow ( ( store ) => ( {
5858 setInputFocused : store . setInputFocused ,
5959 resetChatStore : store . reset ,
60- } ) )
60+ } ) ) ,
6161 )
6262
6363 const {
@@ -75,29 +75,27 @@ export const App = ({
7575 } )
7676
7777 const headerContent = useMemo ( ( ) => {
78- if ( ! loadedAgentsData ) {
79- return null
80- }
81-
8278 const homeDir = os . homedir ( )
83- const repoRoot = path . dirname ( loadedAgentsData . agentsDir )
79+ const repoRoot = getProjectRoot ( )
8480 const relativePath = path . relative ( homeDir , repoRoot )
8581 const displayPath = relativePath . startsWith ( '..' )
8682 ? repoRoot
8783 : `~/${ relativePath } `
8884
89- const sortedAgents = [ ...loadedAgentsData . agents ] . sort ( ( a , b ) => {
90- const displayNameComparison = ( a . displayName || '' )
91- . toLowerCase ( )
92- . localeCompare ( ( b . displayName || '' ) . toLowerCase ( ) )
85+ const sortedAgents = loadedAgentsData
86+ ? [ ...loadedAgentsData . agents ] . sort ( ( a , b ) => {
87+ const displayNameComparison = ( a . displayName || '' )
88+ . toLowerCase ( )
89+ . localeCompare ( ( b . displayName || '' ) . toLowerCase ( ) )
9390
94- return (
95- displayNameComparison ||
96- a . id . toLowerCase ( ) . localeCompare ( b . id . toLowerCase ( ) )
97- )
98- } )
91+ return (
92+ displayNameComparison ||
93+ a . id . toLowerCase ( ) . localeCompare ( b . id . toLowerCase ( ) )
94+ )
95+ } )
96+ : null
9997
100- const agentCount = sortedAgents . length
98+ const agentCount = sortedAgents ? .length
10199
102100 const formatIdentifier = ( agent : { id : string ; displayName : string } ) =>
103101 agent . displayName && agent . displayName !== agent . id
@@ -119,13 +117,13 @@ export const App = ({
119117 )
120118 }
121119
122- const agentListContent = (
120+ const agentListContent = sortedAgents ? (
123121 < box style = { { flexDirection : 'column' , gap : 0 } } >
124122 { sortedAgents . map ( renderAgentListItem ) }
125123 </ box >
126- )
124+ ) : null
127125
128- const headerText = pluralize ( agentCount , 'local agent' )
126+ const headerText = agentCount ? pluralize ( agentCount , 'local agent' ) : null
129127
130128 return (
131129 < box
@@ -162,18 +160,20 @@ export const App = ({
162160 onActivate = { ( ) => openFileAtPath ( repoRoot ) }
163161 />
164162 </ text >
165- < box style = { { marginBottom : 1 } } >
166- < ToolCallItem
167- name = { headerText }
168- content = { agentListContent }
169- isCollapsed = { isAgentListCollapsed }
170- isStreaming = { false }
171- streamingPreview = ""
172- finishedPreview = ""
173- onToggle = { ( ) => setIsAgentListCollapsed ( ! isAgentListCollapsed ) }
174- dense
175- />
176- </ box >
163+ { headerText ? (
164+ < box style = { { marginBottom : 1 } } >
165+ < ToolCallItem
166+ name = { headerText }
167+ content = { agentListContent }
168+ isCollapsed = { isAgentListCollapsed }
169+ isStreaming = { false }
170+ streamingPreview = ""
171+ finishedPreview = ""
172+ onToggle = { ( ) => setIsAgentListCollapsed ( ! isAgentListCollapsed ) }
173+ dense
174+ />
175+ </ box >
176+ ) : null }
177177 { validationErrors . length > 0 && (
178178 < box style = { { flexDirection : 'column' , gap : 0 } } >
179179 { createValidationErrorBlocks ( {
0 commit comments