Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/terraphim-session-analyzer/src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ impl Analyzer {
match self.analyze_session(parser, target_file) {
Ok(analysis) => {
// If target file specified, only include sessions with relevant operations
if let Some(_target) = target_file {
if analysis.file_operations.is_empty() {
return None; // Skip sessions without target file operations
}
if let Some(_target) = target_file
&& analysis.file_operations.is_empty()
{
return None; // Skip sessions without target file operations
}
Some(Ok(analysis))
}
Expand Down
24 changes: 12 additions & 12 deletions crates/terraphim-session-analyzer/src/connectors/aider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,10 @@ impl SessionConnector for AiderConnector {
.is_some_and(|n| n == ".aider.chat.history.md")
})
{
if let Some(limit) = options.limit {
if sessions.len() >= limit {
break;
}
if let Some(limit) = options.limit
&& sessions.len() >= limit
{
break;
}

match self.parse_history_file(entry.path()) {
Expand All @@ -122,10 +122,10 @@ impl AiderConnector {
// New session starts with "# aider chat started at"
if line.starts_with("# aider chat started at") {
// Save previous session if exists
if let Some(builder) = current_session.take() {
if let Some(session) = builder.build(path) {
sessions.push(session);
}
if let Some(builder) = current_session.take()
&& let Some(session) = builder.build(path)
{
sessions.push(session);
}

// Parse timestamp: "# aider chat started at 2025-06-19 14:32:16"
Expand All @@ -137,10 +137,10 @@ impl AiderConnector {
}

// Don't forget the last session
if let Some(builder) = current_session {
if let Some(session) = builder.build(path) {
sessions.push(session);
}
if let Some(builder) = current_session
&& let Some(session) = builder.build(path)
{
sessions.push(session);
}

Ok(sessions)
Expand Down
8 changes: 4 additions & 4 deletions crates/terraphim-session-analyzer/src/connectors/codex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,10 @@ impl SessionConnector for CodexConnector {
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "jsonl"))
{
if let Some(limit) = options.limit {
if sessions.len() >= limit {
break;
}
if let Some(limit) = options.limit
&& sessions.len() >= limit
{
break;
}

match self.parse_session_file(entry.path()) {
Expand Down
10 changes: 5 additions & 5 deletions crates/terraphim-session-analyzer/src/connectors/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,11 @@ impl SessionConnector for CursorConnector {
}

// Apply limit if specified
if let Some(limit) = options.limit {
if sessions.len() >= limit {
sessions.truncate(limit);
break;
}
if let Some(limit) = options.limit
&& sessions.len() >= limit
{
sessions.truncate(limit);
break;
}
}

Expand Down
39 changes: 19 additions & 20 deletions crates/terraphim-session-analyzer/src/connectors/opencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,30 +86,29 @@ impl SessionConnector for OpenCodeConnector {
if line.trim().is_empty() {
continue;
}
if let Ok(entry) = serde_json::from_str::<OpenCodeEntry>(line) {
if let Some(input) = entry.input {
if !input.is_empty() {
messages.push(NormalizedMessage {
idx,
role: "user".to_string(),
author: None,
content: input,
created_at: None,
extra: serde_json::json!({
"mode": entry.mode,
"parts": entry.parts,
}),
});
}
}
if let Ok(entry) = serde_json::from_str::<OpenCodeEntry>(line)
&& let Some(input) = entry.input
&& !input.is_empty()
{
messages.push(NormalizedMessage {
idx,
role: "user".to_string(),
author: None,
content: input,
created_at: None,
extra: serde_json::json!({
"mode": entry.mode,
"parts": entry.parts,
}),
});
}
}

// Apply limit if specified
if let Some(limit) = options.limit {
if limit > 0 {
messages.truncate(limit);
}
if let Some(limit) = options.limit
&& limit > 0
{
messages.truncate(limit);
}

if messages.is_empty() {
Expand Down
111 changes: 53 additions & 58 deletions crates/terraphim-session-analyzer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,10 @@ fn list_sessions(cli: &Cli, detailed: bool, project_filter: Option<&str>) -> Res

for analysis in &analyses {
// Apply project filter if specified
if let Some(filter) = &project_filter {
if !analysis.project_path.contains(filter) {
continue;
}
if let Some(filter) = &project_filter
&& !analysis.project_path.contains(filter)
{
continue;
}

println!("{} {}", "Session:".bold(), analysis.session_id.yellow());
Expand Down Expand Up @@ -401,7 +401,7 @@ fn list_sessions(cli: &Cli, detailed: bool, project_filter: Option<&str>) -> Res
.filter(|a| {
project_filter
.as_ref()
.map_or(true, |f| a.project_path.contains(f))
.is_none_or(|f| a.project_path.contains(f))
})
.count()
} else {
Expand Down Expand Up @@ -1003,24 +1003,22 @@ fn analyze_tools(
.into_iter()
.filter(|(name, stats)| {
// Tool name filter
if let Some(tool_filter_str) = tool_filter {
if !name
if let Some(tool_filter_str) = tool_filter
&& !name
.to_lowercase()
.contains(&tool_filter_str.to_lowercase())
{
return false;
}
{
return false;
}

// Agent filter
if let Some(agent_filter_str) = agent_filter {
if !stats
if let Some(agent_filter_str) = agent_filter
&& !stats
.agents_using
.iter()
.any(|a| a.to_lowercase().contains(&agent_filter_str.to_lowercase()))
{
return false;
}
{
return false;
}

// Minimum usage filter
Expand Down Expand Up @@ -1124,12 +1122,12 @@ fn find_session_path(session_id: &str, cli: &Cli) -> Result<PathBuf> {
.into_iter()
.filter_map(|e| e.ok())
{
if entry.file_type().is_file() {
if let Some(name) = entry.file_name().to_str() {
if name.ends_with(".jsonl") && name.contains(session_id) {
return Ok(entry.path().to_path_buf());
}
}
if entry.file_type().is_file()
&& let Some(name) = entry.file_name().to_str()
&& name.ends_with(".jsonl")
&& name.contains(session_id)
{
return Ok(entry.path().to_path_buf());
}
}

Expand All @@ -1147,43 +1145,40 @@ fn extract_tool_invocations_from_session(
for entry in parser.entries() {
if let Message::Assistant { content, .. } = &entry.message {
for block in content {
if let ContentBlock::ToolUse { name, input, .. } = block {
if name == "Bash" {
if let Some(command) = input.get("command").and_then(|v| v.as_str()) {
let matches = matcher.find_matches(command);

for tool_match in matches {
// Parse the command context
if let Some((full_cmd, args, flags)) =
tool_analyzer::parse_command_context(command, tool_match.start)
{
if let Ok(timestamp) = models::parse_timestamp(&entry.timestamp)
{
// Map category string to ToolCategory enum
let category = match tool_match.category.as_str() {
"package-manager" => ToolCategory::PackageManager,
"version-control" => ToolCategory::Git,
"testing" => ToolCategory::Testing,
"linting" => ToolCategory::Linting,
"cloudflare" => ToolCategory::CloudDeploy,
_ => ToolCategory::Other(tool_match.category.clone()),
};

invocations.push(ToolInvocation {
timestamp,
tool_name: tool_match.tool_name.clone(),
tool_category: category,
command_line: full_cmd,
arguments: args,
flags,
exit_code: None,
agent_context: None,
session_id: entry.session_id.clone(),
message_id: entry.uuid.clone(),
});
}
}
}
if let ContentBlock::ToolUse { name, input, .. } = block
&& name == "Bash"
&& let Some(command) = input.get("command").and_then(|v| v.as_str())
{
let matches = matcher.find_matches(command);

for tool_match in matches {
// Parse the command context
if let Some((full_cmd, args, flags)) =
tool_analyzer::parse_command_context(command, tool_match.start)
&& let Ok(timestamp) = models::parse_timestamp(&entry.timestamp)
{
// Map category string to ToolCategory enum
let category = match tool_match.category.as_str() {
"package-manager" => ToolCategory::PackageManager,
"version-control" => ToolCategory::Git,
"testing" => ToolCategory::Testing,
"linting" => ToolCategory::Linting,
"cloudflare" => ToolCategory::CloudDeploy,
_ => ToolCategory::Other(tool_match.category.clone()),
};

invocations.push(ToolInvocation {
timestamp,
tool_name: tool_match.tool_name.clone(),
tool_category: category,
command_line: full_cmd,
arguments: args,
flags,
exit_code: None,
agent_context: None,
session_id: entry.session_id.clone(),
message_id: entry.uuid.clone(),
});
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions crates/terraphim-session-analyzer/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,12 +440,11 @@ pub fn extract_file_path(input: &serde_json::Value) -> Option<String> {
}

// For MultiEdit, check the edits array
if let Some(edits) = input.get("edits").and_then(|v| v.as_array()) {
if !edits.is_empty() {
if let Some(file_path) = input.get("file_path").and_then(|v| v.as_str()) {
return Some(file_path.to_string());
}
}
if let Some(edits) = input.get("edits").and_then(|v| v.as_array())
&& !edits.is_empty()
&& let Some(file_path) = input.get("file_path").and_then(|v| v.as_str())
{
return Some(file_path.to_string());
}

None
Expand Down
Loading
Loading