Merge origin/main into feat/cursor-cli

Merges latest main branch changes including:
- MCP server support and configuration
- Pipeline configuration system
- Prompt customization settings
- GitHub issue comments in validation
- Auth middleware improvements
- Various UI/UX improvements

All Cursor CLI features preserved:
- Multi-provider support (Claude + Cursor)
- Model override capabilities
- Phase model configuration
- Provider tabs in settings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Kacper
2025-12-31 01:22:18 +01:00
163 changed files with 15300 additions and 1045 deletions

View File

@@ -19,7 +19,14 @@ import {
FeatureTextFilePath as DescriptionTextFilePath,
ImagePreviewMap,
} from '@/components/ui/description-image-dropzone';
import { MessageSquare, Settings2, SlidersHorizontal, Sparkles, ChevronDown } from 'lucide-react';
import {
MessageSquare,
Settings2,
SlidersHorizontal,
Sparkles,
ChevronDown,
Play,
} from 'lucide-react';
import { toast } from 'sonner';
import { getElectronAPI } from '@/lib/electron';
import { modelSupportsThinking } from '@/lib/utils';
@@ -57,25 +64,28 @@ import {
} from '@automaker/dependency-resolver';
import { isCursorModel, PROVIDER_PREFIXES } from '@automaker/types';
type FeatureData = {
title: string;
category: string;
description: string;
images: FeatureImage[];
imagePaths: DescriptionImagePath[];
textFilePaths: DescriptionTextFilePath[];
skipTests: boolean;
model: AgentModel;
thinkingLevel: ThinkingLevel;
branchName: string; // Can be empty string to use current branch
priority: number;
planningMode: PlanningMode;
requirePlanApproval: boolean;
dependencies?: string[];
};
interface AddFeatureDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
onAdd: (feature: {
title: string;
category: string;
description: string;
images: FeatureImage[];
imagePaths: DescriptionImagePath[];
textFilePaths: DescriptionTextFilePath[];
skipTests: boolean;
model: ModelAlias;
thinkingLevel: ThinkingLevel;
branchName: string; // Can be empty string to use current branch
priority: number;
planningMode: PlanningMode;
requirePlanApproval: boolean;
dependencies?: string[];
}) => void;
onAdd: (feature: FeatureData) => void;
onAddAndStart?: (feature: FeatureData) => void;
categorySuggestions: string[];
branchSuggestions: string[];
branchCardCounts?: Record<string, number>; // Map of branch name to unarchived card count
@@ -94,6 +104,7 @@ export function AddFeatureDialog({
open,
onOpenChange,
onAdd,
onAddAndStart,
categorySuggestions,
branchSuggestions,
branchCardCounts,
@@ -188,16 +199,16 @@ export function AddFeatureDialog({
allFeatures,
]);
const handleAdd = () => {
const buildFeatureData = (): FeatureData | null => {
if (!newFeature.description.trim()) {
setDescriptionError(true);
return;
return null;
}
// Validate branch selection when "other branch" is selected
if (useWorktrees && !useCurrentBranch && !newFeature.branchName.trim()) {
toast.error('Please select a branch name');
return;
return null;
}
const category = newFeature.category || 'Uncategorized';
@@ -235,7 +246,7 @@ export function AddFeatureDialog({
}
}
onAdd({
return {
title: newFeature.title,
category,
description: finalDescription,
@@ -251,9 +262,10 @@ export function AddFeatureDialog({
requirePlanApproval,
// In spawn mode, automatically add parent as dependency
dependencies: isSpawnMode && parentFeature ? [parentFeature.id] : undefined,
});
};
};
// Reset form
const resetForm = () => {
setNewFeature({
title: '',
category: '',
@@ -276,6 +288,20 @@ export function AddFeatureDialog({
onOpenChange(false);
};
const handleAction = (actionFn?: (data: FeatureData) => void) => {
if (!actionFn) return;
const featureData = buildFeatureData();
if (!featureData) return;
actionFn(featureData);
resetForm();
};
const handleAdd = () => handleAction(onAdd);
const handleAddAndStart = () => handleAction(onAddAndStart);
const handleDialogClose = (open: boolean) => {
onOpenChange(open);
if (!open) {
@@ -606,6 +632,17 @@ export function AddFeatureDialog({
<Button variant="ghost" onClick={() => onOpenChange(false)}>
Cancel
</Button>
{onAddAndStart && (
<Button
onClick={handleAddAndStart}
variant="secondary"
data-testid="confirm-add-and-start-feature"
disabled={useWorktrees && !useCurrentBranch && !newFeature.branchName.trim()}
>
<Play className="w-4 h-4 mr-2" />
Make
</Button>
)}
<HotkeyButton
onClick={handleAdd}
hotkey={{ key: 'Enter', cmdCtrl: true }}