feat: enhanced Code Context and Project Summary Features (#1191)

* fix: docker prod env variable fix

* lint and typecheck

* removed hardcoded tag

* better summary generation

* improved  summary generation for context optimization

* remove think tags from the generation
This commit is contained in:
Anirban Kar
2025-01-29 15:37:20 +05:30
committed by GitHub
parent a199295ad8
commit 7016111906
14 changed files with 416 additions and 86 deletions

View File

@@ -16,7 +16,7 @@ export async function createSummary(props: {
contextOptimization?: boolean;
onFinish?: (resp: GenerateTextResult<Record<string, CoreTool<any, any>>, never>) => void;
}) {
const { messages, env: serverEnv, apiKeys, providerSettings, contextOptimization, onFinish } = props;
const { messages, env: serverEnv, apiKeys, providerSettings, onFinish } = props;
let currentModel = DEFAULT_MODEL;
let currentProvider = DEFAULT_PROVIDER.name;
const processedMessages = messages.map((message) => {
@@ -29,9 +29,9 @@ export async function createSummary(props: {
} else if (message.role == 'assistant') {
let content = message.content;
if (contextOptimization) {
content = simplifyBoltActions(content);
}
content = simplifyBoltActions(content);
content = content.replace(/<div class=\\"__boltThought__\\">.*?<\/div>/s, '');
content = content.replace(/<think>.*?<\/think>/s, '');
return { ...message, content };
}
@@ -92,6 +92,8 @@ ${summary.summary}`;
}
}
logger.debug('Sliced Messages:', slicedMessages.length);
const extractTextContent = (message: Message) =>
Array.isArray(message.content)
? (message.content.find((item) => item.type === 'text')?.text as string) || ''
@@ -100,25 +102,82 @@ ${summary.summary}`;
// select files from the list of code file from the project that might be useful for the current request from the user
const resp = await generateText({
system: `
You are a software engineer. You are working on a project. tou need to summarize the work till now and provide a summary of the chat till now.
You are a software engineer. You are working on a project. you need to summarize the work till now and provide a summary of the chat till now.
${summaryText}
RULES:
* Only provide the summary of the chat till now.
* Do not provide any new information.
`,
prompt: `
please provide a summary of the chat till now.
below is the latest chat:
Please only use the following format to generate the summary:
---
# Project Overview
- **Project**: {project_name} - {brief_description}
- **Current Phase**: {phase}
- **Tech Stack**: {languages}, {frameworks}, {key_dependencies}
- **Environment**: {critical_env_details}
# Conversation Context
- **Last Topic**: {main_discussion_point}
- **Key Decisions**: {important_decisions_made}
- **User Context**:
- Technical Level: {expertise_level}
- Preferences: {coding_style_preferences}
- Communication: {preferred_explanation_style}
# Implementation Status
## Current State
- **Active Feature**: {feature_in_development}
- **Progress**: {what_works_and_what_doesn't}
- **Blockers**: {current_challenges}
## Code Evolution
- **Recent Changes**: {latest_modifications}
- **Working Patterns**: {successful_approaches}
- **Failed Approaches**: {attempted_solutions_that_failed}
# Requirements
- **Implemented**: {completed_features}
- **In Progress**: {current_focus}
- **Pending**: {upcoming_features}
- **Technical Constraints**: {critical_constraints}
# Critical Memory
- **Must Preserve**: {crucial_technical_context}
- **User Requirements**: {specific_user_needs}
- **Known Issues**: {documented_problems}
# Next Actions
- **Immediate**: {next_steps}
- **Open Questions**: {unresolved_issues}
---
Note:
4. Keep entries concise and focused on information needed for continuity
---
RULES:
* Only provide the whole summary of the chat till now.
* Do not provide any new information.
* DO not need to think too much just start writing imidiately
* do not write any thing other that the summary with with the provided structure
`,
prompt: `
Here is the previous summary of the chat:
<old_summary>
${summaryText}
</old_summary>
Below is the chat after that:
---
<new_chats>
${slicedMessages
.map((x) => {
return `---\n[${x.role}] ${extractTextContent(x)}\n---`;
})
.join('\n')}
</new_chats>
---
Please provide a summary of the chat till now including the hitorical summary of the chat.
`,
model: provider.getModelInstance({
model: currentModel,

View File

@@ -23,7 +23,7 @@ export async function selectContext(props: {
summary: string;
onFinish?: (resp: GenerateTextResult<Record<string, CoreTool<any, any>>, never>) => void;
}) {
const { messages, env: serverEnv, apiKeys, files, providerSettings, contextOptimization, summary, onFinish } = props;
const { messages, env: serverEnv, apiKeys, files, providerSettings, summary, onFinish } = props;
let currentModel = DEFAULT_MODEL;
let currentProvider = DEFAULT_PROVIDER.name;
const processedMessages = messages.map((message) => {
@@ -36,9 +36,10 @@ export async function selectContext(props: {
} else if (message.role == 'assistant') {
let content = message.content;
if (contextOptimization) {
content = simplifyBoltActions(content);
}
content = simplifyBoltActions(content);
content = content.replace(/<div class=\\"__boltThought__\\">.*?<\/div>/s, '');
content = content.replace(/<think>.*?<\/think>/s, '');
return { ...message, content };
}

View File

@@ -7,7 +7,7 @@ import { PromptLibrary } from '~/lib/common/prompt-library';
import { allowedHTMLElements } from '~/utils/markdown';
import { LLMManager } from '~/lib/modules/llm/manager';
import { createScopedLogger } from '~/utils/logger';
import { createFilesContext, extractPropertiesFromMessage, simplifyBoltActions } from './utils';
import { createFilesContext, extractPropertiesFromMessage } from './utils';
import { getFilePaths } from './select-context';
export type Messages = Message[];
@@ -27,6 +27,7 @@ export async function streamText(props: {
contextOptimization?: boolean;
contextFiles?: FileMap;
summary?: string;
messageSliceId?: number;
}) {
const {
messages,
@@ -51,10 +52,8 @@ export async function streamText(props: {
return { ...message, content };
} else if (message.role == 'assistant') {
let content = message.content;
if (contextOptimization) {
content = simplifyBoltActions(content);
}
content = content.replace(/<div class=\\"__boltThought__\\">.*?<\/div>/s, '');
content = content.replace(/<think>.*?<\/think>/s, '');
return { ...message, content };
}
@@ -110,7 +109,7 @@ Below are all the files present in the project:
${filePaths.join('\n')}
---
Below is the context loaded into context buffer for you to have knowledge of and might need changes to fullfill current user request.
Below is the artifact containing the context loaded into context buffer for you to have knowledge of and might need changes to fullfill current user request.
CONTEXT BUFFER:
---
${codeContext}
@@ -126,10 +125,14 @@ ${props.summary}
---
`;
const lastMessage = processedMessages.pop();
if (props.messageSliceId) {
processedMessages = processedMessages.slice(props.messageSliceId);
} else {
const lastMessage = processedMessages.pop();
if (lastMessage) {
processedMessages = [lastMessage];
if (lastMessage) {
processedMessages = [lastMessage];
}
}
}
}

View File

@@ -82,10 +82,10 @@ export function createFilesContext(files: FileMap, useRelativePath?: boolean) {
filePath = path.replace('/home/project/', '');
}
return `<file path="${filePath}">\n${codeWithLinesNumbers}\n</file>`;
return `<boltAction type="file" filePath="${filePath}">${codeWithLinesNumbers}</boltAction>`;
});
return `<codebase>${fileContexts.join('\n\n')}\n\n</codebase>`;
return `<boltArtifact id="code-content" title="Code Content" >\n${fileContexts.join('\n')}\n</boltArtifact>`;
}
export function extractCurrentContext(messages: Message[]) {