@@ -38,7 +38,10 @@ mod repl;
3838
3939use client:: { ApiClient , SearchResponse } ;
4040use service:: TuiService ;
41- use terraphim_types:: { Document , LogicalOperator , NormalizedTermValue , RoleName , SearchQuery } ;
41+ use terraphim_types:: {
42+ Document , Layer , LogicalOperator , NormalizedTermValue , RoleName , SearchQuery ,
43+ extract_first_paragraph,
44+ } ;
4245use terraphim_update:: { check_for_updates, check_for_updates_startup, update_binary} ;
4346
4447#[ derive( clap:: ValueEnum , Debug , Clone ) ]
@@ -475,6 +478,10 @@ struct SearchDocumentOutput {
475478 title : String ,
476479 url : String ,
477480 rank : Option < u64 > ,
481+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
482+ tags : Option < Vec < String > > ,
483+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
484+ summary : Option < String > ,
478485}
479486
480487#[ derive( Debug , Serialize ) ]
@@ -485,6 +492,38 @@ struct SearchOutput {
485492 results : Vec < SearchDocumentOutput > ,
486493}
487494
495+ /// Extension trait to convert Document to layered output
496+ impl SearchDocumentOutput {
497+ fn from_document ( doc : & Document , layer : & Layer ) -> Self {
498+ match layer {
499+ Layer :: One => Self {
500+ id : doc. id . clone ( ) ,
501+ title : doc. title . clone ( ) ,
502+ url : doc. url . clone ( ) ,
503+ rank : doc. rank ,
504+ tags : doc. tags . clone ( ) ,
505+ summary : None ,
506+ } ,
507+ Layer :: Two => Self {
508+ id : doc. id . clone ( ) ,
509+ title : doc. title . clone ( ) ,
510+ url : doc. url . clone ( ) ,
511+ rank : doc. rank ,
512+ tags : doc. tags . clone ( ) ,
513+ summary : Some ( extract_first_paragraph ( & doc. body ) ) ,
514+ } ,
515+ Layer :: Three => Self {
516+ id : doc. id . clone ( ) ,
517+ title : doc. title . clone ( ) ,
518+ url : doc. url . clone ( ) ,
519+ rank : doc. rank ,
520+ tags : doc. tags . clone ( ) ,
521+ summary : None , // For full content, summary not needed
522+ } ,
523+ }
524+ }
525+ }
526+
488527fn print_json_output < T : Serialize > ( value : & T , mode : CommandOutputMode ) -> Result < ( ) > {
489528 let out = match mode {
490529 CommandOutputMode :: Human => serde_json:: to_string_pretty ( value) ?,
@@ -540,6 +579,9 @@ enum Command {
540579 role : Option < String > ,
541580 #[ arg( long, default_value_t = 10 ) ]
542581 limit : usize ,
582+ /// Output layer: 1=minimal (title+tags), 2=summary, 3=full (default)
583+ #[ arg( long, default_value_t = 3 , value_name = "1|2|3" ) ]
584+ layer : u8 ,
543585 } ,
544586 /// Manage roles (list, select)
545587 Roles {
@@ -1119,13 +1161,18 @@ async fn run_offline_command(
11191161 operator,
11201162 role,
11211163 limit,
1164+ layer,
11221165 } => {
11231166 let role_name = if let Some ( role) = role {
11241167 RoleName :: new ( & role)
11251168 } else {
11261169 service. get_selected_role ( ) . await
11271170 } ;
11281171
1172+ // Parse and validate layer
1173+ let layer =
1174+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
1175+
11291176 let results = if let Some ( additional_terms) = terms {
11301177 // Multi-term query with logical operators
11311178 let mut all_terms = vec ! [ query. clone( ) ] ;
@@ -1159,6 +1206,7 @@ async fn run_offline_command(
11591206 skip : Some ( 0 ) ,
11601207 limit : Some ( limit) ,
11611208 role : Some ( role_name. clone ( ) ) ,
1209+ layer,
11621210 } ;
11631211
11641212 service. search_with_query ( & search_query) . await ?
@@ -1171,23 +1219,33 @@ async fn run_offline_command(
11711219
11721220 if output. is_machine_readable ( ) {
11731221 let payload = SearchOutput {
1174- query,
1222+ query : query . clone ( ) ,
11751223 role : role_name. to_string ( ) ,
11761224 count : results. len ( ) ,
11771225 results : results
11781226 . iter ( )
1179- . map ( |doc| SearchDocumentOutput {
1180- id : doc. id . clone ( ) ,
1181- title : doc. title . clone ( ) ,
1182- url : doc. url . clone ( ) ,
1183- rank : doc. rank ,
1184- } )
1227+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
11851228 . collect ( ) ,
11861229 } ;
11871230 print_json_output ( & payload, output. mode ) ?;
11881231 } else {
11891232 for doc in results. iter ( ) {
1190- println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1233+ match layer {
1234+ Layer :: One => {
1235+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1236+ }
1237+ Layer :: Two => {
1238+ let summary = extract_first_paragraph ( & doc. body ) ;
1239+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1240+ println ! ( " {}" , summary) ;
1241+ }
1242+ Layer :: Three => {
1243+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1244+ if let Some ( ref tags) = doc. tags {
1245+ println ! ( " Tags: {}" , tags. join( ", " ) ) ;
1246+ }
1247+ }
1248+ }
11911249 }
11921250 }
11931251 Ok ( ( ) )
@@ -2110,6 +2168,7 @@ async fn run_server_command(
21102168 operator,
21112169 role,
21122170 limit,
2171+ layer,
21132172 } => {
21142173 // Get selected role from server if not specified
21152174 let role_name = if let Some ( role) = role {
@@ -2119,6 +2178,10 @@ async fn run_server_command(
21192178 config_res. config . selected_role
21202179 } ;
21212180
2181+ // Parse and validate layer
2182+ let layer =
2183+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
2184+
21222185 let q = if let Some ( additional_terms) = terms {
21232186 // Multi-term query with logical operators
21242187 let search_terms: Vec < NormalizedTermValue > = additional_terms
@@ -2133,6 +2196,7 @@ async fn run_server_command(
21332196 skip : Some ( 0 ) ,
21342197 limit : Some ( limit) ,
21352198 role : Some ( role_name) ,
2199+ layer,
21362200 }
21372201 } else {
21382202 // Single term query (backward compatibility)
@@ -2143,6 +2207,7 @@ async fn run_server_command(
21432207 skip : Some ( 0 ) ,
21442208 limit : Some ( limit) ,
21452209 role : Some ( role_name) ,
2210+ layer,
21462211 }
21472212 } ;
21482213
@@ -2177,12 +2242,7 @@ async fn run_server_command(
21772242 results : res
21782243 . results
21792244 . iter ( )
2180- . map ( |doc| SearchDocumentOutput {
2181- id : doc. id . clone ( ) ,
2182- title : doc. title . clone ( ) ,
2183- url : doc. url . clone ( ) ,
2184- rank : doc. rank ,
2185- } )
2245+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
21862246 . collect ( ) ,
21872247 } ;
21882248 print_json_output ( & payload, output. mode ) ?;
@@ -2893,6 +2953,7 @@ fn ui_loop(
28932953 skip : Some ( 0 ) ,
28942954 limit : Some ( 10 ) ,
28952955 role : Some ( RoleName :: new ( & role) ) ,
2956+ layer : Layer :: default ( ) ,
28962957 } ;
28972958 let resp = api. search ( & q) . await ?;
28982959 let lines: Vec < String > = resp
0 commit comments