Skip to content

Commit 45cc8c3

Browse files
AlexMikhalevAlex
andauthored
feat: Auto-import sessions on first use (#707)
* feat: auto-import sessions on first use (remove explicit import command) This change implements Option 1 for removing the explicit import command: - SessionService now auto-imports when cache is empty on first query - Removed 'sessions import' and 'sessions import-from' CLI commands - Removed '/sessions import' REPL command - Updated help text to reflect new behavior - Added enable_auto_import/disable_auto_import methods for testing - Sessions are automatically imported on list, search, stats, and sessions_by_source Breaking changes: - 'terraphim-agent sessions import' command removed - 'terraphim-agent sessions import-from' command removed - '/sessions import' REPL command removed (shows deprecation message) Benefits: - Simpler UX - no manual import step needed - Transparent to users - sessions just work - Reduced cognitive load - one less command to learn * ci: retrigger workflow after cancellation * ci: trigger workflow after runner restart * style: fix formatting and clippy warnings - Remove unnecessary return statement in commands.rs - Apply consistent import ordering and formatting --------- Co-authored-by: Alex <alex@example.com>
1 parent eceef77 commit 45cc8c3

4 files changed

Lines changed: 120 additions & 175 deletions

File tree

crates/terraphim_agent/src/main.rs

Lines changed: 10 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -806,35 +806,21 @@ fn get_session_cache_path() -> std::path::PathBuf {
806806
enum SessionsSub {
807807
/// Detect available session sources (Claude Code, Cursor, etc.)
808808
Sources,
809-
/// Import sessions from all available sources
810-
Import {
811-
/// Limit number of sessions to import
812-
#[arg(long, default_value_t = 100)]
813-
limit: usize,
814-
},
815-
/// Import sessions from a specific source
816-
ImportFrom {
817-
/// Source ID (e.g., "claude-code-native")
818-
source: String,
819-
/// Limit number of sessions to import
820-
#[arg(long, default_value_t = 100)]
821-
limit: usize,
822-
},
823-
/// List all cached sessions
809+
/// List all cached sessions (auto-imports if cache is empty)
824810
List {
825811
/// Limit number of sessions to show
826812
#[arg(long, default_value_t = 20)]
827813
limit: usize,
828814
},
829-
/// Search sessions by query string
815+
/// Search sessions by query string (auto-imports if cache is empty)
830816
Search {
831817
/// Search query
832818
query: String,
833819
/// Limit number of results
834820
#[arg(long, default_value_t = 10)]
835821
limit: usize,
836822
},
837-
/// Show session statistics
823+
/// Show session statistics (auto-imports if cache is empty)
838824
Stats,
839825
}
840826

@@ -1839,7 +1825,7 @@ async fn run_offline_command(
18391825

18401826
#[cfg(feature = "repl-sessions")]
18411827
Command::Sessions { sub } => {
1842-
use terraphim_sessions::{SessionService, connector::ImportOptions};
1828+
use terraphim_sessions::SessionService;
18431829

18441830
let service = SessionService::new();
18451831

@@ -1878,46 +1864,10 @@ async fn run_offline_command(
18781864
}
18791865
Ok(())
18801866
}
1881-
SessionsSub::Import { limit } => {
1882-
let options = ImportOptions {
1883-
limit: Some(limit),
1884-
..Default::default()
1885-
};
1886-
match service.import_all(&options).await {
1887-
Ok(sessions) => {
1888-
// Save to cache file
1889-
let cache_path = get_session_cache_path();
1890-
if let Ok(data) = serde_json::to_string_pretty(&sessions) {
1891-
let _ = std::fs::write(&cache_path, data);
1892-
}
1893-
println!("Imported {} sessions.", sessions.len());
1894-
Ok(())
1895-
}
1896-
Err(e) => Err(anyhow::anyhow!("Import failed: {}", e)),
1897-
}
1898-
}
1899-
SessionsSub::ImportFrom { source, limit } => {
1900-
let options = ImportOptions {
1901-
limit: Some(limit),
1902-
..Default::default()
1903-
};
1904-
match service.import_from(&source, &options).await {
1905-
Ok(sessions) => {
1906-
// Save to cache file
1907-
let cache_path = get_session_cache_path();
1908-
if let Ok(data) = serde_json::to_string_pretty(&sessions) {
1909-
let _ = std::fs::write(&cache_path, data);
1910-
}
1911-
println!("Imported {} sessions from {}.", sessions.len(), source);
1912-
Ok(())
1913-
}
1914-
Err(e) => Err(anyhow::anyhow!("Import from {} failed: {}", source, e)),
1915-
}
1916-
}
19171867
SessionsSub::List { limit } => {
19181868
let sessions = service.list_sessions().await;
19191869
if sessions.is_empty() {
1920-
println!("No sessions in cache. Import first with 'sessions import'.");
1870+
println!("No sessions found.");
19211871
} else {
19221872
println!("Cached sessions ({} total):", sessions.len());
19231873
for session in sessions.iter().take(limit) {
@@ -1934,10 +1884,7 @@ async fn run_offline_command(
19341884
SessionsSub::Search { query, limit } => {
19351885
let results = service.search(&query).await;
19361886
if results.is_empty() {
1937-
println!(
1938-
"No sessions matching '{}'. Import first with 'sessions import'.",
1939-
query
1940-
);
1887+
println!("No sessions matching '{}'.", query);
19411888
} else {
19421889
println!("Found {} matching sessions:", results.len());
19431890
for session in results.iter().take(limit) {
@@ -2613,7 +2560,7 @@ async fn run_server_command(
26132560

26142561
#[cfg(feature = "repl-sessions")]
26152562
Command::Sessions { sub } => {
2616-
use terraphim_sessions::{SessionService, connector::ImportOptions};
2563+
use terraphim_sessions::SessionService;
26172564

26182565
let rt = Runtime::new()?;
26192566
rt.block_on(async {
@@ -2641,46 +2588,11 @@ async fn run_server_command(
26412588
}
26422589
Ok(())
26432590
}
2644-
SessionsSub::Import { limit } => {
2645-
let options = ImportOptions {
2646-
limit: Some(limit),
2647-
..Default::default()
2648-
};
2649-
match service.import_all(&options).await {
2650-
Ok(sessions) => {
2651-
// Save to cache file
2652-
let cache_path = get_session_cache_path();
2653-
if let Ok(data) = serde_json::to_string_pretty(&sessions) {
2654-
let _ = std::fs::write(&cache_path, data);
2655-
}
2656-
println!("Imported {} sessions.", sessions.len());
2657-
Ok(())
2658-
}
2659-
Err(e) => Err(anyhow::anyhow!("Import failed: {}", e)),
2660-
}
2661-
}
2662-
SessionsSub::ImportFrom { source, limit } => {
2663-
let options = ImportOptions {
2664-
limit: Some(limit),
2665-
..Default::default()
2666-
};
2667-
match service.import_from(&source, &options).await {
2668-
Ok(sessions) => {
2669-
// Save to cache file
2670-
let cache_path = get_session_cache_path();
2671-
if let Ok(data) = serde_json::to_string_pretty(&sessions) {
2672-
let _ = std::fs::write(&cache_path, data);
2673-
}
2674-
println!("Imported {} sessions from {}.", sessions.len(), source);
2675-
Ok(())
2676-
}
2677-
Err(e) => Err(anyhow::anyhow!("Import from {} failed: {}", source, e)),
2678-
}
2679-
}
2591+
26802592
SessionsSub::List { limit } => {
26812593
let sessions = service.list_sessions().await;
26822594
if sessions.is_empty() {
2683-
println!("No sessions in cache. Import first with 'sessions import'.");
2595+
println!("No sessions found.");
26842596
} else {
26852597
println!("Cached sessions ({} total):", sessions.len());
26862598
for session in sessions.iter().take(limit) {
@@ -2697,10 +2609,7 @@ async fn run_server_command(
26972609
SessionsSub::Search { query, limit } => {
26982610
let results = service.search(&query).await;
26992611
if results.is_empty() {
2700-
println!(
2701-
"No sessions matching '{}'. Import first with 'sessions import'.",
2702-
query
2703-
);
2612+
println!("No sessions matching '{}'.", query);
27042613
} else {
27052614
println!("Found {} matching sessions:", results.len());
27062615
for session in results.iter().take(limit) {

crates/terraphim_agent/src/repl/commands.rs

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,7 @@ pub enum FileSubcommand {
155155
pub enum SessionsSubcommand {
156156
/// Detect available session sources
157157
Sources,
158-
/// Import sessions from a source
159-
Import {
160-
source: Option<String>,
161-
limit: Option<usize>,
162-
},
163-
/// List imported sessions
158+
/// List imported sessions (auto-imports if cache is empty)
164159
List {
165160
source: Option<String>,
166161
limit: Option<usize>,
@@ -1105,47 +1100,9 @@ impl FromStr for ReplCommand {
11051100
"sources" | "detect" => Ok(ReplCommand::Sessions {
11061101
subcommand: SessionsSubcommand::Sources,
11071102
}),
1108-
"import" => {
1109-
let mut source = None;
1110-
let mut limit = None;
1111-
let mut i = 2;
1112-
1113-
while i < parts.len() {
1114-
match parts[i] {
1115-
"--source" => {
1116-
if i + 1 < parts.len() {
1117-
source = Some(parts[i + 1].to_string());
1118-
i += 2;
1119-
} else {
1120-
return Err(anyhow!("--source requires a value"));
1121-
}
1122-
}
1123-
"--limit" => {
1124-
if i + 1 < parts.len() {
1125-
limit = Some(
1126-
parts[i + 1]
1127-
.parse::<usize>()
1128-
.map_err(|_| anyhow!("Invalid limit value"))?,
1129-
);
1130-
i += 2;
1131-
} else {
1132-
return Err(anyhow!("--limit requires a value"));
1133-
}
1134-
}
1135-
_ => {
1136-
// Treat as source if no flag prefix
1137-
if source.is_none() && !parts[i].starts_with("--") {
1138-
source = Some(parts[i].to_string());
1139-
}
1140-
i += 1;
1141-
}
1142-
}
1143-
}
1144-
1145-
Ok(ReplCommand::Sessions {
1146-
subcommand: SessionsSubcommand::Import { source, limit },
1147-
})
1148-
}
1103+
"import" => Err(anyhow!(
1104+
"The 'import' command has been removed. Sessions are now automatically imported when needed. Use '/sessions list' or '/sessions search <query>' instead."
1105+
)),
11491106
"list" | "ls" => {
11501107
let mut source = None;
11511108
let mut limit = None;
@@ -1345,7 +1302,7 @@ impl FromStr for ReplCommand {
13451302
})
13461303
}
13471304
_ => Err(anyhow!(
1348-
"Unknown sessions subcommand: {}. Use: sources, import, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file",
1305+
"Unknown sessions subcommand: {}. Use: sources, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file",
13491306
parts[1]
13501307
)),
13511308
}
@@ -1502,7 +1459,7 @@ impl ReplCommand {
15021459

15031460
#[cfg(feature = "repl-sessions")]
15041461
"sessions" => Some(
1505-
"/sessions <subcommand> - AI coding session history (sources, import, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file)",
1462+
"/sessions <subcommand> - AI coding session history (sources, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file)",
15061463
),
15071464

15081465
_ => None,

crates/terraphim_agent/src/repl/handler.rs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,7 +1766,7 @@ impl ReplHandler {
17661766
use comfy_table::presets::UTF8_FULL;
17671767
use comfy_table::{Cell, Table};
17681768
use terraphim_sessions::{
1769-
ConnectorStatus, FileAccess, ImportOptions, MessageRole, Session, SessionService,
1769+
ConnectorStatus, FileAccess, MessageRole, Session, SessionService,
17701770
};
17711771

17721772
// Get or create session service
@@ -1820,24 +1820,6 @@ impl ReplHandler {
18201820
println!("{}", table);
18211821
}
18221822

1823-
SessionsSubcommand::Import { source, limit } => {
1824-
let options = ImportOptions::new().with_limit(limit.unwrap_or(100));
1825-
1826-
println!("\n{} Importing sessions...", "⏳".bold());
1827-
1828-
let sessions = if let Some(source_id) = source {
1829-
svc.import_from(&source_id, &options).await?
1830-
} else {
1831-
svc.import_all(&options).await?
1832-
};
1833-
1834-
println!(
1835-
"{} Imported {} session(s)",
1836-
"✅".bold(),
1837-
sessions.len().to_string().green()
1838-
);
1839-
}
1840-
18411823
SessionsSubcommand::List { source, limit } => {
18421824
let sessions = if let Some(source_id) = source {
18431825
svc.sessions_by_source(&source_id).await
@@ -1852,10 +1834,7 @@ impl ReplHandler {
18521834
};
18531835

18541836
if sessions.is_empty() {
1855-
println!(
1856-
"{} No sessions found. Run '/sessions import' first.",
1857-
"ℹ".blue().bold()
1858-
);
1837+
println!("{} No sessions found.", "ℹ".blue().bold());
18591838
return Ok(());
18601839
}
18611840

0 commit comments

Comments
 (0)