@@ -7,13 +7,21 @@ pub async fn execute(
77 name : Option < & str > ,
88 output : & str ,
99 all_namespaces : bool ,
10+ library : bool ,
1011) -> Result < ( ) > {
1112 // Parse resource type
1213 let rt = ResourceType :: from_str ( resource_type)
1314 . ok_or_else ( || anyhow:: anyhow!( "Unknown resource type: {}" , resource_type) ) ?;
1415
15- // Build resource list (placeholder until persistent storage is implemented)
16- let resources = get_mock_resources ( & rt, name, all_namespaces) ;
16+ // Build resource list - either from library or mock data
17+ let resources = if library {
18+ get_library_resources ( & rt, name) ?
19+ } else {
20+ get_mock_resources ( & rt, name, all_namespaces)
21+ } ;
22+
23+ // When listing library, always show domains (namespaces)
24+ let show_namespaces = all_namespaces || library;
1725
1826 // Format and display output
1927 match output {
@@ -45,16 +53,115 @@ pub async fn execute(
4553 }
4654 "wide" | _ => {
4755 // Table format (default)
48- print_table_header ( & rt, all_namespaces ) ;
56+ print_table_header ( & rt, show_namespaces ) ;
4957 for resource in resources {
50- print_table_row ( & rt, & resource, all_namespaces ) ;
58+ print_table_row ( & rt, & resource, show_namespaces ) ;
5159 }
5260 }
5361 }
5462
5563 Ok ( ( ) )
5664}
5765
66+ /// Get resources from the built-in library directory
67+ fn get_library_resources (
68+ rt : & ResourceType ,
69+ name : Option < & str > ,
70+ ) -> Result < Vec < serde_json:: Value > > {
71+ // Only agents are in the library currently
72+ if !matches ! ( rt, ResourceType :: Agent ) {
73+ return Ok ( vec ! [ ] ) ;
74+ }
75+
76+ // Find the library directory - check common locations
77+ let library_path = find_library_path ( ) ?;
78+ let mut resources = Vec :: new ( ) ;
79+
80+ // Scan all subdirectories (domains) for agent YAML files
81+ if let Ok ( entries) = std:: fs:: read_dir ( & library_path) {
82+ for entry in entries. flatten ( ) {
83+ let path = entry. path ( ) ;
84+ if path. is_dir ( ) {
85+ let domain = path. file_name ( )
86+ . and_then ( |n| n. to_str ( ) )
87+ . unwrap_or ( "unknown" )
88+ . to_string ( ) ;
89+
90+ // Scan for YAML files in each domain
91+ if let Ok ( files) = std:: fs:: read_dir ( & path) {
92+ for file in files. flatten ( ) {
93+ let file_path = file. path ( ) ;
94+ if file_path. extension ( ) . map_or ( false , |e| e == "yaml" || e == "yml" ) {
95+ if let Ok ( content) = std:: fs:: read_to_string ( & file_path) {
96+ if let Ok ( agent) = serde_yaml:: from_str :: < serde_json:: Value > ( & content) {
97+ let agent_name = agent
98+ . get ( "metadata" )
99+ . and_then ( |m| m. get ( "name" ) )
100+ . and_then ( |n| n. as_str ( ) )
101+ . unwrap_or ( "unknown" ) ;
102+
103+ // Filter by name if provided
104+ if let Some ( filter) = name {
105+ if agent_name != filter {
106+ continue ;
107+ }
108+ }
109+
110+ // Add domain to metadata
111+ let mut enriched = agent. clone ( ) ;
112+ if let Some ( metadata) = enriched. get_mut ( "metadata" ) {
113+ if let Some ( obj) = metadata. as_object_mut ( ) {
114+ obj. insert ( "namespace" . to_string ( ) , serde_json:: json!( domain) ) ;
115+ }
116+ }
117+
118+ // Add status for display
119+ if let Some ( obj) = enriched. as_object_mut ( ) {
120+ obj. insert ( "status" . to_string ( ) , serde_json:: json!( {
121+ "phase" : "Available"
122+ } ) ) ;
123+ }
124+
125+ resources. push ( enriched) ;
126+ }
127+ }
128+ }
129+ }
130+ }
131+ }
132+ }
133+ }
134+
135+ Ok ( resources)
136+ }
137+
138+ /// Find the library directory - check multiple possible locations
139+ fn find_library_path ( ) -> Result < std:: path:: PathBuf > {
140+ // Check common locations
141+ let candidates = [
142+ std:: path:: PathBuf :: from ( "library" ) ,
143+ std:: path:: PathBuf :: from ( "./library" ) ,
144+ std:: env:: current_exe ( )
145+ . ok ( )
146+ . and_then ( |p| p. parent ( ) . map ( |p| p. join ( "library" ) ) )
147+ . unwrap_or_default ( ) ,
148+ std:: env:: current_exe ( )
149+ . ok ( )
150+ . and_then ( |p| p. parent ( ) . and_then ( |p| p. parent ( ) ) . map ( |p| p. join ( "library" ) ) )
151+ . unwrap_or_default ( ) ,
152+ ] ;
153+
154+ for candidate in candidates {
155+ if candidate. exists ( ) && candidate. is_dir ( ) {
156+ return Ok ( candidate) ;
157+ }
158+ }
159+
160+ Err ( anyhow:: anyhow!(
161+ "Library directory not found. Make sure you're running from the project root or the library is installed."
162+ ) )
163+ }
164+
58165fn get_mock_resources (
59166 rt : & ResourceType ,
60167 name : Option < & str > ,
@@ -115,11 +222,11 @@ fn print_table_header(rt: &ResourceType, all_namespaces: bool) {
115222 match rt {
116223 ResourceType :: Agent => {
117224 if all_namespaces {
118- println ! ( "\n NAMESPACE NAME STATUS MODEL AGE" ) ;
119- println ! ( "{}" , "=" . repeat( 75 ) ) ;
225+ println ! ( "\n {:<14} {:<24} {:<11} {:<24} {}" , "DOMAIN" , "NAME" , " STATUS" , " MODEL" , " AGE") ;
226+ println ! ( "{}" , "=" . repeat( 80 ) ) ;
120227 } else {
121- println ! ( "\n NAME STATUS MODEL AGE" ) ;
122- println ! ( "{}" , "=" . repeat( 60 ) ) ;
228+ println ! ( "\n {:<24} {:<11} {:<24} {}" , "NAME" , " STATUS" , " MODEL" , " AGE") ;
229+ println ! ( "{}" , "=" . repeat( 65 ) ) ;
123230 }
124231 }
125232 ResourceType :: Workflow => {
@@ -171,14 +278,28 @@ fn print_table_row(rt: &ResourceType, resource: &serde_json::Value, all_namespac
171278 . and_then ( |p| p. as_str ( ) )
172279 . unwrap_or ( "Unknown" ) ;
173280
174- let age = "5m" ; // Placeholder
281+ // Get model from spec if available (for library agents)
282+ let model = resource
283+ . get ( "spec" )
284+ . and_then ( |s| s. get ( "model" ) )
285+ . and_then ( |m| m. as_str ( ) )
286+ . unwrap_or ( "claude-sonnet-4" ) ;
287+
288+ // Truncate model name if too long
289+ let model_display = if model. len ( ) > 24 {
290+ format ! ( "{}..." , & model[ ..21 ] )
291+ } else {
292+ model. to_string ( )
293+ } ;
294+
295+ let age = "-" ; // Library agents don't have age
175296
176297 match rt {
177298 ResourceType :: Agent => {
178299 if all_namespaces {
179- println ! ( "{:<12 } {:<16 } {:<9 } {:<18 } {}" , namespace, name, status, "claude-sonnet-4" , age) ;
300+ println ! ( "{:<14 } {:<24 } {:<11 } {:<24 } {}" , namespace, name, status, model_display , age) ;
180301 } else {
181- println ! ( "{:<16 } {:<9 } {:<18 } {}" , name, status, "claude-sonnet-4" , age) ;
302+ println ! ( "{:<24 } {:<11 } {:<24 } {}" , name, status, model_display , age) ;
182303 }
183304 }
184305 ResourceType :: Workflow => {
0 commit comments