@@ -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 {
@@ -1130,13 +1172,18 @@ async fn run_offline_command(
11301172 operator,
11311173 role,
11321174 limit,
1175+ layer,
11331176 } => {
11341177 let role_name = if let Some ( role) = role {
11351178 RoleName :: new ( & role)
11361179 } else {
11371180 service. get_selected_role ( ) . await
11381181 } ;
11391182
1183+ // Parse and validate layer
1184+ let layer =
1185+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
1186+
11401187 let results = if let Some ( additional_terms) = terms {
11411188 // Multi-term query with logical operators
11421189 let mut all_terms = vec ! [ query. clone( ) ] ;
@@ -1170,6 +1217,7 @@ async fn run_offline_command(
11701217 skip : Some ( 0 ) ,
11711218 limit : Some ( limit) ,
11721219 role : Some ( role_name. clone ( ) ) ,
1220+ layer,
11731221 } ;
11741222
11751223 service. search_with_query ( & search_query) . await ?
@@ -1182,23 +1230,33 @@ async fn run_offline_command(
11821230
11831231 if output. is_machine_readable ( ) {
11841232 let payload = SearchOutput {
1185- query,
1233+ query : query . clone ( ) ,
11861234 role : role_name. to_string ( ) ,
11871235 count : results. len ( ) ,
11881236 results : results
11891237 . iter ( )
1190- . map ( |doc| SearchDocumentOutput {
1191- id : doc. id . clone ( ) ,
1192- title : doc. title . clone ( ) ,
1193- url : doc. url . clone ( ) ,
1194- rank : doc. rank ,
1195- } )
1238+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
11961239 . collect ( ) ,
11971240 } ;
11981241 print_json_output ( & payload, output. mode ) ?;
11991242 } else {
12001243 for doc in results. iter ( ) {
1201- println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1244+ match layer {
1245+ Layer :: One => {
1246+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1247+ }
1248+ Layer :: Two => {
1249+ let summary = extract_first_paragraph ( & doc. body ) ;
1250+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1251+ println ! ( " {}" , summary) ;
1252+ }
1253+ Layer :: Three => {
1254+ println ! ( "- {}\t {}" , doc. rank. unwrap_or_default( ) , doc. title) ;
1255+ if let Some ( ref tags) = doc. tags {
1256+ println ! ( " Tags: {}" , tags. join( ", " ) ) ;
1257+ }
1258+ }
1259+ }
12021260 }
12031261 }
12041262 Ok ( ( ) )
@@ -2172,6 +2230,7 @@ async fn run_server_command(
21722230 operator,
21732231 role,
21742232 limit,
2233+ layer,
21752234 } => {
21762235 // Get selected role from server if not specified
21772236 let role_name = if let Some ( role) = role {
@@ -2181,6 +2240,10 @@ async fn run_server_command(
21812240 config_res. config . selected_role
21822241 } ;
21832242
2243+ // Parse and validate layer
2244+ let layer =
2245+ terraphim_types:: Layer :: from_u8 ( layer) . unwrap_or ( terraphim_types:: Layer :: Three ) ;
2246+
21842247 let q = if let Some ( additional_terms) = terms {
21852248 // Multi-term query with logical operators
21862249 let search_terms: Vec < NormalizedTermValue > = additional_terms
@@ -2195,6 +2258,7 @@ async fn run_server_command(
21952258 skip : Some ( 0 ) ,
21962259 limit : Some ( limit) ,
21972260 role : Some ( role_name) ,
2261+ layer,
21982262 }
21992263 } else {
22002264 // Single term query (backward compatibility)
@@ -2205,6 +2269,7 @@ async fn run_server_command(
22052269 skip : Some ( 0 ) ,
22062270 limit : Some ( limit) ,
22072271 role : Some ( role_name) ,
2272+ layer,
22082273 }
22092274 } ;
22102275
@@ -2239,12 +2304,7 @@ async fn run_server_command(
22392304 results : res
22402305 . results
22412306 . iter ( )
2242- . map ( |doc| SearchDocumentOutput {
2243- id : doc. id . clone ( ) ,
2244- title : doc. title . clone ( ) ,
2245- url : doc. url . clone ( ) ,
2246- rank : doc. rank ,
2247- } )
2307+ . map ( |doc| SearchDocumentOutput :: from_document ( doc, & layer) )
22482308 . collect ( ) ,
22492309 } ;
22502310 print_json_output ( & payload, output. mode ) ?;
@@ -2955,6 +3015,7 @@ fn ui_loop(
29553015 skip : Some ( 0 ) ,
29563016 limit : Some ( 10 ) ,
29573017 role : Some ( RoleName :: new ( & role) ) ,
3018+ layer : Layer :: default ( ) ,
29583019 } ;
29593020 let resp = api. search ( & q) . await ?;
29603021 let lines: Vec < String > = resp
0 commit comments