11import { AutocompleteInput } from "../types"
22import { CURSOR_MARKER } from "./ghostConstants"
3- import { isCommentLine , cleanComment } from "./CommentHelpers"
43import type { TextDocument , Range } from "vscode"
54
65export function getBaseSystemInstructions ( ) : string {
7- return `CRITICAL OUTPUT FORMAT:
8- You must respond with XML-formatted changes ONLY. No explanations or text outside XML tags.
9-
10- Format: <change><search><![CDATA[exact_code]]></search><replace><![CDATA[new_code]]></replace></change>
11-
12- MANDATORY XML STRUCTURE RULES:
13- - Every <change> tag MUST have a closing </change> tag
14- - Every <search> tag MUST have a closing </search> tag
15- - Every <replace> tag MUST have a closing </replace> tag
16- - Every <![CDATA[ MUST have a closing ]]>
17- - XML tags should be properly formatted and nested
18- - Multiple <change> blocks allowed for different modifications
19-
20- CHANGE ORDERING PRIORITY:
21- - CRITICAL: Order all <change> blocks by proximity to the cursor marker (<<<AUTOCOMPLETE_HERE>>>)
22- - Put changes closest to the cursor marker FIRST in your response
23- - This allows immediate display of the most relevant suggestions to the user
24- - Changes further from the cursor should come later in the response
25- - Measure proximity by line distance from the cursor marker position
26-
27- CONTENT MATCHING RULES:
28- - Search content must match EXACTLY (including whitespace, indentation, and line breaks)
29- - Use CDATA wrappers for all code content
30- - Preserve all line breaks and formatting within CDATA sections
31- - Never generate overlapping changes
32- - The <search> block must contain exact text that exists in the code
33- - If you can't find exact match, don't generate that change
34-
35- EXAMPLE:
36- <change><search><![CDATA[function example() {
37- // old code
38- }]]></search><replace><![CDATA[function example() {
39- // new code
40- }]]></replace></change>
41-
42- --
6+ return `You are a HOLE FILLER. You are provided with a file containing holes, formatted as '{{FILL_HERE}}'. Your TASK is to complete with a string to replace this hole with, inside a <COMPLETION/> XML tag, including context-aware indentation, if needed. All completions MUST be truthful, accurate, well-written and correct.
7+
8+ ## Context Tags
9+ <LANGUAGE>: file language | <RECENT_EDITS>: recent changes | <QUERY>: code with {{FILL_HERE}}
10+
11+ ## EXAMPLE QUERY:
12+
13+ <QUERY>
14+ function sum_evens(lim) {
15+ var sum = 0;
16+ for (var i = 0; i < lim; ++i) {
17+ {{FILL_HERE}}
18+ }
19+ return sum;
20+ }
21+ </QUERY>
22+
23+ TASK: Fill the {{FILL_HERE}} hole.
24+
25+ ## CORRECT COMPLETION
26+
27+ <COMPLETION>if (i % 2 === 0) {
28+ sum += i;
29+ }</COMPLETION>
30+
31+ ## EXAMPLE QUERY:
32+
33+ <QUERY>
34+ def sum_list(lst):
35+ total = 0
36+ for x in lst:
37+ {{FILL_HERE}}
38+ return total
39+
40+ print sum_list([1, 2, 3])
41+ </QUERY>
42+
43+ ## CORRECT COMPLETION:
44+
45+ <COMPLETION> total += x</COMPLETION>
46+
47+ ## EXAMPLE QUERY:
48+
49+ <QUERY>
50+ // data Tree a = Node (Tree a) (Tree a) | Leaf a
51+
52+ // sum :: Tree Int -> Int
53+ // sum (Node lft rgt) = sum lft + sum rgt
54+ // sum (Leaf val) = val
55+
56+ // convert to TypeScript:
57+ {{FILL_HERE}}
58+ </QUERY>
59+
60+ ## CORRECT COMPLETION:
61+
62+ <COMPLETION>type Tree<T>
63+ = {$:"Node", lft: Tree<T>, rgt: Tree<T>}
64+ | {$:"Leaf", val: T};
65+
66+ function sum(tree: Tree<number>): number {
67+ switch (tree.$) {
68+ case "Node":
69+ return sum(tree.lft) + sum(tree.rgt);
70+ case "Leaf":
71+ return tree.val;
72+ }
73+ }</COMPLETION>
74+
75+ ## EXAMPLE QUERY:
76+
77+ The 5th {{FILL_HERE}} is Jupiter.
78+
79+ ## CORRECT COMPLETION:
80+
81+ <COMPLETION>planet from the Sun</COMPLETION>
82+
83+ ## EXAMPLE QUERY:
84+
85+ function hypothenuse(a, b) {
86+ return Math.sqrt({{FILL_HERE}}b ** 2);
87+ }
88+
89+ ## CORRECT COMPLETION:
90+
91+ <COMPLETION>a ** 2 + </COMPLETION>
4392
4493`
4594}
@@ -56,20 +105,6 @@ export function addCursorMarker(document: TextDocument, range?: Range): string {
56105}
57106
58107export class AutoTriggerStrategy {
59- shouldTreatAsComment ( prefix : string , languageId : string ) : boolean {
60- const lines = prefix . split ( "\n" )
61- const currentLine = lines [ lines . length - 1 ] . trim ( ) || ""
62- const previousLine = lines . length > 1 ? lines [ lines . length - 2 ] . trim ( ) : ""
63-
64- if ( isCommentLine ( currentLine , languageId ) ) {
65- return true
66- } else if ( currentLine === "" && previousLine ) {
67- return isCommentLine ( previousLine , languageId )
68- } else {
69- return false
70- }
71- }
72-
73108 getPrompts (
74109 autocompleteInput : AutocompleteInput ,
75110 prefix : string ,
@@ -79,24 +114,17 @@ export class AutoTriggerStrategy {
79114 systemPrompt : string
80115 userPrompt : string
81116 } {
82- if ( this . shouldTreatAsComment ( prefix , languageId ) ) {
83- return {
84- systemPrompt : this . getCommentsSystemInstructions ( ) ,
85- userPrompt : this . getCommentsUserPrompt ( prefix , suffix , languageId ) ,
86- }
87- } else {
88- return {
89- systemPrompt : this . getSystemInstructions ( ) ,
90- userPrompt : this . getUserPrompt ( autocompleteInput , prefix , suffix , languageId ) ,
91- }
117+ return {
118+ systemPrompt : this . getSystemInstructions ( ) ,
119+ userPrompt : this . getUserPrompt ( autocompleteInput , prefix , suffix , languageId ) ,
92120 }
93121 }
94122
95123 getSystemInstructions ( ) : string {
96124 return (
97125 getBaseSystemInstructions ( ) +
98- `Task: Subtle Auto-Completion
99- Provide non-intrusive completions after a typing pause. Be conservative and helpful .
126+ `Task: Auto-Completion
127+ Provide a subtle, non-intrusive completion after a typing pause.
100128
101129`
102130 )
@@ -106,108 +134,24 @@ Provide non-intrusive completions after a typing pause. Be conservative and help
106134 * Build minimal prompt for auto-trigger
107135 */
108136 getUserPrompt ( autocompleteInput : AutocompleteInput , prefix : string , suffix : string , languageId : string ) : string {
109- let prompt = ""
137+ let prompt = `<LANGUAGE> ${ languageId } </LANGUAGE>\n\n`
110138
111- // Start with recent typing context from autocompleteInput
112139 if ( autocompleteInput . recentlyEditedRanges && autocompleteInput . recentlyEditedRanges . length > 0 ) {
113- prompt += "## Recent Typing \n"
140+ prompt += "<RECENT_EDITS> \n"
114141 autocompleteInput . recentlyEditedRanges . forEach ( ( range , index ) => {
115142 const description = `Edited ${ range . filepath } at line ${ range . range . start . line } `
116143 prompt += `${ index + 1 } . ${ description } \n`
117144 } )
118- prompt += "\n"
145+ prompt += "</RECENT_EDITS>\n \n"
119146 }
120147
121- // Add current position from autocompleteInput
122- const line = autocompleteInput . pos . line + 1
123- const char = autocompleteInput . pos . character + 1
124- prompt += `## Current Position\n`
125- prompt += `Line ${ line } , Character ${ char } \n\n`
126-
127- // Add the full document with cursor marker
128- const codeWithCursor = `${ prefix } ${ CURSOR_MARKER } ${ suffix } `
129- prompt += "## Full Code\n"
130- prompt += `\`\`\`${ languageId } \n${ codeWithCursor } \n\`\`\`\n\n`
131-
132- // Add specific instructions
133- prompt += "## Instructions\n"
134- prompt += `Provide a minimal, obvious completion at the cursor position (${ CURSOR_MARKER } ).\n`
135- prompt += `IMPORTANT: Your <search> block must include the cursor marker ${ CURSOR_MARKER } to target the exact location.\n`
136- prompt += `Include surrounding text with the cursor marker to avoid conflicts with similar code elsewhere.\n`
137- prompt += "Complete only what the user appears to be typing.\n"
138- prompt += "Single line preferred, no new features.\n"
139- prompt += "If nothing obvious to complete, provide NO suggestion.\n"
148+ prompt += `<QUERY>
149+ ${ prefix } {{FILL_HERE}}${ suffix }
150+ </QUERY>
140151
141- return prompt
142- }
152+ TASK: Fill the {{FILL_HERE}} hole. Answer only with the CORRECT completion, and NOTHING ELSE. Do it now.
153+ Return the COMPLETION tags`
143154
144- getCommentsSystemInstructions ( ) : string {
145- return (
146- getBaseSystemInstructions ( ) +
147- `You are an expert code generation assistant that implements code based on comments.
148-
149- ## Core Responsibilities:
150- 1. Read and understand the comment's intent
151- 2. Generate complete, working code that fulfills the comment's requirements
152- 3. Follow the existing code style and patterns
153- 4. Add appropriate error handling
154- 5. Include necessary imports or dependencies
155-
156- ## Code Generation Guidelines:
157- - Generate only the code that directly implements the comment
158- - Match the indentation level of the comment
159- - Use descriptive variable and function names
160- - Follow language-specific best practices
161- - Add type annotations where appropriate
162- - Consider edge cases mentioned in the comment
163- - If the comment describes multiple steps, implement them all
164-
165- ## Comment Types to Handle:
166- - TODO comments: Implement the described task
167- - FIXME comments: Fix the described issue
168- - Implementation comments: Generate the described functionality
169- - Algorithm descriptions: Implement the described algorithm
170- - API/Interface descriptions: Implement the described interface
171-
172- ## Output Requirements:
173- - Generate ONLY executable code that implements the comment
174- - PRESERVE all existing code and comments in the provided context
175- - Do not repeat the comment you are implementing in your output
176- - Do not add explanatory comments unless necessary for complex logic
177- - Ensure the code is production-ready
178- - When using search/replace format, include ALL existing code to preserve it`
179- )
180- }
181-
182- getCommentsUserPrompt ( prefix : string , suffix : string , languageId : string ) : string {
183- // Extract the comment from the prefix
184- const lines = prefix . split ( "\n" )
185- const lastLine = lines [ lines . length - 1 ]
186- const previousLine = lines . length > 1 ? lines [ lines . length - 2 ] : ""
187-
188- // Determine which line contains the comment
189- const commentLine = isCommentLine ( lastLine , languageId ) ? lastLine : previousLine
190- const comment = cleanComment ( commentLine , languageId )
191-
192- const codeWithCursor = `${ prefix } ${ CURSOR_MARKER } ${ suffix } `
193-
194- let prompt = `## Comment-Driven Development
195- - Language: ${ languageId }
196- - Comment to Implement:
197- \`\`\`
198- ${ comment }
199- \`\`\`
200-
201- ## Full Code
202- \`\`\`${ languageId }
203- ${ codeWithCursor }
204- \`\`\`
205-
206- ## Instructions
207- Generate code that implements the functionality described in the comment.
208- The code should be placed at the cursor position (${ CURSOR_MARKER } ).
209- Focus on implementing exactly what the comment describes.
210- `
211155 return prompt
212156 }
213157}
0 commit comments