feat: bootstrap context из AGENT.md и memory/ файлов
- loadBootstrapContext() загружает AGENT.md, memory/notes.md, memory/projects/*.md - Лимит 15K символов, автотрункейт - agentHome передаётся из router в agent options - System prompt из agent.json сохранён как fallback
This commit is contained in:
parent
dea2bcaef6
commit
db90b64f54
58
src/agent.ts
58
src/agent.ts
@ -29,6 +29,8 @@ export interface AgentOptions {
|
||||
allowedPaths?: string[];
|
||||
/** Additional custom tools (e.g. tracker tools) */
|
||||
customTools?: ToolDefinition[];
|
||||
/** Agent home directory for loading bootstrap files (AGENT.md, memory/) */
|
||||
agentHome?: string;
|
||||
}
|
||||
|
||||
export interface AgentMessage {
|
||||
@ -37,6 +39,53 @@ export interface AgentMessage {
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
// --- Bootstrap context loader ---
|
||||
const BOOTSTRAP_FILES = ['AGENT.md', 'memory/notes.md'];
|
||||
const BOOTSTRAP_MAX_CHARS = 15_000;
|
||||
|
||||
function loadBootstrapContext(agentHome: string): string {
|
||||
const parts: string[] = [];
|
||||
let totalChars = 0;
|
||||
|
||||
for (const relPath of BOOTSTRAP_FILES) {
|
||||
const filePath = path.join(agentHome, relPath);
|
||||
try {
|
||||
if (!fs.existsSync(filePath)) continue;
|
||||
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
||||
if (!content) continue;
|
||||
const remaining = BOOTSTRAP_MAX_CHARS - totalChars;
|
||||
if (remaining <= 0) break;
|
||||
const truncated = content.length > remaining ? content.slice(0, remaining) + '\n[...truncated]' : content;
|
||||
parts.push(`## ${relPath}\n${truncated}`);
|
||||
totalChars += truncated.length;
|
||||
} catch {
|
||||
// skip unreadable files
|
||||
}
|
||||
}
|
||||
|
||||
// Also load per-project memory files
|
||||
const projectMemDir = path.join(agentHome, 'memory', 'projects');
|
||||
try {
|
||||
if (fs.existsSync(projectMemDir)) {
|
||||
for (const file of fs.readdirSync(projectMemDir).filter(f => f.endsWith('.md'))) {
|
||||
const filePath = path.join(projectMemDir, file);
|
||||
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
||||
if (!content) continue;
|
||||
const remaining = BOOTSTRAP_MAX_CHARS - totalChars;
|
||||
if (remaining <= 200) break;
|
||||
const truncated = content.length > remaining ? content.slice(0, remaining) + '\n[...truncated]' : content;
|
||||
parts.push(`## memory/projects/${file}\n${truncated}`);
|
||||
totalChars += truncated.length;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// skip
|
||||
}
|
||||
|
||||
if (parts.length === 0) return '';
|
||||
return `# Agent Context (bootstrap)\n\n${parts.join('\n\n')}`;
|
||||
}
|
||||
|
||||
// --- Model alias map: short name → full model ID ---
|
||||
const MODEL_ALIASES: Record<string, string> = {
|
||||
'sonnet': 'claude-sonnet-4-6',
|
||||
@ -185,6 +234,15 @@ export async function* runAgent(
|
||||
// Build system prompt additions
|
||||
const promptParts: string[] = [];
|
||||
|
||||
// Load bootstrap context from agent home (AGENT.md, memory/)
|
||||
if (options.agentHome) {
|
||||
const bootstrapContext = loadBootstrapContext(options.agentHome);
|
||||
if (bootstrapContext) {
|
||||
promptParts.push(bootstrapContext);
|
||||
log.info({ chars: bootstrapContext.length }, 'Bootstrap context loaded');
|
||||
}
|
||||
}
|
||||
|
||||
if (skillsXml) {
|
||||
promptParts.push(
|
||||
'## Skills (mandatory)',
|
||||
|
||||
@ -100,13 +100,14 @@ export class EventRouter {
|
||||
sessionId: this.config.sessionId,
|
||||
model: this.config.model,
|
||||
provider: this.config.provider,
|
||||
systemPrompt: this.config.prompt || undefined,
|
||||
systemPrompt: this.config.prompt || undefined, // fallback if no AGENT.md
|
||||
skillsDir: this.config.agentHome,
|
||||
sessionDir: path.join(this.config.agentHome, 'sessions'),
|
||||
allowedPaths: this.config.allowedPaths.length > 0
|
||||
? this.config.allowedPaths
|
||||
: [this.config.agentHome],
|
||||
customTools: this.trackerTools,
|
||||
agentHome: this.config.agentHome,
|
||||
})) {
|
||||
if (msg.type === 'error') {
|
||||
this.log.error({ error: msg.content }, 'Agent error');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user