Skip to content

Commit

Permalink
Merge pull request #85 from arshad-yaseen/completion-intentation-matc…
Browse files Browse the repository at this point in the history
…hing

Completion Intentation Matching
  • Loading branch information
arshad-yaseen authored Nov 23, 2024
2 parents 9ad212d + 8a34f11 commit ab13b4d
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 152 deletions.
2 changes: 1 addition & 1 deletion src/classes/copilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {
DEFAULT_COPILOT_MODEL,
DEFAULT_COPILOT_PROVIDER,
} from '../constants';
import {generateCompletionPrompt} from '../helpers/prompt';
import {
createProviderEndpoint,
createProviderHeaders,
createRequestBody,
parseProviderChatCompletion,
} from '../helpers/provider';
import {deprecated, report} from '../logger';
import generateCompletionPrompt from '../prompts/completion-prompt';
import {
ChatCompletion,
ChatCompletionCreateParams,
Expand Down
14 changes: 8 additions & 6 deletions src/core/completion/handler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {CompletionValidator} from '../../classes';
import {CompletionFormatter, CompletionValidator} from '../../classes';
import {CompletionCache} from '../../classes/completion-cache';
import {CompletionRange} from '../../classes/completion-range';
import {constructCompletionMetadata, fetchCompletionItem} from '../../helpers';
Expand All @@ -11,10 +11,7 @@ import {
TriggerType,
} from '../../types';
import {debouncedAsync, getTextBeforeCursor} from '../../utils';
import {
createInlineCompletionResult,
formatCompletion,
} from '../../utils/completion';
import {createInlineCompletionResult} from '../../utils/completion';

const DEBOUNCE_DELAYS = {
[TriggerType.OnTyping]: 300,
Expand Down Expand Up @@ -122,7 +119,12 @@ const handleInlineCompletions = async ({
});

if (completion) {
const formattedCompletion = formatCompletion(completion);
const formattedCompletion = CompletionFormatter.create(completion)
.removeMarkdownCodeSyntax()
.removeExcessiveNewlines()
.removeInvalidLineBreaks()
.build();

const completionRange = new CompletionRange(monaco);
const completionInsertionRange = completionRange.computeInsertionRange(
pos,
Expand Down
98 changes: 98 additions & 0 deletions src/helpers/prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {CompletionMetadata, PromptData, RelatedFile} from '../types';
import {joinWithAnd} from '../utils';

const formatRelatedFiles = (
relatedFiles: RelatedFile[] | undefined,
): string => {
if (!relatedFiles?.length) return '';

return relatedFiles
.map(({path, content}) =>
`
<related_file>
<path>${path}</path>
<content>
\`\`\`
${content}
\`\`\`
</content>
</related_file>`.trim(),
)
.join('\n\n');
};

export const generateCompletionPrompt = (
metadata: CompletionMetadata,
): PromptData => {
const {
technologies = [],
filename,
relatedFiles,
language,
textBeforeCursor = '',
textAfterCursor = '',
editorState: {completionMode},
} = metadata;

const languageOrTechnologies = joinWithAnd(
[language, ...technologies].filter(
(t): t is string => typeof t === 'string' && Boolean(t),
),
);

const system = `You are an expert ${
languageOrTechnologies ? `${languageOrTechnologies} ` : ''
}AI code completion assistant specialized in generating precise, contextually-aware code completions.
ROLE AND CONTEXT:
- You complete code exactly where the <cursor> placeholder is located in the provided code
- You are working in file: ${filename || 'current file'}
- Primary language: ${language || 'detected from context'}
- Completion mode: ${completionMode}
CRITICAL COMPLETION RULES:
1. Generate ONLY the exact code needed at cursor position - no explanations, no comments
2. NEVER repeat any code that appears before <cursor>
3. Start completion EXACTLY at cursor position
4. Maintain consistent code style and patterns with surrounding code
5. Preserve proper spacing and indentation:
- Add spaces between tokens for readability
- Match existing indentation patterns
- Use appropriate newlines for multi-line completions
6. Follow ${completionMode} mode requirements:
${
completionMode === 'continue'
? '- Continue writing code naturally from cursor position'
: completionMode === 'insert'
? '- Insert precisely fitting code between before/after cursor segments'
: '- Complete the current code block or structure'
}
7. Respect Monaco editor's subwordSmart inline suggestion behavior
8. Ensure completions are syntactically correct and contextually appropriate
9. Consider and maintain consistency with any provided related files
COMPLETION SPACING AND INDENTATION EXAMPLES:
1. Input: "console.log('Hello<cursor>');"
Output: " World" (note the leading space)
2. Input: "function calc(a,<cursor>)"
Output: " b, c" (note the spaces around parameters)
3. Input:
{
name: "John",
<cursor>
}
Output: "age: 30,\n city: 'New York'" (note indentation)
Analyze all context carefully before generating completions. Ensure high relevance and accuracy.`;

const user = `${formatRelatedFiles(relatedFiles)}
Current code with cursor position:
\`\`\`
${textBeforeCursor}<cursor>${textAfterCursor}
\`\`\``;

return {system, user};
};
42 changes: 0 additions & 42 deletions src/prompts/completion-prompt.ts

This file was deleted.

93 changes: 0 additions & 93 deletions src/prompts/index.ts

This file was deleted.

9 changes: 0 additions & 9 deletions src/utils/completion.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,5 @@
import {CompletionFormatter} from '../classes';
import {EditorInlineCompletion, EditorInlineCompletionsResult} from '../types';

export const formatCompletion = (completion: string): string => {
return CompletionFormatter.create(completion)
.removeMarkdownCodeSyntax()
.removeExcessiveNewlines()
.removeInvalidLineBreaks()
.build();
};

export const createInlineCompletionResult = (
items: EditorInlineCompletion[],
): EditorInlineCompletionsResult => ({
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ export default function Home() {
endpoint: '/api/complete',
language: 'javascript',
maxContextLines: 60,
trigger: 'onTyping',
relatedFiles: [
{
path: './utils/index.js',
content:
'export function reverse(str) { return str.split("").reverse().join(""); }',
},
],
});

// monaco.editor.addEditorAction({
Expand Down

0 comments on commit ab13b4d

Please sign in to comment.