Files
automaker/libs/prompts/src/merge.ts
Shirone 285f526e0c feat: centralize prompts and add customization UI for App Spec, Context, Suggestions, Tasks
- Add 4 new prompt type interfaces (AppSpecPrompts, ContextDescriptionPrompts,
  SuggestionsPrompts, TaskExecutionPrompts) with resolved types
- Add default prompts for all new categories to @automaker/prompts/defaults.ts
- Add merge functions for new prompt categories in merge.ts
- Update settings-helpers.ts getPromptCustomization() to return all 12 categories
- Update server routes (generate-spec, generate-features-from-spec, describe-file,
  describe-image, generate-suggestions) to use centralized prompts
- Add 4 new tabs in prompt customization UI (App Spec, Context, Suggestions, Tasks)
- Fix Ideation tab layout using grid-cols-4 for even distribution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 20:13:14 +01:00

339 lines
11 KiB
TypeScript

/**
* Prompt Merging Utilities
*
* Merges user-customized prompts with built-in defaults.
* Used by services to get effective prompts at runtime.
*
* Custom prompts have an `enabled` flag - when true, the custom value is used.
* When false or undefined, the default is used instead.
*/
import type {
PromptCustomization,
AutoModePrompts,
AgentPrompts,
BacklogPlanPrompts,
EnhancementPrompts,
CommitMessagePrompts,
TitleGenerationPrompts,
IssueValidationPrompts,
IdeationPrompts,
AppSpecPrompts,
ContextDescriptionPrompts,
SuggestionsPrompts,
TaskExecutionPrompts,
CustomPrompt,
ResolvedAutoModePrompts,
ResolvedAgentPrompts,
ResolvedBacklogPlanPrompts,
ResolvedEnhancementPrompts,
ResolvedCommitMessagePrompts,
ResolvedTitleGenerationPrompts,
ResolvedIssueValidationPrompts,
ResolvedIdeationPrompts,
ResolvedAppSpecPrompts,
ResolvedContextDescriptionPrompts,
ResolvedSuggestionsPrompts,
ResolvedTaskExecutionPrompts,
} from '@automaker/types';
import {
DEFAULT_AUTO_MODE_PROMPTS,
DEFAULT_AGENT_PROMPTS,
DEFAULT_BACKLOG_PLAN_PROMPTS,
DEFAULT_ENHANCEMENT_PROMPTS,
DEFAULT_COMMIT_MESSAGE_PROMPTS,
DEFAULT_TITLE_GENERATION_PROMPTS,
DEFAULT_ISSUE_VALIDATION_PROMPTS,
DEFAULT_IDEATION_PROMPTS,
DEFAULT_APP_SPEC_PROMPTS,
DEFAULT_CONTEXT_DESCRIPTION_PROMPTS,
DEFAULT_SUGGESTIONS_PROMPTS,
DEFAULT_TASK_EXECUTION_PROMPTS,
} from './defaults.js';
/**
* Resolve a custom prompt to its effective string value
* Returns the custom value if enabled=true, otherwise returns the default
*/
function resolvePrompt(custom: CustomPrompt | undefined, defaultValue: string): string {
return custom?.enabled ? custom.value : defaultValue;
}
/**
* Merge custom Auto Mode prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeAutoModePrompts(custom?: AutoModePrompts): ResolvedAutoModePrompts {
return {
planningLite: resolvePrompt(custom?.planningLite, DEFAULT_AUTO_MODE_PROMPTS.planningLite),
planningLiteWithApproval: resolvePrompt(
custom?.planningLiteWithApproval,
DEFAULT_AUTO_MODE_PROMPTS.planningLiteWithApproval
),
planningSpec: resolvePrompt(custom?.planningSpec, DEFAULT_AUTO_MODE_PROMPTS.planningSpec),
planningFull: resolvePrompt(custom?.planningFull, DEFAULT_AUTO_MODE_PROMPTS.planningFull),
featurePromptTemplate: resolvePrompt(
custom?.featurePromptTemplate,
DEFAULT_AUTO_MODE_PROMPTS.featurePromptTemplate
),
followUpPromptTemplate: resolvePrompt(
custom?.followUpPromptTemplate,
DEFAULT_AUTO_MODE_PROMPTS.followUpPromptTemplate
),
continuationPromptTemplate: resolvePrompt(
custom?.continuationPromptTemplate,
DEFAULT_AUTO_MODE_PROMPTS.continuationPromptTemplate
),
pipelineStepPromptTemplate: resolvePrompt(
custom?.pipelineStepPromptTemplate,
DEFAULT_AUTO_MODE_PROMPTS.pipelineStepPromptTemplate
),
};
}
/**
* Merge custom Agent prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeAgentPrompts(custom?: AgentPrompts): ResolvedAgentPrompts {
return {
systemPrompt: resolvePrompt(custom?.systemPrompt, DEFAULT_AGENT_PROMPTS.systemPrompt),
};
}
/**
* Merge custom Backlog Plan prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeBacklogPlanPrompts(custom?: BacklogPlanPrompts): ResolvedBacklogPlanPrompts {
return {
systemPrompt: resolvePrompt(custom?.systemPrompt, DEFAULT_BACKLOG_PLAN_PROMPTS.systemPrompt),
userPromptTemplate: resolvePrompt(
custom?.userPromptTemplate,
DEFAULT_BACKLOG_PLAN_PROMPTS.userPromptTemplate
),
};
}
/**
* Merge custom Enhancement prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeEnhancementPrompts(custom?: EnhancementPrompts): ResolvedEnhancementPrompts {
return {
improveSystemPrompt: resolvePrompt(
custom?.improveSystemPrompt,
DEFAULT_ENHANCEMENT_PROMPTS.improveSystemPrompt
),
technicalSystemPrompt: resolvePrompt(
custom?.technicalSystemPrompt,
DEFAULT_ENHANCEMENT_PROMPTS.technicalSystemPrompt
),
simplifySystemPrompt: resolvePrompt(
custom?.simplifySystemPrompt,
DEFAULT_ENHANCEMENT_PROMPTS.simplifySystemPrompt
),
acceptanceSystemPrompt: resolvePrompt(
custom?.acceptanceSystemPrompt,
DEFAULT_ENHANCEMENT_PROMPTS.acceptanceSystemPrompt
),
uxReviewerSystemPrompt: resolvePrompt(
custom?.uxReviewerSystemPrompt,
DEFAULT_ENHANCEMENT_PROMPTS.uxReviewerSystemPrompt
),
};
}
/**
* Merge custom Commit Message prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeCommitMessagePrompts(
custom?: CommitMessagePrompts
): ResolvedCommitMessagePrompts {
return {
systemPrompt: resolvePrompt(custom?.systemPrompt, DEFAULT_COMMIT_MESSAGE_PROMPTS.systemPrompt),
};
}
/**
* Merge custom Title Generation prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeTitleGenerationPrompts(
custom?: TitleGenerationPrompts
): ResolvedTitleGenerationPrompts {
return {
systemPrompt: resolvePrompt(
custom?.systemPrompt,
DEFAULT_TITLE_GENERATION_PROMPTS.systemPrompt
),
};
}
/**
* Merge custom Issue Validation prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeIssueValidationPrompts(
custom?: IssueValidationPrompts
): ResolvedIssueValidationPrompts {
return {
systemPrompt: resolvePrompt(
custom?.systemPrompt,
DEFAULT_ISSUE_VALIDATION_PROMPTS.systemPrompt
),
};
}
/**
* Merge custom Ideation prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeIdeationPrompts(custom?: IdeationPrompts): ResolvedIdeationPrompts {
return {
ideationSystemPrompt: resolvePrompt(
custom?.ideationSystemPrompt,
DEFAULT_IDEATION_PROMPTS.ideationSystemPrompt
),
suggestionsSystemPrompt: resolvePrompt(
custom?.suggestionsSystemPrompt,
DEFAULT_IDEATION_PROMPTS.suggestionsSystemPrompt
),
};
}
/**
* Merge custom App Spec prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeAppSpecPrompts(custom?: AppSpecPrompts): ResolvedAppSpecPrompts {
return {
generateSpecSystemPrompt: resolvePrompt(
custom?.generateSpecSystemPrompt,
DEFAULT_APP_SPEC_PROMPTS.generateSpecSystemPrompt
),
structuredSpecInstructions: resolvePrompt(
custom?.structuredSpecInstructions,
DEFAULT_APP_SPEC_PROMPTS.structuredSpecInstructions
),
generateFeaturesFromSpecPrompt: resolvePrompt(
custom?.generateFeaturesFromSpecPrompt,
DEFAULT_APP_SPEC_PROMPTS.generateFeaturesFromSpecPrompt
),
};
}
/**
* Merge custom Context Description prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeContextDescriptionPrompts(
custom?: ContextDescriptionPrompts
): ResolvedContextDescriptionPrompts {
return {
describeFilePrompt: resolvePrompt(
custom?.describeFilePrompt,
DEFAULT_CONTEXT_DESCRIPTION_PROMPTS.describeFilePrompt
),
describeImagePrompt: resolvePrompt(
custom?.describeImagePrompt,
DEFAULT_CONTEXT_DESCRIPTION_PROMPTS.describeImagePrompt
),
};
}
/**
* Merge custom Suggestions prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeSuggestionsPrompts(custom?: SuggestionsPrompts): ResolvedSuggestionsPrompts {
return {
featuresPrompt: resolvePrompt(
custom?.featuresPrompt,
DEFAULT_SUGGESTIONS_PROMPTS.featuresPrompt
),
refactoringPrompt: resolvePrompt(
custom?.refactoringPrompt,
DEFAULT_SUGGESTIONS_PROMPTS.refactoringPrompt
),
securityPrompt: resolvePrompt(
custom?.securityPrompt,
DEFAULT_SUGGESTIONS_PROMPTS.securityPrompt
),
performancePrompt: resolvePrompt(
custom?.performancePrompt,
DEFAULT_SUGGESTIONS_PROMPTS.performancePrompt
),
baseTemplate: resolvePrompt(custom?.baseTemplate, DEFAULT_SUGGESTIONS_PROMPTS.baseTemplate),
};
}
/**
* Merge custom Task Execution prompts with defaults
* Custom prompts override defaults only when enabled=true
*/
export function mergeTaskExecutionPrompts(
custom?: TaskExecutionPrompts
): ResolvedTaskExecutionPrompts {
return {
taskPromptTemplate: resolvePrompt(
custom?.taskPromptTemplate,
DEFAULT_TASK_EXECUTION_PROMPTS.taskPromptTemplate
),
implementationInstructions: resolvePrompt(
custom?.implementationInstructions,
DEFAULT_TASK_EXECUTION_PROMPTS.implementationInstructions
),
playwrightVerificationInstructions: resolvePrompt(
custom?.playwrightVerificationInstructions,
DEFAULT_TASK_EXECUTION_PROMPTS.playwrightVerificationInstructions
),
learningExtractionSystemPrompt: resolvePrompt(
custom?.learningExtractionSystemPrompt,
DEFAULT_TASK_EXECUTION_PROMPTS.learningExtractionSystemPrompt
),
learningExtractionUserPromptTemplate: resolvePrompt(
custom?.learningExtractionUserPromptTemplate,
DEFAULT_TASK_EXECUTION_PROMPTS.learningExtractionUserPromptTemplate
),
planRevisionTemplate: resolvePrompt(
custom?.planRevisionTemplate,
DEFAULT_TASK_EXECUTION_PROMPTS.planRevisionTemplate
),
continuationAfterApprovalTemplate: resolvePrompt(
custom?.continuationAfterApprovalTemplate,
DEFAULT_TASK_EXECUTION_PROMPTS.continuationAfterApprovalTemplate
),
resumeFeatureTemplate: resolvePrompt(
custom?.resumeFeatureTemplate,
DEFAULT_TASK_EXECUTION_PROMPTS.resumeFeatureTemplate
),
projectAnalysisPrompt: resolvePrompt(
custom?.projectAnalysisPrompt,
DEFAULT_TASK_EXECUTION_PROMPTS.projectAnalysisPrompt
),
};
}
/**
* Merge all custom prompts with defaults
* Returns a complete PromptCustomization with all fields populated
*/
export function mergeAllPrompts(custom?: PromptCustomization) {
return {
autoMode: mergeAutoModePrompts(custom?.autoMode),
agent: mergeAgentPrompts(custom?.agent),
backlogPlan: mergeBacklogPlanPrompts(custom?.backlogPlan),
enhancement: mergeEnhancementPrompts(custom?.enhancement),
commitMessage: mergeCommitMessagePrompts(custom?.commitMessage),
titleGeneration: mergeTitleGenerationPrompts(custom?.titleGeneration),
issueValidation: mergeIssueValidationPrompts(custom?.issueValidation),
ideation: mergeIdeationPrompts(custom?.ideation),
appSpec: mergeAppSpecPrompts(custom?.appSpec),
contextDescription: mergeContextDescriptionPrompts(custom?.contextDescription),
suggestions: mergeSuggestionsPrompts(custom?.suggestions),
taskExecution: mergeTaskExecutionPrompts(custom?.taskExecution),
};
}