mirror of
https://github.com/siteboon/claudecodeui.git
synced 2025-12-12 21:29:42 +00:00
Enhance project directory handling by integrating extractProjectDirectory and clearProjectDirectoryCache functions. Adjust git route handlers to utilize the new directory extraction logic for improved project path resolution.
This commit is contained in:
@@ -2,6 +2,17 @@ const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const readline = require('readline');
|
||||
|
||||
// Cache for extracted project directories
|
||||
const projectDirectoryCache = new Map();
|
||||
let cacheTimestamp = Date.now();
|
||||
|
||||
// Clear cache when needed (called when project files change)
|
||||
function clearProjectDirectoryCache() {
|
||||
projectDirectoryCache.clear();
|
||||
cacheTimestamp = Date.now();
|
||||
console.log('🗑️ Project directory cache cleared');
|
||||
}
|
||||
|
||||
// Load project configuration file
|
||||
async function loadProjectConfig() {
|
||||
const configPath = path.join(process.env.HOME, '.claude', 'project-config.json');
|
||||
@@ -54,12 +65,20 @@ async function generateDisplayName(projectName, actualProjectDir = null) {
|
||||
return projectPath;
|
||||
}
|
||||
|
||||
// Extract the actual project directory from JSONL sessions
|
||||
// Extract the actual project directory from JSONL sessions (with caching)
|
||||
async function extractProjectDirectory(projectName) {
|
||||
// Check cache first
|
||||
if (projectDirectoryCache.has(projectName)) {
|
||||
return projectDirectoryCache.get(projectName);
|
||||
}
|
||||
|
||||
console.log(`🔍 Extracting project directory for: ${projectName}`);
|
||||
|
||||
const projectDir = path.join(process.env.HOME, '.claude', 'projects', projectName);
|
||||
const cwdCounts = new Map();
|
||||
let latestTimestamp = 0;
|
||||
let latestCwd = null;
|
||||
let extractedPath;
|
||||
|
||||
try {
|
||||
const files = await fs.readdir(projectDir);
|
||||
@@ -67,75 +86,87 @@ async function extractProjectDirectory(projectName) {
|
||||
|
||||
if (jsonlFiles.length === 0) {
|
||||
// Fall back to decoded project name if no sessions
|
||||
return projectName.replace(/-/g, '/');
|
||||
}
|
||||
|
||||
// Process all JSONL files to collect cwd values
|
||||
for (const file of jsonlFiles) {
|
||||
const jsonlFile = path.join(projectDir, file);
|
||||
const fileStream = require('fs').createReadStream(jsonlFile);
|
||||
const rl = readline.createInterface({
|
||||
input: fileStream,
|
||||
crlfDelay: Infinity
|
||||
});
|
||||
|
||||
for await (const line of rl) {
|
||||
if (line.trim()) {
|
||||
try {
|
||||
const entry = JSON.parse(line);
|
||||
|
||||
if (entry.cwd) {
|
||||
// Count occurrences of each cwd
|
||||
cwdCounts.set(entry.cwd, (cwdCounts.get(entry.cwd) || 0) + 1);
|
||||
extractedPath = projectName.replace(/-/g, '/');
|
||||
} else {
|
||||
// Process all JSONL files to collect cwd values
|
||||
for (const file of jsonlFiles) {
|
||||
const jsonlFile = path.join(projectDir, file);
|
||||
const fileStream = require('fs').createReadStream(jsonlFile);
|
||||
const rl = readline.createInterface({
|
||||
input: fileStream,
|
||||
crlfDelay: Infinity
|
||||
});
|
||||
|
||||
for await (const line of rl) {
|
||||
if (line.trim()) {
|
||||
try {
|
||||
const entry = JSON.parse(line);
|
||||
|
||||
// Track the most recent cwd
|
||||
const timestamp = new Date(entry.timestamp || 0).getTime();
|
||||
if (timestamp > latestTimestamp) {
|
||||
latestTimestamp = timestamp;
|
||||
latestCwd = entry.cwd;
|
||||
if (entry.cwd) {
|
||||
// Count occurrences of each cwd
|
||||
cwdCounts.set(entry.cwd, (cwdCounts.get(entry.cwd) || 0) + 1);
|
||||
|
||||
// Track the most recent cwd
|
||||
const timestamp = new Date(entry.timestamp || 0).getTime();
|
||||
if (timestamp > latestTimestamp) {
|
||||
latestTimestamp = timestamp;
|
||||
latestCwd = entry.cwd;
|
||||
}
|
||||
}
|
||||
} catch (parseError) {
|
||||
// Skip malformed lines
|
||||
}
|
||||
} catch (parseError) {
|
||||
// Skip malformed lines
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the best cwd to use
|
||||
if (cwdCounts.size === 0) {
|
||||
// No cwd found, fall back to decoded project name
|
||||
extractedPath = projectName.replace(/-/g, '/');
|
||||
} else if (cwdCounts.size === 1) {
|
||||
// Only one cwd, use it
|
||||
extractedPath = Array.from(cwdCounts.keys())[0];
|
||||
} else {
|
||||
// Multiple cwd values - prefer the most recent one if it has reasonable usage
|
||||
const mostRecentCount = cwdCounts.get(latestCwd) || 0;
|
||||
const maxCount = Math.max(...cwdCounts.values());
|
||||
|
||||
// Use most recent if it has at least 25% of the max count
|
||||
if (mostRecentCount >= maxCount * 0.25) {
|
||||
extractedPath = latestCwd;
|
||||
} else {
|
||||
// Otherwise use the most frequently used cwd
|
||||
for (const [cwd, count] of cwdCounts.entries()) {
|
||||
if (count === maxCount) {
|
||||
extractedPath = cwd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback (shouldn't reach here)
|
||||
if (!extractedPath) {
|
||||
extractedPath = latestCwd || projectName.replace(/-/g, '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the best cwd to use
|
||||
if (cwdCounts.size === 0) {
|
||||
// No cwd found, fall back to decoded project name
|
||||
return projectName.replace(/-/g, '/');
|
||||
}
|
||||
// Cache the result
|
||||
projectDirectoryCache.set(projectName, extractedPath);
|
||||
console.log(`💾 Cached project directory: ${projectName} -> ${extractedPath}`);
|
||||
|
||||
if (cwdCounts.size === 1) {
|
||||
// Only one cwd, use it
|
||||
return Array.from(cwdCounts.keys())[0];
|
||||
}
|
||||
|
||||
// Multiple cwd values - prefer the most recent one if it has reasonable usage
|
||||
const mostRecentCount = cwdCounts.get(latestCwd) || 0;
|
||||
const maxCount = Math.max(...cwdCounts.values());
|
||||
|
||||
// Use most recent if it has at least 25% of the max count
|
||||
if (mostRecentCount >= maxCount * 0.25) {
|
||||
return latestCwd;
|
||||
}
|
||||
|
||||
// Otherwise use the most frequently used cwd
|
||||
for (const [cwd, count] of cwdCounts.entries()) {
|
||||
if (count === maxCount) {
|
||||
return cwd;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback (shouldn't reach here)
|
||||
return latestCwd || projectName.replace(/-/g, '/');
|
||||
return extractedPath;
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error extracting project directory for ${projectName}:`, error);
|
||||
// Fall back to decoded project name
|
||||
return projectName.replace(/-/g, '/');
|
||||
extractedPath = projectName.replace(/-/g, '/');
|
||||
|
||||
// Cache the fallback result too
|
||||
projectDirectoryCache.set(projectName, extractedPath);
|
||||
|
||||
return extractedPath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,5 +613,6 @@ module.exports = {
|
||||
addProjectManually,
|
||||
loadProjectConfig,
|
||||
saveProjectConfig,
|
||||
extractProjectDirectory
|
||||
extractProjectDirectory,
|
||||
clearProjectDirectoryCache
|
||||
};
|
||||
Reference in New Issue
Block a user