Skip to content

Commit d623c66

Browse files
committed
feat(sessions): add Files and ByFile subcommands to terraphim-agent
Add SessionsSubcommand::Files { session_id, json } variant Add SessionsSubcommand::ByFile { file_path, json } variant Add command parsing for new subcommands with --json flag support Add handler methods with table and JSON output Export FileAccess and FileOperation from terraphim_sessions Part of: #611
1 parent bd3bc67 commit d623c66

68 files changed

Lines changed: 23338 additions & 4 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

crates/terraphim_agent/src/repl/commands.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ pub enum SessionsSubcommand {
191191
},
192192
/// Enrich sessions with concepts (Phase 3)
193193
Enrich { session_id: Option<String> },
194+
/// List files accessed by a session
195+
Files { session_id: String, json: bool },
196+
/// Find sessions by file path
197+
ByFile { file_path: String, json: bool },
194198
}
195199

196200
#[derive(Debug, Clone, PartialEq)]
@@ -1320,8 +1324,28 @@ impl FromStr for ReplCommand {
13201324
subcommand: SessionsSubcommand::Enrich { session_id },
13211325
})
13221326
}
1327+
"files" => {
1328+
if parts.len() < 3 {
1329+
return Err(anyhow!("Sessions files requires a session ID"));
1330+
}
1331+
let session_id = parts[2].to_string();
1332+
let json = parts.iter().any(|&p| p == "--json");
1333+
Ok(ReplCommand::Sessions {
1334+
subcommand: SessionsSubcommand::Files { session_id, json },
1335+
})
1336+
}
1337+
"by-file" => {
1338+
if parts.len() < 3 {
1339+
return Err(anyhow!("Sessions by-file requires a file path"));
1340+
}
1341+
let file_path = parts[2].to_string();
1342+
let json = parts.iter().any(|&p| p == "--json");
1343+
Ok(ReplCommand::Sessions {
1344+
subcommand: SessionsSubcommand::ByFile { file_path, json },
1345+
})
1346+
}
13231347
_ => Err(anyhow!(
1324-
"Unknown sessions subcommand: {}. Use: sources, import, list, search, stats, show, concepts, related, timeline, export, enrich",
1348+
"Unknown sessions subcommand: {}. Use: sources, import, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file",
13251349
parts[1]
13261350
)),
13271351
}
@@ -1478,7 +1502,7 @@ impl ReplCommand {
14781502

14791503
#[cfg(feature = "repl-sessions")]
14801504
"sessions" => Some(
1481-
"/sessions <subcommand> - AI coding session history (sources, import, list, search, stats, show, concepts, related, timeline, export, enrich)",
1505+
"/sessions <subcommand> - AI coding session history (sources, import, list, search, stats, show, concepts, related, timeline, export, enrich, files, by-file)",
14821506
),
14831507

14841508
_ => None,

crates/terraphim_agent/src/repl/handler.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1761,11 +1761,12 @@ impl ReplHandler {
17611761
#[cfg(feature = "repl-sessions")]
17621762
async fn handle_sessions(&mut self, subcommand: SessionsSubcommand) -> Result<()> {
17631763
use colored::Colorize;
1764+
use comfy_table::Color;
17641765
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
17651766
use comfy_table::presets::UTF8_FULL;
17661767
use comfy_table::{Cell, Table};
17671768
use terraphim_sessions::{
1768-
ConnectorStatus, ImportOptions, MessageRole, Session, SessionService,
1769+
ConnectorStatus, FileAccess, ImportOptions, MessageRole, Session, SessionService,
17691770
};
17701771

17711772
// Get or create session service
@@ -2358,6 +2359,109 @@ impl ReplHandler {
23582359
);
23592360
}
23602361
}
2362+
2363+
SessionsSubcommand::Files { session_id, json } => {
2364+
if let Some(files) = svc.extract_files(&session_id).await {
2365+
if files.is_empty() {
2366+
println!(
2367+
"{} No files found in session {}",
2368+
"ℹ".blue(),
2369+
session_id.cyan()
2370+
);
2371+
} else if json {
2372+
match serde_json::to_string_pretty(&files) {
2373+
Ok(output) => println!("{}", output),
2374+
Err(e) => println!("{} Failed to serialize: {}", "✗".red().bold(), e),
2375+
}
2376+
} else {
2377+
println!("\n{} Files in session {}:", "📁".bold(), session_id.cyan());
2378+
println!();
2379+
2380+
let mut table = Table::new();
2381+
table
2382+
.load_preset(UTF8_FULL)
2383+
.apply_modifier(UTF8_ROUND_CORNERS)
2384+
.set_header(vec![
2385+
Cell::new("Path").add_attribute(comfy_table::Attribute::Bold),
2386+
Cell::new("Operation").add_attribute(comfy_table::Attribute::Bold),
2387+
Cell::new("Tool").add_attribute(comfy_table::Attribute::Bold),
2388+
]);
2389+
2390+
for FileAccess {
2391+
path,
2392+
operation,
2393+
tool_name,
2394+
..
2395+
} in files
2396+
{
2397+
let op_cell = match operation {
2398+
terraphim_sessions::FileOperation::Read => {
2399+
Cell::new("read").fg(Color::Green)
2400+
}
2401+
terraphim_sessions::FileOperation::Write => {
2402+
Cell::new("write").fg(Color::Yellow)
2403+
}
2404+
};
2405+
table.add_row(vec![
2406+
Cell::new(path),
2407+
op_cell,
2408+
Cell::new(tool_name).fg(Color::Cyan),
2409+
]);
2410+
}
2411+
println!("{}", table);
2412+
}
2413+
} else {
2414+
println!("{} Session '{}' not found", "⚠".yellow().bold(), session_id);
2415+
}
2416+
}
2417+
2418+
SessionsSubcommand::ByFile { file_path, json } => {
2419+
let sessions = svc.sessions_by_file(&file_path).await;
2420+
if sessions.is_empty() {
2421+
println!(
2422+
"{} No sessions found that touched '{}'",
2423+
"ℹ".blue(),
2424+
file_path.cyan()
2425+
);
2426+
} else if json {
2427+
match serde_json::to_string_pretty(&sessions) {
2428+
Ok(output) => println!("{}", output),
2429+
Err(e) => println!("{} Failed to serialize: {}", "✗".red().bold(), e),
2430+
}
2431+
} else {
2432+
println!(
2433+
"\n{} Sessions that touched '{}':",
2434+
"📂".bold(),
2435+
file_path.cyan()
2436+
);
2437+
println!();
2438+
2439+
let mut table = Table::new();
2440+
table
2441+
.load_preset(UTF8_FULL)
2442+
.apply_modifier(UTF8_ROUND_CORNERS)
2443+
.set_header(vec![
2444+
Cell::new("ID").add_attribute(comfy_table::Attribute::Bold),
2445+
Cell::new("Source").add_attribute(comfy_table::Attribute::Bold),
2446+
Cell::new("Title").add_attribute(comfy_table::Attribute::Bold),
2447+
Cell::new("Messages").add_attribute(comfy_table::Attribute::Bold),
2448+
]);
2449+
2450+
for session in sessions {
2451+
let title = session
2452+
.title
2453+
.clone()
2454+
.unwrap_or_else(|| "(no title)".to_string());
2455+
table.add_row(vec![
2456+
Cell::new(&session.id).fg(Color::Cyan),
2457+
Cell::new(&session.source).fg(Color::Magenta),
2458+
Cell::new(title),
2459+
Cell::new(session.message_count().to_string()),
2460+
]);
2461+
}
2462+
println!("{}", table);
2463+
}
2464+
}
23612465
}
23622466

23632467
Ok(())

crates/terraphim_sessions/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ pub mod enrichment;
3939

4040
// Re-exports for convenience
4141
pub use connector::{ConnectorRegistry, ConnectorStatus, ImportOptions, SessionConnector};
42-
pub use model::{ContentBlock, Message, MessageRole, Session, SessionMetadata};
42+
pub use model::{
43+
ContentBlock, FileAccess, FileOperation, Message, MessageRole, Session, SessionMetadata,
44+
};
4345
pub use service::SessionService;
4446

4547
#[cfg(feature = "enrichment")]

0 commit comments

Comments
 (0)