feat: Introduce @automaker/prompts package for AI prompt templates

Changes:
- Added a new package, @automaker/prompts, containing AI prompt templates for enhancing user-written task descriptions.
- Implemented four enhancement modes: improve, technical, simplify, and acceptance, each with corresponding system prompts and examples.
- Updated relevant packages to utilize the new prompts package, ensuring backward compatibility with existing imports.
- Enhanced documentation to include usage examples and integration details for the new prompts.

Benefits:
 Streamlined AI prompt management across the codebase
 Improved clarity and usability for AI-powered features
 Comprehensive documentation for developers

All tests passing.
This commit is contained in:
Kacper
2025-12-21 02:11:23 +01:00
parent 55c49516c8
commit 0ce6b6d4b1
24 changed files with 2134 additions and 938 deletions

View File

@@ -25,6 +25,7 @@
"@automaker/git-utils": "^1.0.0",
"@automaker/model-resolver": "^1.0.0",
"@automaker/platform": "^1.0.0",
"@automaker/prompts": "^1.0.0",
"@automaker/types": "^1.0.0",
"@automaker/utils": "^1.0.0",
"cors": "^2.8.5",

View File

@@ -1,448 +1,25 @@
/**
* Enhancement Prompts Library - AI-powered text enhancement for task descriptions
* Enhancement Prompts - Re-exported from @automaker/prompts
*
* Provides prompt templates and utilities for enhancing user-written task descriptions:
* - Improve: Transform vague requests into clear, actionable tasks
* - Technical: Add implementation details and technical specifications
* - Simplify: Make verbose descriptions concise and focused
* - Acceptance: Add testable acceptance criteria
*
* Uses chain-of-thought prompting with few-shot examples for consistent results.
* This file now re-exports enhancement prompts from the shared @automaker/prompts package
* to maintain backward compatibility with existing imports in the server codebase.
*/
import type { EnhancementMode, EnhancementExample } from "@automaker/types";
// Re-export enhancement types from shared package
export type { EnhancementMode, EnhancementExample } from "@automaker/types";
/**
* System prompt for the "improve" enhancement mode.
* Transforms vague or unclear requests into clear, actionable task descriptions.
*/
export const IMPROVE_SYSTEM_PROMPT = `You are an expert at transforming vague, unclear, or incomplete task descriptions into clear, actionable specifications.
Your task is to take a user's rough description and improve it by:
1. ANALYZE the input:
- Identify the core intent behind the request
- Note any ambiguities or missing details
- Determine what success would look like
2. CLARIFY the scope:
- Define clear boundaries for the task
- Identify implicit requirements
- Add relevant context that may be assumed
3. STRUCTURE the output:
- Write a clear, actionable title
- Provide a concise description of what needs to be done
- Break down into specific sub-tasks if appropriate
4. ENHANCE with details:
- Add specific, measurable outcomes where possible
- Include edge cases to consider
- Note any dependencies or prerequisites
Output ONLY the improved task description. Do not include explanations, markdown formatting, or meta-commentary about your changes.`;
/**
* System prompt for the "technical" enhancement mode.
* Adds implementation details and technical specifications.
*/
export const TECHNICAL_SYSTEM_PROMPT = `You are a senior software engineer skilled at adding technical depth to feature descriptions.
Your task is to enhance a task description with technical implementation details:
1. ANALYZE the requirement:
- Understand the functional goal
- Identify the technical domain (frontend, backend, database, etc.)
- Consider the likely tech stack based on context
2. ADD technical specifications:
- Suggest specific technologies, libraries, or patterns
- Define API contracts or data structures if relevant
- Note performance considerations
- Identify security implications
3. OUTLINE implementation approach:
- Break down into technical sub-tasks
- Suggest file structure or component organization
- Note integration points with existing systems
4. CONSIDER edge cases:
- Error handling requirements
- Loading and empty states
- Boundary conditions
Output ONLY the enhanced technical description. Keep it concise but comprehensive. Do not include explanations about your reasoning.`;
/**
* System prompt for the "simplify" enhancement mode.
* Makes verbose descriptions concise and focused.
*/
export const SIMPLIFY_SYSTEM_PROMPT = `You are an expert editor who excels at making verbose text concise without losing meaning.
Your task is to simplify a task description while preserving essential information:
1. IDENTIFY the core message:
- Extract the primary goal or requirement
- Note truly essential details
- Separate nice-to-have from must-have information
2. ELIMINATE redundancy:
- Remove repeated information
- Cut unnecessary qualifiers and hedging language
- Remove filler words and phrases
3. CONSOLIDATE related points:
- Merge overlapping requirements
- Group related items together
- Use concise language
4. PRESERVE critical details:
- Keep specific technical requirements
- Retain important constraints
- Maintain actionable specifics
Output ONLY the simplified description. Aim for 30-50% reduction in length while keeping all essential information. Do not explain your changes.`;
/**
* System prompt for the "acceptance" enhancement mode.
* Adds testable acceptance criteria to task descriptions.
*/
export const ACCEPTANCE_SYSTEM_PROMPT = `You are a QA specialist skilled at defining testable acceptance criteria for software features.
Your task is to enhance a task description by adding clear acceptance criteria:
1. UNDERSTAND the feature:
- Identify all user-facing behaviors
- Note system state changes
- Consider different user roles or scenarios
2. DEFINE acceptance criteria using Given-When-Then format:
- Given: The initial context or preconditions
- When: The action or trigger
- Then: The expected outcome
3. COVER key scenarios:
- Happy path (successful completion)
- Edge cases (boundary conditions)
- Error scenarios (what should NOT happen)
- Performance requirements if relevant
4. MAKE criteria testable:
- Use specific, measurable outcomes
- Avoid vague terms like "quickly" or "easily"
- Include specific values where applicable
Output the original description followed by a clear "Acceptance Criteria:" section with numbered, testable criteria. Do not include explanations about your process.`;
/**
* Few-shot examples for the "improve" enhancement mode
*/
export const IMPROVE_EXAMPLES: EnhancementExample[] = [
{
input: "add dark mode",
output: `Add Dark Mode Theme Support
Implement a dark mode option that allows users to switch between light and dark themes throughout the application.
Requirements:
- Add a theme toggle switch in the settings area
- Store user's theme preference persistently
- Apply dark theme colors to all UI components
- Respect system preference as default if user hasn't set a preference
- Ensure smooth transition when switching themes`,
},
{
input: "fix the login bug",
output: `Fix Login Authentication Flow
Investigate and resolve issues preventing users from successfully logging in to the application.
Requirements:
- Identify the specific failure point in the login process
- Ensure proper credential validation
- Handle error states with clear user feedback
- Verify session token is correctly stored after successful login
- Test with various credential combinations (valid, invalid, edge cases)`,
},
{
input: "make it faster",
output: `Improve Application Performance
Optimize application loading and response times to enhance user experience.
Requirements:
- Profile current performance to identify bottlenecks
- Implement code splitting and lazy loading for routes/components
- Optimize database queries and add appropriate indexes
- Add caching for frequently accessed data
- Set performance budget targets (e.g., LCP < 2.5s, FID < 100ms)
- Measure and document improvements`,
},
];
/**
* Few-shot examples for the "technical" enhancement mode
*/
export const TECHNICAL_EXAMPLES: EnhancementExample[] = [
{
input: "Add user profile page",
output: `Add User Profile Page
Create a dedicated profile page for viewing and editing user information.
Technical Implementation:
- Frontend: React component at /profile route with form validation
- API Endpoint: GET/PUT /api/users/:id for fetching and updating profile
- Data Model: Extend User schema with profile fields (avatar, bio, preferences)
- File Upload: Integrate cloud storage for avatar images with client-side resizing
- State Management: Use optimistic updates for better UX
- Validation: Server-side validation matching client-side rules
Components:
- ProfileHeader (avatar, name, edit button)
- ProfileForm (editable fields with validation)
- AvatarUploader (drag-drop with preview)
Security: Ensure users can only edit their own profile (auth middleware)`,
},
{
input: "Add search functionality",
output: `Add Search Functionality
Implement full-text search across application content.
Technical Implementation:
- Search Engine: Use Elasticsearch or PostgreSQL full-text search
- API: GET /api/search?q={query}&type={type}&page={page}
- Indexing: Create search index with relevant fields, update on content changes
- Frontend: Debounced search input (300ms) with typeahead suggestions
- Results: Paginated results with highlighted matching text
Architecture:
- SearchService class handling query building and execution
- SearchIndex worker for background indexing
- SearchResults component with filtering and sorting
Performance:
- Implement search result caching (Redis, 5-minute TTL)
- Limit results per page (20 items)
- Add query complexity limits to prevent abuse`,
},
];
/**
* Few-shot examples for the "simplify" enhancement mode
*/
export const SIMPLIFY_EXAMPLES: EnhancementExample[] = [
{
input: `We need to implement a feature that would allow our users to be able to export their data in various different formats. The formats we are thinking about supporting include CSV which is commonly used for spreadsheet applications, and also JSON which is good for developers, and possibly PDF for people who want a printable version. The user should be able to go somewhere in the UI and select which format they want and then download their data in that format. We should probably also show some kind of progress indicator while the export is happening since it might take a while for large datasets.`,
output: `Add Data Export Feature
Allow users to export their data in CSV, JSON, or PDF format.
Requirements:
- Add export button/menu in the UI
- Support three formats: CSV (spreadsheets), JSON (developers), PDF (printing)
- Show progress indicator during export
- Handle large datasets gracefully`,
},
{
input: `The current notification system is not working very well and users are complaining about it. Sometimes they don't receive notifications at all, and other times they receive too many notifications and feel overwhelmed. We also have had reports that the notifications are not appearing correctly on mobile devices. Additionally, some users have requested the ability to customize which types of notifications they receive. We should look into all of these issues and make the notification system work better overall.`,
output: `Fix and Improve Notification System
Address reliability issues and add user controls for notifications.
Issues to fix:
- Missing notifications (delivery reliability)
- Notification overload (implement batching/digest)
- Mobile display problems
Enhancements:
- Add notification preferences (per-type controls)
- Test across devices and platforms`,
},
];
/**
* Few-shot examples for the "acceptance" enhancement mode
*/
export const ACCEPTANCE_EXAMPLES: EnhancementExample[] = [
{
input: "Add password reset functionality",
output: `Add Password Reset Functionality
Allow users to reset their password via email when they forget it.
Acceptance Criteria:
1. Given a user is on the login page, when they click "Forgot Password", then they should see a password reset form requesting their email.
2. Given a user enters a valid registered email, when they submit the form, then they should receive a password reset email within 2 minutes.
3. Given a user clicks the reset link in their email, when the link is less than 1 hour old, then they should see a form to enter a new password.
4. Given a user enters a new valid password (min 8 chars, 1 number, 1 special char), when they submit, then their password should be updated and they should be redirected to login.
5. Given a user enters an unregistered email, when they submit the reset form, then they should see the same success message (security: don't reveal which emails exist).
6. Given a reset link older than 1 hour, when a user clicks it, then they should see an expiration message with option to request a new link.`,
},
{
input: "Shopping cart checkout",
output: `Shopping Cart Checkout
Implement the checkout flow for purchasing items in the shopping cart.
Acceptance Criteria:
1. Given a user has items in their cart, when they click "Checkout", then they should see an order summary with item details and total price.
2. Given a user is on the checkout page, when they enter valid shipping information, then the form should validate in real-time and show estimated delivery date.
3. Given valid shipping info is entered, when the user proceeds to payment, then they should see available payment methods (credit card, PayPal).
4. Given valid payment details are entered, when the user confirms the order, then the payment should be processed and order confirmation displayed within 5 seconds.
5. Given a successful order, when confirmation is shown, then the user should receive an email receipt and their cart should be emptied.
6. Given a payment failure, when the error occurs, then the user should see a clear error message and their cart should remain intact.
7. Given the user closes the browser during checkout, when they return, then their cart contents should still be available.`,
},
];
/**
* Map of enhancement modes to their system prompts
*/
const SYSTEM_PROMPTS: Record<EnhancementMode, string> = {
improve: IMPROVE_SYSTEM_PROMPT,
technical: TECHNICAL_SYSTEM_PROMPT,
simplify: SIMPLIFY_SYSTEM_PROMPT,
acceptance: ACCEPTANCE_SYSTEM_PROMPT,
};
/**
* Map of enhancement modes to their few-shot examples
*/
const EXAMPLES: Record<EnhancementMode, EnhancementExample[]> = {
improve: IMPROVE_EXAMPLES,
technical: TECHNICAL_EXAMPLES,
simplify: SIMPLIFY_EXAMPLES,
acceptance: ACCEPTANCE_EXAMPLES,
};
/**
* Enhancement prompt configuration returned by getEnhancementPrompt
*/
export interface EnhancementPromptConfig {
/** System prompt for the enhancement mode */
systemPrompt: string;
/** Description of what this mode does */
description: string;
}
/**
* Descriptions for each enhancement mode
*/
const MODE_DESCRIPTIONS: Record<EnhancementMode, string> = {
improve: "Transform vague requests into clear, actionable task descriptions",
technical: "Add implementation details and technical specifications",
simplify: "Make verbose descriptions concise and focused",
acceptance: "Add testable acceptance criteria to task descriptions",
};
/**
* Get the enhancement prompt configuration for a given mode
*
* @param mode - The enhancement mode (falls back to 'improve' if invalid)
* @returns The enhancement prompt configuration
*/
export function getEnhancementPrompt(mode: string): EnhancementPromptConfig {
const normalizedMode = mode.toLowerCase() as EnhancementMode;
const validMode = normalizedMode in SYSTEM_PROMPTS ? normalizedMode : "improve";
return {
systemPrompt: SYSTEM_PROMPTS[validMode],
description: MODE_DESCRIPTIONS[validMode],
};
}
/**
* Get the system prompt for a specific enhancement mode
*
* @param mode - The enhancement mode to get the prompt for
* @returns The system prompt string
*/
export function getSystemPrompt(mode: EnhancementMode): string {
return SYSTEM_PROMPTS[mode];
}
/**
* Get the few-shot examples for a specific enhancement mode
*
* @param mode - The enhancement mode to get examples for
* @returns Array of input/output example pairs
*/
export function getExamples(mode: EnhancementMode): EnhancementExample[] {
return EXAMPLES[mode];
}
/**
* Build a user prompt for enhancement with optional few-shot examples
*
* @param mode - The enhancement mode
* @param text - The text to enhance
* @param includeExamples - Whether to include few-shot examples (default: true)
* @returns The formatted user prompt string
*/
export function buildUserPrompt(
mode: EnhancementMode,
text: string,
includeExamples: boolean = true
): string {
const examples = includeExamples ? getExamples(mode) : [];
if (examples.length === 0) {
return `Please enhance the following task description:\n\n${text}`;
}
// Build few-shot examples section
const examplesSection = examples
.map(
(example, index) =>
`Example ${index + 1}:\nInput: ${example.input}\nOutput: ${example.output}`
)
.join("\n\n---\n\n");
return `Here are some examples of how to enhance task descriptions:
${examplesSection}
---
Now, please enhance the following task description:
${text}`;
}
/**
* Check if a mode is a valid enhancement mode
*
* @param mode - The mode to check
* @returns True if the mode is valid
*/
export function isValidEnhancementMode(mode: string): mode is EnhancementMode {
return mode in SYSTEM_PROMPTS;
}
/**
* Get all available enhancement modes
*
* @returns Array of available enhancement mode names
*/
export function getAvailableEnhancementModes(): EnhancementMode[] {
return Object.keys(SYSTEM_PROMPTS) as EnhancementMode[];
}
export {
IMPROVE_SYSTEM_PROMPT,
TECHNICAL_SYSTEM_PROMPT,
SIMPLIFY_SYSTEM_PROMPT,
ACCEPTANCE_SYSTEM_PROMPT,
IMPROVE_EXAMPLES,
TECHNICAL_EXAMPLES,
SIMPLIFY_EXAMPLES,
ACCEPTANCE_EXAMPLES,
getEnhancementPrompt,
getSystemPrompt,
getExamples,
buildUserPrompt,
isValidEnhancementMode,
getAvailableEnhancementModes,
} from '@automaker/prompts';
export type { EnhancementMode, EnhancementExample } from '@automaker/prompts';

View File

@@ -1,428 +1,35 @@
/**
* Settings Types - Shared types for file-based settings storage
* Settings Types - Re-exported from @automaker/types
*
* Defines the structure for global settings, credentials, and per-project settings
* that are persisted to disk in JSON format. These types are used by both the server
* (for file I/O via SettingsService) and the UI (for state management and sync).
* This file now re-exports settings types from the shared @automaker/types package
* to maintain backward compatibility with existing imports in the server codebase.
*/
/**
* ThemeMode - Available color themes for the UI
*
* Includes system theme and multiple color schemes:
* - System: Respects OS dark/light mode preference
* - Light/Dark: Basic light and dark variants
* - Color Schemes: Retro, Dracula, Nord, Monokai, Tokyo Night, Solarized, Gruvbox,
* Catppuccin, OneDark, Synthwave, Red, Cream, Sunset, Gray
*/
export type ThemeMode =
| "light"
| "dark"
| "system"
| "retro"
| "dracula"
| "nord"
| "monokai"
| "tokyonight"
| "solarized"
| "gruvbox"
| "catppuccin"
| "onedark"
| "synthwave"
| "red"
| "cream"
| "sunset"
| "gray";
export type {
ThemeMode,
KanbanCardDetailLevel,
AgentModel,
PlanningMode,
ThinkingLevel,
ModelProvider,
KeyboardShortcuts,
AIProfile,
ProjectRef,
TrashedProjectRef,
ChatSessionRef,
GlobalSettings,
Credentials,
BoardBackgroundSettings,
WorktreeInfo,
ProjectSettings,
} from '@automaker/types';
/** KanbanCardDetailLevel - Controls how much information is displayed on kanban cards */
export type KanbanCardDetailLevel = "minimal" | "standard" | "detailed";
/** AgentModel - Available Claude models for feature generation and planning */
export type AgentModel = "opus" | "sonnet" | "haiku";
/** PlanningMode - Planning levels for feature generation workflows */
export type PlanningMode = "skip" | "lite" | "spec" | "full";
/** ThinkingLevel - Extended thinking levels for Claude models (reasoning intensity) */
export type ThinkingLevel = "none" | "low" | "medium" | "high" | "ultrathink";
/** ModelProvider - AI model provider for credentials and API key management */
export type ModelProvider = "claude";
/**
* KeyboardShortcuts - User-configurable keyboard bindings for common actions
*
* Each property maps an action to a keyboard shortcut string
* (e.g., "Ctrl+K", "Alt+N", "Shift+P")
*/
export interface KeyboardShortcuts {
/** Open board view */
board: string;
/** Open agent panel */
agent: string;
/** Open feature spec editor */
spec: string;
/** Open context files panel */
context: string;
/** Open settings */
settings: string;
/** Open AI profiles */
profiles: string;
/** Open terminal */
terminal: string;
/** Toggle sidebar visibility */
toggleSidebar: string;
/** Add new feature */
addFeature: string;
/** Add context file */
addContextFile: string;
/** Start next feature generation */
startNext: string;
/** Create new chat session */
newSession: string;
/** Open project picker */
openProject: string;
/** Open project picker (alternate) */
projectPicker: string;
/** Cycle to previous project */
cyclePrevProject: string;
/** Cycle to next project */
cycleNextProject: string;
/** Add new AI profile */
addProfile: string;
/** Split terminal right */
splitTerminalRight: string;
/** Split terminal down */
splitTerminalDown: string;
/** Close current terminal */
closeTerminal: string;
}
/**
* AIProfile - Configuration for an AI model with specific parameters
*
* Profiles can be built-in defaults or user-created. They define which model to use,
* thinking level, and other parameters for feature generation tasks.
*/
export interface AIProfile {
/** Unique identifier for the profile */
id: string;
/** Display name for the profile */
name: string;
/** User-friendly description */
description: string;
/** Which Claude model to use (opus, sonnet, haiku) */
model: AgentModel;
/** Extended thinking level for reasoning-based tasks */
thinkingLevel: ThinkingLevel;
/** Provider (currently only "claude") */
provider: ModelProvider;
/** Whether this is a built-in default profile */
isBuiltIn: boolean;
/** Optional icon identifier or emoji */
icon?: string;
}
/**
* ProjectRef - Minimal reference to a project stored in global settings
*
* Used for the projects list and project history. Full project data is loaded separately.
*/
export interface ProjectRef {
/** Unique identifier */
id: string;
/** Display name */
name: string;
/** Absolute filesystem path to project directory */
path: string;
/** ISO timestamp of last time project was opened */
lastOpened?: string;
/** Project-specific theme override (or undefined to use global) */
theme?: string;
}
/**
* TrashedProjectRef - Reference to a project in the trash/recycle bin
*
* Extends ProjectRef with deletion metadata. User can permanently delete or restore.
*/
export interface TrashedProjectRef extends ProjectRef {
/** ISO timestamp when project was moved to trash */
trashedAt: string;
/** Whether project folder was deleted from disk */
deletedFromDisk?: boolean;
}
/**
* ChatSessionRef - Minimal reference to a chat session
*
* Used for session lists and history. Full session content is stored separately.
*/
export interface ChatSessionRef {
/** Unique session identifier */
id: string;
/** User-given or AI-generated title */
title: string;
/** Project that session belongs to */
projectId: string;
/** ISO timestamp of creation */
createdAt: string;
/** ISO timestamp of last message */
updatedAt: string;
/** Whether session is archived */
archived: boolean;
}
/**
* GlobalSettings - User preferences and state stored globally in {DATA_DIR}/settings.json
*
* This is the main settings file that persists user preferences across sessions.
* Includes theme, UI state, feature defaults, keyboard shortcuts, AI profiles, and projects.
* Format: JSON with version field for migration support.
*/
export interface GlobalSettings {
/** Version number for schema migration */
version: number;
// Theme Configuration
/** Currently selected theme */
theme: ThemeMode;
// UI State Preferences
/** Whether sidebar is currently open */
sidebarOpen: boolean;
/** Whether chat history panel is open */
chatHistoryOpen: boolean;
/** How much detail to show on kanban cards */
kanbanCardDetailLevel: KanbanCardDetailLevel;
// Feature Generation Defaults
/** Max features to generate concurrently */
maxConcurrency: number;
/** Default: skip tests during feature generation */
defaultSkipTests: boolean;
/** Default: enable dependency blocking */
enableDependencyBlocking: boolean;
/** Default: use git worktrees for feature branches */
useWorktrees: boolean;
/** Default: only show AI profiles (hide other settings) */
showProfilesOnly: boolean;
/** Default: planning approach (skip/lite/spec/full) */
defaultPlanningMode: PlanningMode;
/** Default: require manual approval before generating */
defaultRequirePlanApproval: boolean;
/** ID of currently selected AI profile (null = use built-in) */
defaultAIProfileId: string | null;
// Audio Preferences
/** Mute completion notification sound */
muteDoneSound: boolean;
// AI Model Selection
/** Which model to use for feature name/description enhancement */
enhancementModel: AgentModel;
// Input Configuration
/** User's keyboard shortcut bindings */
keyboardShortcuts: KeyboardShortcuts;
// AI Profiles
/** User-created AI profiles */
aiProfiles: AIProfile[];
// Project Management
/** List of active projects */
projects: ProjectRef[];
/** Projects in trash/recycle bin */
trashedProjects: TrashedProjectRef[];
/** History of recently opened project IDs */
projectHistory: string[];
/** Current position in project history for navigation */
projectHistoryIndex: number;
// File Browser and UI Preferences
/** Last directory opened in file picker */
lastProjectDir?: string;
/** Recently accessed folders for quick access */
recentFolders: string[];
/** Whether worktree panel is collapsed in current view */
worktreePanelCollapsed: boolean;
// Session Tracking
/** Maps project path -> last selected session ID in that project */
lastSelectedSessionByProject: Record<string, string>;
}
/**
* Credentials - API keys stored in {DATA_DIR}/credentials.json
*
* Sensitive data stored separately from general settings.
* Keys should never be exposed in UI or logs.
*/
export interface Credentials {
/** Version number for schema migration */
version: number;
/** API keys for various providers */
apiKeys: {
/** Anthropic Claude API key */
anthropic: string;
/** Google API key (for embeddings or other services) */
google: string;
/** OpenAI API key (for compatibility or alternative providers) */
openai: string;
};
}
/**
* BoardBackgroundSettings - Kanban board appearance customization
*
* Controls background images, opacity, borders, and visual effects for the board.
*/
export interface BoardBackgroundSettings {
/** Path to background image file (null = no image) */
imagePath: string | null;
/** Version/timestamp of image for cache busting */
imageVersion?: number;
/** Opacity of cards (0-1) */
cardOpacity: number;
/** Opacity of columns (0-1) */
columnOpacity: number;
/** Show border around columns */
columnBorderEnabled: boolean;
/** Apply glassmorphism effect to cards */
cardGlassmorphism: boolean;
/** Show border around cards */
cardBorderEnabled: boolean;
/** Opacity of card borders (0-1) */
cardBorderOpacity: number;
/** Hide scrollbar in board view */
hideScrollbar: boolean;
}
/**
* WorktreeInfo - Information about a git worktree
*
* Tracks worktree location, branch, and dirty state for project management.
*/
export interface WorktreeInfo {
/** Absolute path to worktree directory */
path: string;
/** Branch checked out in this worktree */
branch: string;
/** Whether this is the main worktree */
isMain: boolean;
/** Whether worktree has uncommitted changes */
hasChanges?: boolean;
/** Number of files with changes */
changedFilesCount?: number;
}
/**
* ProjectSettings - Project-specific overrides stored in {projectPath}/.automaker/settings.json
*
* Allows per-project customization without affecting global settings.
* All fields are optional - missing values fall back to global settings.
*/
export interface ProjectSettings {
/** Version number for schema migration */
version: number;
// Theme Configuration (project-specific override)
/** Project theme (undefined = use global setting) */
theme?: ThemeMode;
// Worktree Management
/** Project-specific worktree preference override */
useWorktrees?: boolean;
/** Current worktree being used in this project */
currentWorktree?: { path: string | null; branch: string };
/** List of worktrees available in this project */
worktrees?: WorktreeInfo[];
// Board Customization
/** Project-specific board background settings */
boardBackground?: BoardBackgroundSettings;
// Session Tracking
/** Last chat session selected in this project */
lastSelectedSessionId?: string;
}
/**
* Default values and constants
*/
/** Default keyboard shortcut bindings */
export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = {
board: "K",
agent: "A",
spec: "D",
context: "C",
settings: "S",
profiles: "M",
terminal: "T",
toggleSidebar: "`",
addFeature: "N",
addContextFile: "N",
startNext: "G",
newSession: "N",
openProject: "O",
projectPicker: "P",
cyclePrevProject: "Q",
cycleNextProject: "E",
addProfile: "N",
splitTerminalRight: "Alt+D",
splitTerminalDown: "Alt+S",
closeTerminal: "Alt+W",
};
/** Default global settings used when no settings file exists */
export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
version: 1,
theme: "dark",
sidebarOpen: true,
chatHistoryOpen: false,
kanbanCardDetailLevel: "standard",
maxConcurrency: 3,
defaultSkipTests: true,
enableDependencyBlocking: true,
useWorktrees: false,
showProfilesOnly: false,
defaultPlanningMode: "skip",
defaultRequirePlanApproval: false,
defaultAIProfileId: null,
muteDoneSound: false,
enhancementModel: "sonnet",
keyboardShortcuts: DEFAULT_KEYBOARD_SHORTCUTS,
aiProfiles: [],
projects: [],
trashedProjects: [],
projectHistory: [],
projectHistoryIndex: -1,
lastProjectDir: undefined,
recentFolders: [],
worktreePanelCollapsed: false,
lastSelectedSessionByProject: {},
};
/** Default credentials (empty strings - user must provide API keys) */
export const DEFAULT_CREDENTIALS: Credentials = {
version: 1,
apiKeys: {
anthropic: "",
google: "",
openai: "",
},
};
/** Default project settings (empty - all settings are optional and fall back to global) */
export const DEFAULT_PROJECT_SETTINGS: ProjectSettings = {
version: 1,
};
/** Current version of the global settings schema */
export const SETTINGS_VERSION = 1;
/** Current version of the credentials schema */
export const CREDENTIALS_VERSION = 1;
/** Current version of the project settings schema */
export const PROJECT_SETTINGS_VERSION = 1;
export {
DEFAULT_KEYBOARD_SHORTCUTS,
DEFAULT_GLOBAL_SETTINGS,
DEFAULT_CREDENTIALS,
DEFAULT_PROJECT_SETTINGS,
SETTINGS_VERSION,
CREDENTIALS_VERSION,
PROJECT_SETTINGS_VERSION,
} from '@automaker/types';

View File

@@ -4,14 +4,7 @@ import { cn } from "@/lib/utils";
import { ImageIcon, X, Loader2 } from "lucide-react";
import { Textarea } from "@/components/ui/textarea";
import { getElectronAPI } from "@/lib/electron";
import { useAppStore } from "@/store/app-store";
export interface FeatureImagePath {
id: string;
path: string; // Path to the temp file
filename: string;
mimeType: string;
}
import { useAppStore, type FeatureImagePath } from "@/store/app-store";
// Map to store preview data by image ID (persisted across component re-mounts)
export type ImagePreviewMap = Map<string, string>;

View File

@@ -1,4 +1,4 @@
import { AgentModel, ThinkingLevel } from "@/store/app-store";
import type { AgentModel, ThinkingLevel } from "@/store/app-store";
import {
Brain,
Zap,

View File

@@ -1,6 +1,15 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
import type { Project, TrashedProject } from "@/lib/electron";
import type {
Feature as BaseFeature,
FeatureImagePath,
AgentModel,
PlanningMode,
ThinkingLevel,
ModelProvider,
AIProfile,
} from '@automaker/types';
export type ViewMode =
| "welcome"
@@ -238,6 +247,10 @@ export interface ChatSession {
archived: boolean;
}
// Re-export for backward compatibility
export type { FeatureImagePath, AgentModel, PlanningMode, ThinkingLevel, ModelProvider, AIProfile };
// UI-specific: base64-encoded images (not in shared types)
export interface FeatureImage {
id: string;
data: string; // base64 encoded
@@ -246,68 +259,22 @@ export interface FeatureImage {
size: number;
}
export interface FeatureImagePath {
id: string;
path: string; // Path to the temp file
filename: string;
mimeType: string;
}
// Available models for feature execution (alias for consistency)
export type ClaudeModel = AgentModel;
// Available models for feature execution
export type ClaudeModel = "opus" | "sonnet" | "haiku";
export type AgentModel = ClaudeModel;
// Model provider type
export type ModelProvider = "claude";
// Thinking level (budget_tokens) options
export type ThinkingLevel = "none" | "low" | "medium" | "high" | "ultrathink";
// Planning mode for feature specifications
export type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';
// AI Provider Profile - user-defined presets for model configurations
export interface AIProfile {
id: string;
name: string;
description: string;
model: AgentModel;
thinkingLevel: ThinkingLevel;
provider: ModelProvider;
isBuiltIn: boolean; // Built-in profiles cannot be deleted
icon?: string; // Optional icon name from lucide
}
export interface Feature {
id: string;
title?: string;
titleGenerating?: boolean;
category: string;
description: string;
steps: string[];
// UI-specific Feature extension with UI-only fields and stricter types
export interface Feature extends Omit<BaseFeature, 'steps' | 'imagePaths' | 'status'> {
steps: string[]; // Required in UI (not optional)
status:
| "backlog"
| "in_progress"
| "waiting_approval"
| "verified"
| "completed";
images?: FeatureImage[];
imagePaths?: FeatureImagePath[]; // Paths to temp files for agent context
startedAt?: string; // ISO timestamp for when the card moved to in_progress
skipTests?: boolean; // When true, skip TDD approach and require manual verification
summary?: string; // Summary of what was done/modified by the agent
model?: AgentModel; // Model to use for this feature (defaults to opus)
thinkingLevel?: ThinkingLevel; // Thinking level for extended thinking (defaults to none)
error?: string; // Error message if the agent errored during processing
priority?: number; // Priority: 1 = high, 2 = medium, 3 = low
dependencies?: string[]; // Array of feature IDs this feature depends on
// Branch info - worktree path is derived at runtime from branchName
branchName?: string; // Name of the feature branch (undefined = use current worktree)
justFinishedAt?: string; // ISO timestamp when agent just finished and moved to waiting_approval (shows badge for 2 minutes)
planningMode?: PlanningMode; // Planning mode for this feature
planSpec?: PlanSpec; // Generated spec/plan data
requirePlanApproval?: boolean; // Whether to pause and require manual approval before implementation
prUrl?: string; // Pull request URL when a PR has been created for this feature
images?: FeatureImage[]; // UI-specific base64 images
imagePaths?: FeatureImagePath[]; // Stricter type than base (no string | union)
justFinishedAt?: string; // UI-specific: ISO timestamp when agent just finished
prUrl?: string; // UI-specific: Pull request URL
}
// Parsed task from spec (for spec and full planning modes)

View File

@@ -10,6 +10,7 @@ AutoMaker uses a monorepo structure with shared packages in `libs/`:
libs/
├── types/ # Type definitions (no dependencies)
├── utils/ # Utility functions
├── prompts/ # AI prompt templates
├── platform/ # Platform utilities
├── model-resolver/ # Claude model resolution
├── dependency-resolver/# Feature dependency resolution
@@ -54,6 +55,38 @@ import { createLogger, classifyError } from '@automaker/utils';
**Never import from:** `lib/logger`, `lib/error-handler`, `lib/prompt-builder`, `lib/image-handler`
### @automaker/prompts
**Use when:** You need AI prompt templates for text enhancement or other AI-powered features.
**Import for:**
- `getEnhancementPrompt(mode)` - Get complete prompt for enhancement mode
- `getSystemPrompt(mode)` - Get system prompt for specific mode
- `getExamples(mode)` - Get few-shot examples for a mode
- `buildUserPrompt(description, mode)` - Build user prompt with examples
- `isValidEnhancementMode(mode)` - Check if mode is valid
- `IMPROVE_SYSTEM_PROMPT` - System prompt for improving vague descriptions
- `TECHNICAL_SYSTEM_PROMPT` - System prompt for adding technical details
- `SIMPLIFY_SYSTEM_PROMPT` - System prompt for simplifying verbose text
- `ACCEPTANCE_SYSTEM_PROMPT` - System prompt for adding acceptance criteria
**Example:**
```typescript
import { getEnhancementPrompt, isValidEnhancementMode } from '@automaker/prompts';
if (isValidEnhancementMode('improve')) {
const { systemPrompt, userPrompt } = getEnhancementPrompt('improve', description);
const result = await callClaude(systemPrompt, userPrompt);
}
```
**Never import from:** `lib/enhancement-prompts`
**Enhancement modes:**
- `improve` - Transform vague requests into clear, actionable tasks
- `technical` - Add implementation details and technical specifications
- `simplify` - Make verbose descriptions concise and focused
- `acceptance` - Add testable acceptance criteria
### @automaker/platform
**Use when:** You need to work with AutoMaker's directory structure or spawn processes.
@@ -271,6 +304,9 @@ import { CLAUDE_MODEL_MAP, DEFAULT_MODELS } from '@automaker/types';
// Import utilities from @automaker/utils
import { createLogger, classifyError } from '@automaker/utils';
// Import prompts from @automaker/prompts
import { getEnhancementPrompt, isValidEnhancementMode } from '@automaker/prompts';
// Import platform utils from @automaker/platform
import { getFeatureDir, ensureAutomakerDir } from '@automaker/platform';
@@ -294,6 +330,7 @@ import { createLogger } from '../lib/logger'; // ❌
import { resolveModelString } from '../lib/model-resolver'; // ❌
import { isGitRepo } from '../routes/common'; // ❌
import { resolveDependencies } from '../lib/dependency-resolver'; // ❌
import { getEnhancementPrompt } from '../lib/enhancement-prompts'; // ❌
// DON'T import from old lib/ paths
import { getFeatureDir } from '../lib/automaker-paths'; // ❌
@@ -310,6 +347,7 @@ When refactoring server code, check:
- [ ] All `Feature` imports use `@automaker/types`
- [ ] All `ExecuteOptions` imports use `@automaker/types`
- [ ] All logger usage uses `@automaker/utils`
- [ ] All prompt templates use `@automaker/prompts`
- [ ] All path operations use `@automaker/platform`
- [ ] All model resolution uses `@automaker/model-resolver`
- [ ] All dependency checks use `@automaker/dependency-resolver`
@@ -326,6 +364,7 @@ Understanding the dependency chain helps prevent circular dependencies:
@automaker/types (no dependencies)
@automaker/utils
@automaker/prompts
@automaker/platform
@automaker/model-resolver
@automaker/dependency-resolver
@@ -352,8 +391,10 @@ npm install # Installs and links workspace packages
## Module Format
- **dependency-resolver**: ES modules (`type: "module"`) for Vite compatibility
- **All others**: CommonJS for Node.js compatibility
All packages use ES modules (`type: "module"`) with NodeNext module resolution:
- Requires explicit `.js` extensions in import statements
- Compatible with both Node.js (server) and Vite (UI)
- Centralized ESM configuration in `libs/tsconfig.base.json`
## Testing
@@ -372,7 +413,8 @@ import { Feature } from '../../../src/services/feature-loader';
**Quick reference:**
- Types → `@automaker/types`
- Logging/Errors → `@automaker/utils`
- Logging/Errors/Utils`@automaker/utils`
- AI Prompts → `@automaker/prompts`
- Paths/Security → `@automaker/platform`
- Model Resolution → `@automaker/model-resolver`
- Dependency Ordering → `@automaker/dependency-resolver`

254
libs/prompts/README.md Normal file
View File

@@ -0,0 +1,254 @@
# @automaker/prompts
AI prompt templates for text enhancement and other AI-powered features in AutoMaker.
## Overview
This package provides professionally-crafted prompt templates for enhancing user-written task descriptions using Claude. It includes system prompts, few-shot examples, and utility functions for different enhancement modes: improve, technical, simplify, and acceptance.
## Installation
```bash
npm install @automaker/prompts
```
## Exports
### Enhancement Modes
Four modes are available, each optimized for a specific enhancement task:
- **improve** - Transform vague requests into clear, actionable tasks
- **technical** - Add implementation details and technical specifications
- **simplify** - Make verbose descriptions concise and focused
- **acceptance** - Add testable acceptance criteria
### System Prompts
Direct access to system prompts for each mode:
```typescript
import {
IMPROVE_SYSTEM_PROMPT,
TECHNICAL_SYSTEM_PROMPT,
SIMPLIFY_SYSTEM_PROMPT,
ACCEPTANCE_SYSTEM_PROMPT
} from '@automaker/prompts';
console.log(IMPROVE_SYSTEM_PROMPT); // Full system prompt for improve mode
```
### Helper Functions
#### `getEnhancementPrompt(mode, description)`
Get complete prompt (system + user) for an enhancement mode:
```typescript
import { getEnhancementPrompt } from '@automaker/prompts';
const result = getEnhancementPrompt('improve', 'make app faster');
console.log(result.systemPrompt); // System instructions for improve mode
console.log(result.userPrompt); // User prompt with examples and input
```
#### `getSystemPrompt(mode)`
Get only the system prompt for a mode:
```typescript
import { getSystemPrompt } from '@automaker/prompts';
const systemPrompt = getSystemPrompt('technical');
```
#### `getExamples(mode)`
Get few-shot examples for a mode:
```typescript
import { getExamples } from '@automaker/prompts';
const examples = getExamples('simplify');
// Returns array of { input, output } pairs
```
#### `buildUserPrompt(description, mode)`
Build user prompt with examples:
```typescript
import { buildUserPrompt } from '@automaker/prompts';
const userPrompt = buildUserPrompt('add login page', 'improve');
// Includes examples + user's description
```
#### `isValidEnhancementMode(mode)`
Check if a mode is valid:
```typescript
import { isValidEnhancementMode } from '@automaker/prompts';
if (isValidEnhancementMode('improve')) {
// Mode is valid
}
```
#### `getAvailableEnhancementModes()`
Get list of all available modes:
```typescript
import { getAvailableEnhancementModes } from '@automaker/prompts';
const modes = getAvailableEnhancementModes();
// Returns: ['improve', 'technical', 'simplify', 'acceptance']
```
## Usage Examples
### Basic Enhancement
```typescript
import { getEnhancementPrompt } from '@automaker/prompts';
async function enhanceDescription(description: string, mode: string) {
const { systemPrompt, userPrompt } = getEnhancementPrompt(mode, description);
const response = await claude.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: systemPrompt,
messages: [{ role: 'user', content: userPrompt }]
});
return response.content[0].text;
}
// Example usage
const improved = await enhanceDescription('make app faster', 'improve');
// → "Optimize application performance by profiling bottlenecks..."
const technical = await enhanceDescription('add search', 'technical');
// → "Implement full-text search with the following components:..."
```
### Mode Validation
```typescript
import { isValidEnhancementMode, getAvailableEnhancementModes } from '@automaker/prompts';
function validateAndEnhance(mode: string, description: string) {
if (!isValidEnhancementMode(mode)) {
const available = getAvailableEnhancementModes().join(', ');
throw new Error(`Invalid mode "${mode}". Available: ${available}`);
}
return enhanceDescription(description, mode);
}
```
### Custom Prompt Building
```typescript
import { getSystemPrompt, buildUserPrompt, getExamples } from '@automaker/prompts';
// Get components separately for custom workflows
const systemPrompt = getSystemPrompt('simplify');
const examples = getExamples('simplify');
const userPrompt = buildUserPrompt(userInput, 'simplify');
// Use with custom processing
const response = await processWithClaude(systemPrompt, userPrompt);
```
### Server Route Example
```typescript
import { getEnhancementPrompt, isValidEnhancementMode } from '@automaker/prompts';
import { createLogger } from '@automaker/utils';
const logger = createLogger('EnhancementRoute');
app.post('/api/enhance', async (req, res) => {
const { description, mode } = req.body;
if (!isValidEnhancementMode(mode)) {
return res.status(400).json({ error: 'Invalid enhancement mode' });
}
try {
const { systemPrompt, userPrompt } = getEnhancementPrompt(mode, description);
const result = await claude.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 1024,
system: systemPrompt,
messages: [{ role: 'user', content: userPrompt }]
});
logger.info(`Enhanced with mode: ${mode}`);
res.json({ enhanced: result.content[0].text });
} catch (error) {
logger.error('Enhancement failed:', error);
res.status(500).json({ error: 'Enhancement failed' });
}
});
```
## Enhancement Mode Details
### Improve Mode
Transforms vague or unclear requests into clear, actionable specifications.
**Before:** "make app faster"
**After:** "Optimize application performance by:
1. Profiling code to identify bottlenecks
2. Implementing caching for frequently accessed data
3. Optimizing database queries..."
### Technical Mode
Adds implementation details and technical specifications.
**Before:** "add search"
**After:** "Implement full-text search using:
- Backend: Elasticsearch or PostgreSQL full-text search
- Frontend: Debounced search input with loading states
- API: GET /api/search endpoint with pagination..."
### Simplify Mode
Makes verbose descriptions concise while preserving essential information.
**Before:** "We really need to make sure that the application has the capability to allow users to be able to search for various items..."
**After:** "Add search functionality for items with filters and results display."
### Acceptance Mode
Adds testable acceptance criteria to feature descriptions.
**Before:** "user login"
**After:** "User login feature
- User can enter email and password
- System validates credentials
- On success: redirect to dashboard
- On failure: show error message
- Remember me option persists login..."
## Dependencies
- `@automaker/types` - Type definitions for EnhancementMode and EnhancementExample
## Used By
- `@automaker/server` - Enhancement API routes
- Future packages requiring AI-powered text enhancement
## License
SEE LICENSE IN LICENSE

25
libs/prompts/package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "@automaker/prompts",
"version": "1.0.0",
"type": "module",
"description": "AI prompt templates for AutoMaker",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"watch": "tsc --watch",
"test": "vitest run",
"test:watch": "vitest"
},
"keywords": ["automaker", "prompts", "ai"],
"author": "AutoMaker Team",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"@automaker/types": "^1.0.0"
},
"devDependencies": {
"@types/node": "^22.10.5",
"typescript": "^5.7.3",
"vitest": "^4.0.16"
}
}

View File

@@ -0,0 +1,448 @@
/**
* Enhancement Prompts Library - AI-powered text enhancement for task descriptions
*
* Provides prompt templates and utilities for enhancing user-written task descriptions:
* - Improve: Transform vague requests into clear, actionable tasks
* - Technical: Add implementation details and technical specifications
* - Simplify: Make verbose descriptions concise and focused
* - Acceptance: Add testable acceptance criteria
*
* Uses chain-of-thought prompting with few-shot examples for consistent results.
*/
import type { EnhancementMode, EnhancementExample } from "@automaker/types";
// Re-export enhancement types from shared package
export type { EnhancementMode, EnhancementExample } from "@automaker/types";
/**
* System prompt for the "improve" enhancement mode.
* Transforms vague or unclear requests into clear, actionable task descriptions.
*/
export const IMPROVE_SYSTEM_PROMPT = `You are an expert at transforming vague, unclear, or incomplete task descriptions into clear, actionable specifications.
Your task is to take a user's rough description and improve it by:
1. ANALYZE the input:
- Identify the core intent behind the request
- Note any ambiguities or missing details
- Determine what success would look like
2. CLARIFY the scope:
- Define clear boundaries for the task
- Identify implicit requirements
- Add relevant context that may be assumed
3. STRUCTURE the output:
- Write a clear, actionable title
- Provide a concise description of what needs to be done
- Break down into specific sub-tasks if appropriate
4. ENHANCE with details:
- Add specific, measurable outcomes where possible
- Include edge cases to consider
- Note any dependencies or prerequisites
Output ONLY the improved task description. Do not include explanations, markdown formatting, or meta-commentary about your changes.`;
/**
* System prompt for the "technical" enhancement mode.
* Adds implementation details and technical specifications.
*/
export const TECHNICAL_SYSTEM_PROMPT = `You are a senior software engineer skilled at adding technical depth to feature descriptions.
Your task is to enhance a task description with technical implementation details:
1. ANALYZE the requirement:
- Understand the functional goal
- Identify the technical domain (frontend, backend, database, etc.)
- Consider the likely tech stack based on context
2. ADD technical specifications:
- Suggest specific technologies, libraries, or patterns
- Define API contracts or data structures if relevant
- Note performance considerations
- Identify security implications
3. OUTLINE implementation approach:
- Break down into technical sub-tasks
- Suggest file structure or component organization
- Note integration points with existing systems
4. CONSIDER edge cases:
- Error handling requirements
- Loading and empty states
- Boundary conditions
Output ONLY the enhanced technical description. Keep it concise but comprehensive. Do not include explanations about your reasoning.`;
/**
* System prompt for the "simplify" enhancement mode.
* Makes verbose descriptions concise and focused.
*/
export const SIMPLIFY_SYSTEM_PROMPT = `You are an expert editor who excels at making verbose text concise without losing meaning.
Your task is to simplify a task description while preserving essential information:
1. IDENTIFY the core message:
- Extract the primary goal or requirement
- Note truly essential details
- Separate nice-to-have from must-have information
2. ELIMINATE redundancy:
- Remove repeated information
- Cut unnecessary qualifiers and hedging language
- Remove filler words and phrases
3. CONSOLIDATE related points:
- Merge overlapping requirements
- Group related items together
- Use concise language
4. PRESERVE critical details:
- Keep specific technical requirements
- Retain important constraints
- Maintain actionable specifics
Output ONLY the simplified description. Aim for 30-50% reduction in length while keeping all essential information. Do not explain your changes.`;
/**
* System prompt for the "acceptance" enhancement mode.
* Adds testable acceptance criteria to task descriptions.
*/
export const ACCEPTANCE_SYSTEM_PROMPT = `You are a QA specialist skilled at defining testable acceptance criteria for software features.
Your task is to enhance a task description by adding clear acceptance criteria:
1. UNDERSTAND the feature:
- Identify all user-facing behaviors
- Note system state changes
- Consider different user roles or scenarios
2. DEFINE acceptance criteria using Given-When-Then format:
- Given: The initial context or preconditions
- When: The action or trigger
- Then: The expected outcome
3. COVER key scenarios:
- Happy path (successful completion)
- Edge cases (boundary conditions)
- Error scenarios (what should NOT happen)
- Performance requirements if relevant
4. MAKE criteria testable:
- Use specific, measurable outcomes
- Avoid vague terms like "quickly" or "easily"
- Include specific values where applicable
Output the original description followed by a clear "Acceptance Criteria:" section with numbered, testable criteria. Do not include explanations about your process.`;
/**
* Few-shot examples for the "improve" enhancement mode
*/
export const IMPROVE_EXAMPLES: EnhancementExample[] = [
{
input: "add dark mode",
output: `Add Dark Mode Theme Support
Implement a dark mode option that allows users to switch between light and dark themes throughout the application.
Requirements:
- Add a theme toggle switch in the settings area
- Store user's theme preference persistently
- Apply dark theme colors to all UI components
- Respect system preference as default if user hasn't set a preference
- Ensure smooth transition when switching themes`,
},
{
input: "fix the login bug",
output: `Fix Login Authentication Flow
Investigate and resolve issues preventing users from successfully logging in to the application.
Requirements:
- Identify the specific failure point in the login process
- Ensure proper credential validation
- Handle error states with clear user feedback
- Verify session token is correctly stored after successful login
- Test with various credential combinations (valid, invalid, edge cases)`,
},
{
input: "make it faster",
output: `Improve Application Performance
Optimize application loading and response times to enhance user experience.
Requirements:
- Profile current performance to identify bottlenecks
- Implement code splitting and lazy loading for routes/components
- Optimize database queries and add appropriate indexes
- Add caching for frequently accessed data
- Set performance budget targets (e.g., LCP < 2.5s, FID < 100ms)
- Measure and document improvements`,
},
];
/**
* Few-shot examples for the "technical" enhancement mode
*/
export const TECHNICAL_EXAMPLES: EnhancementExample[] = [
{
input: "Add user profile page",
output: `Add User Profile Page
Create a dedicated profile page for viewing and editing user information.
Technical Implementation:
- Frontend: React component at /profile route with form validation
- API Endpoint: GET/PUT /api/users/:id for fetching and updating profile
- Data Model: Extend User schema with profile fields (avatar, bio, preferences)
- File Upload: Integrate cloud storage for avatar images with client-side resizing
- State Management: Use optimistic updates for better UX
- Validation: Server-side validation matching client-side rules
Components:
- ProfileHeader (avatar, name, edit button)
- ProfileForm (editable fields with validation)
- AvatarUploader (drag-drop with preview)
Security: Ensure users can only edit their own profile (auth middleware)`,
},
{
input: "Add search functionality",
output: `Add Search Functionality
Implement full-text search across application content.
Technical Implementation:
- Search Engine: Use Elasticsearch or PostgreSQL full-text search
- API: GET /api/search?q={query}&type={type}&page={page}
- Indexing: Create search index with relevant fields, update on content changes
- Frontend: Debounced search input (300ms) with typeahead suggestions
- Results: Paginated results with highlighted matching text
Architecture:
- SearchService class handling query building and execution
- SearchIndex worker for background indexing
- SearchResults component with filtering and sorting
Performance:
- Implement search result caching (Redis, 5-minute TTL)
- Limit results per page (20 items)
- Add query complexity limits to prevent abuse`,
},
];
/**
* Few-shot examples for the "simplify" enhancement mode
*/
export const SIMPLIFY_EXAMPLES: EnhancementExample[] = [
{
input: `We need to implement a feature that would allow our users to be able to export their data in various different formats. The formats we are thinking about supporting include CSV which is commonly used for spreadsheet applications, and also JSON which is good for developers, and possibly PDF for people who want a printable version. The user should be able to go somewhere in the UI and select which format they want and then download their data in that format. We should probably also show some kind of progress indicator while the export is happening since it might take a while for large datasets.`,
output: `Add Data Export Feature
Allow users to export their data in CSV, JSON, or PDF format.
Requirements:
- Add export button/menu in the UI
- Support three formats: CSV (spreadsheets), JSON (developers), PDF (printing)
- Show progress indicator during export
- Handle large datasets gracefully`,
},
{
input: `The current notification system is not working very well and users are complaining about it. Sometimes they don't receive notifications at all, and other times they receive too many notifications and feel overwhelmed. We also have had reports that the notifications are not appearing correctly on mobile devices. Additionally, some users have requested the ability to customize which types of notifications they receive. We should look into all of these issues and make the notification system work better overall.`,
output: `Fix and Improve Notification System
Address reliability issues and add user controls for notifications.
Issues to fix:
- Missing notifications (delivery reliability)
- Notification overload (implement batching/digest)
- Mobile display problems
Enhancements:
- Add notification preferences (per-type controls)
- Test across devices and platforms`,
},
];
/**
* Few-shot examples for the "acceptance" enhancement mode
*/
export const ACCEPTANCE_EXAMPLES: EnhancementExample[] = [
{
input: "Add password reset functionality",
output: `Add Password Reset Functionality
Allow users to reset their password via email when they forget it.
Acceptance Criteria:
1. Given a user is on the login page, when they click "Forgot Password", then they should see a password reset form requesting their email.
2. Given a user enters a valid registered email, when they submit the form, then they should receive a password reset email within 2 minutes.
3. Given a user clicks the reset link in their email, when the link is less than 1 hour old, then they should see a form to enter a new password.
4. Given a user enters a new valid password (min 8 chars, 1 number, 1 special char), when they submit, then their password should be updated and they should be redirected to login.
5. Given a user enters an unregistered email, when they submit the reset form, then they should see the same success message (security: don't reveal which emails exist).
6. Given a reset link older than 1 hour, when a user clicks it, then they should see an expiration message with option to request a new link.`,
},
{
input: "Shopping cart checkout",
output: `Shopping Cart Checkout
Implement the checkout flow for purchasing items in the shopping cart.
Acceptance Criteria:
1. Given a user has items in their cart, when they click "Checkout", then they should see an order summary with item details and total price.
2. Given a user is on the checkout page, when they enter valid shipping information, then the form should validate in real-time and show estimated delivery date.
3. Given valid shipping info is entered, when the user proceeds to payment, then they should see available payment methods (credit card, PayPal).
4. Given valid payment details are entered, when the user confirms the order, then the payment should be processed and order confirmation displayed within 5 seconds.
5. Given a successful order, when confirmation is shown, then the user should receive an email receipt and their cart should be emptied.
6. Given a payment failure, when the error occurs, then the user should see a clear error message and their cart should remain intact.
7. Given the user closes the browser during checkout, when they return, then their cart contents should still be available.`,
},
];
/**
* Map of enhancement modes to their system prompts
*/
const SYSTEM_PROMPTS: Record<EnhancementMode, string> = {
improve: IMPROVE_SYSTEM_PROMPT,
technical: TECHNICAL_SYSTEM_PROMPT,
simplify: SIMPLIFY_SYSTEM_PROMPT,
acceptance: ACCEPTANCE_SYSTEM_PROMPT,
};
/**
* Map of enhancement modes to their few-shot examples
*/
const EXAMPLES: Record<EnhancementMode, EnhancementExample[]> = {
improve: IMPROVE_EXAMPLES,
technical: TECHNICAL_EXAMPLES,
simplify: SIMPLIFY_EXAMPLES,
acceptance: ACCEPTANCE_EXAMPLES,
};
/**
* Enhancement prompt configuration returned by getEnhancementPrompt
*/
export interface EnhancementPromptConfig {
/** System prompt for the enhancement mode */
systemPrompt: string;
/** Description of what this mode does */
description: string;
}
/**
* Descriptions for each enhancement mode
*/
const MODE_DESCRIPTIONS: Record<EnhancementMode, string> = {
improve: "Transform vague requests into clear, actionable task descriptions",
technical: "Add implementation details and technical specifications",
simplify: "Make verbose descriptions concise and focused",
acceptance: "Add testable acceptance criteria to task descriptions",
};
/**
* Get the enhancement prompt configuration for a given mode
*
* @param mode - The enhancement mode (falls back to 'improve' if invalid)
* @returns The enhancement prompt configuration
*/
export function getEnhancementPrompt(mode: string): EnhancementPromptConfig {
const normalizedMode = mode.toLowerCase() as EnhancementMode;
const validMode = normalizedMode in SYSTEM_PROMPTS ? normalizedMode : "improve";
return {
systemPrompt: SYSTEM_PROMPTS[validMode],
description: MODE_DESCRIPTIONS[validMode],
};
}
/**
* Get the system prompt for a specific enhancement mode
*
* @param mode - The enhancement mode to get the prompt for
* @returns The system prompt string
*/
export function getSystemPrompt(mode: EnhancementMode): string {
return SYSTEM_PROMPTS[mode];
}
/**
* Get the few-shot examples for a specific enhancement mode
*
* @param mode - The enhancement mode to get examples for
* @returns Array of input/output example pairs
*/
export function getExamples(mode: EnhancementMode): EnhancementExample[] {
return EXAMPLES[mode];
}
/**
* Build a user prompt for enhancement with optional few-shot examples
*
* @param mode - The enhancement mode
* @param text - The text to enhance
* @param includeExamples - Whether to include few-shot examples (default: true)
* @returns The formatted user prompt string
*/
export function buildUserPrompt(
mode: EnhancementMode,
text: string,
includeExamples: boolean = true
): string {
const examples = includeExamples ? getExamples(mode) : [];
if (examples.length === 0) {
return `Please enhance the following task description:\n\n${text}`;
}
// Build few-shot examples section
const examplesSection = examples
.map(
(example, index) =>
`Example ${index + 1}:\nInput: ${example.input}\nOutput: ${example.output}`
)
.join("\n\n---\n\n");
return `Here are some examples of how to enhance task descriptions:
${examplesSection}
---
Now, please enhance the following task description:
${text}`;
}
/**
* Check if a mode is a valid enhancement mode
*
* @param mode - The mode to check
* @returns True if the mode is valid
*/
export function isValidEnhancementMode(mode: string): mode is EnhancementMode {
return mode in SYSTEM_PROMPTS;
}
/**
* Get all available enhancement modes
*
* @returns Array of available enhancement mode names
*/
export function getAvailableEnhancementModes(): EnhancementMode[] {
return Object.keys(SYSTEM_PROMPTS) as EnhancementMode[];
}

25
libs/prompts/src/index.ts Normal file
View File

@@ -0,0 +1,25 @@
/**
* @automaker/prompts
* AI prompt templates for AutoMaker
*/
// Enhancement prompts
export {
IMPROVE_SYSTEM_PROMPT,
TECHNICAL_SYSTEM_PROMPT,
SIMPLIFY_SYSTEM_PROMPT,
ACCEPTANCE_SYSTEM_PROMPT,
IMPROVE_EXAMPLES,
TECHNICAL_EXAMPLES,
SIMPLIFY_EXAMPLES,
ACCEPTANCE_EXAMPLES,
getEnhancementPrompt,
getSystemPrompt,
getExamples,
buildUserPrompt,
isValidEnhancementMode,
getAvailableEnhancementModes,
} from './enhancement.js';
// Re-export types from @automaker/types
export type { EnhancementMode, EnhancementExample } from '@automaker/types';

View File

@@ -0,0 +1,526 @@
import { describe, it, expect } from "vitest";
import {
getEnhancementPrompt,
getSystemPrompt,
getExamples,
buildUserPrompt,
isValidEnhancementMode,
getAvailableEnhancementModes,
IMPROVE_SYSTEM_PROMPT,
TECHNICAL_SYSTEM_PROMPT,
SIMPLIFY_SYSTEM_PROMPT,
ACCEPTANCE_SYSTEM_PROMPT,
IMPROVE_EXAMPLES,
TECHNICAL_EXAMPLES,
SIMPLIFY_EXAMPLES,
ACCEPTANCE_EXAMPLES,
} from "../src/enhancement.js";
describe("enhancement.ts", () => {
describe("System Prompt Constants", () => {
it("should export IMPROVE_SYSTEM_PROMPT", () => {
expect(IMPROVE_SYSTEM_PROMPT).toBeDefined();
expect(typeof IMPROVE_SYSTEM_PROMPT).toBe("string");
expect(IMPROVE_SYSTEM_PROMPT).toContain("vague, unclear");
expect(IMPROVE_SYSTEM_PROMPT).toContain("actionable");
});
it("should export TECHNICAL_SYSTEM_PROMPT", () => {
expect(TECHNICAL_SYSTEM_PROMPT).toBeDefined();
expect(typeof TECHNICAL_SYSTEM_PROMPT).toBe("string");
expect(TECHNICAL_SYSTEM_PROMPT).toContain("technical");
expect(TECHNICAL_SYSTEM_PROMPT).toContain("implementation");
});
it("should export SIMPLIFY_SYSTEM_PROMPT", () => {
expect(SIMPLIFY_SYSTEM_PROMPT).toBeDefined();
expect(typeof SIMPLIFY_SYSTEM_PROMPT).toBe("string");
expect(SIMPLIFY_SYSTEM_PROMPT).toContain("verbose");
expect(SIMPLIFY_SYSTEM_PROMPT).toContain("concise");
});
it("should export ACCEPTANCE_SYSTEM_PROMPT", () => {
expect(ACCEPTANCE_SYSTEM_PROMPT).toBeDefined();
expect(typeof ACCEPTANCE_SYSTEM_PROMPT).toBe("string");
expect(ACCEPTANCE_SYSTEM_PROMPT).toContain("acceptance criteria");
expect(ACCEPTANCE_SYSTEM_PROMPT).toContain("testable");
});
});
describe("Examples Constants", () => {
it("should export IMPROVE_EXAMPLES with valid structure", () => {
expect(IMPROVE_EXAMPLES).toBeDefined();
expect(Array.isArray(IMPROVE_EXAMPLES)).toBe(true);
expect(IMPROVE_EXAMPLES.length).toBeGreaterThan(0);
IMPROVE_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty("input");
expect(example).toHaveProperty("output");
expect(typeof example.input).toBe("string");
expect(typeof example.output).toBe("string");
});
});
it("should export TECHNICAL_EXAMPLES with valid structure", () => {
expect(TECHNICAL_EXAMPLES).toBeDefined();
expect(Array.isArray(TECHNICAL_EXAMPLES)).toBe(true);
expect(TECHNICAL_EXAMPLES.length).toBeGreaterThan(0);
TECHNICAL_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty("input");
expect(example).toHaveProperty("output");
expect(typeof example.input).toBe("string");
expect(typeof example.output).toBe("string");
});
});
it("should export SIMPLIFY_EXAMPLES with valid structure", () => {
expect(SIMPLIFY_EXAMPLES).toBeDefined();
expect(Array.isArray(SIMPLIFY_EXAMPLES)).toBe(true);
expect(SIMPLIFY_EXAMPLES.length).toBeGreaterThan(0);
SIMPLIFY_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty("input");
expect(example).toHaveProperty("output");
expect(typeof example.input).toBe("string");
expect(typeof example.output).toBe("string");
});
});
it("should export ACCEPTANCE_EXAMPLES with valid structure", () => {
expect(ACCEPTANCE_EXAMPLES).toBeDefined();
expect(Array.isArray(ACCEPTANCE_EXAMPLES)).toBe(true);
expect(ACCEPTANCE_EXAMPLES.length).toBeGreaterThan(0);
ACCEPTANCE_EXAMPLES.forEach((example) => {
expect(example).toHaveProperty("input");
expect(example).toHaveProperty("output");
expect(typeof example.input).toBe("string");
expect(typeof example.output).toBe("string");
});
});
it("should have shorter outputs in SIMPLIFY_EXAMPLES", () => {
SIMPLIFY_EXAMPLES.forEach((example) => {
// Simplify examples should have shorter output than input
// (though not always strictly enforced, it's the general pattern)
expect(example.output).toBeDefined();
expect(example.output.length).toBeGreaterThan(0);
});
});
});
describe("getEnhancementPrompt", () => {
it("should return prompt config for 'improve' mode", () => {
const result = getEnhancementPrompt("improve");
expect(result).toHaveProperty("systemPrompt");
expect(result).toHaveProperty("description");
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(result.description).toContain("vague");
expect(result.description).toContain("actionable");
});
it("should return prompt config for 'technical' mode", () => {
const result = getEnhancementPrompt("technical");
expect(result).toHaveProperty("systemPrompt");
expect(result).toHaveProperty("description");
expect(result.systemPrompt).toBe(TECHNICAL_SYSTEM_PROMPT);
expect(result.description).toContain("implementation");
});
it("should return prompt config for 'simplify' mode", () => {
const result = getEnhancementPrompt("simplify");
expect(result).toHaveProperty("systemPrompt");
expect(result).toHaveProperty("description");
expect(result.systemPrompt).toBe(SIMPLIFY_SYSTEM_PROMPT);
expect(result.description).toContain("verbose");
});
it("should return prompt config for 'acceptance' mode", () => {
const result = getEnhancementPrompt("acceptance");
expect(result).toHaveProperty("systemPrompt");
expect(result).toHaveProperty("description");
expect(result.systemPrompt).toBe(ACCEPTANCE_SYSTEM_PROMPT);
expect(result.description).toContain("acceptance");
});
it("should handle uppercase mode", () => {
const result = getEnhancementPrompt("IMPROVE");
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
});
it("should handle mixed case mode", () => {
const result = getEnhancementPrompt("TeChnIcaL");
expect(result.systemPrompt).toBe(TECHNICAL_SYSTEM_PROMPT);
});
it("should fall back to 'improve' for invalid mode", () => {
const result = getEnhancementPrompt("invalid-mode");
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(result.description).toContain("vague");
});
it("should fall back to 'improve' for empty string", () => {
const result = getEnhancementPrompt("");
expect(result.systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
});
});
describe("getSystemPrompt", () => {
it("should return IMPROVE_SYSTEM_PROMPT for 'improve'", () => {
const result = getSystemPrompt("improve");
expect(result).toBe(IMPROVE_SYSTEM_PROMPT);
});
it("should return TECHNICAL_SYSTEM_PROMPT for 'technical'", () => {
const result = getSystemPrompt("technical");
expect(result).toBe(TECHNICAL_SYSTEM_PROMPT);
});
it("should return SIMPLIFY_SYSTEM_PROMPT for 'simplify'", () => {
const result = getSystemPrompt("simplify");
expect(result).toBe(SIMPLIFY_SYSTEM_PROMPT);
});
it("should return ACCEPTANCE_SYSTEM_PROMPT for 'acceptance'", () => {
const result = getSystemPrompt("acceptance");
expect(result).toBe(ACCEPTANCE_SYSTEM_PROMPT);
});
});
describe("getExamples", () => {
it("should return IMPROVE_EXAMPLES for 'improve'", () => {
const result = getExamples("improve");
expect(result).toBe(IMPROVE_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return TECHNICAL_EXAMPLES for 'technical'", () => {
const result = getExamples("technical");
expect(result).toBe(TECHNICAL_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return SIMPLIFY_EXAMPLES for 'simplify'", () => {
const result = getExamples("simplify");
expect(result).toBe(SIMPLIFY_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
it("should return ACCEPTANCE_EXAMPLES for 'acceptance'", () => {
const result = getExamples("acceptance");
expect(result).toBe(ACCEPTANCE_EXAMPLES);
expect(result.length).toBeGreaterThan(0);
});
});
describe("buildUserPrompt", () => {
const testText = "Add a login feature";
describe("with examples (default)", () => {
it("should include examples by default for 'improve' mode", () => {
const result = buildUserPrompt("improve", testText);
expect(result).toContain("Here are some examples");
expect(result).toContain("Example 1:");
expect(result).toContain(IMPROVE_EXAMPLES[0].input);
expect(result).toContain(IMPROVE_EXAMPLES[0].output);
expect(result).toContain(testText);
});
it("should include examples by default for 'technical' mode", () => {
const result = buildUserPrompt("technical", testText);
expect(result).toContain("Here are some examples");
expect(result).toContain("Example 1:");
expect(result).toContain(TECHNICAL_EXAMPLES[0].input);
expect(result).toContain(testText);
});
it("should include examples when explicitly set to true", () => {
const result = buildUserPrompt("improve", testText, true);
expect(result).toContain("Here are some examples");
expect(result).toContain(testText);
});
it("should format all examples with numbered labels", () => {
const result = buildUserPrompt("improve", testText);
IMPROVE_EXAMPLES.forEach((_, index) => {
expect(result).toContain(`Example ${index + 1}:`);
});
});
it("should separate examples with dividers", () => {
const result = buildUserPrompt("improve", testText);
// Count dividers (---) - should be (examples.length) + 1
const dividerCount = (result.match(/---/g) || []).length;
expect(dividerCount).toBe(IMPROVE_EXAMPLES.length);
});
it("should include 'Now, please enhance' before user text", () => {
const result = buildUserPrompt("improve", testText);
expect(result).toContain("Now, please enhance the following");
expect(result).toContain(testText);
});
});
describe("without examples", () => {
it("should not include examples when includeExamples is false", () => {
const result = buildUserPrompt("improve", testText, false);
expect(result).not.toContain("Here are some examples");
expect(result).not.toContain("Example 1:");
expect(result).not.toContain(IMPROVE_EXAMPLES[0].input);
});
it("should have simple prompt without examples", () => {
const result = buildUserPrompt("improve", testText, false);
expect(result).toBe(
`Please enhance the following task description:\n\n${testText}`
);
});
it("should preserve user text without examples", () => {
const result = buildUserPrompt("technical", testText, false);
expect(result).toContain(testText);
expect(result).toContain("Please enhance");
});
});
describe("text formatting", () => {
it("should preserve multiline text", () => {
const multilineText = "Line 1\nLine 2\nLine 3";
const result = buildUserPrompt("improve", multilineText);
expect(result).toContain(multilineText);
});
it("should handle empty text", () => {
const result = buildUserPrompt("improve", "");
// With examples by default, it should contain "Now, please enhance"
expect(result).toContain("Now, please enhance");
expect(result).toContain("Here are some examples");
});
it("should handle whitespace-only text", () => {
const result = buildUserPrompt("improve", " ");
expect(result).toContain(" ");
});
it("should handle special characters in text", () => {
const specialText = "Test <html> & \"quotes\" 'apostrophes'";
const result = buildUserPrompt("improve", specialText);
expect(result).toContain(specialText);
});
});
describe("all modes", () => {
it("should work for all valid enhancement modes", () => {
const modes: Array<"improve" | "technical" | "simplify" | "acceptance"> =
["improve", "technical", "simplify", "acceptance"];
modes.forEach((mode) => {
const result = buildUserPrompt(mode, testText);
expect(result).toBeDefined();
expect(result).toContain(testText);
expect(result.length).toBeGreaterThan(testText.length);
});
});
});
});
describe("isValidEnhancementMode", () => {
it("should return true for 'improve'", () => {
expect(isValidEnhancementMode("improve")).toBe(true);
});
it("should return true for 'technical'", () => {
expect(isValidEnhancementMode("technical")).toBe(true);
});
it("should return true for 'simplify'", () => {
expect(isValidEnhancementMode("simplify")).toBe(true);
});
it("should return true for 'acceptance'", () => {
expect(isValidEnhancementMode("acceptance")).toBe(true);
});
it("should return false for invalid mode", () => {
expect(isValidEnhancementMode("invalid")).toBe(false);
});
it("should return false for empty string", () => {
expect(isValidEnhancementMode("")).toBe(false);
});
it("should return false for uppercase mode", () => {
// Should be case-sensitive since we check object keys directly
expect(isValidEnhancementMode("IMPROVE")).toBe(false);
});
it("should return false for mixed case mode", () => {
expect(isValidEnhancementMode("ImProve")).toBe(false);
});
it("should return false for partial mode names", () => {
expect(isValidEnhancementMode("impro")).toBe(false);
expect(isValidEnhancementMode("tech")).toBe(false);
});
it("should return false for mode with extra characters", () => {
expect(isValidEnhancementMode("improve ")).toBe(false);
expect(isValidEnhancementMode(" improve")).toBe(false);
});
});
describe("getAvailableEnhancementModes", () => {
it("should return array of all enhancement modes", () => {
const modes = getAvailableEnhancementModes();
expect(Array.isArray(modes)).toBe(true);
expect(modes.length).toBe(4);
});
it("should include all valid modes", () => {
const modes = getAvailableEnhancementModes();
expect(modes).toContain("improve");
expect(modes).toContain("technical");
expect(modes).toContain("simplify");
expect(modes).toContain("acceptance");
});
it("should return modes in consistent order", () => {
const modes1 = getAvailableEnhancementModes();
const modes2 = getAvailableEnhancementModes();
expect(modes1).toEqual(modes2);
});
it("should return all valid modes that pass isValidEnhancementMode", () => {
const modes = getAvailableEnhancementModes();
modes.forEach((mode) => {
expect(isValidEnhancementMode(mode)).toBe(true);
});
});
});
describe("Integration tests", () => {
it("should work together: getEnhancementPrompt + buildUserPrompt", () => {
const mode = "improve";
const text = "Add search feature";
const { systemPrompt, description } = getEnhancementPrompt(mode);
const userPrompt = buildUserPrompt(mode, text);
expect(systemPrompt).toBe(IMPROVE_SYSTEM_PROMPT);
expect(description).toBeDefined();
expect(userPrompt).toContain(text);
});
it("should handle complete enhancement workflow", () => {
const availableModes = getAvailableEnhancementModes();
expect(availableModes.length).toBeGreaterThan(0);
availableModes.forEach((mode) => {
const isValid = isValidEnhancementMode(mode);
expect(isValid).toBe(true);
const systemPrompt = getSystemPrompt(mode);
expect(systemPrompt).toBeDefined();
expect(systemPrompt.length).toBeGreaterThan(0);
const examples = getExamples(mode);
expect(Array.isArray(examples)).toBe(true);
expect(examples.length).toBeGreaterThan(0);
const userPrompt = buildUserPrompt(mode, "test description");
expect(userPrompt).toContain("test description");
});
});
it("should provide consistent data across functions", () => {
const mode = "technical";
const promptConfig = getEnhancementPrompt(mode);
const systemPrompt = getSystemPrompt(mode);
const examples = getExamples(mode);
expect(promptConfig.systemPrompt).toBe(systemPrompt);
expect(examples).toBe(TECHNICAL_EXAMPLES);
});
});
describe("Examples content validation", () => {
it("IMPROVE_EXAMPLES should demonstrate improvement", () => {
IMPROVE_EXAMPLES.forEach((example) => {
// Output should be longer and more detailed than input
expect(example.output.length).toBeGreaterThan(example.input.length);
// Input should be brief/vague
expect(example.input.length).toBeLessThan(100);
});
});
it("TECHNICAL_EXAMPLES should contain technical terms", () => {
const technicalTerms = [
"API",
"endpoint",
"component",
"database",
"frontend",
"backend",
"validation",
"schema",
"React",
"GET",
"PUT",
"POST",
];
TECHNICAL_EXAMPLES.forEach((example) => {
const hasAnyTechnicalTerm = technicalTerms.some((term) =>
example.output.includes(term)
);
expect(hasAnyTechnicalTerm).toBe(true);
});
});
it("ACCEPTANCE_EXAMPLES should contain acceptance criteria format", () => {
ACCEPTANCE_EXAMPLES.forEach((example) => {
// Should contain numbered criteria or Given-When-Then format
const hasAcceptanceCriteria =
example.output.includes("Acceptance Criteria") ||
example.output.match(/\d+\./g);
expect(hasAcceptanceCriteria).toBeTruthy();
// Should contain Given-When-Then format
const hasGWT =
example.output.includes("Given") &&
example.output.includes("when") &&
example.output.includes("then");
expect(hasGWT).toBe(true);
});
});
});
});

View File

@@ -0,0 +1,9 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}

View File

@@ -0,0 +1,21 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "node",
include: ["tests/**/*.test.ts"],
coverage: {
provider: "v8",
reporter: ["text", "json", "html"],
include: ["src/**/*.ts"],
exclude: ["src/**/*.d.ts", "src/index.ts"],
thresholds: {
lines: 90,
functions: 95,
branches: 85,
statements: 90,
},
},
},
});

View File

@@ -2,6 +2,8 @@
* Feature types for AutoMaker feature management
*/
import type { PlanningMode } from './settings.js';
export interface FeatureImagePath {
id: string;
path: string;
@@ -28,7 +30,7 @@ export interface Feature {
branchName?: string; // Name of the feature branch (undefined = use current worktree)
skipTests?: boolean;
thinkingLevel?: string;
planningMode?: 'skip' | 'lite' | 'spec' | 'full';
planningMode?: PlanningMode;
requirePlanApproval?: boolean;
planSpec?: {
status: 'pending' | 'generating' | 'generated' | 'approved' | 'rejected';
@@ -47,4 +49,3 @@ export interface Feature {
}
export type FeatureStatus = 'pending' | 'running' | 'completed' | 'failed' | 'verified';
export type PlanningMode = 'skip' | 'lite' | 'spec' | 'full';

View File

@@ -20,7 +20,6 @@ export type {
Feature,
FeatureImagePath,
FeatureStatus,
PlanningMode,
} from './feature.js';
// Session types
@@ -48,6 +47,7 @@ export {
CLAUDE_MODEL_MAP,
DEFAULT_MODELS,
type ModelAlias,
type AgentModel,
} from './model.js';
// Event types
@@ -69,3 +69,43 @@ export type {
EnhancementMode,
EnhancementExample,
} from './enhancement.js';
// Settings types and constants
export type {
ThemeMode,
KanbanCardDetailLevel,
PlanningMode,
ThinkingLevel,
ModelProvider,
KeyboardShortcuts,
AIProfile,
ProjectRef,
TrashedProjectRef,
ChatSessionRef,
GlobalSettings,
Credentials,
BoardBackgroundSettings,
WorktreeInfo,
ProjectSettings,
} from './settings.js';
export {
DEFAULT_KEYBOARD_SHORTCUTS,
DEFAULT_GLOBAL_SETTINGS,
DEFAULT_CREDENTIALS,
DEFAULT_PROJECT_SETTINGS,
SETTINGS_VERSION,
CREDENTIALS_VERSION,
PROJECT_SETTINGS_VERSION,
} from './settings.js';
// Model display constants
export type {
ModelOption,
ThinkingLevelOption,
} from './model-display.js';
export {
CLAUDE_MODELS,
THINKING_LEVELS,
THINKING_LEVEL_LABELS,
getModelDisplayName,
} from './model-display.js';

View File

@@ -0,0 +1,111 @@
/**
* Model Display Constants - UI metadata for AI models
*
* Provides display labels, descriptions, and metadata for AI models
* and thinking levels used throughout the application UI.
*/
import type { AgentModel, ThinkingLevel } from './settings.js';
/**
* ModelOption - Display metadata for a model option in the UI
*/
export interface ModelOption {
/** Model identifier */
id: AgentModel;
/** Display name shown to user */
label: string;
/** Descriptive text explaining model capabilities */
description: string;
/** Optional badge text (e.g., "Speed", "Balanced", "Premium") */
badge?: string;
/** AI provider (currently only "claude") */
provider: "claude";
}
/**
* ThinkingLevelOption - Display metadata for thinking level selection
*/
export interface ThinkingLevelOption {
/** Thinking level identifier */
id: ThinkingLevel;
/** Display label */
label: string;
}
/**
* Claude model options with full metadata for UI display
*
* Ordered from fastest/cheapest (Haiku) to most capable (Opus).
*/
export const CLAUDE_MODELS: ModelOption[] = [
{
id: "haiku",
label: "Claude Haiku",
description: "Fast and efficient for simple tasks.",
badge: "Speed",
provider: "claude",
},
{
id: "sonnet",
label: "Claude Sonnet",
description: "Balanced performance with strong reasoning.",
badge: "Balanced",
provider: "claude",
},
{
id: "opus",
label: "Claude Opus",
description: "Most capable model for complex work.",
badge: "Premium",
provider: "claude",
},
];
/**
* Thinking level options with display labels
*
* Ordered from least to most intensive reasoning.
*/
export const THINKING_LEVELS: ThinkingLevelOption[] = [
{ id: "none", label: "None" },
{ id: "low", label: "Low" },
{ id: "medium", label: "Medium" },
{ id: "high", label: "High" },
{ id: "ultrathink", label: "Ultrathink" },
];
/**
* Map of thinking levels to short display labels
*
* Used for compact UI elements like badges or dropdowns.
*/
export const THINKING_LEVEL_LABELS: Record<ThinkingLevel, string> = {
none: "None",
low: "Low",
medium: "Med",
high: "High",
ultrathink: "Ultra",
};
/**
* Get display name for a model
*
* @param model - Model identifier or full model string
* @returns Human-readable model name
*
* @example
* ```typescript
* getModelDisplayName("haiku"); // "Claude Haiku"
* getModelDisplayName("sonnet"); // "Claude Sonnet"
* getModelDisplayName("claude-opus-4-20250514"); // "claude-opus-4-20250514"
* ```
*/
export function getModelDisplayName(model: AgentModel | string): string {
const displayNames: Record<string, string> = {
haiku: "Claude Haiku",
sonnet: "Claude Sonnet",
opus: "Claude Opus",
};
return displayNames[model] || model;
}

View File

@@ -15,3 +15,9 @@ export const DEFAULT_MODELS = {
} as const;
export type ModelAlias = keyof typeof CLAUDE_MODEL_MAP;
/**
* AgentModel - Alias for ModelAlias for backward compatibility
* Represents available Claude models: "opus" | "sonnet" | "haiku"
*/
export type AgentModel = ModelAlias;

430
libs/types/src/settings.ts Normal file
View File

@@ -0,0 +1,430 @@
/**
* Settings Types - Shared types for file-based settings storage
*
* Defines the structure for global settings, credentials, and per-project settings
* that are persisted to disk in JSON format. These types are used by both the server
* (for file I/O via SettingsService) and the UI (for state management and sync).
*/
import type { AgentModel } from './model.js';
// Re-export AgentModel for convenience
export type { AgentModel };
/**
* ThemeMode - Available color themes for the UI
*
* Includes system theme and multiple color schemes:
* - System: Respects OS dark/light mode preference
* - Light/Dark: Basic light and dark variants
* - Color Schemes: Retro, Dracula, Nord, Monokai, Tokyo Night, Solarized, Gruvbox,
* Catppuccin, OneDark, Synthwave, Red, Cream, Sunset, Gray
*/
export type ThemeMode =
| "light"
| "dark"
| "system"
| "retro"
| "dracula"
| "nord"
| "monokai"
| "tokyonight"
| "solarized"
| "gruvbox"
| "catppuccin"
| "onedark"
| "synthwave"
| "red"
| "cream"
| "sunset"
| "gray";
/** KanbanCardDetailLevel - Controls how much information is displayed on kanban cards */
export type KanbanCardDetailLevel = "minimal" | "standard" | "detailed";
/** PlanningMode - Planning levels for feature generation workflows */
export type PlanningMode = "skip" | "lite" | "spec" | "full";
/** ThinkingLevel - Extended thinking levels for Claude models (reasoning intensity) */
export type ThinkingLevel = "none" | "low" | "medium" | "high" | "ultrathink";
/** ModelProvider - AI model provider for credentials and API key management */
export type ModelProvider = "claude";
/**
* KeyboardShortcuts - User-configurable keyboard bindings for common actions
*
* Each property maps an action to a keyboard shortcut string
* (e.g., "Ctrl+K", "Alt+N", "Shift+P")
*/
export interface KeyboardShortcuts {
/** Open board view */
board: string;
/** Open agent panel */
agent: string;
/** Open feature spec editor */
spec: string;
/** Open context files panel */
context: string;
/** Open settings */
settings: string;
/** Open AI profiles */
profiles: string;
/** Open terminal */
terminal: string;
/** Toggle sidebar visibility */
toggleSidebar: string;
/** Add new feature */
addFeature: string;
/** Add context file */
addContextFile: string;
/** Start next feature generation */
startNext: string;
/** Create new chat session */
newSession: string;
/** Open project picker */
openProject: string;
/** Open project picker (alternate) */
projectPicker: string;
/** Cycle to previous project */
cyclePrevProject: string;
/** Cycle to next project */
cycleNextProject: string;
/** Add new AI profile */
addProfile: string;
/** Split terminal right */
splitTerminalRight: string;
/** Split terminal down */
splitTerminalDown: string;
/** Close current terminal */
closeTerminal: string;
}
/**
* AIProfile - Configuration for an AI model with specific parameters
*
* Profiles can be built-in defaults or user-created. They define which model to use,
* thinking level, and other parameters for feature generation tasks.
*/
export interface AIProfile {
/** Unique identifier for the profile */
id: string;
/** Display name for the profile */
name: string;
/** User-friendly description */
description: string;
/** Which Claude model to use (opus, sonnet, haiku) */
model: AgentModel;
/** Extended thinking level for reasoning-based tasks */
thinkingLevel: ThinkingLevel;
/** Provider (currently only "claude") */
provider: ModelProvider;
/** Whether this is a built-in default profile */
isBuiltIn: boolean;
/** Optional icon identifier or emoji */
icon?: string;
}
/**
* ProjectRef - Minimal reference to a project stored in global settings
*
* Used for the projects list and project history. Full project data is loaded separately.
*/
export interface ProjectRef {
/** Unique identifier */
id: string;
/** Display name */
name: string;
/** Absolute filesystem path to project directory */
path: string;
/** ISO timestamp of last time project was opened */
lastOpened?: string;
/** Project-specific theme override (or undefined to use global) */
theme?: string;
}
/**
* TrashedProjectRef - Reference to a project in the trash/recycle bin
*
* Extends ProjectRef with deletion metadata. User can permanently delete or restore.
*/
export interface TrashedProjectRef extends ProjectRef {
/** ISO timestamp when project was moved to trash */
trashedAt: string;
/** Whether project folder was deleted from disk */
deletedFromDisk?: boolean;
}
/**
* ChatSessionRef - Minimal reference to a chat session
*
* Used for session lists and history. Full session content is stored separately.
*/
export interface ChatSessionRef {
/** Unique session identifier */
id: string;
/** User-given or AI-generated title */
title: string;
/** Project that session belongs to */
projectId: string;
/** ISO timestamp of creation */
createdAt: string;
/** ISO timestamp of last message */
updatedAt: string;
/** Whether session is archived */
archived: boolean;
}
/**
* GlobalSettings - User preferences and state stored globally in {DATA_DIR}/settings.json
*
* This is the main settings file that persists user preferences across sessions.
* Includes theme, UI state, feature defaults, keyboard shortcuts, AI profiles, and projects.
* Format: JSON with version field for migration support.
*/
export interface GlobalSettings {
/** Version number for schema migration */
version: number;
// Theme Configuration
/** Currently selected theme */
theme: ThemeMode;
// UI State Preferences
/** Whether sidebar is currently open */
sidebarOpen: boolean;
/** Whether chat history panel is open */
chatHistoryOpen: boolean;
/** How much detail to show on kanban cards */
kanbanCardDetailLevel: KanbanCardDetailLevel;
// Feature Generation Defaults
/** Max features to generate concurrently */
maxConcurrency: number;
/** Default: skip tests during feature generation */
defaultSkipTests: boolean;
/** Default: enable dependency blocking */
enableDependencyBlocking: boolean;
/** Default: use git worktrees for feature branches */
useWorktrees: boolean;
/** Default: only show AI profiles (hide other settings) */
showProfilesOnly: boolean;
/** Default: planning approach (skip/lite/spec/full) */
defaultPlanningMode: PlanningMode;
/** Default: require manual approval before generating */
defaultRequirePlanApproval: boolean;
/** ID of currently selected AI profile (null = use built-in) */
defaultAIProfileId: string | null;
// Audio Preferences
/** Mute completion notification sound */
muteDoneSound: boolean;
// AI Model Selection
/** Which model to use for feature name/description enhancement */
enhancementModel: AgentModel;
// Input Configuration
/** User's keyboard shortcut bindings */
keyboardShortcuts: KeyboardShortcuts;
// AI Profiles
/** User-created AI profiles */
aiProfiles: AIProfile[];
// Project Management
/** List of active projects */
projects: ProjectRef[];
/** Projects in trash/recycle bin */
trashedProjects: TrashedProjectRef[];
/** History of recently opened project IDs */
projectHistory: string[];
/** Current position in project history for navigation */
projectHistoryIndex: number;
// File Browser and UI Preferences
/** Last directory opened in file picker */
lastProjectDir?: string;
/** Recently accessed folders for quick access */
recentFolders: string[];
/** Whether worktree panel is collapsed in current view */
worktreePanelCollapsed: boolean;
// Session Tracking
/** Maps project path -> last selected session ID in that project */
lastSelectedSessionByProject: Record<string, string>;
}
/**
* Credentials - API keys stored in {DATA_DIR}/credentials.json
*
* Sensitive data stored separately from general settings.
* Keys should never be exposed in UI or logs.
*/
export interface Credentials {
/** Version number for schema migration */
version: number;
/** API keys for various providers */
apiKeys: {
/** Anthropic Claude API key */
anthropic: string;
/** Google API key (for embeddings or other services) */
google: string;
/** OpenAI API key (for compatibility or alternative providers) */
openai: string;
};
}
/**
* BoardBackgroundSettings - Kanban board appearance customization
*
* Controls background images, opacity, borders, and visual effects for the board.
*/
export interface BoardBackgroundSettings {
/** Path to background image file (null = no image) */
imagePath: string | null;
/** Version/timestamp of image for cache busting */
imageVersion?: number;
/** Opacity of cards (0-1) */
cardOpacity: number;
/** Opacity of columns (0-1) */
columnOpacity: number;
/** Show border around columns */
columnBorderEnabled: boolean;
/** Apply glassmorphism effect to cards */
cardGlassmorphism: boolean;
/** Show border around cards */
cardBorderEnabled: boolean;
/** Opacity of card borders (0-1) */
cardBorderOpacity: number;
/** Hide scrollbar in board view */
hideScrollbar: boolean;
}
/**
* WorktreeInfo - Information about a git worktree
*
* Tracks worktree location, branch, and dirty state for project management.
*/
export interface WorktreeInfo {
/** Absolute path to worktree directory */
path: string;
/** Branch checked out in this worktree */
branch: string;
/** Whether this is the main worktree */
isMain: boolean;
/** Whether worktree has uncommitted changes */
hasChanges?: boolean;
/** Number of files with changes */
changedFilesCount?: number;
}
/**
* ProjectSettings - Project-specific overrides stored in {projectPath}/.automaker/settings.json
*
* Allows per-project customization without affecting global settings.
* All fields are optional - missing values fall back to global settings.
*/
export interface ProjectSettings {
/** Version number for schema migration */
version: number;
// Theme Configuration (project-specific override)
/** Project theme (undefined = use global setting) */
theme?: ThemeMode;
// Worktree Management
/** Project-specific worktree preference override */
useWorktrees?: boolean;
/** Current worktree being used in this project */
currentWorktree?: { path: string | null; branch: string };
/** List of worktrees available in this project */
worktrees?: WorktreeInfo[];
// Board Customization
/** Project-specific board background settings */
boardBackground?: BoardBackgroundSettings;
// Session Tracking
/** Last chat session selected in this project */
lastSelectedSessionId?: string;
}
/**
* Default values and constants
*/
/** Default keyboard shortcut bindings */
export const DEFAULT_KEYBOARD_SHORTCUTS: KeyboardShortcuts = {
board: "K",
agent: "A",
spec: "D",
context: "C",
settings: "S",
profiles: "M",
terminal: "T",
toggleSidebar: "`",
addFeature: "N",
addContextFile: "N",
startNext: "G",
newSession: "N",
openProject: "O",
projectPicker: "P",
cyclePrevProject: "Q",
cycleNextProject: "E",
addProfile: "N",
splitTerminalRight: "Alt+D",
splitTerminalDown: "Alt+S",
closeTerminal: "Alt+W",
};
/** Default global settings used when no settings file exists */
export const DEFAULT_GLOBAL_SETTINGS: GlobalSettings = {
version: 1,
theme: "dark",
sidebarOpen: true,
chatHistoryOpen: false,
kanbanCardDetailLevel: "standard",
maxConcurrency: 3,
defaultSkipTests: true,
enableDependencyBlocking: true,
useWorktrees: false,
showProfilesOnly: false,
defaultPlanningMode: "skip",
defaultRequirePlanApproval: false,
defaultAIProfileId: null,
muteDoneSound: false,
enhancementModel: "sonnet",
keyboardShortcuts: DEFAULT_KEYBOARD_SHORTCUTS,
aiProfiles: [],
projects: [],
trashedProjects: [],
projectHistory: [],
projectHistoryIndex: -1,
lastProjectDir: undefined,
recentFolders: [],
worktreePanelCollapsed: false,
lastSelectedSessionByProject: {},
};
/** Default credentials (empty strings - user must provide API keys) */
export const DEFAULT_CREDENTIALS: Credentials = {
version: 1,
apiKeys: {
anthropic: "",
google: "",
openai: "",
},
};
/** Default project settings (empty - all settings are optional and fall back to global) */
export const DEFAULT_PROJECT_SETTINGS: ProjectSettings = {
version: 1,
};
/** Current version of the global settings schema */
export const SETTINGS_VERSION = 1;
/** Current version of the credentials schema */
export const CREDENTIALS_VERSION = 1;
/** Current version of the project settings schema */
export const PROJECT_SETTINGS_VERSION = 1;

View File

@@ -108,3 +108,27 @@ export function getUserFriendlyErrorMessage(error: unknown): string {
return info.message;
}
/**
* Extract error message from an unknown error value
*
* Simple utility for getting a string error message from any error type.
* Returns the error's message property if it's an Error, otherwise
* converts to string. Used throughout the codebase for consistent
* error message extraction.
*
* @param error - The error value (Error object, string, or unknown)
* @returns Error message string
*
* @example
* ```typescript
* try {
* throw new Error("Something went wrong");
* } catch (error) {
* const message = getErrorMessage(error); // "Something went wrong"
* }
* ```
*/
export function getErrorMessage(error: unknown): string {
return error instanceof Error ? error.message : "Unknown error";
}

View File

@@ -10,6 +10,7 @@ export {
isAuthenticationError,
classifyError,
getUserFriendlyErrorMessage,
getErrorMessage,
} from './error-handler.js';
// Conversation utilities
@@ -48,3 +49,9 @@ export {
mkdirSafe,
existsSafe,
} from './fs-utils.js';
// Path utilities
export {
normalizePath,
pathsEqual,
} from './path-utils.js';

View File

@@ -0,0 +1,54 @@
/**
* Path Utilities - Cross-platform path manipulation helpers
*
* Provides functions for normalizing and comparing file system paths
* across different operating systems (Windows, macOS, Linux).
*/
/**
* Normalize a path by converting backslashes to forward slashes
*
* This ensures consistent path representation across platforms:
* - Windows: C:\Users\foo\bar -> C:/Users/foo/bar
* - Unix: /home/foo/bar -> /home/foo/bar (unchanged)
*
* @param p - Path string to normalize
* @returns Normalized path with forward slashes
*
* @example
* ```typescript
* normalizePath("C:\\Users\\foo\\bar"); // "C:/Users/foo/bar"
* normalizePath("/home/foo/bar"); // "/home/foo/bar"
* ```
*/
export function normalizePath(p: string): string {
return p.replace(/\\/g, "/");
}
/**
* Compare two paths for equality after normalization
*
* Handles null/undefined values and normalizes paths before comparison.
* Useful for checking if two paths refer to the same location regardless
* of platform-specific path separators.
*
* @param p1 - First path to compare (or null/undefined)
* @param p2 - Second path to compare (or null/undefined)
* @returns true if paths are equal (or both null/undefined), false otherwise
*
* @example
* ```typescript
* pathsEqual("C:\\foo\\bar", "C:/foo/bar"); // true
* pathsEqual("/home/user", "/home/user"); // true
* pathsEqual("/home/user", "/home/other"); // false
* pathsEqual(null, undefined); // false
* pathsEqual(null, null); // true
* ```
*/
export function pathsEqual(
p1: string | undefined | null,
p2: string | undefined | null
): boolean {
if (!p1 || !p2) return p1 === p2;
return normalizePath(p1) === normalizePath(p2);
}

28
package-lock.json generated
View File

@@ -27,6 +27,7 @@
"@automaker/git-utils": "^1.0.0",
"@automaker/model-resolver": "^1.0.0",
"@automaker/platform": "^1.0.0",
"@automaker/prompts": "^1.0.0",
"@automaker/types": "^1.0.0",
"@automaker/utils": "^1.0.0",
"cors": "^2.8.5",
@@ -253,6 +254,29 @@
"undici-types": "~6.21.0"
}
},
"libs/prompts": {
"name": "@automaker/prompts",
"version": "1.0.0",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"@automaker/types": "^1.0.0"
},
"devDependencies": {
"@types/node": "^22.10.5",
"typescript": "^5.7.3",
"vitest": "^4.0.16"
}
},
"libs/prompts/node_modules/@types/node": {
"version": "22.19.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.3.tgz",
"integrity": "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"libs/types": {
"name": "@automaker/types",
"version": "1.0.0",
@@ -333,6 +357,10 @@
"resolved": "libs/platform",
"link": true
},
"node_modules/@automaker/prompts": {
"resolved": "libs/prompts",
"link": true
},
"node_modules/@automaker/server": {
"resolved": "apps/server",
"link": true

View File

@@ -18,7 +18,7 @@
"dev:server": "npm run dev --workspace=apps/server",
"dev:full": "concurrently \"npm run dev:server\" \"npm run dev:web\"",
"build": "npm run build --workspace=apps/ui",
"build:packages": "npm run build -w @automaker/types && npm run build -w @automaker/utils && npm run build -w @automaker/platform -w @automaker/model-resolver -w @automaker/dependency-resolver && npm run build -w @automaker/git-utils",
"build:packages": "npm run build -w @automaker/types && npm run build -w @automaker/utils && npm run build -w @automaker/prompts && npm run build -w @automaker/platform -w @automaker/model-resolver -w @automaker/dependency-resolver && npm run build -w @automaker/git-utils",
"build:server": "npm run build --workspace=apps/server",
"build:electron": "npm run build:electron --workspace=apps/ui",
"build:electron:dir": "npm run build:electron:dir --workspace=apps/ui",