Просмотр исходного кода

Merge branch 'main' into beatlevic/test-cases-llm-cleanup

Coen Stevens 4 месяцев назад
Родитель
Сommit
8e940d3984

+ 0 - 5
.changeset/dry-hornets-press.md

@@ -1,5 +0,0 @@
----
-"kilo-code": patch
----
-
-Improved Fast Apply error messages

+ 0 - 5
.changeset/metal-countries-notice.md

@@ -1,5 +0,0 @@
----
-"kilo-code": patch
----
-
-Add custom base URL support to OVHcloud provider

+ 0 - 5
.changeset/olive-cars-flash.md

@@ -1,5 +0,0 @@
----
-"kilo-code": patch
----
-
-A checkpoint is now created before _every_ tool call

+ 0 - 11
.changeset/red-years-stick.md

@@ -1,11 +0,0 @@
----
-"kilo-code": minor
----
-
-Include changes from Roo Code v3.28.14-v3.28.15
-
-- Fix: properly reset cost limit tracking when user clicks "Reset and Continue" (#6889 by @alecoot, PR by app/roomote)
-- Fix: improve save button activation in prompts settings (#5780 by @beccare, PR by app/roomote)
-- Fix: overeager 'there are unsaved changes' dialog in settings (thanks @brunobergher!)
-- Fix: Claude Sonnet 4.5 compatibility improvements (thanks @mrubens!)
-- Remove unsupported Gemini 2.5 Flash Image Preview free model (thanks @SannidhyaSah!)

+ 0 - 5
.changeset/twenty-apes-write.md

@@ -1,5 +0,0 @@
----
-"kilo-code": minor
----
-
-Add a display setting that hides costs below a user-defined threshold

+ 20 - 0
CHANGELOG.md

@@ -1,5 +1,25 @@
 # kilo-code
 
+## [v4.102.0]
+
+- [#2854](https://github.com/Kilo-Org/kilocode/pull/2854) [`bd5d7fc`](https://github.com/Kilo-Org/kilocode/commit/bd5d7fc5f0c67ac2b040dbdefbd90d0396e0b60e) Thanks [@kevinvandijk](https://github.com/kevinvandijk)! - Include changes from Roo Code v3.28.14-v3.28.15
+
+    - Fix: properly reset cost limit tracking when user clicks "Reset and Continue" (#6889 by @alecoot, PR by app/roomote)
+    - Fix: improve save button activation in prompts settings (#5780 by @beccare, PR by app/roomote)
+    - Fix: overeager 'there are unsaved changes' dialog in settings (thanks @brunobergher!)
+    - Fix: Claude Sonnet 4.5 compatibility improvements (thanks @mrubens!)
+    - Remove unsupported Gemini 2.5 Flash Image Preview free model (thanks @SannidhyaSah!)
+
+- [#1652](https://github.com/Kilo-Org/kilocode/pull/1652) [`b3caf38`](https://github.com/Kilo-Org/kilocode/commit/b3caf38e44f2f6ccd58f3e92cd68edce48a96844) Thanks [@hassoncs](https://github.com/hassoncs)! - Add a display setting that hides costs below a user-defined threshold
+
+### Patch Changes
+
+- [#2871](https://github.com/Kilo-Org/kilocode/pull/2871) [`0403f82`](https://github.com/Kilo-Org/kilocode/commit/0403f820a8413656eecbe3bbfe252a52c2999e37) Thanks [@chrarnoldus](https://github.com/chrarnoldus)! - Improved Fast Apply error messages
+
+- [#2851](https://github.com/Kilo-Org/kilocode/pull/2851) [`9e6a897`](https://github.com/Kilo-Org/kilocode/commit/9e6a89796f04f6215e31ac7950669783387a11de) Thanks [@eliasto](https://github.com/eliasto)! - Add custom base URL support to OVHcloud provider
+
+- [#2870](https://github.com/Kilo-Org/kilocode/pull/2870) [`4730e08`](https://github.com/Kilo-Org/kilocode/commit/4730e080f99bcd414a3eb0a71a04ab5fd6dbcb6e) Thanks [@chrarnoldus](https://github.com/chrarnoldus)! - A checkpoint is now created before _every_ tool call
+
 ## [v4.101.0]
 
 - [#2518](https://github.com/Kilo-Org/kilocode/pull/2518) [`01106a8`](https://github.com/Kilo-Org/kilocode/commit/01106a8d35159ccea34e290a2174d44d83fecd64) Thanks [@eliasto](https://github.com/eliasto)! - OVHcloud AI Endpoints provider added

+ 12 - 6
apps/kilocode-docs/docs/basic-usage/autocomplete.md

@@ -64,17 +64,23 @@ This is ideal for:
 
 You can customize this keyboard shortcut as well in your VS Code settings.
 
-## Disable Rival Autocomplete
+We recommend disabling rival autocompletes to optimize your experience with Kilo Code. To disable GitHub Copilot autocomplete in VSCode, go to **Settings** and navigate to **GitHub** > **Copilot: Advanced** (or search for 'copilot'). Then, toggle to 'disabled':
 
-We recommend disabling rival autocompletes to optimize your experience with Kilo Code. To disable Github Copilot autocomplete in VSCode, go to **Settings** and navigate to **Github** > **Copilot: Advanced** (or search for 'copilot'). Then, toggle to 'disabled':
-
-<img width="2370" height="858" alt="Disable Github Copilot in VSCode" src="https://github.com/user-attachments/assets/60c69417-1d1c-4a48-9820-5390c30ae25c" />
+<img
+  src="https://github.com/user-attachments/assets/60c69417-1d1c-4a48-9820-5390c30ae25c"
+  alt="Disable GitHub Copilot in VSCode"
+  width="600"
+/>
 
+If using Cursor, go to **Settings** > **Cursor Settings** > **Tab**, and toggle off 'Cursor Tab':
 
+<img
+  src="https://github.com/user-attachments/assets/fd2eeae2-f770-40ca-8a72-a9d5a1c17d47"
+  alt="Disable Cursor autocomplete"
+  width="600"
+/>
 
-If using Cursor, go to **Settings** > **Cursor Settings** > **Tab**, and toggle off 'Cursor Tab':
 
-<img width="1366" height="486" alt="Disable Cursor autocomplete" src="https://github.com/user-attachments/assets/fd2eeae2-f770-40ca-8a72-a9d5a1c17d47" />
 
 
 ## Advanced Settings

+ 1 - 1
src/package.json

@@ -3,7 +3,7 @@
 	"displayName": "%extension.displayName%",
 	"description": "%extension.description%",
 	"publisher": "kilocode",
-	"version": "4.101.0",
+	"version": "4.102.0",
 	"icon": "assets/icons/logo-outline-black.png",
 	"galleryBanner": {
 		"color": "#FFFFFF",

+ 1 - 12
src/services/ghost/PromptStrategyManager.ts

@@ -3,12 +3,8 @@ import { PromptStrategy } from "./types/PromptStrategy"
 
 // Import all strategies
 import { UserRequestStrategy } from "./strategies/UserRequestStrategy"
-import { SelectionRefactorStrategy } from "./strategies/SelectionRefactorStrategy"
 import { CommentDrivenStrategy } from "./strategies/CommentDrivenStrategy"
-import { NewLineCompletionStrategy } from "./strategies/NewLineCompletionStrategy"
-import { InlineCompletionStrategy } from "./strategies/InlineCompletionStrategy"
 import { AutoTriggerStrategy } from "./strategies/AutoTriggerStrategy"
-import { FimCodestralStrategy } from "./strategies/FimCodestralStrategy"
 
 /**
  * Manages prompt strategies and selects the appropriate one based on context
@@ -24,14 +20,7 @@ export class PromptStrategyManager {
 		this.overrideStrategy = options?.overrideStrategy
 
 		// Register all strategies in priority order
-		this.strategies = [
-			new UserRequestStrategy(),
-			new SelectionRefactorStrategy(),
-			new NewLineCompletionStrategy(),
-			new CommentDrivenStrategy(),
-			new InlineCompletionStrategy(),
-			new FimCodestralStrategy(),
-		]
+		this.strategies = [new UserRequestStrategy(), new CommentDrivenStrategy()]
 		this.autoTriggerStrategy = new AutoTriggerStrategy()
 	}
 

+ 2 - 3
src/services/ghost/__tests__/GhostStrategy.test.ts

@@ -111,9 +111,8 @@ describe("GhostStrategy", () => {
 
 			const result = manager.buildPrompt(commentContext)
 
-			// Should select NewLineCompletionStrategy when cursor is on empty line
-			// (even if previous line has a comment, empty line takes precedence)
-			expect(result.strategy.name).toBe("New Line Completion")
+			// CommentDrivenStrategy handles empty lines after comments
+			expect(result.strategy.name).toBe("Comment Driven")
 		})
 
 		it("should fallback to AutoTriggerStrategy when no specific strategy matches", () => {

+ 0 - 70
src/services/ghost/strategies/FimCodestralStrategy.ts

@@ -1,70 +0,0 @@
-import { GhostSuggestionContext } from "../types"
-import { PromptStrategy, UseCaseType } from "../types/PromptStrategy"
-import { CURSOR_MARKER } from "../ghostConstants"
-import { getBaseSystemInstructions } from "./StrategyHelpers"
-
-/**
- * Strategy using Fill-In-the-Middle (FIM) format for Codestral
- * Uses the [SUFFIX][PREFIX] format optimized for Mistral Codestral models
- *
- * This strategy implements the FIM prompt template with special [SUFFIX] and [PREFIX] markers
- * that Codestral models are trained to understand for code completion.
- */
-export class FimCodestralStrategy implements PromptStrategy {
-	name = "FIM Codestral"
-	type = UseCaseType.FIM_CODESTRAL
-
-	canHandle(_context: GhostSuggestionContext): boolean {
-		// This strategy can handle all cases when explicitly selected
-		// In production, you'd add specific logic here
-		return false // We will enable in the next PR -- 2025-10-09
-	}
-
-	getSystemInstructions(customInstructions?: string): string {
-		return (
-			getBaseSystemInstructions() +
-			`You are an AI assistant specialized in code completion using Fill-In-the-Middle (FIM) format.
-
-## FIM Format Understanding
-The user prompt follows the Codestral FIM format:
-- [SUFFIX] marker followed by code that comes AFTER the cursor
-- [PREFIX] marker followed by code that comes BEFORE the cursor
-- The ${CURSOR_MARKER} marker indicates the exact cursor position
-
-## Your Task
-Generate code to fill in at the cursor position. The code should:
-1. Fit naturally between the prefix and suffix
-2. Follow the existing code style and patterns
-3. Be syntactically correct
-4. Complete the intended functionality
-5. Be minimal - only complete what's necessary
-
-## Important Rules
-1. Your <search> block MUST include the ${CURSOR_MARKER} marker
-2. Include sufficient context around the cursor to uniquely identify the location
-3. The <replace> block should contain the complete text including your completion
-4. Generate only ONE <change> block
-5. Focus on the immediate completion need
-6. Consider common code patterns and idioms
-7. Maintain consistency with surrounding code`
-		)
-	}
-
-	getUserPrompt(context: GhostSuggestionContext): string {
-		if (!context.document || !context.range) {
-			return "No context available for completion."
-		}
-
-		const document = context.document
-		const position = context.range.start
-
-		// FIXME: use addCursorMarker from StrategyHelpers.ts
-		// Get the code before and after the cursor
-		const fullText = document.getText()
-		const offset = document.offsetAt(position)
-		const textBeforeCursor = fullText.substring(0, offset)
-		const textAfterCursor = fullText.substring(offset)
-
-		return `[SUFFIX]${textAfterCursor}[PREFIX]${textBeforeCursor}${CURSOR_MARKER}`
-	}
-}

+ 0 - 152
src/services/ghost/strategies/InlineCompletionStrategy.ts

@@ -1,152 +0,0 @@
-import { GhostSuggestionContext } from "../types"
-import { PromptStrategy, UseCaseType } from "../types/PromptStrategy"
-import { CURSOR_MARKER } from "../ghostConstants"
-import { formatDocumentWithCursor, getBaseSystemInstructions } from "./StrategyHelpers"
-
-export class InlineCompletionStrategy implements PromptStrategy {
-	name = "Inline Completion"
-	type = UseCaseType.INLINE_COMPLETION
-
-	canHandle(context: GhostSuggestionContext): boolean {
-		if (!context.document || !context.range) return false
-
-		const currentLine = context.document.lineAt(context.range.start.line).text
-		const cursorPosition = context.range.start.character
-
-		// Check if cursor is in the middle of a line with content before it
-		const hasContentBefore = cursorPosition > 0 && currentLine.substring(0, cursorPosition).trim().length > 0
-		const isNotAtEnd = cursorPosition < currentLine.length
-
-		// This strategy handles mid-line completions
-		return hasContentBefore && !context.userInput && !context.range.isEmpty === false && isNotAtEnd
-	}
-
-	getSystemInstructions(customInstructions?: string): string {
-		return (
-			getBaseSystemInstructions() +
-			`You are an expert code completion assistant specializing in inline completions.
-
-## Core Responsibilities:
-1. Complete partial statements and expressions
-2. Finish method calls and property accesses
-3. Complete variable assignments
-4. Finish conditional expressions
-5. Complete function parameters
-
-## Completion Guidelines:
-- Analyze the partial code before the cursor
-- Determine the most likely completion based on context
-- Complete only the current statement or expression
-- Maintain consistency with surrounding code style
-- Use appropriate types and return values
-- Consider common patterns and idioms
-
-## Context Analysis:
-- Identify the type of statement being written
-- Check for unclosed brackets, parentheses, or quotes
-- Analyze variable types and method signatures
-- Consider the current scope and available symbols
-- Look for patterns in similar code nearby
-
-## CRITICAL: Cursor Marker Usage
-- The cursor position is marked with ${CURSOR_MARKER}
-- Your <search> block MUST include the cursor marker to avoid conflicts
-- When creating <search> content, include text around the cursor marker
-- This ensures you target the exact location, not similar text elsewhere
-- Example: If cursor is at "const x = <<<AUTOCOMPLETE_HERE>>>", your <search> should include the marker
-
-## Output Requirements:
-- Generate ONLY the completion text
-- Do not repeat the existing partial code
-- Complete just enough to finish the current expression
-- Ensure syntactic correctness
-- Match the existing code style`
-		)
-	}
-
-	getUserPrompt(context: GhostSuggestionContext): string {
-		if (!context.document || !context.range) {
-			return "No context available for inline completion."
-		}
-
-		const document = context.document
-		const position = context.range.start
-		const currentLine = document.lineAt(position.line).text
-		const beforeCursor = currentLine.substring(0, position.character)
-		const afterCursor = currentLine.substring(position.character)
-
-		// Analyze what needs to be completed
-		const completionType = this.analyzeCompletionType(beforeCursor)
-
-		let prompt = `## Inline Completion Context\n`
-		prompt += `- Language: ${document.languageId}\n`
-		prompt += `- Current Line Before Cursor: \`${beforeCursor}\`\n`
-		prompt += `- Current Line After Cursor: \`${afterCursor}\`\n`
-		prompt += `- Completion Type: ${completionType}\n\n`
-
-		// Add the full document with cursor marker
-		if (context.document) {
-			prompt += "## Full Code\n"
-			prompt += formatDocumentWithCursor(context.document, context.range)
-			prompt += "\n\n"
-		}
-
-		prompt += `## Instructions\n`
-		prompt += `Complete the partial code at the cursor position (${CURSOR_MARKER}).\n`
-		prompt += `IMPORTANT: Your <search> block must include the cursor marker ${CURSOR_MARKER} to target the exact location.\n`
-		prompt += `Include surrounding text with the cursor marker to avoid conflicts with similar code elsewhere.\n`
-		prompt += `Focus on completing the ${completionType}.\n`
-
-		return prompt
-	}
-
-	/**
-	 * Analyzes the partial code to determine what type of completion is needed
-	 */
-	private analyzeCompletionType(beforeCursor: string): string {
-		const trimmed = beforeCursor.trim()
-
-		// Method call
-		if (/\.\w*$/.test(trimmed)) {
-			return "method_or_property_access"
-		}
-
-		// Function call parameters
-		if (/\w+\([^)]*$/.test(trimmed)) {
-			return "function_parameters"
-		}
-
-		// Variable assignment
-		if (/(?:const|let|var|final|val|auto)\s+\w+\s*=\s*$/.test(trimmed)) {
-			return "variable_assignment"
-		}
-
-		// Array or object literal
-		if (/[\[{][^}\]]*$/.test(trimmed)) {
-			return "literal_completion"
-		}
-
-		// Conditional expression
-		if (/(?:if|while|for)\s*\([^)]*$/.test(trimmed)) {
-			return "conditional_expression"
-		}
-
-		// Return statement
-		if (/return\s+.*$/.test(trimmed)) {
-			return "return_statement"
-		}
-
-		// Import/require statement
-		if (/(?:import|require|from|using)\s+.*$/.test(trimmed)) {
-			return "import_statement"
-		}
-
-		// String literal
-		if (/["'`][^"'`]*$/.test(trimmed)) {
-			return "string_literal"
-		}
-
-		// Generic expression
-		return "expression"
-	}
-}

+ 0 - 317
src/services/ghost/strategies/NewLineCompletionStrategy.ts

@@ -1,317 +0,0 @@
-import type { TextDocument, Range } from "vscode"
-import { GhostSuggestionContext } from "../types"
-import { PromptStrategy, UseCaseType } from "../types/PromptStrategy"
-import { CURSOR_MARKER } from "../ghostConstants"
-import { formatDocumentWithCursor, getBaseSystemInstructions } from "./StrategyHelpers"
-
-export class NewLineCompletionStrategy implements PromptStrategy {
-	name = "New Line Completion"
-	type = UseCaseType.NEW_LINE
-
-	canHandle(context: GhostSuggestionContext): boolean {
-		if (!context.document || !context.range) return false
-
-		const line = context.document.lineAt(context.range.start.line).text
-		return line.trim() === ""
-	}
-
-	getSystemInstructions(customInstructions?: string): string {
-		return (
-			getBaseSystemInstructions() +
-			`Task: Proactive Code Completion for New Lines
-The user has created a new line. Suggest the most logical next code based on context.
-
-Completion Guidelines:
-- Analyze surrounding code structure
-- Consider common patterns for the current context
-- Be proactive but not overly creative
-- Suggest complete, syntactically correct statements
-- Keep suggestions concise (1-3 lines typically)
-- Match the existing code style and indentation
-
-Common Patterns to Consider:
-- After if/else: complete the block or add else clause
-- After function signature: add opening brace or return statement
-- After loop declaration: add loop body
-- Inside function near end: add return statement
-- After variable declaration: initialize or use the variable
-- After opening brace: add appropriate content for that block
-- Before closing brace: complete any missing statements
-- After comment: implement what the comment describes and preserve the comment
-
-Context Clues:
-- Check if previous line is incomplete (missing semicolon, etc.)
-- Look for patterns in surrounding code
-- Consider the current scope (function, class, module)
-- Check indentation level for context
-- Look at recent edits for user intent
-
-Important:
-- Don't add unnecessary code
-- Respect existing code patterns and comments
-- Maintain consistent style
-- Consider the most likely next step`
-		)
-	}
-
-	/**
-	 * Build prompt focused on surrounding context
-	 */
-	getUserPrompt(context: GhostSuggestionContext): string {
-		let prompt = ""
-
-		// Start with cursor context
-		if (context.range) {
-			const lineNum = context.range.start.line + 1
-			prompt += `## Cursor Context\n`
-			prompt += `Line ${lineNum} (empty line)\n\n`
-		}
-
-		// Add recent operations if available
-		if (context.recentOperations && context.recentOperations.length > 0) {
-			prompt += this.formatRecentOperations(context.recentOperations)
-			prompt += "\n"
-		}
-
-		// Add the full document with cursor marker
-		if (context.document) {
-			prompt += "## Full Code\n"
-			prompt += formatDocumentWithCursor(context.document, context.range)
-			prompt += "\n\n"
-		}
-
-		// Add context analysis
-		if (context.document && context.range) {
-			const surrounding = this.getSurroundingCode(
-				context.document,
-				context.range,
-				15, // More lines before
-				10, // Fewer lines after
-			)
-			prompt += this.analyzeContext(surrounding, context)
-		}
-
-		// Add specific instructions
-		prompt += "## Instructions\n"
-		prompt += `Suggest the most logical code for the cursor position (${CURSOR_MARKER}).\n`
-		prompt += "Consider the pattern being established and complete it naturally.\n"
-		prompt += "Keep suggestions concise and immediately useful.\n"
-
-		// Add context-specific hints
-		if (context.document && context.range) {
-			const hints = this.getContextualHints(context.document, context.range)
-			if (hints) {
-				prompt += "\n" + hints
-			}
-		}
-
-		return prompt
-	}
-
-	/**
-	 * Analyze surrounding code to provide context
-	 */
-	private analyzeContext(
-		surrounding: { before: string; after: string; currentLine: string },
-		context: Partial<GhostSuggestionContext>,
-	): string {
-		let analysis = "## Context Analysis\n"
-
-		// Check what's immediately before
-		const linesBefore = surrounding.before.trim().split("\n")
-		const lastLine = linesBefore[linesBefore.length - 1] || ""
-
-		if (lastLine) {
-			// Check for incomplete statements
-			if (this.isIncompleteStatement(lastLine)) {
-				analysis += "- Previous line appears incomplete\n"
-			}
-
-			// Check for specific patterns
-			if (lastLine.includes("if") || lastLine.includes("else")) {
-				analysis += "- Inside conditional block\n"
-			}
-			if (lastLine.includes("for") || lastLine.includes("while")) {
-				analysis += "- Inside loop\n"
-			}
-			if (lastLine.includes("function") || lastLine.includes("=>")) {
-				analysis += "- Inside or after function declaration\n"
-			}
-			if (lastLine.includes("class")) {
-				analysis += "- Inside class definition\n"
-			}
-			if (lastLine.includes("//") || lastLine.includes("/*")) {
-				analysis += "- After comment - consider implementing described functionality\n"
-			}
-		}
-
-		// Check what's immediately after
-		const linesAfter = surrounding.after.trim().split("\n")
-		const nextLine = linesAfter[0] || ""
-
-		if (nextLine) {
-			if (nextLine.includes("}")) {
-				analysis += "- Before closing brace - might need completion\n"
-			}
-			if (nextLine.includes("return")) {
-				analysis += "- Before return statement\n"
-			}
-		}
-
-		// Check indentation level
-		if (context.range && context.document) {
-			const currentIndent = this.getIndentationLevel(context.document, context.range.start.line)
-			analysis += `- Indentation level: ${currentIndent}\n`
-		}
-
-		analysis += "\n"
-		return analysis
-	}
-
-	/**
-	 * Get contextual hints based on surrounding code
-	 */
-	private getContextualHints(document: TextDocument, range: Range): string {
-		const lineNum = range.start.line
-		let hints = "### Hints:\n"
-
-		// Check previous line
-		if (lineNum > 0) {
-			const prevLine = document.lineAt(lineNum - 1).text
-
-			if (prevLine.includes("{") && !prevLine.includes("}")) {
-				hints += "- Opening brace detected - add content for the block\n"
-			}
-			if (prevLine.match(/^\s*(if|else if|while|for|switch|try|catch)/)) {
-				hints += "- Control structure detected - complete the block\n"
-			}
-			if (prevLine.match(/^\s*(function|const.*=.*function|.*=>\s*$)/)) {
-				hints += "- Function declaration detected - add function body\n"
-			}
-			if (prevLine.match(/^\s*\/\//)) {
-				hints += "- Comment detected - consider implementing described code\n"
-			}
-			if (prevLine.match(/^\s*(const|let|var)\s+\w+\s*$/)) {
-				hints += "- Variable declaration without value - add initialization\n"
-			}
-		}
-
-		// Check next line
-		if (lineNum < document.lineCount - 1) {
-			const nextLine = document.lineAt(lineNum + 1).text
-
-			if (nextLine.includes("}")) {
-				hints += "- Closing brace ahead - complete the block\n"
-			}
-			if (nextLine.match(/^\s*return/)) {
-				hints += "- Return statement ahead - add logic before return\n"
-			}
-		}
-
-		// Check if we're at the end of a function
-		if (this.isNearFunctionEnd(document, lineNum)) {
-			hints += "- Near function end - consider adding return statement\n"
-		}
-
-		return hints
-	}
-
-	/**
-	 * Get the indentation level of a line
-	 */
-	private getIndentationLevel(document: TextDocument, lineNum: number): number {
-		if (lineNum >= document.lineCount) return 0
-
-		const line = document.lineAt(lineNum).text
-		const match = line.match(/^(\s*)/)
-		return match ? match[1].length : 0
-	}
-
-	/**
-	 * Check if we're near the end of a function
-	 */
-	private isNearFunctionEnd(document: TextDocument, lineNum: number): boolean {
-		// Simple heuristic: check if there's a closing brace within 3 lines
-		for (let i = lineNum + 1; i < Math.min(lineNum + 4, document.lineCount); i++) {
-			const line = document.lineAt(i).text
-			if (line.includes("}")) {
-				// Check if this might be a function closing brace
-				// by looking for function-related keywords before
-				for (let j = Math.max(0, lineNum - 10); j < lineNum; j++) {
-					const prevLine = document.lineAt(j).text
-					if (prevLine.match(/function|=>|\{/)) {
-						return true
-					}
-				}
-			}
-		}
-		return false
-	}
-
-	/**
-	 * Formats recent operations for inclusion in prompts
-	 */
-	private formatRecentOperations(operations: any[]): string {
-		if (!operations || operations.length === 0) return ""
-
-		let result = "## Recent Actions\n"
-		operations.slice(0, 5).forEach((op, index) => {
-			result += `${index + 1}. ${op.description}\n`
-			if (op.content) {
-				result += `   \`\`\`\n   ${op.content}\n   \`\`\`\n`
-			}
-		})
-
-		return result
-	}
-
-	/**
-	 * Helper to check if a line appears to be incomplete
-	 */
-	private isIncompleteStatement(line: string): boolean {
-		const trimmed = line.trim()
-
-		// Check for common incomplete patterns
-		const incompletePatterns = [
-			/^(if|else if|while|for|switch|try|catch)\s*\(.*\)\s*$/, // Control structures without body
-			/^(function|class|interface|type|enum)\s+\w+.*[^{]$/, // Declarations without body
-			/[,\+\-\*\/\=\|\&]\s*$/, // Operators at end
-			/^(const|let|var)\s+\w+\s*=\s*$/, // Variable declaration without value
-			/\.\s*$/, // Property access incomplete
-			/\(\s*$/, // Opening parenthesis
-			/^\s*\.\w*$/, // Method chaining incomplete
-		]
-
-		return incompletePatterns.some((pattern) => pattern.test(trimmed))
-	}
-
-	/**
-	 * Gets surrounding code context (lines before and after cursor)
-	 */
-	private getSurroundingCode(
-		document: TextDocument,
-		range: Range,
-		linesBefore: number = 10,
-		linesAfter: number = 10,
-	): { before: string; after: string; currentLine: string } {
-		const currentLineNum = range.start.line
-		const startLine = Math.max(0, currentLineNum - linesBefore)
-		const endLine = Math.min(document.lineCount - 1, currentLineNum + linesAfter)
-
-		let before = ""
-		let after = ""
-		const currentLine = document.lineAt(currentLineNum).text
-
-		// Get lines before cursor
-		for (let i = startLine; i < currentLineNum; i++) {
-			before += document.lineAt(i).text + "\n"
-		}
-
-		// Get lines after cursor
-		for (let i = currentLineNum + 1; i <= endLine; i++) {
-			after += document.lineAt(i).text + "\n"
-		}
-
-		return { before, after, currentLine }
-	}
-}

+ 0 - 149
src/services/ghost/strategies/SelectionRefactorStrategy.ts

@@ -1,149 +0,0 @@
-import { GhostSuggestionContext } from "../types"
-import { PromptStrategy, UseCaseType } from "../types/PromptStrategy"
-import { CURSOR_MARKER } from "../ghostConstants"
-import { formatDiagnostics, formatDocumentWithCursor, getBaseSystemInstructions } from "./StrategyHelpers"
-
-export class SelectionRefactorStrategy implements PromptStrategy {
-	name = "Selection Refactor"
-	type = UseCaseType.SELECTION_REFACTOR
-
-	canHandle(context: GhostSuggestionContext): boolean {
-		// Handle when there's a selection but no explicit user input
-		// (User input with selection is handled by UserRequestStrategy)
-		return !!(context.range && !context.range.isEmpty && !context.userInput)
-	}
-
-	getSystemInstructions(customInstructions?: string): string {
-		return (
-			getBaseSystemInstructions() +
-			`You are an expert code refactoring assistant. Your task is to improve selected code while maintaining its functionality.
-
-## Core Responsibilities:
-1. Analyze the selected code for improvement opportunities
-2. Apply best practices and design patterns
-3. Improve readability and maintainability
-4. Optimize performance where applicable
-5. Ensure backward compatibility
-
-## Refactoring Guidelines:
-- Extract complex logic into well-named functions
-- Reduce code duplication
-- Improve variable and function names
-- Simplify conditional logic
-- Apply SOLID principles where appropriate
-- Add or improve type annotations (for typed languages)
-- Consider edge cases and error handling
-
-## Output Requirements:
-- Provide ONLY the refactored code
-- Maintain the same functionality
-- Preserve the original indentation level
-- Include brief inline comments for significant changes
-- Do not include explanations outside the code
-
-Remember: The goal is to improve the code quality while keeping the exact same behavior.`
-		)
-	}
-
-	getUserPrompt(context: GhostSuggestionContext): string {
-		if (!context.document || !context.range) {
-			return "No selection available for refactoring."
-		}
-
-		const selectedCode = context.document.getText(context.range)
-		const language = context.document.languageId
-
-		// Analyze what kind of refactoring might be needed
-		const refactoringSuggestions = this.analyzeRefactoringNeeds(selectedCode)
-
-		let prompt = `## Selection Refactoring Context\n`
-		prompt += `- Language: ${language}\n`
-		prompt += `- Selected Code Lines: ${context.range.start.line + 1}-${context.range.end.line + 1}\n`
-		prompt += `- Refactoring Suggestions: ${refactoringSuggestions.slice(0, 3).join(", ")}\n\n`
-
-		if (context.diagnostics && context.diagnostics.length > 0) {
-			prompt += formatDiagnostics(context.diagnostics)
-			prompt += "\n"
-		}
-
-		// Add the full document with cursor marker
-		if (context.document) {
-			prompt += "## Full Code\n"
-			prompt += formatDocumentWithCursor(context.document, context.range)
-			prompt += "\n\n"
-		}
-
-		prompt += `## Instructions\n`
-		prompt += `Refactor the selected code at the cursor position (${CURSOR_MARKER}) to improve its quality, readability, and maintainability.\n`
-		prompt += `Focus on: ${refactoringSuggestions.slice(0, 3).join(", ")}\n`
-		prompt += `Maintain the same functionality while improving the code structure.\n`
-
-		return prompt
-	}
-
-	/**
-	 * Analyzes code to suggest refactoring opportunities
-	 */
-	private analyzeRefactoringNeeds(code: string): string[] {
-		const suggestions: string[] = []
-
-		// Check for long functions
-		const lines = code.split("\n")
-		if (lines.length > 20) {
-			suggestions.push("Consider extracting smaller functions")
-		}
-
-		// Check for deeply nested code
-		const maxIndent = Math.max(...lines.map((line) => line.match(/^[\t ]*/)?.[0].length || 0))
-		if (maxIndent > 12) {
-			suggestions.push("Reduce nesting levels")
-		}
-
-		// Check for magic numbers
-		if (/\b\d{2,}\b/.test(code) && !/["'].*\d{2,}.*["']/.test(code)) {
-			suggestions.push("Extract magic numbers to named constants")
-		}
-
-		// Check for long lines
-		if (lines.some((line) => line.length > 100)) {
-			suggestions.push("Break long lines for better readability")
-		}
-
-		// Check for multiple responsibilities
-		const functionMatches = code.match(/function\s+\w+|const\s+\w+\s*=\s*(?:async\s*)?\(/g)
-		if (functionMatches && functionMatches.length > 3) {
-			suggestions.push("Consider single responsibility principle")
-		}
-
-		// Check for complex conditionals
-		if (/if\s*\([^)]{50,}\)/.test(code) || /&&.*&&.*&&/.test(code) || /\|\|.*\|\|.*\|\|/.test(code)) {
-			suggestions.push("Simplify complex conditional expressions")
-		}
-
-		// Check for duplicate code patterns
-		const codePatterns = code.match(/\b\w+\s*\([^)]*\)/g) || []
-		const seen = new Set<string>()
-		const hasDuplicates = codePatterns.some((pattern) => {
-			if (seen.has(pattern)) {
-				return true
-			}
-			seen.add(pattern)
-			return false
-		})
-		if (hasDuplicates) {
-			suggestions.push("Remove code duplication")
-		}
-
-		// Check for poor naming
-		if (/\b[a-z]\b(?!\.)/.test(code)) {
-			suggestions.push("Improve variable naming")
-		}
-
-		// Default suggestion if no specific issues found
-		if (suggestions.length === 0) {
-			suggestions.push("Apply general best practices")
-		}
-
-		return suggestions
-	}
-}