mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-01 08:13:37 +00:00
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:
@@ -10,6 +10,11 @@ import type {
|
||||
CursorModelId,
|
||||
PhaseModelConfig,
|
||||
PhaseModelKey,
|
||||
MCPServerConfig,
|
||||
FeatureStatusWithPipeline,
|
||||
PipelineConfig,
|
||||
PipelineStep,
|
||||
PromptCustomization,
|
||||
} from '@automaker/types';
|
||||
import { getAllCursorModelIds, DEFAULT_PHASE_MODELS } from '@automaker/types';
|
||||
|
||||
@@ -267,7 +272,7 @@ export interface Feature extends Omit<
|
||||
category: string;
|
||||
description: string;
|
||||
steps: string[]; // Required in UI (not optional)
|
||||
status: 'backlog' | 'in_progress' | 'waiting_approval' | 'verified' | 'completed';
|
||||
status: FeatureStatusWithPipeline;
|
||||
images?: FeatureImage[]; // UI-specific base64 images
|
||||
imagePaths?: FeatureImagePath[]; // Stricter type than base (no string | union)
|
||||
textFilePaths?: FeatureTextFilePath[]; // Text file attachments for context
|
||||
@@ -348,6 +353,7 @@ export interface TerminalState {
|
||||
scrollbackLines: number; // Number of lines to keep in scrollback buffer
|
||||
lineHeight: number; // Line height multiplier for terminal text
|
||||
maxSessions: number; // Maximum concurrent terminal sessions (server setting)
|
||||
lastActiveProjectPath: string | null; // Last project path to detect route changes vs project switches
|
||||
}
|
||||
|
||||
// Persisted terminal layout - now includes sessionIds for reconnection
|
||||
@@ -491,6 +497,15 @@ export interface AppState {
|
||||
|
||||
// Claude Agent SDK Settings
|
||||
autoLoadClaudeMd: boolean; // Auto-load CLAUDE.md files using SDK's settingSources option
|
||||
enableSandboxMode: boolean; // Enable sandbox mode for bash commands (may cause issues on some systems)
|
||||
|
||||
// MCP Servers
|
||||
mcpServers: MCPServerConfig[]; // List of configured MCP servers for agent use
|
||||
mcpAutoApproveTools: boolean; // Auto-approve MCP tool calls without permission prompts
|
||||
mcpUnrestrictedTools: boolean; // Allow unrestricted tools when MCP servers are enabled
|
||||
|
||||
// Prompt Customization
|
||||
promptCustomization: PromptCustomization; // Custom prompts for Auto Mode, Agent, Backlog Plan, Enhancement
|
||||
|
||||
// Project Analysis
|
||||
projectAnalysis: ProjectAnalysis | null;
|
||||
@@ -543,6 +558,9 @@ export interface AppState {
|
||||
claudeRefreshInterval: number; // Refresh interval in seconds (default: 60)
|
||||
claudeUsage: ClaudeUsage | null;
|
||||
claudeUsageLastUpdated: number | null;
|
||||
|
||||
// Pipeline Configuration (per-project, keyed by project path)
|
||||
pipelineConfigByProject: Record<string, PipelineConfig>;
|
||||
}
|
||||
|
||||
// Claude Usage interface matching the server response
|
||||
@@ -777,6 +795,12 @@ export interface AppActions {
|
||||
|
||||
// Claude Agent SDK Settings actions
|
||||
setAutoLoadClaudeMd: (enabled: boolean) => Promise<void>;
|
||||
setEnableSandboxMode: (enabled: boolean) => Promise<void>;
|
||||
setMcpAutoApproveTools: (enabled: boolean) => Promise<void>;
|
||||
setMcpUnrestrictedTools: (enabled: boolean) => Promise<void>;
|
||||
|
||||
// Prompt Customization actions
|
||||
setPromptCustomization: (customization: PromptCustomization) => Promise<void>;
|
||||
|
||||
// AI Profile actions
|
||||
addAIProfile: (profile: Omit<AIProfile, 'id'>) => void;
|
||||
@@ -785,6 +809,12 @@ export interface AppActions {
|
||||
reorderAIProfiles: (oldIndex: number, newIndex: number) => void;
|
||||
resetAIProfiles: () => void;
|
||||
|
||||
// MCP Server actions
|
||||
addMCPServer: (server: Omit<MCPServerConfig, 'id'>) => void;
|
||||
updateMCPServer: (id: string, updates: Partial<MCPServerConfig>) => void;
|
||||
removeMCPServer: (id: string) => void;
|
||||
reorderMCPServers: (oldIndex: number, newIndex: number) => void;
|
||||
|
||||
// Project Analysis actions
|
||||
setProjectAnalysis: (analysis: ProjectAnalysis | null) => void;
|
||||
setIsAnalyzing: (analyzing: boolean) => void;
|
||||
@@ -835,6 +865,7 @@ export interface AppActions {
|
||||
setTerminalScrollbackLines: (lines: number) => void;
|
||||
setTerminalLineHeight: (lineHeight: number) => void;
|
||||
setTerminalMaxSessions: (maxSessions: number) => void;
|
||||
setTerminalLastActiveProjectPath: (projectPath: string | null) => void;
|
||||
addTerminalTab: (name?: string) => string;
|
||||
removeTerminalTab: (tabId: string) => void;
|
||||
setActiveTerminalTab: (tabId: string) => void;
|
||||
@@ -874,6 +905,21 @@ export interface AppActions {
|
||||
} | null
|
||||
) => void;
|
||||
|
||||
// Pipeline actions
|
||||
setPipelineConfig: (projectPath: string, config: PipelineConfig) => void;
|
||||
getPipelineConfig: (projectPath: string) => PipelineConfig | null;
|
||||
addPipelineStep: (
|
||||
projectPath: string,
|
||||
step: Omit<PipelineStep, 'id' | 'createdAt' | 'updatedAt'>
|
||||
) => PipelineStep;
|
||||
updatePipelineStep: (
|
||||
projectPath: string,
|
||||
stepId: string,
|
||||
updates: Partial<Omit<PipelineStep, 'id' | 'createdAt'>>
|
||||
) => void;
|
||||
deletePipelineStep: (projectPath: string, stepId: string) => void;
|
||||
reorderPipelineSteps: (projectPath: string, stepIds: string[]) => void;
|
||||
|
||||
// Reset
|
||||
reset: () => void;
|
||||
}
|
||||
@@ -964,6 +1010,11 @@ const initialState: AppState = {
|
||||
enabledCursorModels: getAllCursorModelIds(), // All Cursor models enabled by default
|
||||
cursorDefaultModel: 'auto', // Default to auto selection
|
||||
autoLoadClaudeMd: false, // Default to disabled (user must opt-in)
|
||||
enableSandboxMode: true, // Default to enabled for security (can be disabled if issues occur)
|
||||
mcpServers: [], // No MCP servers configured by default
|
||||
mcpAutoApproveTools: true, // Default to enabled - bypass permission prompts for MCP tools
|
||||
mcpUnrestrictedTools: true, // Default to enabled - don't filter allowedTools when MCP enabled
|
||||
promptCustomization: {}, // Empty by default - all prompts use built-in defaults
|
||||
aiProfiles: DEFAULT_AI_PROFILES,
|
||||
projectAnalysis: null,
|
||||
isAnalyzing: false,
|
||||
@@ -983,6 +1034,7 @@ const initialState: AppState = {
|
||||
scrollbackLines: 5000,
|
||||
lineHeight: 1.0,
|
||||
maxSessions: 100,
|
||||
lastActiveProjectPath: null,
|
||||
},
|
||||
terminalLayoutByProject: {},
|
||||
specCreatingForProject: null,
|
||||
@@ -990,6 +1042,10 @@ const initialState: AppState = {
|
||||
defaultRequirePlanApproval: false,
|
||||
defaultAIProfileId: null,
|
||||
pendingPlanApproval: null,
|
||||
claudeRefreshInterval: 60,
|
||||
claudeUsage: null,
|
||||
claudeUsageLastUpdated: null,
|
||||
pipelineConfigByProject: {},
|
||||
};
|
||||
|
||||
export const useAppStore = create<AppState & AppActions>()(
|
||||
@@ -1636,6 +1692,32 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
setEnableSandboxMode: async (enabled) => {
|
||||
set({ enableSandboxMode: enabled });
|
||||
// Sync to server settings file
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
setMcpAutoApproveTools: async (enabled) => {
|
||||
set({ mcpAutoApproveTools: enabled });
|
||||
// Sync to server settings file
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
setMcpUnrestrictedTools: async (enabled) => {
|
||||
set({ mcpUnrestrictedTools: enabled });
|
||||
// Sync to server settings file
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
|
||||
// Prompt Customization actions
|
||||
setPromptCustomization: async (customization) => {
|
||||
set({ promptCustomization: customization });
|
||||
// Sync to server settings file
|
||||
const { syncSettingsToServer } = await import('@/hooks/use-settings-migration');
|
||||
await syncSettingsToServer();
|
||||
},
|
||||
|
||||
// AI Profile actions
|
||||
addAIProfile: (profile) => {
|
||||
@@ -1677,6 +1759,29 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
set({ aiProfiles: [...DEFAULT_AI_PROFILES, ...userProfiles] });
|
||||
},
|
||||
|
||||
// MCP Server actions
|
||||
addMCPServer: (server) => {
|
||||
const id = `mcp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
set({ mcpServers: [...get().mcpServers, { ...server, id, enabled: true }] });
|
||||
},
|
||||
|
||||
updateMCPServer: (id, updates) => {
|
||||
set({
|
||||
mcpServers: get().mcpServers.map((s) => (s.id === id ? { ...s, ...updates } : s)),
|
||||
});
|
||||
},
|
||||
|
||||
removeMCPServer: (id) => {
|
||||
set({ mcpServers: get().mcpServers.filter((s) => s.id !== id) });
|
||||
},
|
||||
|
||||
reorderMCPServers: (oldIndex, newIndex) => {
|
||||
const servers = [...get().mcpServers];
|
||||
const [movedServer] = servers.splice(oldIndex, 1);
|
||||
servers.splice(newIndex, 0, movedServer);
|
||||
set({ mcpServers: servers });
|
||||
},
|
||||
|
||||
// Project Analysis actions
|
||||
setProjectAnalysis: (analysis) => set({ projectAnalysis: analysis }),
|
||||
setIsAnalyzing: (analyzing) => set({ isAnalyzing: analyzing }),
|
||||
@@ -2103,6 +2208,8 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
scrollbackLines: current.scrollbackLines,
|
||||
lineHeight: current.lineHeight,
|
||||
maxSessions: current.maxSessions,
|
||||
// Preserve lastActiveProjectPath - it will be updated separately when needed
|
||||
lastActiveProjectPath: current.lastActiveProjectPath,
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -2187,6 +2294,13 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
});
|
||||
},
|
||||
|
||||
setTerminalLastActiveProjectPath: (projectPath) => {
|
||||
const current = get().terminalState;
|
||||
set({
|
||||
terminalState: { ...current, lastActiveProjectPath: projectPath },
|
||||
});
|
||||
},
|
||||
|
||||
addTerminalTab: (name) => {
|
||||
const current = get().terminalState;
|
||||
const newTabId = `tab-${Date.now()}`;
|
||||
@@ -2651,6 +2765,105 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
claudeUsageLastUpdated: usage ? Date.now() : null,
|
||||
}),
|
||||
|
||||
// Pipeline actions
|
||||
setPipelineConfig: (projectPath, config) => {
|
||||
set({
|
||||
pipelineConfigByProject: {
|
||||
...get().pipelineConfigByProject,
|
||||
[projectPath]: config,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
getPipelineConfig: (projectPath) => {
|
||||
return get().pipelineConfigByProject[projectPath] || null;
|
||||
},
|
||||
|
||||
addPipelineStep: (projectPath, step) => {
|
||||
const config = get().pipelineConfigByProject[projectPath] || { version: 1, steps: [] };
|
||||
const now = new Date().toISOString();
|
||||
const newStep: PipelineStep = {
|
||||
...step,
|
||||
id: `step_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 8)}`,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
const newSteps = [...config.steps, newStep].sort((a, b) => a.order - b.order);
|
||||
newSteps.forEach((s, index) => {
|
||||
s.order = index;
|
||||
});
|
||||
|
||||
set({
|
||||
pipelineConfigByProject: {
|
||||
...get().pipelineConfigByProject,
|
||||
[projectPath]: { ...config, steps: newSteps },
|
||||
},
|
||||
});
|
||||
|
||||
return newStep;
|
||||
},
|
||||
|
||||
updatePipelineStep: (projectPath, stepId, updates) => {
|
||||
const config = get().pipelineConfigByProject[projectPath];
|
||||
if (!config) return;
|
||||
|
||||
const stepIndex = config.steps.findIndex((s) => s.id === stepId);
|
||||
if (stepIndex === -1) return;
|
||||
|
||||
const updatedSteps = [...config.steps];
|
||||
updatedSteps[stepIndex] = {
|
||||
...updatedSteps[stepIndex],
|
||||
...updates,
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
set({
|
||||
pipelineConfigByProject: {
|
||||
...get().pipelineConfigByProject,
|
||||
[projectPath]: { ...config, steps: updatedSteps },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
deletePipelineStep: (projectPath, stepId) => {
|
||||
const config = get().pipelineConfigByProject[projectPath];
|
||||
if (!config) return;
|
||||
|
||||
const newSteps = config.steps.filter((s) => s.id !== stepId);
|
||||
newSteps.forEach((s, index) => {
|
||||
s.order = index;
|
||||
});
|
||||
|
||||
set({
|
||||
pipelineConfigByProject: {
|
||||
...get().pipelineConfigByProject,
|
||||
[projectPath]: { ...config, steps: newSteps },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
reorderPipelineSteps: (projectPath, stepIds) => {
|
||||
const config = get().pipelineConfigByProject[projectPath];
|
||||
if (!config) return;
|
||||
|
||||
const stepMap = new Map(config.steps.map((s) => [s.id, s]));
|
||||
const reorderedSteps = stepIds
|
||||
.map((id, index) => {
|
||||
const step = stepMap.get(id);
|
||||
if (!step) return null;
|
||||
return { ...step, order: index, updatedAt: new Date().toISOString() };
|
||||
})
|
||||
.filter((s): s is PipelineStep => s !== null);
|
||||
|
||||
set({
|
||||
pipelineConfigByProject: {
|
||||
...get().pipelineConfigByProject,
|
||||
[projectPath]: { ...config, steps: reorderedSteps },
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// Reset
|
||||
reset: () => set(initialState),
|
||||
}),
|
||||
@@ -2735,6 +2948,7 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
activeTabId: state.terminalState?.activeTabId ?? null,
|
||||
activeSessionId: state.terminalState?.activeSessionId ?? null,
|
||||
maximizedSessionId: state.terminalState?.maximizedSessionId ?? null,
|
||||
lastActiveProjectPath: state.terminalState?.lastActiveProjectPath ?? null,
|
||||
// Restore persisted settings
|
||||
defaultFontSize: persistedSettings.defaultFontSize ?? 14,
|
||||
defaultRunScript: persistedSettings.defaultRunScript ?? '',
|
||||
@@ -2784,6 +2998,13 @@ export const useAppStore = create<AppState & AppActions>()(
|
||||
enabledCursorModels: state.enabledCursorModels,
|
||||
cursorDefaultModel: state.cursorDefaultModel,
|
||||
autoLoadClaudeMd: state.autoLoadClaudeMd,
|
||||
enableSandboxMode: state.enableSandboxMode,
|
||||
// MCP settings
|
||||
mcpServers: state.mcpServers,
|
||||
mcpAutoApproveTools: state.mcpAutoApproveTools,
|
||||
mcpUnrestrictedTools: state.mcpUnrestrictedTools,
|
||||
// Prompt customization
|
||||
promptCustomization: state.promptCustomization,
|
||||
// Profiles and sessions
|
||||
aiProfiles: state.aiProfiles,
|
||||
chatSessions: state.chatSessions,
|
||||
|
||||
@@ -201,6 +201,7 @@ export const useSetupStore = create<SetupState & SetupActions>()(
|
||||
isFirstRun: state.isFirstRun,
|
||||
setupComplete: state.setupComplete,
|
||||
skipClaudeSetup: state.skipClaudeSetup,
|
||||
claudeAuthStatus: state.claudeAuthStatus,
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user