mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-01-31 06:42:03 +00:00
feat: implement context file loading system for agent prompts
- Introduced a new utility function `loadContextFiles` to load project-specific context files from the `.automaker/context/` directory, enhancing agent prompts with project rules and guidelines. - Updated `AgentService` and `AutoModeService` to utilize the new context loading functionality, combining context prompts with existing system prompts for improved agent performance. - Added comprehensive documentation on the context files system, including usage examples and metadata structure, to facilitate better understanding and implementation. - Removed redundant context loading logic from `AutoModeService`, streamlining the codebase. These changes aim to improve the agent's contextual awareness and adherence to project-specific conventions.
This commit is contained in:
@@ -7,7 +7,12 @@ import path from 'path';
|
||||
import * as secureFs from '../lib/secure-fs.js';
|
||||
import type { EventEmitter } from '../lib/events.js';
|
||||
import type { ExecuteOptions } from '@automaker/types';
|
||||
import { readImageAsBase64, buildPromptWithImages, isAbortError } from '@automaker/utils';
|
||||
import {
|
||||
readImageAsBase64,
|
||||
buildPromptWithImages,
|
||||
isAbortError,
|
||||
loadContextFiles,
|
||||
} from '@automaker/utils';
|
||||
import { ProviderFactory } from '../providers/provider-factory.js';
|
||||
import { createChatOptions, validateWorkingDirectory } from '../lib/sdk-options.js';
|
||||
import { PathNotAllowedError } from '@automaker/platform';
|
||||
@@ -178,12 +183,27 @@ export class AgentService {
|
||||
await this.saveSession(sessionId, session.messages);
|
||||
|
||||
try {
|
||||
// Determine the effective working directory for context loading
|
||||
const effectiveWorkDir = workingDirectory || session.workingDirectory;
|
||||
|
||||
// Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.)
|
||||
const { formattedPrompt: contextFilesPrompt } = await loadContextFiles({
|
||||
projectPath: effectiveWorkDir,
|
||||
fsModule: secureFs as Parameters<typeof loadContextFiles>[0]['fsModule'],
|
||||
});
|
||||
|
||||
// Build combined system prompt with base prompt and context files
|
||||
const baseSystemPrompt = this.getSystemPrompt();
|
||||
const combinedSystemPrompt = contextFilesPrompt
|
||||
? `${contextFilesPrompt}\n\n${baseSystemPrompt}`
|
||||
: baseSystemPrompt;
|
||||
|
||||
// Build SDK options using centralized configuration
|
||||
const sdkOptions = createChatOptions({
|
||||
cwd: workingDirectory || session.workingDirectory,
|
||||
cwd: effectiveWorkDir,
|
||||
model: model,
|
||||
sessionModel: session.model,
|
||||
systemPrompt: this.getSystemPrompt(),
|
||||
systemPrompt: combinedSystemPrompt,
|
||||
abortController: session.abortController!,
|
||||
});
|
||||
|
||||
@@ -203,8 +223,8 @@ export class AgentService {
|
||||
const options: ExecuteOptions = {
|
||||
prompt: '', // Will be set below based on images
|
||||
model: effectiveModel,
|
||||
cwd: workingDirectory || session.workingDirectory,
|
||||
systemPrompt: this.getSystemPrompt(),
|
||||
cwd: effectiveWorkDir,
|
||||
systemPrompt: combinedSystemPrompt,
|
||||
maxTurns: maxTurns,
|
||||
allowedTools: allowedTools,
|
||||
abortController: session.abortController!,
|
||||
|
||||
@@ -11,10 +11,15 @@
|
||||
|
||||
import { ProviderFactory } from '../providers/provider-factory.js';
|
||||
import type { ExecuteOptions, Feature } from '@automaker/types';
|
||||
import { buildPromptWithImages, isAbortError, classifyError } from '@automaker/utils';
|
||||
import {
|
||||
buildPromptWithImages,
|
||||
isAbortError,
|
||||
classifyError,
|
||||
loadContextFiles,
|
||||
} from '@automaker/utils';
|
||||
import { resolveModelString, DEFAULT_MODELS } from '@automaker/model-resolver';
|
||||
import { resolveDependencies, areDependenciesSatisfied } from '@automaker/dependency-resolver';
|
||||
import { getFeatureDir, getAutomakerDir, getFeaturesDir, getContextDir } from '@automaker/platform';
|
||||
import { getFeatureDir, getAutomakerDir, getFeaturesDir } from '@automaker/platform';
|
||||
import { exec } from 'child_process';
|
||||
import { promisify } from 'util';
|
||||
import path from 'path';
|
||||
@@ -549,7 +554,10 @@ export class AutoModeService {
|
||||
// Build the prompt - use continuation prompt if provided (for recovery after plan approval)
|
||||
let prompt: string;
|
||||
// Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.) - passed as system prompt
|
||||
const contextFiles = await this.loadContextFiles(projectPath);
|
||||
const { formattedPrompt: contextFilesPrompt } = await loadContextFiles({
|
||||
projectPath,
|
||||
fsModule: secureFs as Parameters<typeof loadContextFiles>[0]['fsModule'],
|
||||
});
|
||||
|
||||
if (options?.continuationPrompt) {
|
||||
// Continuation prompt is used when recovering from a plan approval
|
||||
@@ -595,7 +603,7 @@ export class AutoModeService {
|
||||
projectPath,
|
||||
planningMode: feature.planningMode,
|
||||
requirePlanApproval: feature.requirePlanApproval,
|
||||
systemPrompt: contextFiles || undefined,
|
||||
systemPrompt: contextFilesPrompt || undefined,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -736,7 +744,10 @@ export class AutoModeService {
|
||||
}
|
||||
|
||||
// Load project context files (CLAUDE.md, CODE_QUALITY.md, etc.) - passed as system prompt
|
||||
const contextFiles = await this.loadContextFiles(projectPath);
|
||||
const { formattedPrompt: contextFilesPrompt } = await loadContextFiles({
|
||||
projectPath,
|
||||
fsModule: secureFs as Parameters<typeof loadContextFiles>[0]['fsModule'],
|
||||
});
|
||||
|
||||
// Build complete prompt with feature info, previous context, and follow-up instructions
|
||||
let fullPrompt = `## Follow-up on Feature Implementation
|
||||
@@ -864,7 +875,7 @@ Address the follow-up instructions above. Review the previous work and make the
|
||||
projectPath,
|
||||
planningMode: 'skip', // Follow-ups don't require approval
|
||||
previousContent: previousContext || undefined,
|
||||
systemPrompt: contextFiles || undefined,
|
||||
systemPrompt: contextFilesPrompt || undefined,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1044,63 +1055,6 @@ Address the follow-up instructions above. Review the previous work and make the
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load context files from .automaker/context/ directory
|
||||
* These are user-defined context files (CLAUDE.md, CODE_QUALITY.md, etc.)
|
||||
* that provide project-specific rules and guidelines for the agent.
|
||||
*/
|
||||
private async loadContextFiles(projectPath: string): Promise<string> {
|
||||
// Use path.resolve for cross-platform absolute path handling
|
||||
const contextDir = path.resolve(getContextDir(projectPath));
|
||||
|
||||
try {
|
||||
// Check if directory exists first
|
||||
await secureFs.access(contextDir);
|
||||
|
||||
const files = await secureFs.readdir(contextDir);
|
||||
// Filter for text-based context files (case-insensitive for Windows)
|
||||
const textFiles = files.filter((f) => {
|
||||
const lower = f.toLowerCase();
|
||||
return lower.endsWith('.md') || lower.endsWith('.txt');
|
||||
});
|
||||
|
||||
if (textFiles.length === 0) return '';
|
||||
|
||||
const contents: string[] = [];
|
||||
for (const file of textFiles) {
|
||||
// Use path.join for cross-platform path construction
|
||||
const filePath = path.join(contextDir, file);
|
||||
const content = (await secureFs.readFile(filePath, 'utf-8')) as string;
|
||||
contents.push(`## ${file}\n\n${content}`);
|
||||
}
|
||||
|
||||
console.log(`[AutoMode] Loaded ${textFiles.length} context file(s): ${textFiles.join(', ')}`);
|
||||
|
||||
return `# ⚠️ CRITICAL: Project Context Files - READ AND FOLLOW STRICTLY
|
||||
|
||||
**IMPORTANT**: The following context files contain MANDATORY project-specific rules and conventions. You MUST:
|
||||
1. Read these rules carefully before taking any action
|
||||
2. Follow ALL commands exactly as shown (e.g., if the project uses \`pnpm\`, NEVER use \`npm\` or \`npx\`)
|
||||
3. Follow ALL coding conventions, commit message formats, and architectural patterns specified
|
||||
4. Reference these rules before running ANY shell commands or making commits
|
||||
|
||||
Failure to follow these rules will result in broken builds, failed CI, and rejected commits.
|
||||
|
||||
${contents.join('\n\n---\n\n')}
|
||||
|
||||
---
|
||||
|
||||
**REMINDER**: Before running any command, verify you are using the correct package manager and following the conventions above.
|
||||
|
||||
---
|
||||
|
||||
`;
|
||||
} catch {
|
||||
// Context directory doesn't exist or is empty - this is fine
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze project to gather context
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user