Version 2.47.0 Release: Recursive Project Knowledge Flow and Follow-up Context Injection
This commit is contained in:
@@ -281,6 +281,12 @@ export class AgentExecutor {
|
||||
if (localPathContext) {
|
||||
contextBlock += `\n\n${localPathContext}`;
|
||||
}
|
||||
const recentProjectKnowledgeContext = prompt && loopDepth === 0 && !localPathContext
|
||||
? this.buildRecentProjectKnowledgeContext(prompt, rootPath)
|
||||
: '';
|
||||
if (recentProjectKnowledgeContext) {
|
||||
contextBlock += `\n\n${recentProjectKnowledgeContext}`;
|
||||
}
|
||||
|
||||
// 2. Setup History
|
||||
if (prompt !== null) {
|
||||
@@ -763,6 +769,80 @@ export class AgentExecutor {
|
||||
&& /\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+/i.test(prompt);
|
||||
}
|
||||
|
||||
private isProjectKnowledgeFollowupRequest(prompt: string): boolean {
|
||||
return /(아키텍처|구조|조사|분석|설계|흐름|모듈|역할|개선|architecture|structure|design|flow|module|investigate|analy[sz]e)/i.test(prompt);
|
||||
}
|
||||
|
||||
private buildRecentProjectKnowledgeContext(prompt: string, rootPath: string): string {
|
||||
if (!rootPath || !this.isProjectKnowledgeFollowupRequest(prompt)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const recordPath = this.findRecentProjectKnowledgeRecord(rootPath);
|
||||
if (!recordPath) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(recordPath, 'utf8');
|
||||
return [
|
||||
'[RECENT LOCAL PROJECT KNOWLEDGE]',
|
||||
'The current user request appears to continue a previous local project knowledge discussion.',
|
||||
`Use this recently generated project knowledge record as project evidence: ${recordPath}`,
|
||||
'When answering, explicitly say that the analysis is based on the recently generated project knowledge record and local project structure. Do not imply that Second Brain Trace was the only evidence.',
|
||||
'If deeper architecture detail is needed, recommend reading the concrete source files next instead of asking for the project path again.',
|
||||
'',
|
||||
summarizeText(content, 5000)
|
||||
].join('\n');
|
||||
} catch (error: any) {
|
||||
logError('Failed to load recent project knowledge record.', { recordPath, error: error?.message || String(error) });
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
private findRecentProjectKnowledgeRecord(rootPath: string): string | null {
|
||||
const fromHistory = [...this.chatHistory]
|
||||
.reverse()
|
||||
.map((message) => typeof message.content === 'string'
|
||||
? message.content.match(/\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+_project_knowledge_overview\.md/i)?.[0]
|
||||
: undefined)
|
||||
.find(Boolean);
|
||||
if (fromHistory && fs.existsSync(fromHistory)) {
|
||||
return fromHistory;
|
||||
}
|
||||
|
||||
const recordsRoot = path.join(rootPath, 'docs', 'records');
|
||||
if (!fs.existsSync(recordsRoot)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const candidates: string[] = [];
|
||||
const visit = (dir: string, depth: number) => {
|
||||
if (depth > 5) return;
|
||||
let entries: fs.Dirent[] = [];
|
||||
try {
|
||||
entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (!entry.name.startsWith('.')) visit(fullPath, depth + 1);
|
||||
continue;
|
||||
}
|
||||
if (/_project_knowledge_overview\.md$/i.test(entry.name)) {
|
||||
candidates.push(fullPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
visit(recordsRoot, 0);
|
||||
|
||||
return candidates
|
||||
.filter((file) => fs.existsSync(file))
|
||||
.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs)[0] || null;
|
||||
}
|
||||
|
||||
private extractLocalProjectPaths(prompt: string): string[] {
|
||||
const matches = prompt.match(/\/Volumes\/Data\/project\/Antigravity\/[^\s`"'<>]+/gi) || [];
|
||||
return Array.from(new Set(matches.map((value) => value.replace(/[),.;\]]+$/g, ''))));
|
||||
|
||||
Reference in New Issue
Block a user