@@ -72,8 +72,20 @@ enum Command {
7272 path : Option < PathBuf > ,
7373 } ,
7474
75- /// Interactively configure vault profile.
76- Configure ,
75+ /// Configure engraph settings.
76+ Configure {
77+ /// Enable intelligence features.
78+ #[ arg( long, conflicts_with = "disable_intelligence" ) ]
79+ enable_intelligence : bool ,
80+
81+ /// Disable intelligence features.
82+ #[ arg( long, conflicts_with = "enable_intelligence" ) ]
83+ disable_intelligence : bool ,
84+
85+ /// Override a model: --model embed|rerank|expand <uri>
86+ #[ arg( long, num_args = 2 , value_names = & [ "TYPE" , "URI" ] ) ]
87+ model : Option < Vec < String > > ,
88+ } ,
7789
7890 /// Manage embedding models.
7991 Models {
@@ -206,6 +218,38 @@ enum ModelsAction {
206218 Info { name : String } ,
207219}
208220
221+ /// Prompt user to enable intelligence, download models if yes.
222+ fn prompt_intelligence ( data_dir : & std:: path:: Path ) -> Result < bool > {
223+ eprint ! (
224+ "\n Enable AI-powered search intelligence?\n \n \
225+ This downloads ~1.3GB of additional models for:\n \
226+ \x20 - Query expansion (rewrites your search into multiple variations)\n \
227+ \x20 - Result reranking (LLM scores each result for relevance)\n \n \
228+ Enable now? [y/N] "
229+ ) ;
230+ io:: stderr ( ) . flush ( ) ?;
231+ let mut answer = String :: new ( ) ;
232+ io:: stdin ( ) . lock ( ) . read_line ( & mut answer) ?;
233+ let enable = answer. trim ( ) . eq_ignore_ascii_case ( "y" ) ;
234+
235+ if enable {
236+ let models_dir = data_dir. join ( "models" ) ;
237+ let defaults = engraph:: llm:: ModelDefaults :: default ( ) ;
238+ println ! ( "Downloading intelligence models (~1.3GB)..." ) ;
239+ let rerank_uri = engraph:: llm:: HfModelUri :: parse ( & defaults. rerank_uri ) ?;
240+ engraph:: llm:: ensure_model ( & rerank_uri, & models_dir) ?;
241+ let expand_uri = engraph:: llm:: HfModelUri :: parse ( & defaults. expand_uri ) ?;
242+ engraph:: llm:: ensure_model ( & expand_uri, & models_dir) ?;
243+ println ! ( "Done." ) ;
244+ } else {
245+ println ! (
246+ "Intelligence disabled. You can enable later with: engraph configure --enable-intelligence"
247+ ) ;
248+ }
249+
250+ Ok ( enable)
251+ }
252+
209253/// Check whether an index has been built by looking for engraph.db in data_dir.
210254fn index_exists ( data_dir : & std:: path:: Path ) -> bool {
211255 data_dir. join ( "engraph.db" ) . exists ( )
@@ -294,6 +338,13 @@ async fn main() -> Result<()> {
294338 }
295339 }
296340
341+ // First-run intelligence prompt (only if not yet configured)
342+ if cfg. intelligence . is_none ( ) {
343+ let enable = prompt_intelligence ( & data_dir) ?;
344+ cfg. intelligence = Some ( enable) ;
345+ cfg. save ( ) ?;
346+ }
347+
297348 let result = indexer:: run_index ( & vault_path, & cfg, rebuild) ?;
298349
299350 println ! (
@@ -413,11 +464,74 @@ async fn main() -> Result<()> {
413464
414465 println ! ( ) ;
415466 println ! ( "Wrote {}" , data_dir. join( "vault.toml" ) . display( ) ) ;
467+
468+ // Intelligence onboarding (only if not yet configured)
469+ if cfg. intelligence . is_none ( ) {
470+ let enable = prompt_intelligence ( & data_dir) ?;
471+ cfg. intelligence = Some ( enable) ;
472+ cfg. save ( ) ?;
473+ }
416474 }
417475
418- Command :: Configure => {
476+ Command :: Configure {
477+ enable_intelligence,
478+ disable_intelligence,
479+ model,
480+ } => {
481+ let mut cfg = Config :: load ( ) ?;
482+
483+ if enable_intelligence {
484+ cfg. intelligence = Some ( true ) ;
485+ println ! ( "Intelligence enabled. Models will be downloaded on first search." ) ;
486+ let models_dir = data_dir. join ( "models" ) ;
487+ let defaults = engraph:: llm:: ModelDefaults :: default ( ) ;
488+ println ! ( "Downloading intelligence models (~1.3GB)..." ) ;
489+ let rerank_uri = engraph:: llm:: HfModelUri :: parse (
490+ cfg. models . rerank . as_deref ( ) . unwrap_or ( & defaults. rerank_uri ) ,
491+ ) ?;
492+ engraph:: llm:: ensure_model ( & rerank_uri, & models_dir) ?;
493+ let expand_uri = engraph:: llm:: HfModelUri :: parse (
494+ cfg. models . expand . as_deref ( ) . unwrap_or ( & defaults. expand_uri ) ,
495+ ) ?;
496+ engraph:: llm:: ensure_model ( & expand_uri, & models_dir) ?;
497+ println ! ( "Done." ) ;
498+ } else if disable_intelligence {
499+ cfg. intelligence = Some ( false ) ;
500+ println ! ( "Intelligence disabled. Models remain cached." ) ;
501+ }
502+
503+ if let Some ( parts) = model
504+ && parts. len ( ) == 2
505+ {
506+ let model_type = & parts[ 0 ] ;
507+ let uri = & parts[ 1 ] ;
508+ engraph:: llm:: HfModelUri :: parse ( uri) ?;
509+ match model_type. as_str ( ) {
510+ "embed" => {
511+ cfg. models . embed = Some ( uri. clone ( ) ) ;
512+ println ! ( "Embedding model set to: {uri}" ) ;
513+ println ! ( "Warning: Next 'engraph index' will re-embed your entire vault." ) ;
514+ }
515+ "rerank" => {
516+ cfg. models . rerank = Some ( uri. clone ( ) ) ;
517+ println ! ( "Reranker model set to: {uri}" ) ;
518+ }
519+ "expand" => {
520+ cfg. models . expand = Some ( uri. clone ( ) ) ;
521+ println ! ( "Expansion model set to: {uri}" ) ;
522+ }
523+ other => {
524+ anyhow:: bail!(
525+ "Unknown model type: {other}. Use: embed, rerank, or expand."
526+ ) ;
527+ }
528+ }
529+ }
530+
531+ cfg. save ( ) ?;
419532 println ! (
420- "Interactive configuration not yet implemented. Run 'engraph init' for auto-detection."
533+ "Configuration saved to {}" ,
534+ data_dir. join( "config.toml" ) . display( )
421535 ) ;
422536 }
423537
0 commit comments