@@ -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 {
@@ -1141,13 +1183,18 @@ async fn run_offline_command(
11411183 operator,
11421184 role,
11431185 limit,
1186+ layer,
11441187 } => {
11451188 let role_name = if let Some ( role) = role {
11461189 RoleName :: new ( & role)
11471190 } else {
11481191 service. get_selected_role ( ) . await
11491192 } ;
11501193
1194+ // Parse and validate layer
1195+ let layer =
1196+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
1197+
11511198 let results = if let Some ( additional_terms) = terms {
11521199 // Multi-term query with logical operators
11531200 let mut all_terms = vec ! [ query. clone( ) ] ;
@@ -1181,6 +1228,7 @@ async fn run_offline_command(
11811228 skip : Some ( 0 ) ,
11821229 limit : Some ( limit) ,
11831230 role : Some ( role_name. clone ( ) ) ,
1231+ layer,
11841232 } ;
11851233
11861234 service. search_with_query ( & search_query) . await ?
@@ -1193,23 +1241,33 @@ async fn run_offline_command(
11931241
11941242 if output. is_machine_readable ( ) {
11951243 let payload = SearchOutput {
1196- query,
1244+ query : query . clone ( ) ,
11971245 role : role_name. to_string ( ) ,
11981246 count : results. len ( ) ,
11991247 results : results
12001248 . iter ( )
1201- . map ( |doc| SearchDocumentOutput {
1202- id : doc. id . clone ( ) ,
1203- title : doc. title . clone ( ) ,
1204- url : doc. url . clone ( ) ,
1205- rank : doc. rank ,
1206- } )
1249+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
12071250 . collect ( ) ,
12081251 } ;
12091252 print_json_output ( & payload, output. mode ) ?;
12101253 } else {
12111254 for doc in results. iter ( ) {
1212- println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1255+ match layer {
1256+ Layer :: One => {
1257+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1258+ }
1259+ Layer :: Two => {
1260+ let summary = extract_first_paragraph ( & doc. body ) ;
1261+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1262+ println ! ( " {}" , summary) ;
1263+ }
1264+ Layer :: Three => {
1265+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1266+ if let Some ( ref tags) = doc. tags {
1267+ println ! ( " Tags: {}" , tags. join( ", " ) ) ;
1268+ }
1269+ }
1270+ }
12131271 }
12141272 }
12151273 Ok ( ( ) )
@@ -2234,6 +2292,7 @@ async fn run_server_command(
22342292 operator,
22352293 role,
22362294 limit,
2295+ layer,
22372296 } => {
22382297 // Get selected role from server if not specified
22392298 let role_name = if let Some ( role) = role {
@@ -2243,6 +2302,10 @@ async fn run_server_command(
22432302 config_res. config . selected_role
22442303 } ;
22452304
2305+ // Parse and validate layer
2306+ let layer =
2307+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
2308+
22462309 let q = if let Some ( additional_terms) = terms {
22472310 // Multi-term query with logical operators
22482311 let search_terms: Vec < NormalizedTermValue > = additional_terms
@@ -2257,6 +2320,7 @@ async fn run_server_command(
22572320 skip : Some ( 0 ) ,
22582321 limit : Some ( limit) ,
22592322 role : Some ( role_name) ,
2323+ layer,
22602324 }
22612325 } else {
22622326 // Single term query (backward compatibility)
@@ -2267,6 +2331,7 @@ async fn run_server_command(
22672331 skip : Some ( 0 ) ,
22682332 limit : Some ( limit) ,
22692333 role : Some ( role_name) ,
2334+ layer,
22702335 }
22712336 } ;
22722337
@@ -2301,12 +2366,7 @@ async fn run_server_command(
23012366 results : res
23022367 . results
23032368 . iter ( )
2304- . map ( |doc| SearchDocumentOutput {
2305- id : doc. id . clone ( ) ,
2306- title : doc. title . clone ( ) ,
2307- url : doc. url . clone ( ) ,
2308- rank : doc. rank ,
2309- } )
2369+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
23102370 . collect ( ) ,
23112371 } ;
23122372 print_json_output ( & payload, output. mode ) ?;
@@ -3017,6 +3077,7 @@ fn ui_loop(
30173077 skip : Some ( 0 ) ,
30183078 limit : Some ( 10 ) ,
30193079 role : Some ( RoleName :: new ( & role) ) ,
3080+ layer : Layer :: default ( ) ,
30203081 } ;
30213082 let resp = api. search ( & q) . await ?;
30223083 let lines: Vec < String > = resp
0 commit comments