mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-30 06:12:03 +00:00
refactor: sanitize featureId for worktree paths across multiple handlers
- Updated createDiffsHandler, createFileDiffHandler, createInfoHandler, createStatusHandler, and auto-mode service to sanitize featureId when constructing worktree paths. - Ensured consistent handling of featureId to prevent issues with invalid characters in branch names. - Added branchName support in UI components to enhance feature visibility and management. This change improves the robustness of worktree operations and enhances user experience by ensuring valid paths are used throughout the application.
This commit is contained in:
@@ -39,7 +39,10 @@ export function createDiffsHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Git worktrees are stored in project directory
|
// Git worktrees are stored in project directory
|
||||||
const worktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
// (see create.ts: branchName.replace(/[^a-zA-Z0-9_-]/g, '-'))
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Check if worktree exists
|
// Check if worktree exists
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ export function createFileDiffHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Git worktrees are stored in project directory
|
// Git worktrees are stored in project directory
|
||||||
const worktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
// (see create.ts: branchName.replace(/[^a-zA-Z0-9_-]/g, '-'))
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await secureFs.access(worktreePath);
|
await secureFs.access(worktreePath);
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ export function createInfoHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if worktree exists (git worktrees are stored in project directory)
|
// Check if worktree exists (git worktrees are stored in project directory)
|
||||||
const worktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
// (see create.ts: branchName.replace(/[^a-zA-Z0-9_-]/g, '-'))
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
try {
|
try {
|
||||||
await secureFs.access(worktreePath);
|
await secureFs.access(worktreePath);
|
||||||
const { stdout } = await execAsync('git rev-parse --abbrev-ref HEAD', {
|
const { stdout } = await execAsync('git rev-parse --abbrev-ref HEAD', {
|
||||||
|
|||||||
@@ -28,7 +28,10 @@ export function createStatusHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Git worktrees are stored in project directory
|
// Git worktrees are stored in project directory
|
||||||
const worktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
// (see create.ts: branchName.replace(/[^a-zA-Z0-9_-]/g, '-'))
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await secureFs.access(worktreePath);
|
await secureFs.access(worktreePath);
|
||||||
|
|||||||
@@ -2060,7 +2060,9 @@ Address the follow-up instructions above. Review the previous work and make the
|
|||||||
const feature = await this.loadFeature(projectPath, featureId);
|
const feature = await this.loadFeature(projectPath, featureId);
|
||||||
|
|
||||||
// Worktrees are in project dir
|
// Worktrees are in project dir
|
||||||
const worktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const worktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
let workDir = projectPath;
|
let workDir = projectPath;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2143,7 +2145,9 @@ Address the follow-up instructions above. Review the previous work and make the
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: try to find worktree at legacy location
|
// Fallback: try to find worktree at legacy location
|
||||||
const legacyWorktreePath = path.join(projectPath, '.worktrees', featureId);
|
// Sanitize featureId the same way it's sanitized when creating worktrees
|
||||||
|
const sanitizedFeatureId = featureId.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||||
|
const legacyWorktreePath = path.join(projectPath, '.worktrees', sanitizedFeatureId);
|
||||||
try {
|
try {
|
||||||
await secureFs.access(legacyWorktreePath);
|
await secureFs.access(legacyWorktreePath);
|
||||||
workDir = legacyWorktreePath;
|
workDir = legacyWorktreePath;
|
||||||
@@ -2429,22 +2433,25 @@ Format your response as a structured markdown document.`;
|
|||||||
provider?: ModelProvider;
|
provider?: ModelProvider;
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
branchName?: string;
|
||||||
}>
|
}>
|
||||||
> {
|
> {
|
||||||
const agents = await Promise.all(
|
const agents = await Promise.all(
|
||||||
Array.from(this.runningFeatures.values()).map(async (rf) => {
|
Array.from(this.runningFeatures.values()).map(async (rf) => {
|
||||||
// Try to fetch feature data to get title and description
|
// Try to fetch feature data to get title, description, and branchName
|
||||||
let title: string | undefined;
|
let title: string | undefined;
|
||||||
let description: string | undefined;
|
let description: string | undefined;
|
||||||
|
let branchName: string | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const feature = await this.featureLoader.get(rf.projectPath, rf.featureId);
|
const feature = await this.featureLoader.get(rf.projectPath, rf.featureId);
|
||||||
if (feature) {
|
if (feature) {
|
||||||
title = feature.title;
|
title = feature.title;
|
||||||
description = feature.description;
|
description = feature.description;
|
||||||
|
branchName = feature.branchName;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Silently ignore errors - title/description are optional
|
// Silently ignore errors - title/description/branchName are optional
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -2456,6 +2463,7 @@ Format your response as a structured markdown document.`;
|
|||||||
provider: rf.provider,
|
provider: rf.provider,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
branchName,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1415,6 +1415,7 @@ export function BoardView() {
|
|||||||
featureId={outputFeature?.id || ''}
|
featureId={outputFeature?.id || ''}
|
||||||
featureStatus={outputFeature?.status}
|
featureStatus={outputFeature?.status}
|
||||||
onNumberKeyPress={handleOutputModalNumberKeyPress}
|
onNumberKeyPress={handleOutputModalNumberKeyPress}
|
||||||
|
branchName={outputFeature?.branchName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Archive All Verified Dialog */}
|
{/* Archive All Verified Dialog */}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ interface AgentOutputModalProps {
|
|||||||
onNumberKeyPress?: (key: string) => void;
|
onNumberKeyPress?: (key: string) => void;
|
||||||
/** Project path - if not provided, falls back to window.__currentProject for backward compatibility */
|
/** Project path - if not provided, falls back to window.__currentProject for backward compatibility */
|
||||||
projectPath?: string;
|
projectPath?: string;
|
||||||
|
/** Branch name for the feature worktree - used when viewing changes */
|
||||||
|
branchName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ViewMode = 'summary' | 'parsed' | 'raw' | 'changes';
|
type ViewMode = 'summary' | 'parsed' | 'raw' | 'changes';
|
||||||
@@ -40,6 +42,7 @@ export function AgentOutputModal({
|
|||||||
featureStatus,
|
featureStatus,
|
||||||
onNumberKeyPress,
|
onNumberKeyPress,
|
||||||
projectPath: projectPathProp,
|
projectPath: projectPathProp,
|
||||||
|
branchName,
|
||||||
}: AgentOutputModalProps) {
|
}: AgentOutputModalProps) {
|
||||||
const isBacklogPlan = featureId.startsWith('backlog-plan:');
|
const isBacklogPlan = featureId.startsWith('backlog-plan:');
|
||||||
const [output, setOutput] = useState<string>('');
|
const [output, setOutput] = useState<string>('');
|
||||||
@@ -433,7 +436,7 @@ export function AgentOutputModal({
|
|||||||
{projectPath ? (
|
{projectPath ? (
|
||||||
<GitDiffPanel
|
<GitDiffPanel
|
||||||
projectPath={projectPath}
|
projectPath={projectPath}
|
||||||
featureId={featureId}
|
featureId={branchName || featureId}
|
||||||
compact={false}
|
compact={false}
|
||||||
useWorktrees={useWorktrees}
|
useWorktrees={useWorktrees}
|
||||||
className="border-0 rounded-lg"
|
className="border-0 rounded-lg"
|
||||||
|
|||||||
@@ -418,6 +418,7 @@ export function GraphViewPage() {
|
|||||||
featureId={outputFeature?.id || ''}
|
featureId={outputFeature?.id || ''}
|
||||||
featureStatus={outputFeature?.status}
|
featureStatus={outputFeature?.status}
|
||||||
onNumberKeyPress={handleOutputModalNumberKeyPress}
|
onNumberKeyPress={handleOutputModalNumberKeyPress}
|
||||||
|
branchName={outputFeature?.branchName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Backlog Plan Dialog */}
|
{/* Backlog Plan Dialog */}
|
||||||
|
|||||||
@@ -280,6 +280,7 @@ export function RunningAgentsView() {
|
|||||||
}
|
}
|
||||||
featureId={selectedAgent.featureId}
|
featureId={selectedAgent.featureId}
|
||||||
featureStatus="running"
|
featureStatus="running"
|
||||||
|
branchName={selectedAgent.branchName}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user