Add quick-add feature with improved workflows (#802)

* Changes from feature/quick-add

* feat: Clarify system prompt and improve error handling across services. Address PR Feedback

* feat: Improve PR description parsing and refactor event handling

* feat: Add context options to pipeline orchestrator initialization

* fix: Deduplicate React and handle CJS interop for use-sync-external-store

Resolve "Cannot read properties of null (reading 'useState')" errors by
deduplicating React/react-dom and ensuring use-sync-external-store is
bundled together with React to prevent CJS packages from resolving to
different React instances.
This commit is contained in:
gsxdsm
2026-02-22 20:48:09 -08:00
committed by GitHub
parent 9305ecc242
commit e7504b247f
70 changed files with 3141 additions and 560 deletions

View File

@@ -22,6 +22,7 @@ import type {
ServerLogLevel,
ParsedTask,
PlanSpec,
FeatureTemplate,
} from '@automaker/types';
import {
getAllCursorModelIds,
@@ -341,6 +342,7 @@ const initialState: AppState = {
copilotDefaultModel: DEFAULT_COPILOT_MODEL,
disabledProviders: [],
autoLoadClaudeMd: false,
useClaudeCodeSystemPrompt: true,
skipSandboxWarning: false,
mcpServers: [],
defaultEditorCommand: null,
@@ -355,6 +357,7 @@ const initialState: AppState = {
subagentsSources: ['user', 'project'] as Array<'user' | 'project'>,
promptCustomization: {},
eventHooks: [],
featureTemplates: DEFAULT_GLOBAL_SETTINGS.featureTemplates ?? [],
claudeCompatibleProviders: [],
claudeApiProfiles: [],
activeClaudeApiProfileId: null,
@@ -1393,6 +1396,15 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
logger.error('Failed to sync autoLoadClaudeMd:', error);
}
},
setUseClaudeCodeSystemPrompt: async (enabled) => {
set({ useClaudeCodeSystemPrompt: enabled });
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ useClaudeCodeSystemPrompt: enabled });
} catch (error) {
logger.error('Failed to sync useClaudeCodeSystemPrompt:', error);
}
},
setSkipSandboxWarning: async (skip) => {
set({ skipSandboxWarning: skip });
try {
@@ -1437,6 +1449,69 @@ export const useAppStore = create<AppState & AppActions>()((set, get) => ({
}
},
// Feature Template actions
setFeatureTemplates: async (templates) => {
set({ featureTemplates: templates });
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ featureTemplates: templates });
} catch (error) {
logger.error('Failed to sync feature templates:', error);
}
},
addFeatureTemplate: async (template) => {
set((state) => ({
featureTemplates: [...state.featureTemplates, template],
}));
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ featureTemplates: get().featureTemplates });
} catch (error) {
logger.error('Failed to sync feature templates:', error);
}
},
updateFeatureTemplate: async (id, updates) => {
set((state) => ({
featureTemplates: state.featureTemplates.map((t) => (t.id === id ? { ...t, ...updates } : t)),
}));
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ featureTemplates: get().featureTemplates });
} catch (error) {
logger.error('Failed to sync feature templates:', error);
}
},
deleteFeatureTemplate: async (id) => {
set((state) => ({
featureTemplates: state.featureTemplates.filter((t) => t.id !== id),
}));
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ featureTemplates: get().featureTemplates });
} catch (error) {
logger.error('Failed to sync feature templates:', error);
}
},
reorderFeatureTemplates: async (templateIds) => {
set((state) => {
const templateMap = new Map(state.featureTemplates.map((t) => [t.id, t]));
const reordered: FeatureTemplate[] = [];
templateIds.forEach((id, index) => {
const template = templateMap.get(id);
if (template) {
reordered.push({ ...template, order: index });
}
});
return { featureTemplates: reordered };
});
try {
const httpApi = getHttpApiClient();
await httpApi.settings.updateGlobal({ featureTemplates: get().featureTemplates });
} catch (error) {
logger.error('Failed to sync feature templates:', error);
}
},
// Claude-Compatible Provider actions (new system)
addClaudeCompatibleProvider: async (provider) => {
set((state) => ({

View File

@@ -23,6 +23,7 @@ import type {
SidebarStyle,
ThinkingLevel,
ReasoningEffort,
FeatureTemplate,
} from '@automaker/types';
import type {
@@ -234,6 +235,7 @@ export interface AppState {
// Claude Agent SDK Settings
autoLoadClaudeMd: boolean; // Auto-load CLAUDE.md files using SDK's settingSources option
useClaudeCodeSystemPrompt: boolean; // Use Claude Code's built-in system prompt as the base
skipSandboxWarning: boolean; // Skip the sandbox environment warning dialog on startup
// MCP Servers
@@ -265,6 +267,9 @@ export interface AppState {
// Event Hooks
eventHooks: EventHook[]; // Event hooks for custom commands or webhooks
// Feature Templates
featureTemplates: FeatureTemplate[]; // Feature templates for quick task creation
// Claude-Compatible Providers (new system)
claudeCompatibleProviders: ClaudeCompatibleProvider[]; // Providers that expose models to dropdowns
@@ -620,6 +625,7 @@ export interface AppActions {
// Claude Agent SDK Settings actions
setAutoLoadClaudeMd: (enabled: boolean) => Promise<void>;
setUseClaudeCodeSystemPrompt: (enabled: boolean) => Promise<void>;
setSkipSandboxWarning: (skip: boolean) => Promise<void>;
// Editor Configuration actions
@@ -640,6 +646,13 @@ export interface AppActions {
// Event Hook actions
setEventHooks: (hooks: EventHook[]) => Promise<void>;
// Feature Template actions
setFeatureTemplates: (templates: FeatureTemplate[]) => Promise<void>;
addFeatureTemplate: (template: FeatureTemplate) => Promise<void>;
updateFeatureTemplate: (id: string, updates: Partial<FeatureTemplate>) => Promise<void>;
deleteFeatureTemplate: (id: string) => Promise<void>;
reorderFeatureTemplates: (templateIds: string[]) => Promise<void>;
// Claude-Compatible Provider actions (new system)
addClaudeCompatibleProvider: (provider: ClaudeCompatibleProvider) => Promise<void>;
updateClaudeCompatibleProvider: (