From 5f566869dc6403988457bffd70518cb747980a7f Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:43:14 +0000 Subject: [PATCH 1/5] chore(vscode): remove unused autocomplete docs and locales --- .../autocomplete/continuedev/API_REFERENCE.md | 807 ------------------ .../autocomplete/docs/TRANSPLANT-PLAN.md | 761 ----------------- .../docs/investigation-external-imports.md | 409 --------- .../investigation-internal-architecture.md | 456 ---------- .../docs/investigation-vscode-integration.md | 412 --------- .../src/services/autocomplete/i18n/ar.ts | 49 -- .../src/services/autocomplete/i18n/ca.ts | 49 -- .../src/services/autocomplete/i18n/cs.ts | 49 -- .../src/services/autocomplete/i18n/de.ts | 50 -- .../src/services/autocomplete/i18n/es.ts | 49 -- .../src/services/autocomplete/i18n/fr.ts | 49 -- .../src/services/autocomplete/i18n/hi.ts | 50 -- .../src/services/autocomplete/i18n/id.ts | 50 -- .../src/services/autocomplete/i18n/it.ts | 49 -- .../src/services/autocomplete/i18n/ja.ts | 49 -- .../src/services/autocomplete/i18n/ko.ts | 48 -- .../src/services/autocomplete/i18n/nl.ts | 50 -- .../autocomplete/i18n/package-nls-ar.ts | 13 - .../autocomplete/i18n/package-nls-ca.ts | 13 - .../autocomplete/i18n/package-nls-cs.ts | 13 - .../autocomplete/i18n/package-nls-de.ts | 13 - .../autocomplete/i18n/package-nls-en.ts | 14 - .../autocomplete/i18n/package-nls-es.ts | 13 - .../autocomplete/i18n/package-nls-fr.ts | 13 - .../autocomplete/i18n/package-nls-hi.ts | 13 - .../autocomplete/i18n/package-nls-id.ts | 13 - .../autocomplete/i18n/package-nls-it.ts | 13 - .../autocomplete/i18n/package-nls-ja.ts | 13 - .../autocomplete/i18n/package-nls-ko.ts | 13 - .../autocomplete/i18n/package-nls-nl.ts | 13 - .../autocomplete/i18n/package-nls-pl.ts | 13 - .../autocomplete/i18n/package-nls-pt-BR.ts | 13 - .../autocomplete/i18n/package-nls-ru.ts | 13 - .../autocomplete/i18n/package-nls-sk.ts | 13 - .../autocomplete/i18n/package-nls-th.ts | 13 - .../autocomplete/i18n/package-nls-tr.ts | 13 - .../autocomplete/i18n/package-nls-uk.ts | 13 - .../autocomplete/i18n/package-nls-vi.ts | 13 - .../autocomplete/i18n/package-nls-zh-CN.ts | 13 - .../autocomplete/i18n/package-nls-zh-TW.ts | 13 - .../src/services/autocomplete/i18n/pl.ts | 49 -- .../src/services/autocomplete/i18n/pt-BR.ts | 48 -- .../src/services/autocomplete/i18n/ru.ts | 50 -- .../src/services/autocomplete/i18n/sk.ts | 49 -- .../src/services/autocomplete/i18n/th.ts | 49 -- .../src/services/autocomplete/i18n/tr.ts | 50 -- .../src/services/autocomplete/i18n/uk.ts | 49 -- .../src/services/autocomplete/i18n/vi.ts | 50 -- .../src/services/autocomplete/i18n/zh-CN.ts | 47 - .../src/services/autocomplete/i18n/zh-TW.ts | 47 - 50 files changed, 4224 deletions(-) delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/API_REFERENCE.md delete mode 100644 packages/kilo-vscode/src/services/autocomplete/docs/TRANSPLANT-PLAN.md delete mode 100644 packages/kilo-vscode/src/services/autocomplete/docs/investigation-external-imports.md delete mode 100644 packages/kilo-vscode/src/services/autocomplete/docs/investigation-internal-architecture.md delete mode 100644 packages/kilo-vscode/src/services/autocomplete/docs/investigation-vscode-integration.md delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/ar.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/ca.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/cs.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/de.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/es.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/fr.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/hi.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/id.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/it.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/ja.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/ko.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/nl.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ar.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ca.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-cs.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-de.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-en.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-es.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-fr.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-hi.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-id.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-it.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ja.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ko.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-nl.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pl.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pt-BR.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ru.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-sk.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-th.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-tr.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-uk.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-vi.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-CN.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-TW.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/pl.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/pt-BR.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/ru.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/sk.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/th.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/tr.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/uk.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/vi.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/zh-CN.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/i18n/zh-TW.ts diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/API_REFERENCE.md b/packages/kilo-vscode/src/services/autocomplete/continuedev/API_REFERENCE.md deleted file mode 100644 index 216538b0c7f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/API_REFERENCE.md +++ /dev/null @@ -1,807 +0,0 @@ -# API Reference - -Complete API documentation for the Autocomplete & NextEdit library. - -## Table of Contents - -- [CompletionProvider](#completionprovider) -- [NextEditProvider](#nexteditprovider) -- [MinimalConfigProvider](#minimalconfigprovider) -- [Core Interfaces](#core-interfaces) -- [LLM Adapters](#llm-adapters) -- [Types and Interfaces](#types-and-interfaces) - ---- - -## CompletionProvider - -The main class for providing AI-powered code autocompletion. - -**Location**: [`core/autocomplete/CompletionProvider.ts`](core/autocomplete/CompletionProvider.ts) - -### Constructor - -```typescript -constructor( - configHandler: MinimalConfigProvider, - ide: IDE, - _injectedGetLlm: () => Promise, - _onError: (e: any) => void, - getDefinitionsFromLsp: GetLspDefinitionsFunction -) -``` - -**Parameters**: - -- `configHandler`: Configuration provider for autocomplete options -- `ide`: IDE interface implementation for file I/O and editor operations -- `_injectedGetLlm`: Async function that returns the LLM to use for completions -- `_onError`: Error callback function for handling autocomplete errors -- `getDefinitionsFromLsp`: Function to retrieve LSP definitions for enhanced context - -### Methods - -#### `provideInlineCompletionItems()` - -Generates an autocomplete completion for the given input. - -```typescript -async provideInlineCompletionItems( - input: AutocompleteInput, - token: AbortSignal | undefined, - force?: boolean -): Promise -``` - -**Parameters**: - -- `input`: Autocomplete context including file path, cursor position, recent edits -- `token`: AbortSignal to cancel the request -- `force`: If true, bypasses debouncing - -**Returns**: `AutocompleteOutcome` containing the completion text and metadata, or `undefined` if no completion - -**Example**: - -```typescript -const outcome = await completionProvider.provideInlineCompletionItems( - { - filepath: "/path/to/file.ts", - pos: { line: 10, character: 5 }, - completionId: "unique-completion-id", - recentlyEditedRanges: [], - recentlyEditedFiles: new Map(), - clipboardText: "", - }, - abortController.signal, -) -``` - -#### `accept()` - -Marks a completion as accepted by the user. - -```typescript -accept(completionId: string): void -``` - -**Parameters**: - -- `completionId`: Unique identifier for the accepted completion - -**Side Effects**: Updates bracket matching service and completion cache - -#### `markDisplayed()` - -Marks a completion as having been displayed to the user. - -```typescript -markDisplayed(completionId: string, outcome: AutocompleteOutcome): void -``` - -**Parameters**: - -- `completionId`: Unique identifier for the completion -- `outcome`: The autocomplete outcome that was displayed - -#### `cancel()` - -Cancels any in-progress autocomplete requests. - -```typescript -cancel(): void -``` - -### Configuration Options - -See [`MinimalConfigProvider`](#minimalconfigprovider) for configuration options. - ---- - -## NextEditProvider - -The main class for providing predictive multi-location code edits. - -**Location**: [`core/nextEdit/NextEditProvider.ts`](core/nextEdit/NextEditProvider.ts) - -### Constructor - -```typescript -constructor( - configHandler: MinimalConfigProvider, - ide: IDE, - _injectedGetLlm: () => Promise, - _onError: (e: any) => void -) -``` - -**Parameters**: - -- `configHandler`: Configuration provider -- `ide`: IDE interface implementation -- `_injectedGetLlm`: Function returning the LLM for edit predictions -- `_onError`: Error callback - -### Methods - -#### `getNextEditPrediction()` - -Generates predicted edits based on context and recent changes. - -```typescript -async getNextEditPrediction( - context: ModelSpecificContext, - signal?: AbortSignal, - usingFullFileDiff?: boolean -): Promise -``` - -**Parameters**: - -- `context`: Context including file contents, cursor position, recent edits -- `signal`: Optional AbortSignal to cancel the request -- `usingFullFileDiff`: If true, generates full-file diffs; if false, only edits within a region - -**Returns**: `NextEditOutcome` containing predicted edits and final cursor position - -**Example**: - -```typescript -const outcome = await nextEditProvider.getNextEditPrediction( - { - filepath: "/path/to/file.ts", - pos: { line: 15, character: 0 }, - fileContents: currentFileContents, - userEdits: recentDiff, - // ... other context - }, - abortController.signal, - false, // Use partial file diff -) - -if (outcome) { - console.log("Edit regions:", outcome.editableRegions) - console.log("Diff lines:", outcome.diffLines) - console.log("New cursor:", outcome.finalCursorPosition) -} -``` - ---- - -## MinimalConfigProvider - -Simple configuration provider that replaces the complex Continue config system. - -**Location**: [`core/autocomplete/MinimalConfig.ts`](core/autocomplete/MinimalConfig.ts) - -### Constructor - -```typescript -constructor(config?: Partial) -``` - -**Parameters**: - -- `config`: Optional partial configuration to override defaults - -**Example**: - -```typescript -const configProvider = new MinimalConfigProvider({ - tabAutocompleteOptions: { - debounceDelay: 200, - maxPromptTokens: 2048, - prefixPercentage: 0.5, - suffixPercentage: 0.3, - useCache: true, - onlyMyCode: false, - }, - experimental: { - enableStaticContextualization: true, - }, -}) -``` - -### Methods - -#### `loadConfig()` - -Returns the configuration object. - -```typescript -async loadConfig(): Promise<{ config: MinimalConfig }> -``` - -**Returns**: Promise resolving to an object containing the config - -#### `getAutocompleteOptions()` - -Gets autocomplete-specific options. - -```typescript -getAutocompleteOptions(): TabAutocompleteOptions -``` - -**Returns**: Autocomplete configuration options - -#### `isStaticContextualizationEnabled()` - -Checks if static contextualization is enabled. - -```typescript -isStaticContextualizationEnabled(): boolean -``` - -**Returns**: True if enabled, false otherwise - -### Configuration Interface - -```typescript -interface MinimalConfig { - tabAutocompleteOptions?: TabAutocompleteOptions - experimental?: { - enableStaticContextualization?: boolean - } - modelsByRole?: { - autocomplete?: ILLM[] - } - selectedModelByRole?: { - autocomplete?: ILLM - } -} -``` - -### TabAutocompleteOptions - -```typescript -interface TabAutocompleteOptions { - debounceDelay?: number // Debounce delay in ms (default: 150) - maxPromptTokens?: number // Max tokens for prompt (default: 1024) - prefixPercentage?: number // Percentage of tokens for prefix (default: 0.5) - suffixPercentage?: number // Percentage of tokens for suffix (default: 0.3) - maxSuffixPercentage?: number // Max suffix tokens percentage (default: 0.5) - useCache?: boolean // Enable completion caching (default: true) - onlyMyCode?: boolean // Only use workspace files for context (default: false) - template?: string // Custom prompt template - useFileSuffix?: boolean // Include file suffix in context (default: true) - multilineCompletions?: "always" | "never" | "auto" // Multiline behavior (default: 'auto') - slidingWindowPrefixPercentage?: number // Sliding window prefix % (default: 0.75) - slidingWindowSize?: number // Sliding window size (default: 500) - maxSnippetPercentage?: number // Max tokens for snippets (default: 0.6) - recentlyEditedSimilarityThreshold?: number // Similarity threshold (default: 0.3) - useOtherFiles?: boolean // Use other files for context (default: true) - disableInFiles?: string[] // Glob patterns to disable autocomplete - stopTokens?: string[] // Custom stop tokens - tokensPerCompletion?: number // Tokens per completion (default: 256) - transform?: boolean // Apply post-processing transforms (default: true) -} -``` - ---- - -## Core Interfaces - -### IDE Interface - -The IDE interface abstracts editor operations. Implement this to integrate with your editor. - -**Location**: [`core/index.d.ts`](core/index.d.ts) - -```typescript -interface IDE { - // File Operations - readFile(filepath: string): Promise - writeFile(filepath: string, contents: string): Promise - - // Workspace - getWorkspaceDirs(): Promise - listWorkspaceContents(directory?: string): Promise - - // Editor State - getCurrentFile(): Promise - getCursorPosition(): Promise - getVisibleFiles(): Promise - - // Code Navigation - getDefinition(filepath: string, position: Position): Promise - getReferences(filepath: string, position: Position): Promise - getSymbols(filepath: string): Promise - - // File Information - readRangeInFile(filepath: string, range: Range): Promise - getStats(filepath: string): Promise - - // Edits - applyEdits(edits: FileEdit[]): Promise - - // Diff/SCM - getDiff(includeUnstaged: boolean): Promise - getRepoName(dir: string): Promise - getBranch(dir: string): Promise - - // UI - showMessage(message: string, severity?: "info" | "warning" | "error"): Promise - showToast(type: "info" | "warning" | "error", message: string, ...actions: string[]): Promise - - // Terminal - runCommand(command: string, options?: TerminalOptions): Promise - - // Clipboard - getClipboardContent(): Promise<{ text: string; copiedAt: number } | undefined> - - // Search - getSearchResults(query: string): Promise - subprocess(command: string, cwd?: string): Promise<[string, string]> - - // Other - getIdeInfo(): Promise - getIdeSettings(): Promise - isTelemetryEnabled(): Promise - getUniqueId(): Promise -} -``` - -**Key Methods to Implement**: - -- `readFile()`, `writeFile()`: Essential for file I/O -- `getWorkspaceDirs()`: Returns workspace root directories -- `getCurrentFile()`, `getCursorPosition()`: Current editor state -- `applyEdits()`: Apply code changes -- `getDefinition()`: LSP-like functionality for context gathering - -### ILLM Interface - -The ILLM (Language Model) interface abstracts LLM providers. - -**Location**: [`core/index.d.ts`](core/index.d.ts) - -```typescript -interface ILLM { - // Required properties - uniqueId: string - model: string - contextLength: number - completionOptions: CompletionOptions - - // Provider info - get providerName(): string - get underlyingProviderName(): string - - // Optional - apiKey?: string - apiBase?: string - autocompleteOptions?: Partial - promptTemplates?: PromptTemplates - - // Completion methods - complete(prompt: string, signal: AbortSignal, options?: LLMFullCompletionOptions): Promise - - streamComplete( - prompt: string, - signal: AbortSignal, - options?: LLMFullCompletionOptions, - ): AsyncGenerator - - streamFim( - prefix: string, - suffix: string, - signal: AbortSignal, - options?: LLMFullCompletionOptions, - ): AsyncGenerator - - // Chat methods - chat(messages: ChatMessage[], signal: AbortSignal, options?: LLMFullCompletionOptions): Promise - - streamChat( - messages: ChatMessage[], - signal: AbortSignal, - options?: LLMFullCompletionOptions, - ): AsyncGenerator - - // Utility methods - countTokens(text: string): number - supportsImages(): boolean - supportsCompletions(): boolean - supportsFim(): boolean - listModels(): Promise -} -``` - ---- - -## LLM Adapters - -### OpenAI - -Pre-built adapter for OpenAI and OpenAI-compatible APIs. - -**Location**: [`core/llm/llms/OpenAI.ts`](core/llm/llms/OpenAI.ts) - -```typescript -import OpenAI from "@continuedev/core/llm/llms/OpenAI" - -const llm = new OpenAI({ - model: "gpt-4", - apiKey: process.env.OPENAI_API_KEY, - apiBase: "https://api.openai.com/v1", // Optional custom base URL - completionOptions: { - temperature: 0.1, - maxTokens: 1000, - }, -}) -``` - -**Constructor Options**: - -```typescript -interface OpenAIOptions { - model: string - apiKey: string - apiBase?: string - completionOptions?: CompletionOptions - contextLength?: number - autocompleteOptions?: Partial -} -``` - -### Creating Custom LLM Adapters - -To create a custom LLM adapter, implement the `ILLM` interface: - -```typescript -import { ILLM, CompletionOptions } from "@continuedev/core" - -class CustomLLM implements ILLM { - uniqueId = "custom-llm" - model: string - contextLength: number - completionOptions: CompletionOptions - - get providerName() { - return "custom" - } - get underlyingProviderName() { - return "custom" - } - - constructor(options: { model: string }) { - this.model = options.model - this.contextLength = 4096 - this.completionOptions = { - model: options.model, - temperature: 0.1, - } - } - - async complete(prompt: string, signal: AbortSignal): Promise { - // Call your LLM API - const response = await fetch("your-api-endpoint", { - method: "POST", - body: JSON.stringify({ prompt }), - signal, - }) - return await response.text() - } - - async *streamComplete(prompt: string, signal: AbortSignal) { - // Stream from your LLM API - for await (const chunk of streamFromAPI(prompt, signal)) { - yield chunk - } - return { modelTitle: this.model, prompt, completion: "" } - } - - // Implement other required methods... - countTokens(text: string): number { - return text.length / 4 // Rough estimate - } - - supportsImages() { - return false - } - supportsCompletions() { - return true - } - supportsFim() { - return false - } - - // ... other methods -} -``` - ---- - -## Types and Interfaces - -### AutocompleteInput - -Input for autocomplete requests. - -```typescript -interface AutocompleteInput { - filepath: string // Path to the file being edited - pos: Position // Cursor position - completionId: string // Unique ID for this completion request - recentlyEditedRanges: Range[] // Recently edited ranges in this file - recentlyEditedFiles: Map // Recently edited files - clipboardText: string // Current clipboard content - manuallyPassFileContext?: RangeInFile[] // Manually provided context -} -``` - -### AutocompleteOutcome - -Result of an autocomplete request. - -```typescript -interface AutocompleteOutcome { - completion: string // The completion text - completionId: string // Unique ID for this completion - filepath: string // File path - prefix: string // Code prefix (before cursor) - suffix: string // Code suffix (after cursor) - prompt: string // Full prompt sent to LLM - modelTitle: string // Model used - modelProvider: string // Provider used - completionOptions: CompletionOptions // Options used - cacheHit: boolean // Whether cached - latency: number // Response latency in ms -} -``` - -### NextEditOutcome - -Result of a NextEdit prediction. - -```typescript -interface NextEditOutcome { - edits: string // The predicted edit text - diffLines: DiffLine[] // Diff representation - editableRegions: Range[] // Regions that were edited - finalCursorPosition: Position // Predicted cursor position after edits - filepath: string // File path - prompt: string // Prompt sent to LLM - modelTitle: string // Model used - latency: number // Response latency in ms -} -``` - -### Position - -Position in a text document. - -```typescript -interface Position { - line: number // 0-based line number - character: number // 0-based character offset -} -``` - -### Range - -Range in a text document. - -```typescript -interface Range { - start: Position // Start position (inclusive) - end: Position // End position (exclusive) -} -``` - -### RangeInFile - -Range in a specific file. - -```typescript -interface RangeInFile { - filepath: string // File path - range: Range // Range within the file -} -``` - -### DiffLine - -A single line in a diff. - -```typescript -interface DiffLine { - type: "same" | "new" | "old" // Type of change - line: string // Line content - lineNumber: number // Line number in file -} -``` - -### FileEdit - -An edit to apply to a file. - -```typescript -interface FileEdit { - filepath: string // File to edit - range: Range // Range to replace - replacement: string // New content -} -``` - ---- - -## Usage Examples - -### Complete Example: Autocomplete with Custom IDE - -```typescript -import { CompletionProvider, MinimalConfigProvider } from "@continuedev/core/autocomplete" -import { IDE, ILLM, Position } from "@continuedev/core" -import OpenAI from "@continuedev/core/llm/llms/OpenAI" - -// 1. Implement IDE interface -class MyIDE implements IDE { - async readFile(filepath: string): Promise { - return fs.readFileSync(filepath, "utf-8") - } - - async getWorkspaceDirs(): Promise { - return ["/path/to/workspace"] - } - - async getCurrentFile() { - return { - filepath: this.currentFilePath, - contents: await this.readFile(this.currentFilePath), - } - } - - async getCursorPosition(): Promise { - return this.cursorPosition - } - - // ... implement other methods -} - -// 2. Set up configuration -const config = new MinimalConfigProvider({ - tabAutocompleteOptions: { - debounceDelay: 150, - maxPromptTokens: 1024, - useCache: true, - }, -}) - -// 3. Set up LLM -const getLlm = async (): Promise => { - return new OpenAI({ - apiKey: process.env.OPENAI_API_KEY, - model: "gpt-4", - }) -} - -// 4. Create completion provider -const ide = new MyIDE() -const provider = new CompletionProvider( - config, - ide, - getLlm, - (error) => console.error(error), - async () => [], // LSP definitions function -) - -// 5. Request completion -const outcome = await provider.provideInlineCompletionItems( - { - filepath: "/path/to/file.ts", - pos: { line: 10, character: 5 }, - completionId: "completion-1", - recentlyEditedRanges: [], - recentlyEditedFiles: new Map(), - clipboardText: "", - }, - new AbortController().signal, -) - -if (outcome) { - console.log("Completion:", outcome.completion) - provider.markDisplayed("completion-1", outcome) -} -``` - ---- - -## Error Handling - -Both `CompletionProvider` and `NextEditProvider` accept an error callback: - -```typescript -const onError = (error: any) => { - if (error instanceof Error) { - console.error("Error:", error.message) - // Show user notification - showNotification(error.message) - } -} - -const provider = new CompletionProvider( - config, - ide, - getLlm, - onError, // Error callback - getLspDefinitions, -) -``` - -Common errors: - -- **LLM API errors**: Network failures, invalid API keys, rate limits -- **File I/O errors**: Missing files, permission errors -- **Timeout errors**: Long-running requests that are aborted - ---- - -## Performance Considerations - -### Caching - -Completions are automatically cached using an LRU cache. Configure caching: - -```typescript -const config = new MinimalConfigProvider({ - tabAutocompleteOptions: { - useCache: true, // Enable caching (default) - }, -}) -``` - -### Debouncing - -Prevent excessive LLM calls during rapid typing: - -```typescript -const config = new MinimalConfigProvider({ - tabAutocompleteOptions: { - debounceDelay: 150, // Wait 150ms before requesting (default) - }, -}) -``` - -### Abort Signals - -Always provide AbortSignals to cancel in-progress requests: - -```typescript -const controller = new AbortController() - -// Start request -const promise = provider.provideInlineCompletionItems(input, controller.signal) - -// Cancel if needed -controller.abort() -``` - ---- - -## See Also - -- [README.md](README.md) - Project overview and quick start -- [ARCHITECTURE.md](ARCHITECTURE.md) - Technical architecture details -- [EXAMPLES.md](EXAMPLES.md) - More usage examples -- [Core TypeScript Definitions](core/index.d.ts) - Full type definitions diff --git a/packages/kilo-vscode/src/services/autocomplete/docs/TRANSPLANT-PLAN.md b/packages/kilo-vscode/src/services/autocomplete/docs/TRANSPLANT-PLAN.md deleted file mode 100644 index b5d0c291af2..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/docs/TRANSPLANT-PLAN.md +++ /dev/null @@ -1,761 +0,0 @@ -# Transplant Plan: `src/services/autocomplete/` → standalone VS Code extension - -## 1. Executive Summary - -The `src/services/autocomplete/` module provides two autocomplete experiences: - -1. **Inline code completion (ghost text)** via a VS Code [`vscode.InlineCompletionItemProvider`](src/services/autocomplete/docs/investigation-vscode-integration.md:245). -2. **Chat textarea autocomplete** for a webview chat input (optional), driven by webview messages ([`requestChatCompletion`](src/services/autocomplete/docs/investigation-vscode-integration.md:188)). - -To transplant this module into a new VS Code extension, you can copy most of the directory tree as-is, but you must rebuild a small “host shell” around it: - -- A VS Code extension activation/registration layer (commands, providers, status bar, context keys). -- A **settings/state store** that persists the autocomplete settings object. -- An **LLM provider abstraction** that supports streaming **FIM** (fill-in-the-middle) and streaming **chat completions**, plus model metadata and usage/cost reporting. -- A **file ignore / access control abstraction** (to replicate `.kilocodeignore` behavior and prevent sensitive files from being used). -- A **telemetry abstraction** for the events the module emits. -- (Optional) A webview messaging bridge if you want a UI for settings or chat textarea autocomplete. - -This plan defines those interfaces and the minimum VS Code extension scaffolding required, without coupling the new extension to Kilo Code’s current provider implementations. - ---- - -## 2. Interfaces to Implement - -This section defines the abstract interfaces the transplanted module expects. - -> Design principle: the autocomplete module should depend on small, stable interfaces and plain types, not the host extension’s internal classes. - -### 2.1 `IAutocompleteLLMProvider` (LLM Provider Interface) - -**Purpose**: Provide streaming LLM completions for both strategies: - -- **FIM** (prefix + suffix → streamed insertion) -- **Chat completion** (system prompt + user prompt → streamed text and/or structured chunks) - -The module currently routes these via [`AutocompleteModel.generateFimResponse()`](src/services/autocomplete/AutocompleteModel.ts:109) and [`AutocompleteModel.generateResponse()`](src/services/autocomplete/AutocompleteModel.ts:153). - -#### Required API (proposed) - -```ts -export interface AutocompleteUsage { - cost: number - inputTokens: number - outputTokens: number - cacheWriteTokens: number - cacheReadTokens: number -} - -export interface AutocompleteModelInfo { - providerId: string // stable identifier, e.g. openai, anthropic, custom - providerDisplayName?: string // for status bar/UI - modelId: string // stable model identifier - modelDisplayName?: string - supportsFim: boolean -} - -export type ChatStreamChunk = { type: "text"; text: string } | { type: "usage"; usage: AutocompleteUsage } - -export interface IAutocompleteLLMProvider { - /** - * Returns the currently selected model/provider metadata. - * Used for status bar + telemetry context. - */ - getModelInfo(): AutocompleteModelInfo | undefined - - /** - * Whether the selected model supports FIM. - * Used to pick between FIM vs hole-filler strategy. - */ - supportsFim(): boolean - - /** - * Stream a FIM completion. The generator yields raw text chunks. - * Must be abortable. - */ - streamFim(params: { - prefix: string - suffix: string - signal: AbortSignal - requestId?: string - onUsage?: (usage: AutocompleteUsage) => void - }): AsyncGenerator - - /** - * Stream a chat completion. The generator yields text chunks and MAY yield usage. - * Must be abortable. - */ - streamChat(params: { - systemPrompt: string - userPrompt: string - signal: AbortSignal - requestId?: string - }): AsyncGenerator -} -``` - -#### Where it is used - -- Inline completion pipeline triggers either: - - FIM flow via [`AutocompleteModel.generateFimResponse()`](src/services/autocomplete/AutocompleteModel.ts:109), or - - Chat flow via [`AutocompleteModel.generateResponse()`](src/services/autocomplete/AutocompleteModel.ts:153). -- Strategy selection checks [`AutocompleteModel.supportsFim()`](src/services/autocomplete/AutocompleteModel.ts:98). - -#### Notes / constraints - -- **Streaming is mandatory**: the module assumes tokens/chunks arrive incrementally. -- **Abort is mandatory**: VS Code frequently cancels inline completion requests. -- **Usage/cost reporting** is needed for: - - status bar display (session cost), and - - telemetry properties (latency/cost/tokens). - ---- - -### 2.2 `IAutocompleteProfileResolver` (Model selection + credentials) - -**Purpose**: Choose which provider/model to use for autocomplete, and validate credentials. - -In the current code, [`AutocompleteModel.reload()`](src/services/autocomplete/AutocompleteModel.ts:49) scans “profiles” from a settings manager and picks one (including special handling for the `kilocode` provider). - -For a new extension, keep this logic but abstract it. - -#### Required API (proposed) - -```ts -export interface AutocompleteProfile { - id: string - name?: string - type?: "autocomplete" | "general" - providerId: string - modelId: string - // provider-specific credential payload is opaque to autocomplete - credentials: unknown -} - -export interface IAutocompleteProfileResolver { - /** Return all configured profiles the host wants autocomplete to consider. */ - listProfiles(): Promise - - /** Resolve the full profile (including credentials) for a selected profile id. */ - getProfile(id: string): Promise - - /** - * Create an LLM provider instance for the selected profile. - * The autocomplete module treats the provider as opaque beyond the interface. - */ - buildLLMProvider(profile: AutocompleteProfile): Promise -} -``` - -#### Where it is used - -- Provider/model selection and (optional) credential checks happen in [`AutocompleteModel.reload()`](src/services/autocomplete/AutocompleteModel.ts:49). - ---- - -### 2.3 `IAutocompleteSettingsStore` (Settings/State Manager) - -**Purpose**: Persist and retrieve the autocomplete settings object. - -The module currently uses a global state key named `ghostServiceSettings` via `ContextProxy` ([investigation](src/services/autocomplete/docs/investigation-vscode-integration.md:201)). - -#### Settings schema (minimum) - -From [`autocompleteServiceSettingsSchema`](src/services/autocomplete/docs/investigation-vscode-integration.md:216), the settings object is effectively: - -```ts -export interface AutocompleteServiceSettings { - enableAutoTrigger?: boolean - enableSmartInlineTaskKeybinding?: boolean - enableChatAutocomplete?: boolean - provider?: string - model?: string - snoozeUntil?: number - hasKilocodeProfileWithNoBalance?: boolean -} -``` - -The host should own validation (zod or equivalent). The autocomplete module assumes the object exists or is `undefined`. - -#### Required API (proposed) - -```ts -export interface IAutocompleteSettingsStore { - getSettings(): Promise - setSettings(settings: AutocompleteServiceSettings | undefined): Promise - - /** Optional: subscribe for settings changes coming from UI/webview. */ - onDidChangeSettings?(listener: (s: AutocompleteServiceSettings | undefined) => void): { dispose(): void } -} -``` - -#### Where it is used - -- Read settings on startup in [`AutocompleteServiceManager.load()`](src/services/autocomplete/docs/investigation-vscode-integration.md:133). -- Write enriched settings back after load (same section). -- Webview can update settings by message type `ghostServiceSettings` ([`webviewMessageHandler`](src/services/autocomplete/docs/investigation-vscode-integration.md:164)). - ---- - -### 2.4 `IFileIgnoreController` (File Ignore Controller) - -**Purpose**: Decide whether the module may read/use a file path for context. - -In current code this is `RooIgnoreController` (see mock interface in [`RooIgnoreController`](src/core/ignore/__mocks__/RooIgnoreController.ts:3)). It is used for: - -- Filtering/snippet inclusion (only-my-code, ignore patterns) -- Visible editor context filtering - -#### Required API (proposed) - -```ts -export interface IFileIgnoreController { - initialize(): Promise - - /** True if the file can be read/used as context. */ - validateAccess(filePath: string): boolean - - /** Filter a list of candidate paths to those allowed. */ - filterPaths(paths: string[]): string[] - - /** Optional: returns user-facing instructions explaining why access is restricted. */ - getInstructions(): string | undefined - - dispose(): void -} -``` - -#### Where it is used - -- Inline completion gating checks include ignore validation ([architecture summary](src/services/autocomplete/docs/investigation-internal-architecture.md:161)). -- Visible editor context is filtered in [`VisibleCodeTracker`](src/services/autocomplete/docs/investigation-internal-architecture.md:339). - ---- - -### 2.5 `IDE` / `VsCodeIde` (IDE Abstraction) - -**Purpose**: Provide an IDE-agnostic layer used by the embedded Continue.dev fork. - -The continuedev core defines an `IDE` interface in [`continuedev/core/index.d.ts`](src/services/autocomplete/continuedev/core/index.d.ts:376) and ships a VS Code implementation [`VsCodeIde`](src/services/autocomplete/continuedev/core/vscode-test-harness/src/VSCodeIde.ts:1). - -#### Minimum needed methods - -The module’s autocomplete pipeline uses the `IDE` abstraction for: - -- Workspace discovery, reading and writing files -- Open/current file content -- LSP calls (definitions, references, symbols) -- Clipboard access -- Editor-change callback - -The authoritative method list is the `IDE` interface in [`IDE`](src/services/autocomplete/continuedev/core/index.d.ts:376). For transplantation you have two viable options: - -1. **Copy and keep `VsCodeIde`** as-is, and keep the `IDE` interface unchanged. -2. Replace with your own implementation, but it must still satisfy the `IDE` interface contract. - ---- - -### 2.6 `ITelemetryClient` (Telemetry Interface) - -**Purpose**: Record the module’s key product events. - -Current code uses a singleton `TelemetryService` ([`AutocompleteTelemetry`](src/services/autocomplete/classic-auto-complete/AutocompleteTelemetry.ts:57)). To transplant cleanly, replace it with an injected interface. - -#### Events currently captured - -From [`AutocompleteTelemetry`](src/services/autocomplete/classic-auto-complete/AutocompleteTelemetry.ts:105): - -- `AUTOCOMPLETE_SUGGESTION_REQUESTED` -- `AUTOCOMPLETE_SUGGESTION_FILTERED` -- `AUTOCOMPLETE_SUGGESTION_CACHE_HIT` -- `AUTOCOMPLETE_LLM_SUGGESTION_RETURNED` -- `AUTOCOMPLETE_LLM_REQUEST_COMPLETED` -- `AUTOCOMPLETE_LLM_REQUEST_FAILED` -- `AUTOCOMPLETE_ACCEPT_SUGGESTION` -- `AUTOCOMPLETE_UNIQUE_SUGGESTION_SHOWN` - -Additional events mentioned in integration doc: - -- `INLINE_ASSIST_AUTO_TASK` -- `GHOST_SERVICE_DISABLED` - -See telemetry summary in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:357). - -#### Required API (proposed) - -```ts -export type TelemetryEventName = string - -export interface ITelemetryClient { - captureEvent(event: TelemetryEventName, properties?: Record): void -} -``` - -#### Where it is used - -- Inline completion telemetry: [`AutocompleteTelemetry`](src/services/autocomplete/classic-auto-complete/AutocompleteTelemetry.ts:57) -- Service-level disable / code-suggestion telemetry: referenced in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:357) - ---- - -### 2.7 `IWebviewBridge` (Optional) - -**Purpose**: If your new extension has a settings UI and/or chat panel, you need a bridge for messages. - -Current integration uses `ClineProvider` for posting state and receiving messages (see host dependencies list in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:367)). - -Minimum message types used by autocomplete (optional but defined): - -- `ghostServiceSettings` (write settings) -- `snoozeAutocomplete` -- `requestChatCompletion` -- `chatCompletionAccepted` - -If you are not building a webview, you can skip this and omit `chat-autocomplete/` entirely. - ---- - -## 3. VSCode Extension Shell - -This section describes what the new extension must contribute to make the module functional. - -### 3.1 `package.json` - -#### 3.1.1 Activation events - -Current Kilo Code activates broadly: - -- `onLanguage` -- `onStartupFinished` - -See [`src/package.json` snippet in investigation](src/services/autocomplete/docs/investigation-vscode-integration.md:13). - -For a standalone extension you can keep these, or narrow them (e.g. only `onStartupFinished`). - -#### 3.1.2 Commands - -Commands declared in Kilo Code’s `package.json` (some are placeholders): - -- `kilo-code.autocomplete.generateSuggestions` (registered) -- `kilo-code.autocomplete.cancelSuggestions` (declared, not registered) -- `kilo-code.autocomplete.applyCurrentSuggestions` (declared, not registered) -- `kilo-code.autocomplete.applyAllSuggestions` (declared, not registered) -- `kilo-code.autocomplete.goToNextSuggestion` (declared, not registered) -- `kilo-code.autocomplete.goToPreviousSuggestion` (declared, not registered) - -See command table in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:23). - -Commands registered programmatically (must be declared if you want them visible/consistent): - -- `kilo-code.autocomplete.reload` ([`index.ts`](src/services/autocomplete/docs/investigation-vscode-integration.md:117)) -- `kilo-code.autocomplete.codeActionQuickFix` (stub) -- `kilo-code.autocomplete.showIncompatibilityExtensionPopup` -- `kilo-code.autocomplete.disable` -- `kilocode.autocomplete.inline-completion.accepted` (acceptance callback) -- `kilo-code.jetbrains.getInlineCompletions` (JetBrains bridge) - -Recommendation for the new extension: - -- Keep only the commands you truly support. -- If you do not implement “suggested edits” UX, you can drop `apply*` and `goTo*` placeholders. - -#### 3.1.3 Keybindings - -Kilo Code binds: - -- `Escape` → cancel suggestions (but depends on a context key that is never set) -- `Ctrl+L` / `Cmd+L` → generate suggestions (with Copilot conflict split) - -See keybindings in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:47). - -Recommendation: - -- Only contribute keybindings once you implement the associated command end-to-end. -- Ensure any context keys referenced in `when` clauses are actually set. - -#### 3.1.4 Code actions - -If you want the Quick Fix entry point (“Suggested edits”), keep: - -- `contributes.codeActions` declaration -- Register a `CodeActionsProvider` programmatically (as Kilo Code does) - -See code action registration in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:72). - -#### 3.1.5 Configuration contributions - -Kilo Code does **not** contribute `configuration` settings; it stores everything in global state. - -For a new extension you can choose either: - -1. **Global state only** (closest transplant), or -2. **Real VS Code settings** (`contributes.configuration`) and have your settings store bridge to `workspace.getConfiguration`. - -### 3.2 `extension.ts` (activation) - -Minimum activation responsibilities: - -1. Construct/inject dependencies: - - `IAutocompleteSettingsStore` - - `IAutocompleteProfileResolver` / `IAutocompleteLLMProvider` - - `IFileIgnoreController` factory - - `ITelemetryClient` - - (optional) `IWebviewBridge` -2. Initialize ignore controller and settings defaults. -3. Create the autocomplete manager and register VS Code providers. - -The current integration is via `registerAutocompleteProvider(context, provider)` (see activation notes in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:98)). - -Recommendation for transplant structure: - -- Keep `src/services/autocomplete/index.ts` but change it to accept a dependency container instead of a `ClineProvider`. - ---- - -## 4. External Dependencies (npm packages) - -This list is derived from the external import investigation. - -### 4.1 Direct dependencies (autocomplete module) - -- `zod` (JetBrains bridge + continuedev adapters) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:240)) -- `web-tree-sitter` (continuedev tree-sitter integration) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:252)) -- `diff` (continuedev diff utilities) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:266)) -- `fastest-levenshtein` (text similarity) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:273)) -- `lru-cache` and `quick-lru` (caching) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:286)) -- `ignore` (gitignore-like matching in continuedev) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:300)) -- `js-tiktoken` (token counting) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:280)) -- `uri-js` (URI parsing in `VSCodeIde`) ([imports list](src/services/autocomplete/docs/investigation-external-imports.md:313)) - -### 4.2 LLM SDKs (only if you keep continuedev’s provider adapters) - -The continuedev fork includes many LLM adapters and imports these SDKs: - -- `openai` -- `@anthropic-ai/sdk` -- `@aws-sdk/client-bedrock-runtime` -- `@aws-sdk/credential-providers` -- `google-auth-library` -- `dotenv` - -See list in [`investigation-external-imports.md`](src/services/autocomplete/docs/investigation-external-imports.md:169). - -If the new extension has its own LLM system, consider: - -- either stripping unused continuedev adapters to reduce dependency footprint, or -- leaving them but ensuring they do not bloat the extension bundle (tree-shaking). - -### 4.3 Tree-sitter WASM assets - -You must ship tree-sitter WASM and query assets required by continuedev: - -- `web-tree-sitter` expects parser initialization with a `.wasm` file. -- Language grammars are needed to parse various file types. -- Query files live under [`continuedev/tree-sitter/`](src/services/autocomplete/docs/investigation-internal-architecture.md:143) and should be copied. - -Plan for the new extension: - -- Bundle the wasm assets in your extension `dist` or `media` folder. -- Ensure runtime code can resolve them (using `ExtensionContext.extensionUri`). - ---- - -## 5. Files to Copy As-Is - -The following parts are designed to be largely self-contained (per architecture investigation): - -### 5.1 Continue.dev fork (library) - -Copy the entire directory: - -- [`src/services/autocomplete/continuedev/`](src/services/autocomplete/continuedev/core/index.d.ts:1) - -This includes context gathering, templating, postprocessing, tree-sitter queries, and utility helpers. - -### 5.2 Inline completion implementation - -Copy: - -- `src/services/autocomplete/classic-auto-complete/` (all files) -- `src/services/autocomplete/context/` (visible code tracker) -- `src/services/autocomplete/types.ts` - -### 5.3 VS Code UX helpers - -Copy: - -- `src/services/autocomplete/AutocompleteStatusBar.ts` -- `src/services/autocomplete/AutocompleteCodeActionProvider.ts` - -### 5.4 Optional chat textarea autocomplete - -Copy if you have a webview chat UI: - -- `src/services/autocomplete/chat-autocomplete/` - ---- - -## 6. Files Requiring Modification - -Most modifications are to replace Kilo Code specific imports with the new interfaces. - -### 6.1 `AutocompleteModel.ts` - -File: [`AutocompleteModel`](src/services/autocomplete/AutocompleteModel.ts:26) - -Why: - -- Currently depends on `src/api` handlers and `ProviderSettingsManager`. -- Also depends on webview UI constant `PROVIDERS`. - -Change plan: - -- Replace `ProviderSettingsManager` usage with `IAutocompleteProfileResolver`. -- Replace `buildApiHandler` / `ApiHandler` / `FimHandler` with `IAutocompleteLLMProvider`. -- Replace `PROVIDERS` mapping with `providerDisplayName` from `AutocompleteModelInfo`. -- Keep the public surface area stable where possible: - - `supportsFim()` - - `generateFimResponse()` - - `generateResponse()` - - `getModelName()` / `getProviderDisplayName()` - -### 6.2 `AutocompleteServiceManager.ts` and `index.ts` - -Why: - -- Current glue code expects `ContextProxy`, `ClineProvider`, and `TelemetryService`. - -Change plan: - -- Inject `IAutocompleteSettingsStore`, `ITelemetryClient`, ignore-controller factory. -- Replace any webview posting with an optional `IWebviewBridge`. -- Ensure `setContext` keys are correctly set (notably `kilocode.autocomplete.enableSmartInlineTaskKeybinding`, see [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:145)). - -### 6.3 `types.ts` - -Why: - -- Imports `RooIgnoreController` directly. -- Exposes `AutocompleteContextProvider` referencing `VsCodeIde` and `AutocompleteModel`. - -Change plan: - -- Replace `RooIgnoreController` type with `IFileIgnoreController`. -- Keep `VsCodeIde` dependency if you keep continuedev’s VS Code harness; otherwise replace with your own `IDE` implementation. - -### 6.4 `VisibleCodeTracker.ts` - -Why: - -- Depends on `RooIgnoreController` and path utils. - -Change plan: - -- Replace ignore controller import with `IFileIgnoreController`. -- Replace `toRelativePath` with an equivalent helper in the new extension. - -### 6.5 JetBrains bridge - -File: `src/services/autocomplete/AutocompleteJetbrainsBridge.ts`. - -Why: - -- Uses internal Kilo Code wrapper and webview provider. - -Change plan: - -- If the new extension does not support JetBrains, omit it. -- If you do, implement a dedicated transport layer; keep the bridge logic but replace: - - `ClineProvider` - - `getKiloCodeWrapperProperties` - - any Kilo Code-specific types - ---- - -## 7. i18n Setup - -There are two separate i18n mechanisms involved. - -### 7.1 `package.nls.json` (command titles) - -Kilo Code’s `package.json` command titles reference NLS keys like: - -- `autocomplete.commands.generateSuggestions` -- `autocomplete.commands.cancelSuggestions` -- … - -See full list in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:269). - -Transplant options: - -1. Reuse the same keys and provide at least `package.nls.json` (and optionally localized variants). -2. Rename keys and update command declarations accordingly. - -### 7.2 Runtime `t()` keys (status bar/tooltips/progress) - -Runtime strings are accessed via `t()` from `src/i18n` (Kilo Code). - -Keys used live under namespace `kilocode:autocomplete.*` (see JSON excerpt in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:287)). - -Transplant plan: - -- If the new extension already has i18n, add equivalent keys to its runtime translation system. -- Otherwise, simplest is: - - implement a tiny `t(key, vars?)` function that maps to a JSON bundle. - -Minimum runtime keys needed for feature completeness: - -- status bar labels + tooltips (enabled/disabled/snoozed + provider/model + cost) -- progress titles (analyzing/generating/processing/showing) -- incompatibility popup text (if you keep Copilot conflict logic) - ---- - -## 8. Webview Integration (Optional) - -If you want a settings UI or chat panel, you need: - -### 8.1 State shape - -Expose `ghostServiceSettings` (or renamed equivalent) to the webview state. - -See state passing described in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:154). - -### 8.2 Message types - -Support these messages: - -- `ghostServiceSettings` → validate + persist → trigger reload -- `snoozeAutocomplete` → snooze/unsnooze -- `requestChatCompletion` → call chat textarea autocomplete pipeline → respond `chatCompletionResult` -- `chatCompletionAccepted` → fire telemetry - -The message handling mapping is documented in [`investigation-vscode-integration.md`](src/services/autocomplete/docs/investigation-vscode-integration.md:164). - ---- - -## 9. MockTextDocument - -The JetBrains bridge depends on `MockTextDocument` which is outside the autocomplete directory. - -Copy: - -- [`src/services/mocking/MockTextDocument.ts`](src/services/mocking/MockTextDocument.ts:1) - -If you don’t transplant JetBrains support, you can skip this file. - ---- - -## 10. Migration Checklist - -Use this as the practical step-by-step transplant procedure. - -### 10.1 Prepare new extension - -1. Create a new VS Code extension repo (TypeScript). -2. Ensure build pipeline can bundle wasm assets. -3. Add required dependencies (Section 4). - -### 10.2 Copy files - -1. Copy `src/services/autocomplete/` directory into the new extension. -2. If supporting JetBrains bridge, also copy [`MockTextDocument`](src/services/mocking/MockTextDocument.ts:1). -3. Copy tree-sitter query assets under `continuedev/tree-sitter/`. - -### 10.3 Implement host interfaces - -1. Implement [`IAutocompleteSettingsStore`](src/services/autocomplete/docs/TRANSPLANT-PLAN.md:1) (this document) using either: - - `ExtensionContext.globalState`, or - - `workspace.getConfiguration`. -2. Implement [`IFileIgnoreController`](src/services/autocomplete/docs/TRANSPLANT-PLAN.md:1) (this document). -3. Implement [`ITelemetryClient`](src/services/autocomplete/docs/TRANSPLANT-PLAN.md:1) (this document). -4. Implement [`IAutocompleteProfileResolver`](src/services/autocomplete/docs/TRANSPLANT-PLAN.md:1) (this document). -5. Implement [`IAutocompleteLLMProvider`](src/services/autocomplete/docs/TRANSPLANT-PLAN.md:1) (this document) backed by the new extension’s LLM system. - -### 10.4 Refactor autocomplete glue - -1. Refactor [`AutocompleteModel`](src/services/autocomplete/AutocompleteModel.ts:26) to use the new LLM/provider resolver interfaces. -2. Refactor service initialization ([`AutocompleteServiceManager`](src/services/autocomplete/docs/investigation-vscode-integration.md:125)) to use the new settings/telemetry/ignore interfaces. -3. Refactor `index.ts` entry point to accept dependency injection rather than Kilo Code’s provider. - -### 10.5 Wire VS Code extension shell - -1. Implement activation in `extension.ts`: - - instantiate dependencies - - call `registerAutocompleteProvider(...)` -2. Add `package.json` contributions: - - activation events - - commands - - keybindings (optional) - - codeActions contribution (optional) -3. Ensure context keys used in `when` clauses are set via `vscode.commands.executeCommand("setContext", ...)`. - -### 10.6 Validate runtime behavior - -1. Inline completion: - - confirm cancellation works - - confirm debounce behavior - - confirm suggestions appear only for allowed files -2. Status bar: - - confirm provider/model shown - - confirm cost increments -3. (Optional) Webview: - - confirm settings update triggers reload - - confirm chat textarea completion roundtrip works - -## 11. Clarifications - -These decisions were made before implementation began and override any conflicting guidance in the sections above. - -### 11.1 LLM Provider Architecture - -**Decision: Option A — Via CLI backend (Kilo Gateway).** - -FIM is postponed; only the **holefiller** (chat-completion-based) strategy will be used initially. The LLM provider will route completions through the Kilo Gateway backend. The only supported model for now is `mistralai/codestral-2508`. - -### 11.2 Provider & Model Selection - -**Decision: Hardcoded to Kilo Gateway + `mistralai/codestral-2508`.** - -No profile resolver is needed in phase 1. The provider and model are fixed. - -### 11.3 Feature Scope - -| Feature | Decision | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| JetBrains bridge | **Exclude permanently** — delete `AutocompleteJetbrainsBridge.ts` and its tests. This will never be implemented this way. | -| Chat textarea autocomplete | **Include** | -| Code actions | **Include** | -| Continuedev LLM adapters | **Strip to minimum** — remove all adapters not needed for the Kilo Gateway / holefiller path. The module uses `AutocompleteModel`, not the continuedev adapters directly, so most can be removed. | - -### 11.4 Settings Storage - -**Decision: VS Code settings** via `contributes.configuration` in `package.json`. - -### 11.5 Telemetry - -**Decision: Console logging only.** The extension has no telemetry system yet. Keep console logs but do not send actual telemetry events. Implement a no-op `ITelemetryClient`. - -### 11.6 i18n - -**Decision: Wire into `@kilocode/kilo-i18n`.** Use the translations from `src/services/autocomplete/i18n/`. Keys may differ from what `kilo-i18n` uses, so mapping is required. Discard translations for locales not present in `kilo-i18n`. - -### 11.7 File Ignore / Access Control - -**Decision: Dummy `RooIgnoreController`** that allows everything except `.env` files (and similar sensitive defaults). Include a `TODO` comment for proper implementation later. - -### 11.8 Command Prefix - -**Decision: Use `kilo-code.new.autocomplete.*`** to be consistent with the existing extension naming convention. - -### 11.9 NPM Dependencies - -**Decision: Strip unused continuedev code first**, then install only what is actually needed. - -### 11.10 Tree-Sitter WASM Bundling - -**Decision: Bundle in `dist/`** via esbuild copy plugin. - -### 11.11 Singleton vs Dependency Injection - -**Decision: Deferred** — will be determined during implementation based on what works best with the existing `KiloConnectionService` / `KiloProvider` architecture. diff --git a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-external-imports.md b/packages/kilo-vscode/src/services/autocomplete/docs/investigation-external-imports.md deleted file mode 100644 index 56df03c2693..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-external-imports.md +++ /dev/null @@ -1,409 +0,0 @@ -# External Imports Investigation — `src/services/autocomplete/` - -> Generated: 2026-02-12 -> -> This document catalogs **every import** in the autocomplete module that references code -> **outside** of `src/services/autocomplete/`. Test files (`*.test.ts`, `*.spec.ts`, `__tests__/`) -> are excluded. - ---- - -## Table of Contents - -1. [Summary](#summary) -2. [VSCode API](#1-vscode-api) -3. [Internal Project Imports (non-continuedev)](#2-internal-project-imports-non-continuedev-files) -4. [Internal Project Imports (continuedev → outside autocomplete)](#3-internal-project-imports-continuedev-files-reaching-outside-autocomplete) -5. [Webview UI Imports](#4-webview-ui-imports) -6. [Monorepo Packages (`@roo-code/*`)](#5-monorepo-packages-roo-code) -7. [Third-Party npm Packages](#6-third-party-npm-packages) -8. [Node.js Built-in Modules](#7-nodejs-built-in-modules) - ---- - -## Summary - -| Category | Unique Modules | Total Import Sites | -| ---------------------------------------- | -------------------------------------------- | ------------------ | -| VSCode API | 1 (`vscode`) | 14 | -| Internal project (non-continuedev) | 12 distinct targets | 27 | -| Internal project (continuedev → outside) | 3 distinct targets | 3 | -| Webview UI | 1 (`PROVIDERS`) | 2 | -| Monorepo packages | 2 (`@roo-code/types`, `@roo-code/telemetry`) | 9 | -| Third-party npm | 16 distinct packages | 60+ | -| Node.js built-ins | 8 modules | 20+ | - ---- - -## 1. VSCode API - -All files import `* as vscode from "vscode"`. - -| Source File | Symbols | -| --------------------------------------------------------------------------------------- | ------------- | -| `AutocompleteCodeActionProvider.ts` | `* as vscode` | -| `AutocompleteJetbrainsBridge.ts` | `* as vscode` | -| `AutocompleteServiceManager.ts` | `* as vscode` | -| `AutocompleteStatusBar.ts` | `* as vscode` | -| `index.ts` | `* as vscode` | -| `types.ts` | `* as vscode` | -| `chat-autocomplete/ChatTextAreaAutocomplete.ts` | `* as vscode` | -| `classic-auto-complete/AutocompleteInlineCompletionProvider.ts` | `* as vscode` | -| `classic-auto-complete/getProcessedSnippets.ts` | `* as vscode` | -| `context/VisibleCodeTracker.ts` | `* as vscode` | -| `continuedev/core/vscode-test-harness/src/VSCodeIde.ts` | `* as vscode` | -| `continuedev/core/vscode-test-harness/src/autocomplete/lsp.ts` | `* as vscode` | -| `continuedev/core/vscode-test-harness/src/autocomplete/recentlyEdited.ts` | `* as vscode` | -| `continuedev/core/vscode-test-harness/src/autocomplete/RecentlyVisitedRangesService.ts` | `* as vscode` | - ---- - -## 2. Internal Project Imports (non-continuedev files) - -These are imports from files **outside** the `src/services/autocomplete/` directory tree, -originating from the "Kilo Code" layer (not the continuedev fork). - -### `src/core/` imports - -| Source File | Module Path | Symbols | -| --------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------- | -| `AutocompleteJetbrainsBridge.ts` | `../../core/webview/ClineProvider` | `{ ClineProvider }` | -| `AutocompleteJetbrainsBridge.ts` | `../../core/kilocode/wrapper` | `{ getKiloCodeWrapperProperties }` | -| `AutocompleteModel.ts` | `../../core/config/ProviderSettingsManager` | `{ ProviderSettingsManager }` | -| `AutocompleteServiceManager.ts` | `../../core/config/ContextProxy` | `{ ContextProxy }` | -| `AutocompleteServiceManager.ts` | `../../core/webview/ClineProvider` | `{ ClineProvider }` | -| `index.ts` | `../../core/webview/ClineProvider` | `{ ClineProvider }` | -| `types.ts` | `../../core/ignore/RooIgnoreController` | `{ RooIgnoreController }` | -| `chat-autocomplete/ChatTextAreaAutocomplete.ts` | `../../../core/config/ProviderSettingsManager` | `{ ProviderSettingsManager }` | -| `chat-autocomplete/handleChatCompletionRequest.ts` | `../../../core/webview/ClineProvider` | `{ ClineProvider }` | -| `classic-auto-complete/AutocompleteInlineCompletionProvider.ts` | `../../../core/ignore/RooIgnoreController` | `{ RooIgnoreController }` | -| `classic-auto-complete/AutocompleteInlineCompletionProvider.ts` | `../../../core/webview/ClineProvider` | `{ ClineProvider }` | -| `classic-auto-complete/getProcessedSnippets.ts` | `../../../core/ignore/RooIgnoreController` | `{ RooIgnoreController }` | -| `context/VisibleCodeTracker.ts` | `../../../core/ignore/RooIgnoreController` | `type { RooIgnoreController }` | - -### `src/api/` imports - -| Source File | Module Path | Symbols | -| ------------------------------------- | ----------------------------------------- | --------------------------------------------- | -| `AutocompleteModel.ts` | `../../api` | `{ ApiHandler, buildApiHandler, FimHandler }` | -| `AutocompleteModel.ts` | `../../api/providers` | `{ OpenRouterHandler }` | -| `AutocompleteModel.ts` | `../../api/providers/openrouter` | `{ CompletionUsage }` | -| `AutocompleteModel.ts` | `../../api/transform/stream` | `{ ApiStreamChunk }` | -| `AutocompleteModel.ts` | `../../api/providers/kilocode-openrouter` | `{ KilocodeOpenrouterHandler }` | -| `classic-auto-complete/HoleFiller.ts` | `../../../api/transform/stream` | `{ ApiStreamChunk }` | - -### `src/i18n` imports - -| Source File | Module Path | Symbols | -| ----------------------------------- | ------------ | ------- | -| `AutocompleteCodeActionProvider.ts` | `../../i18n` | `{ t }` | -| `AutocompleteServiceManager.ts` | `../../i18n` | `{ t }` | -| `AutocompleteStatusBar.ts` | `../../i18n` | `{ t }` | - -### `src/shared/` imports - -| Source File | Module Path | Symbols | -| --------------------------------------------------- | -------------------------------- | -------------------- | -| `chat-autocomplete/handleChatCompletionAccepted.ts` | `../../../shared/WebviewMessage` | `{ WebviewMessage }` | -| `chat-autocomplete/handleChatCompletionRequest.ts` | `../../../shared/WebviewMessage` | `{ WebviewMessage }` | - -### `src/utils/` imports - -| Source File | Module Path | Symbols | -| ------------------------------- | --------------------- | -------------------- | -| `context/VisibleCodeTracker.ts` | `../../../utils/path` | `{ toRelativePath }` | - -### `src/services/mocking/` imports - -| Source File | Module Path | Symbols | -| -------------------------------- | ----------------------------- | ---------------------- | -| `AutocompleteJetbrainsBridge.ts` | `../mocking/MockTextDocument` | `{ MockTextDocument }` | - ---- - -## 3. Internal Project Imports (continuedev files reaching outside autocomplete) - -These imports originate from `continuedev/` files but reach out of the autocomplete -directory tree entirely (via deeply nested `../../../../../../` paths). - -| Source File | Module Path | Symbols | -| --------------------------------------- | ------------------------------------------------------- | ------------------------ | -| `continuedev/core/llm/llms/KiloCode.ts` | `../../../../../../shared/kilocode/headers` | `{ X_KILOCODE_VERSION }` | -| `continuedev/core/llm/llms/KiloCode.ts` | `../../../../../../shared/package` | `{ Package }` | -| `continuedev/core/llm/llms/KiloCode.ts` | `../../../../../../api/providers/kilocode/IFimProvider` | `{ IFimProvider }` | - ---- - -## 4. Webview UI Imports - -| Source File | Module Path | Symbols | -| -------------------------- | ------------------------------------------------------- | --------------- | -| `AutocompleteModel.ts` | `../../../webview-ui/src/components/settings/constants` | `{ PROVIDERS }` | -| `AutocompleteStatusBar.ts` | `../../../webview-ui/src/components/settings/constants` | `{ PROVIDERS }` | - ---- - -## 5. Monorepo Packages (`@roo-code/*`) - -### `@roo-code/types` - -| Source File | Symbols | -| --------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -| `AutocompleteModel.ts` | `{ modelIdKeysByProvider, ProviderName }` | -| `AutocompleteServiceManager.ts` | `{ AutocompleteServiceSettings, TelemetryEventName }` | -| `AutocompleteStatusBar.ts` | `{ AUTOCOMPLETE_PROVIDER_MODELS, ProviderName }` | -| `classic-auto-complete/AutocompleteInlineCompletionProvider.ts` | `type { AutocompleteServiceSettings }` | -| `classic-auto-complete/AutocompleteTelemetry.ts` | `{ TelemetryEventName }` | -| `utils/kilocode-utils.ts` | `{ getKiloBaseUriFromToken, AUTOCOMPLETE_PROVIDER_MODELS, AutocompleteProviderKey }` | -| `continuedev/core/llm/llms/KiloCode.ts` | `{ getKiloUrlFromToken }` | - -### `@roo-code/telemetry` - -| Source File | Symbols | -| ------------------------------------------------ | ---------------------- | -| `AutocompleteServiceManager.ts` | `{ TelemetryService }` | -| `classic-auto-complete/AutocompleteTelemetry.ts` | `{ TelemetryService }` | - ---- - -## 6. Third-Party npm Packages - -### `openai` / `openai/*` (OpenAI SDK) - -Used extensively in `continuedev/core/llm/` for LLM API adapters. - -| Source File | Module Path | Symbols | -| ------------------------------------------------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | -| `continuedev/core/llm/index.ts` | `openai/resources/index` | `{ ChatCompletionCreateParams }` | -| `continuedev/core/llm/llms/OpenAI.ts` | `openai/resources/index` | `{ ChatCompletionCreateParams, ChatCompletionMessageParam }` | -| `continuedev/core/llm/llms/OpenRouter.ts` | `openai/resources/index` | `{ ChatCompletionCreateParams }` | -| `continuedev/core/llm/openaiTypeConverters.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParams, ChatCompletionMessageParam, CompletionCreateParams }` | -| `continuedev/core/llm/openai-adapters/apis/Anthropic.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/Anthropic.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ChatCompletionCreateParams, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Anthropic.ts` | `openai/resources/index.js` | `{ ChatCompletionCreateParams }` | -| `continuedev/core/llm/openai-adapters/apis/AnthropicUtils.ts` | `openai/resources` | `{ ChatCompletionTool, ChatCompletionToolChoiceOption }` | -| `continuedev/core/llm/openai-adapters/apis/Azure.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/Azure.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/base.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParams, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Bedrock.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/Bedrock.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Cohere.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/Cohere.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/CometAPI.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/ContinueProxy.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/DeepSeek.ts` | `openai/resources/index` | `{ ChatCompletionChunk, Model }` | -| `continuedev/core/llm/openai-adapters/apis/Gemini.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/Gemini.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Inception.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Jina.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/LlamaStack.ts` | `openai/resources/index` | `{ ChatCompletionChunk }` | -| `continuedev/core/llm/openai-adapters/apis/Mock.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Moonshot.ts` | `openai/resources/index` | `{ ChatCompletionChunk, Model }` | -| `continuedev/core/llm/openai-adapters/apis/OpenAI.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/OpenAI.ts` | `openai/resources/index` | `{ ChatCompletion, ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/OpenRouter.ts` | `openai/resources/index` | `{ ChatCompletionCreateParams }` | -| `continuedev/core/llm/openai-adapters/apis/OpenRouterCaching.ts` | `openai/resources/index` | `{ ChatCompletionCreateParams, ChatCompletionMessageParam }` | -| `continuedev/core/llm/openai-adapters/apis/Relace.ts` | `openai/resources/completions.mjs` | `{ Completion, CompletionUsage }` | -| `continuedev/core/llm/openai-adapters/apis/Relace.ts` | `openai/resources/index.mjs` | `{ ChatCompletion, ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Relace.ts` | `openai/resources/models.mjs` | `{ Model }` | -| `continuedev/core/llm/openai-adapters/apis/VertexAI.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/WatsonX.ts` | `openai/index` | `{ OpenAI }` | -| `continuedev/core/llm/openai-adapters/apis/WatsonX.ts` | `openai/resources/index` | `{ ChatCompletionChunk, ... }` | -| `continuedev/core/llm/openai-adapters/apis/WatsonX.ts` | `openai/resources/index.js` | `{ ChatCompletionCreateParams }` | -| `continuedev/core/llm/openai-adapters/util.ts` | `openai/resources/index` | `{ ChatCompletionChunk, CompletionUsage }` | -| `continuedev/core/llm/openai-adapters/util.ts` | `openai/resources/index.js` | `{ ChatCompletion }` | -| `continuedev/core/llm/openai-adapters/util/emptyChatCompletion.ts` | `openai/resources/index` | `{ ChatCompletion }` | -| `continuedev/core/llm/openai-adapters/util/gemini-types.ts` | `openai/resources/index.mjs` | `{ ChatCompletionTool }` | - -### `@anthropic-ai/sdk` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------------------------- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `continuedev/core/llm/openai-adapters/apis/Anthropic.ts` | `@anthropic-ai/sdk/resources` | `{ ContentBlock, ContentBlockDelta, MessageDelta, MessageStartEvent, RawContentBlockStartEvent, RawMessageDeltaEvent }` | -| `continuedev/core/llm/openai-adapters/apis/AnthropicCachingStrategies.ts` | `@anthropic-ai/sdk/resources` | `{ MessageCreateParams }` | -| `continuedev/core/llm/openai-adapters/apis/AnthropicUtils.ts` | `@anthropic-ai/sdk/resources` | `{ Base64ImageSource, MessageParam, Tool, ToolChoice }` | -| `continuedev/core/llm/openai-adapters/apis/OpenRouterCaching.ts` | `@anthropic-ai/sdk/resources` | `{ ContentBlockParam, MessageCreateParams, MessageParam }` | - -### `@aws-sdk/*` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------ | --------------------------------- | -------------------------------------------------------------------------------------------- | -| `continuedev/core/llm/openai-adapters/apis/Bedrock.ts` | `@aws-sdk/client-bedrock-runtime` | `{ BedrockRuntimeClient, ConverseStreamCommand, InvokeModelWithResponseStreamCommand, ... }` | -| `continuedev/core/llm/openai-adapters/apis/Bedrock.ts` | `@aws-sdk/credential-providers` | `{ fromNodeProviderChain }` | - -### `google-auth-library` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------- | --------------------- | --------------------------------------- | -| `continuedev/core/llm/openai-adapters/apis/VertexAI.ts` | `google-auth-library` | `{ AuthClient, GoogleAuth, JWT, auth }` | - -### `zod` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------------ | ----------- | -------- | -| `AutocompleteJetbrainsBridge.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/apis/Azure.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/apis/ContinueProxy.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/apis/OpenAI.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/apis/Relace.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/index.ts` | `zod` | `{ z }` | -| `continuedev/core/llm/openai-adapters/types.ts` | `zod` | `* as z` | - -### `web-tree-sitter` - -| Source File | Module Path | Symbols | -| ----------------------------------------------------------------------------------- | ----------------- | ---------------------------------------------------- | -| `continuedev/core/index.d.ts` | `web-tree-sitter` | `Parser` (default) | -| `continuedev/core/autocomplete/util/ast.ts` | `web-tree-sitter` | `{ Node as SyntaxNode, Tree }` | -| `continuedev/core/autocomplete/context/root-path-context/RootPathContextService.ts` | `web-tree-sitter` | `{ Node as SyntaxNode, Query, Point }` | -| `continuedev/core/autocomplete/context/root-path-context/testUtils.ts` | `web-tree-sitter` | `Parser` (default) | -| `continuedev/core/autocomplete/context/static-context/StaticContextService.ts` | `web-tree-sitter` | `{ Node as SyntaxNode }` | -| `continuedev/core/autocomplete/context/static-context/tree-sitter-utils.ts` | `web-tree-sitter` | `{ Node as SyntaxNode, QueryMatch, Tree }` | -| `continuedev/core/autocomplete/context/static-context/types.ts` | `web-tree-sitter` | `{ Tree }` | -| `continuedev/core/util/treeSitter.ts` | `web-tree-sitter` | `type { Language, Node as SyntaxNode, Query, Tree }` | -| `continuedev/core/vscode-test-harness/src/autocomplete/lsp.ts` | `web-tree-sitter` | `type { Node as SyntaxNode }` | - -### `diff` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------------------- | ----------- | --------------------------------------- | -| `continuedev/core/autocomplete/util/processSingleLineCompletion.ts` | `diff` | `* as Diff` | -| `continuedev/core/diff/myers.ts` | `diff` | `{ diffChars, diffLines, type Change }` | - -### `fastest-levenshtein` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------ | --------------------- | -------------- | -| `continuedev/core/autocomplete/util/textSimilarity.ts` | `fastest-levenshtein` | `{ distance }` | -| `continuedev/core/diff/util.ts` | `fastest-levenshtein` | `{ distance }` | - -### `js-tiktoken` - -| Source File | Module Path | Symbols | -| ------------------------------------- | ------------- | ----------------------------------------------------- | -| `continuedev/core/llm/countTokens.ts` | `js-tiktoken` | `{ Tiktoken, encodingForModel as _encodingForModel }` | - -### `lru-cache` - -| Source File | Module Path | Symbols | -| --------------------------------------------------------------------------------------- | ----------- | -------------- | -| `continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.ts` | `lru-cache` | `{ LRUCache }` | -| `continuedev/core/autocomplete/context/root-path-context/RootPathContextService.ts` | `lru-cache` | `{ LRUCache }` | -| `continuedev/core/vscode-test-harness/src/autocomplete/RecentlyVisitedRangesService.ts` | `lru-cache` | `{ LRUCache }` | - -### `quick-lru` - -| Source File | Module Path | Symbols | -| ----------------------------------------------------------- | ----------- | -------------------- | -| `continuedev/core/autocomplete/util/openedFilesLruCache.ts` | `quick-lru` | `QuickLRU` (default) | - -### `ignore` - -| Source File | Module Path | Symbols | -| ----------------------------------------------------- | ----------- | ------------------ | -| `continuedev/core/autocomplete/prefiltering/index.ts` | `ignore` | `ignore` (default) | -| `continuedev/core/indexing/ignore.ts` | `ignore` | `ignore` (default) | - -### `dotenv` - -| Source File | Module Path | Symbols | -| ----------------------------------------------- | ----------- | ------------------ | -| `continuedev/core/llm/openai-adapters/index.ts` | `dotenv` | `dotenv` (default) | - -### `uri-js` - -| Source File | Module Path | Symbols | -| ------------------------------------------------------- | ----------- | ---------- | -| `continuedev/core/vscode-test-harness/src/VSCodeIde.ts` | `uri-js` | `* as URI` | - -### `vitest` - -| Source File | Module Path | Symbols | -| ---------------------------------------------------------------------- | ----------- | ---------------- | -| `continuedev/core/autocomplete/context/root-path-context/testUtils.ts` | `vitest` | `{ expect, vi }` | -| `continuedev/core/autocomplete/filtering/test/util.ts` | `vitest` | `{ expect }` | -| `continuedev/core/test/vitest.setup.ts` | `vitest` | `{ beforeAll }` | - ---- - -## 7. Node.js Built-in Modules - -| Source File | Module | Symbols | -| ----------------------------------------------------------------------------------- | ------------- | ---------------------------------- | -| `AutocompleteServiceManager.ts` | `crypto` | `crypto` (default) | -| `continuedev/core/autocomplete/util/AutocompleteDebouncer.ts` | `node:crypto` | `{ randomUUID }` | -| `continuedev/core/llm/openai-adapters/apis/Bedrock.ts` | `node:crypto` | `{ randomUUID }` | -| `continuedev/core/autocomplete/context/root-path-context/RootPathContextService.ts` | `crypto` | `{ createHash }` | -| `continuedev/core/autocomplete/context/root-path-context/testUtils.ts` | `fs` | `fs` (default) | -| `continuedev/core/autocomplete/context/root-path-context/testUtils.ts` | `path` | `path` (default) | -| `continuedev/core/autocomplete/context/root-path-context/testUtils.ts` | `node:url` | `{ fileURLToPath }` | -| `continuedev/core/autocomplete/context/static-context/StaticContextService.ts` | `fs/promises` | `* as fs` | -| `continuedev/core/autocomplete/context/static-context/StaticContextService.ts` | `path` | `path` (default) | -| `continuedev/core/autocomplete/context/static-context/StaticContextService.ts` | `url` | `{ pathToFileURL }` | -| `continuedev/core/autocomplete/context/static-context/tree-sitter-utils.ts` | `fs/promises` | `* as fs` | -| `continuedev/core/indexing/ignore.ts` | `path` | `path` (default) | -| `continuedev/core/indexing/ignore.ts` | `url` | `{ fileURLToPath }` | -| `continuedev/core/test/testDir.ts` | `fs` | `fs` (default) | -| `continuedev/core/test/testDir.ts` | `os` | `os` (default) | -| `continuedev/core/test/testDir.ts` | `path` | `path` (default) | -| `continuedev/core/test/vitest.global-setup.ts` | `fs` | `fs` (default) | -| `continuedev/core/test/vitest.global-setup.ts` | `path` | `path` (default) | -| `continuedev/core/test/vitest.setup.ts` | `util` | `{ TextDecoder, TextEncoder }` | -| `continuedev/core/util/filesystem.ts` | `node:fs` | `* as fs` | -| `continuedev/core/util/filesystem.ts` | `node:url` | `{ fileURLToPath }` | -| `continuedev/core/util/paths.ts` | `fs` | `* as fs` | -| `continuedev/core/util/paths.ts` | `os` | `* as os` | -| `continuedev/core/util/paths.ts` | `path` | `* as path` | -| `continuedev/core/util/pathToUri.ts` | `url` | `{ fileURLToPath, pathToFileURL }` | -| `continuedev/core/util/treeSitter.ts` | `node:fs` | `fs` (default) | -| `continuedev/core/util/treeSitter.ts` | `path` | `path` (default) | - ---- - -## Appendix: Unique External Dependency List - -### npm packages (non-Node.js built-in) - -``` -@anthropic-ai/sdk -@aws-sdk/client-bedrock-runtime -@aws-sdk/credential-providers -@roo-code/telemetry -@roo-code/types -diff -dotenv -fastest-levenshtein -google-auth-library -ignore -js-tiktoken -lru-cache -openai -quick-lru -uri-js -vitest -web-tree-sitter -zod -``` - -### Internal project modules imported (outside autocomplete) - -``` -src/api (../../api) -src/api/providers (../../api/providers) -src/api/providers/kilocode-openrouter (../../api/providers/kilocode-openrouter) -src/api/providers/kilocode/IFimProvider (via continuedev KiloCode.ts) -src/api/providers/openrouter (../../api/providers/openrouter) -src/api/transform/stream (../../api/transform/stream) -src/core/config/ContextProxy (../../core/config/ContextProxy) -src/core/config/ProviderSettingsManager (../../core/config/ProviderSettingsManager) -src/core/ignore/RooIgnoreController (../../core/ignore/RooIgnoreController) -src/core/kilocode/wrapper (../../core/kilocode/wrapper) -src/core/webview/ClineProvider (../../core/webview/ClineProvider) -src/i18n (../../i18n) -src/services/mocking/MockTextDocument (../mocking/MockTextDocument) -src/shared/WebviewMessage (../../shared/WebviewMessage) -src/shared/kilocode/headers (via continuedev KiloCode.ts) -src/shared/package (via continuedev KiloCode.ts) -src/utils/path (../../utils/path) -webview-ui/src/components/settings/constants -``` diff --git a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-internal-architecture.md b/packages/kilo-vscode/src/services/autocomplete/docs/investigation-internal-architecture.md deleted file mode 100644 index 7802ef6568a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-internal-architecture.md +++ /dev/null @@ -1,456 +0,0 @@ -# Internal Architecture of the Autocomplete Module - -> Investigation date: 2026-02-12 -> Scope: `src/services/autocomplete/` — all subdirectories and root-level files - ---- - -## High-Level Architecture - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ VS Code Extension Host │ -│ │ -│ index.ts ─► registerAutocompleteProvider() │ -│ │ │ -│ ▼ │ -│ ┌──────────────────────────────────────────────────────────────┐ │ -│ │ AutocompleteServiceManager (singleton orchestrator) │ │ -│ │ • settings, status bar, cost tracking, snooze, commands │ │ -│ │ • owns AutocompleteModel + two completion strategies │ │ -│ └────┬─────────────────────┬──────────────────────┬────────────┘ │ -│ │ │ │ │ -│ ▼ ▼ ▼ │ -│ ┌──────────┐ ┌─────────────────┐ ┌──────────────────────┐ │ -│ │ Autocomplete│ │ Classic Auto- │ │ Chat Text Area │ │ -│ │ Model │ │ Complete │ │ Autocomplete │ │ -│ │ (LLM layer) │ │ (inline ghosts) │ │ (webview chat) │ │ -│ └──────┬───┘ └──────┬──────────┘ └───────┬──────────────┘ │ -│ │ │ │ │ -│ │ ▼ ▼ │ -│ │ ┌──────────────────────┐ ┌────────────────────┐ │ -│ │ │ continuedev/ library │ │ context/ │ │ -│ │ │ (forked Continue.dev)│ │ VisibleCodeTracker │ │ -│ │ │ │ └────────────────────┘ │ -│ │ │ • context retrieval │ │ -│ │ │ • snippet gathering │ ┌────────────────────┐ │ -│ │ │ • prompt templating │ │ utils/ │ │ -│ │ │ • postprocessing │ │ kilocode-utils.ts │ │ -│ │ │ • tree-sitter queries│ └────────────────────┘ │ -│ │ │ • LLM providers │ │ -│ │ └──────────────────────┘ │ -│ │ │ -│ ▼ │ -│ ┌──────────────────────────────────────────────────┐ │ -│ │ External: src/api/ (ApiHandler, FimHandler, │ │ -│ │ buildApiHandler, OpenRouterHandler, etc.) │ │ -│ └──────────────────────────────────────────────────┘ │ -└──────────────────────────────────────────────────────────────────────┘ -``` - ---- - -## 1. Root-Level Files - -### [`index.ts`](../index.ts) - -Entry point. Registers the `AutocompleteServiceManager`, JetBrains bridge, and all VS Code commands (`reload`, `generateSuggestions`, `disable`, `showIncompatibilityExtensionPopup`, code actions). - -### [`AutocompleteServiceManager.ts`](../AutocompleteServiceManager.ts) - -**Singleton orchestrator** for the entire module. - -- Owns an [`AutocompleteModel`](../AutocompleteModel.ts) (LLM abstraction) and an [`AutocompleteInlineCompletionProvider`](../classic-auto-complete/AutocompleteInlineCompletionProvider.ts). -- Manages lifecycle: loads settings from `ContextProxy`, registers/unregisters the VS Code inline completion provider, handles snooze timers. -- Delegates manual "code suggestion" to the inline completion provider. -- Tracks session cost and completion count; forwards them to the status bar. - -**External dependencies:** - -- `vscode` API -- `@roo-code/types` (`AutocompleteServiceSettings`, `TelemetryEventName`) -- `@roo-code/telemetry` (`TelemetryService`) -- `../../core/config/ContextProxy` -- `../../core/webview/ClineProvider` -- `../../i18n` (`t()`) - -### [`AutocompleteModel.ts`](../AutocompleteModel.ts) - -**LLM abstraction layer** — bridges autocomplete requests to the Kilo Code API system. - -- `reload(providerSettingsManager)`: Scans configured profiles to find a usable autocomplete provider. Supports dedicated `"autocomplete"` profiles and fallback to general profiles matching `AUTOCOMPLETE_PROVIDER_MODELS`. -- `supportsFim()`: Checks if the current API handler has a FIM endpoint. -- `generateFimResponse(prefix, suffix, onChunk)`: Streams a Fill-In-the-Middle completion via `FimHandler.streamFim()`. -- `generateResponse(system, user, onChunk)`: Streams a chat completion via `ApiHandler.createMessage()`. -- `hasValidCredentials()`, `getModelName()`, `getProviderDisplayName()`. - -**External dependencies:** - -- `../../api` (`ApiHandler`, `buildApiHandler`, `FimHandler`) -- `../../api/providers` (`OpenRouterHandler`, `KilocodeOpenrouterHandler`) -- `../../api/transform/stream` (`ApiStreamChunk`) -- `../../core/config/ProviderSettingsManager` -- `@roo-code/types` (`modelIdKeysByProvider`, `ProviderName`) -- `webview-ui/.../constants` (`PROVIDERS`) - -### [`AutocompleteStatusBar.ts`](../AutocompleteStatusBar.ts) - -VS Code status bar item showing autocomplete status (enabled/snoozed/disabled, model, cost). - -### [`AutocompleteCodeActionProvider.ts`](../AutocompleteCodeActionProvider.ts) - -VS Code code action provider (quick fix integration point). - -### [`AutocompleteJetbrainsBridge.ts`](../AutocompleteJetbrainsBridge.ts) - -Bridge for JetBrains IDE integration — proxies autocomplete requests from JetBrains to the classic auto-complete provider. - -### [`types.ts`](../types.ts) - -Central type definitions shared across subdirectories: - -- `AutocompleteInput`, `AutocompleteOutcome`, `AutocompletePrompt` (discriminated union: `FimAutocompletePrompt | HoleFillerAutocompletePrompt`) -- `FillInAtCursorSuggestion`, `ResponseMetaData`, `CostTrackingCallback` -- `VisibleCodeContext`, `VisibleEditorInfo`, `VisibleRange`, `DiffInfo` -- `ChatCompletionRequest`, `ChatTextCompletionResult` -- Utility functions: `extractPrefixSuffix()`, `contextToAutocompleteInput()` - ---- - -## 2. `continuedev/` — Forked Continue.dev Library - -### Purpose - -A **streamlined extraction** from the [Continue.dev](https://github.com/continuedev/continue) project, containing only autocomplete and NextEdit functionality. All GUI, chat, agents, and other features have been removed. It serves as a **TypeScript service library** providing: - -1. **Autocomplete pipeline** — `CompletionProvider` orchestrates: prefiltering → context gathering → snippet retrieval → prompt templating → LLM streaming → stream filtering → postprocessing → caching. -2. **Context retrieval** — `ContextRetrievalService`, `ImportDefinitionsService`, `RootPathContextService`. -3. **Snippet gathering** — `getAllSnippets()` collects recently edited files, recently visited ranges, LSP definitions, clipboard, diffs. -4. **Prompt templating** — Model-specific FIM templates (`codestral`, `starcoder`, `deepseek`, etc.), prefix/suffix construction, token-limited rendering. -5. **Stream filtering** — `BracketMatchingService`, `charStream`/`lineStream` transforms, `StreamTransformPipeline`. -6. **Postprocessing** — bracket cleanup, `removePrefixOverlap`, completion formatting. -7. **Tree-sitter integration** — `.scm` query files for 15+ languages covering: code snippets, imports, root-path context, static context (hole/header/type queries), and tag queries. -8. **LLM providers** — `ILLM` interface with implementations for OpenAI, Mistral, OpenRouter, KiloCode, Mock. -9. **Diff engine** — Myers diff algorithm, streaming diff. -10. **Utility layer** — Token counting (llama tokenizer), LRU caching, logging service, debouncing, helper variables. - -### Key Files - -| File | Role | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -| [`core/index.d.ts`](../continuedev/core/index.d.ts) | Core type definitions: `IDE`, `ILLM`, `TabAutocompleteOptions`, `Position`, `Range`, etc. | -| [`core/autocomplete/CompletionProvider.ts`](../continuedev/core/autocomplete/CompletionProvider.ts) | Main orchestrator (not used directly by classic-auto-complete; serves as reference) | -| [`core/autocomplete/context/ContextRetrievalService.ts`](../continuedev/core/autocomplete/context/) | Context gathering service | -| [`core/autocomplete/snippets/getAllSnippets.ts`](../continuedev/core/autocomplete/snippets/getAllSnippets.ts) | Collects all context snippets | -| [`core/autocomplete/templating/`](../continuedev/core/autocomplete/templating/) | Prompt construction, formatting, model-specific templates | -| [`core/autocomplete/postprocessing/`](../continuedev/core/autocomplete/postprocessing/) | Post-processing pipeline | -| [`core/autocomplete/util/HelperVars.ts`](../continuedev/core/autocomplete/util/HelperVars.ts) | Cursor context, pruned prefix/suffix computation | -| [`core/vscode-test-harness/src/VSCodeIde.ts`](../continuedev/core/vscode-test-harness/src/VSCodeIde.ts) | VS Code `IDE` interface implementation | -| [`core/vscode-test-harness/src/autocomplete/lsp.ts`](../continuedev/core/vscode-test-harness/src/autocomplete/lsp.ts) | LSP definition retrieval | -| [`core/vscode-test-harness/src/autocomplete/RecentlyVisitedRangesService.ts`](../continuedev/core/vscode-test-harness/src/autocomplete/RecentlyVisitedRangesService.ts) | Tracks recently visited code ranges | -| [`core/vscode-test-harness/src/autocomplete/recentlyEdited.ts`](../continuedev/core/vscode-test-harness/src/autocomplete/recentlyEdited.ts) | Tracks recently edited code ranges | -| [`core/llm/`](../continuedev/core/llm/) | LLM implementations (OpenAI, Mistral, etc.) | -| [`core/util/parameters.ts`](../continuedev/core/util/parameters.ts) | `DEFAULT_AUTOCOMPLETE_OPTS` | -| [`tree-sitter/`](../continuedev/tree-sitter/) | `.scm` query files for all supported languages | - -### Self-containedness - -The continuedev library is **largely self-contained** with its own: - -- `IDE` interface (abstraction over VS Code/JetBrains) -- `ILLM` interface (abstraction over LLM providers) -- Tree-sitter integration -- Utility layer - -It imports `web-tree-sitter` as an external npm dependency. The `VsCodeIde.ts` implementation within it imports `vscode` API directly. - ---- - -## 3. `classic-auto-complete/` — Inline Code Completion Pipeline - -### Purpose - -The **primary code editor autocomplete** feature. Implements `vscode.InlineCompletionItemProvider` to show ghost text completions as the user types. - -### Completion Pipeline Flow - -``` -VS Code triggers provideInlineCompletionItems() - │ - ▼ -┌──────────────────────────────────────────┐ -│ 1. Gate checks │ -│ • Is auto-trigger enabled? │ -│ • Has valid model/credentials? │ -│ • Is file accessible (RooIgnore)? │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 2. Cache lookup (suggestions history) │ -│ findMatchingSuggestion(): │ -│ • exact match │ -│ • partial_typing (user typed ahead) │ -│ • backward_deletion (user backspaced) │ -│ → If cache hit, return immediately │ -└──────────┬───────────────────────────────┘ - │ (cache miss) - ▼ -┌──────────────────────────────────────────┐ -│ 3. Contextual skip │ -│ shouldSkipAutocomplete(): │ -│ • mid-word typing (len > 2) │ -│ • at end of statement (;, }, )) │ -│ → If skip, return empty │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 4. Prompt building │ -│ Strategy chosen by model.supportsFim()│ -│ │ -│ FIM path (FimPromptBuilder): │ -│ • getProcessedSnippets() → HelperVars │ -│ • getAllSnippetsWithoutRace() → │ -│ context, snippets, LSP defs │ -│ • getTemplateForModel() → FIM format │ -│ • compilePrefixSuffix() → formatted │ -│ │ -│ Chat path (HoleFiller): │ -│ • Same context gathering │ -│ • formatSnippets() → comment context │ -│ • System prompt (hole-filler pattern) │ -│ • {{FILL_HERE}} template │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 5. Debounced LLM request │ -│ • Leading edge on first call │ -│ • Adaptive delay (avg of recent │ -│ latencies, 150ms–1000ms range) │ -│ • Reuses covering pending requests │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 6. LLM call (via AutocompleteModel) │ -│ FIM: model.generateFimResponse() │ -│ → FimHandler.streamFim() │ -│ Chat: model.generateResponse() │ -│ → ApiHandler.createMessage() │ -│ → Collects streaming chunks │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 7. Post-processing │ -│ processSuggestion() → │ -│ postprocessAutocompleteSuggestion(): │ -│ a. continuedev postprocessCompletion() │ -│ (prefix overlap removal, etc.) │ -│ b. applyLanguageFilter() (markdown) │ -│ c. suggestionConsideredDuplication() │ -│ • prefix/suffix duplication │ -│ • edge-line duplication │ -│ • repetitive phrase detection │ -│ • normalized complete-line check │ -└──────────┬───────────────────────────────┘ - │ - ▼ -┌──────────────────────────────────────────┐ -│ 8. Display logic │ -│ • applyFirstLineOnly() — truncate │ -│ multi-line if cursor is mid-line │ -│ • stringToInlineCompletions() → │ -│ vscode.InlineCompletionItem │ -│ • Track in suggestionsHistory │ -│ • Cost tracking callback │ -│ • Telemetry (requested, returned, │ -│ filtered, cache hit, accepted, │ -│ unique shown, visibility tracking) │ -└──────────────────────────────────────────┘ -``` - -### Key Files - -| File | Role | -| ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -| [`AutocompleteInlineCompletionProvider.ts`](../classic-auto-complete/AutocompleteInlineCompletionProvider.ts) | Main provider: debouncing, cache, pipeline orchestration | -| [`FillInTheMiddle.ts`](../classic-auto-complete/FillInTheMiddle.ts) | `FimPromptBuilder` — builds FIM prompts using continuedev's templating | -| [`HoleFiller.ts`](../classic-auto-complete/HoleFiller.ts) | Chat-based completion with `{{FILL_HERE}}` / `` XML tag protocol | -| [`getProcessedSnippets.ts`](../classic-auto-complete/getProcessedSnippets.ts) | Orchestrates context gathering: `HelperVars`, `getAllSnippetsWithoutRace`, access filtering | -| [`contextualSkip.ts`](../classic-auto-complete/contextualSkip.ts) | Determines when to skip autocomplete (mid-word, end-of-statement) | -| [`uselessSuggestionFilter.ts`](../classic-auto-complete/uselessSuggestionFilter.ts) | Duplication detection, postprocessing pipeline integration | -| [`AutocompleteTelemetry.ts`](../classic-auto-complete/AutocompleteTelemetry.ts) | Telemetry events: requested, filtered, cache hit, LLM completed/failed, accepted, unique shown | -| [`language-filters/index.ts`](../classic-auto-complete/language-filters/index.ts) | Language-specific post-filters (currently: markdown) | - -### External Dependencies (outside autocomplete module) - -- `vscode` API (`InlineCompletionItemProvider`, `TextDocument`, `Position`, etc.) -- `../../api/transform/stream` (`ApiStreamChunk`) -- `../../core/ignore/RooIgnoreController` (file access filtering) -- `../../core/webview/ClineProvider` -- `@roo-code/types`, `@roo-code/telemetry` - ---- - -## 4. `chat-autocomplete/` — Chat Text Area Autocomplete - -### Purpose - -Provides **autocomplete for the chat input text area** in the Kilo Code webview. When the user is typing a message in the chat panel, this module suggests completions for natural language text. - -### Architecture - -``` -Webview sends "requestChatCompletion" message - │ - ▼ -handleChatCompletionRequest() - │ - ├── Creates VisibleCodeTracker → captureVisibleCode() - ├── Creates ChatTextAreaAutocomplete - │ │ - │ ├── Initializes AutocompleteModel (same LLM layer) - │ ├── buildPrefix() — includes visible code context - │ │ - │ ├── FIM path: model.generateFimResponse() - │ └── Chat path: model.generateResponse() with chat-specific prompts - │ - │ cleanSuggestion(): - │ ├── removePrefixOverlap() - │ ├── postprocessAutocompleteSuggestion() - │ ├── Filter code-looking suggestions (//, /*, #) - │ └── Truncate at first newline - │ - └── Sends "chatCompletionResult" back to webview -``` - -### Communication - -- **Request**: Webview → Extension: `{ type: "requestChatCompletion", text, requestId }` -- **Response**: Extension → Webview: `{ type: "chatCompletionResult", text, requestId }` -- **Acceptance**: Webview → Extension: `{ type: "chatCompletionAccepted", suggestionLength }` - -### Key Files - -| File | Role | -| ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | -| [`ChatTextAreaAutocomplete.ts`](../chat-autocomplete/ChatTextAreaAutocomplete.ts) | Core logic: prompt building with visible code context, LLM call, cleaning | -| [`handleChatCompletionRequest.ts`](../chat-autocomplete/handleChatCompletionRequest.ts) | Message handler: creates tracker + autocomplete, sends result to webview | -| [`handleChatCompletionAccepted.ts`](../chat-autocomplete/handleChatCompletionAccepted.ts) | Telemetry handler for accepted suggestions | - -### External Dependencies - -- `../../core/webview/ClineProvider` (webview messaging) -- `../../core/config/ProviderSettingsManager` -- Reuses `AutocompleteTelemetry` and `postprocessAutocompleteSuggestion` from classic-auto-complete - ---- - -## 5. `context/` — Visible Code Context - -### Purpose - -Captures what code is **actually visible** in the user's VS Code editor viewports (not just which files are open). - -### [`VisibleCodeTracker.ts`](../context/VisibleCodeTracker.ts) - -- Iterates `vscode.window.visibleTextEditors` -- For each editor: captures file path, language ID, visible line ranges, cursor position, selections -- Extracts diff information from git-scheme URIs -- Filters out files matching security patterns (`isSecurityConcern`) and `.kilocodeignore` rules - -### External Dependencies - -- `vscode` API (`window.visibleTextEditors`, `TextEditor`) -- `../../../utils/path` (`toRelativePath`) -- `../continuedev/core/indexing/ignore` (`isSecurityConcern`) -- `../../../core/ignore/RooIgnoreController` - ---- - -## 6. `utils/` — Utility Functions - -### [`kilocode-utils.ts`](../utils/kilocode-utils.ts) - -- `checkKilocodeBalance(token, orgId)`: HTTP call to `/api/profile/balance` to verify positive balance. -- Re-exports `AUTOCOMPLETE_PROVIDER_MODELS` and `AutocompleteProviderKey` from `@roo-code/types`. - -### External Dependencies - -- `@roo-code/types` (`getKiloBaseUriFromToken`, `AUTOCOMPLETE_PROVIDER_MODELS`, `AutocompleteProviderKey`) -- Node.js `fetch` - ---- - -## Key Interfaces and Abstractions - -### Within the Module - -| Interface | Defined In | Purpose | -| ----------------------------- | ---------- | --------------------------------------------------------------------------------------------- | -| `AutocompleteInput` | `types.ts` | Input for both FIM and hole-filler strategies | -| `AutocompletePrompt` | `types.ts` | Discriminated union: `FimAutocompletePrompt \| HoleFillerAutocompletePrompt` | -| `FillInAtCursorSuggestion` | `types.ts` | Result: `{ text, prefix, suffix }` | -| `ResponseMetaData` | `types.ts` | Cost/token tracking | -| `AutocompleteContextProvider` | `types.ts` | Bundles `ContextRetrievalService` + `VsCodeIde` + `AutocompleteModel` + `RooIgnoreController` | -| `CostTrackingCallback` | `types.ts` | `(cost, inputTokens, outputTokens) => void` | -| `VisibleCodeContext` | `types.ts` | Captured visible editor state | - -### From continuedev - -| Interface | Defined In | Purpose | -| ------------------------ | ---------------------------------------- | -------------------------------------------------------------- | -| `IDE` | `continuedev/core/index.d.ts` | IDE abstraction (file I/O, LSP, editor state) | -| `ILLM` | `continuedev/core/index.d.ts` | LLM abstraction (streamComplete, streamFim, chat, countTokens) | -| `TabAutocompleteOptions` | `continuedev/core/index.d.ts` | Autocomplete configuration options | -| `AutocompleteSnippet` | `continuedev/core/autocomplete/types.ts` | Context snippet with type discrimination | - -### From External Code - -| Interface/Class | From | Used For | -| ------------------------- | --------------------- | ---------------------------------- | -| `ApiHandler` | `src/api/` | Chat-based LLM streaming | -| `FimHandler` | `src/api/` | FIM completion streaming | -| `ProviderSettingsManager` | `src/core/config/` | Profile and provider configuration | -| `ContextProxy` | `src/core/config/` | Global state persistence | -| `ClineProvider` | `src/core/webview/` | Webview messaging, task access | -| `RooIgnoreController` | `src/core/ignore/` | File access filtering | -| `TelemetryService` | `@roo-code/telemetry` | Event tracking | - ---- - -## Self-Contained vs. External Dependencies Summary - -### Self-Contained (within `src/services/autocomplete/`) - -- ✅ Completion pipeline logic (classic + chat) -- ✅ Contextual skip heuristics -- ✅ Suggestion history/cache management -- ✅ Duplication and uselessness filtering -- ✅ Language-specific filters -- ✅ Adaptive debouncing -- ✅ Visible code context capture -- ✅ Chat text area completion logic -- ✅ Telemetry event definitions -- ✅ continuedev library (context retrieval, snippet gathering, prompt templating, tree-sitter queries, postprocessing, LLM abstractions) - -### Requires External Reconstruction - -| Dependency | Source | What It Provides | -| --------------------------- | -------------------- | --------------------------------------------------------------------------------- | -| `ApiHandler` / `FimHandler` | `src/api/` | Actual LLM API calls (streaming FIM + chat) | -| `buildApiHandler()` | `src/api/` | Factory to create API handlers from profiles | -| `ProviderSettingsManager` | `src/core/config/` | Profile management, provider config | -| `ContextProxy` | `src/core/config/` | Persistent global state | -| `ClineProvider` | `src/core/webview/` | Webview messaging + task state | -| `RooIgnoreController` | `src/core/ignore/` | `.kilocodeignore` pattern matching | -| `vscode` API | VS Code | All editor integration (inline completions, status bar, commands, text documents) | -| `@roo-code/types` | `packages/types` | Shared type definitions, provider constants | -| `@roo-code/telemetry` | `packages/telemetry` | Telemetry event capture | -| `../../i18n` | `src/i18n/` | Localization | -| `../../utils/path` | `src/utils/` | Path utilities (`toRelativePath`) | -| `web-tree-sitter` | npm | Tree-sitter WASM parser (used by continuedev) | -| `PROVIDERS` constant | `webview-ui/` | Provider display name mapping | diff --git a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-vscode-integration.md b/packages/kilo-vscode/src/services/autocomplete/docs/investigation-vscode-integration.md deleted file mode 100644 index 5a8f99b92d0..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/docs/investigation-vscode-integration.md +++ /dev/null @@ -1,412 +0,0 @@ -# Investigation: VSCode Extension Integration Points for Autocomplete - -This document captures every integration point between the autocomplete feature and the -VSCode extension infrastructure. It's intended for use when recreating the extension shell -in a standalone package. - ---- - -## 1. package.json Contributions - -### 1.1 Activation Events - -```jsonc -// src/package.json lines 51-54 -"activationEvents": [ - "onLanguage", // activates for ANY language - "onStartupFinished" // activates after startup completes -] -``` - -There are no autocomplete-specific activation events. Both events are general-purpose. - -### 1.2 Commands - -Commands declared in `src/package.json` `contributes.commands`: - -| Command ID | Title Key | Registered in Code? | -| ------------------------------------------------ | ------------------------------------------------ | ------------------------------------------ | -| `kilo-code.autocomplete.generateSuggestions` | `%autocomplete.commands.generateSuggestions%` | ✅ `src/services/autocomplete/index.ts:26` | -| `kilo-code.autocomplete.cancelSuggestions` | `%autocomplete.commands.cancelSuggestions%` | ❌ Never registered — placeholder | -| `kilo-code.autocomplete.applyCurrentSuggestions` | `%autocomplete.commands.applyCurrentSuggestion%` | ❌ Never registered — placeholder | -| `kilo-code.autocomplete.applyAllSuggestions` | `%autocomplete.commands.applyAllSuggestions%` | ❌ Never registered — placeholder | -| `kilo-code.autocomplete.goToNextSuggestion` | `%autocomplete.commands.goToNextSuggestion%` | ❌ Never registered — placeholder | -| `kilo-code.autocomplete.goToPreviousSuggestion` | `%autocomplete.commands.goToPreviousSuggestion%` | ❌ Never registered — placeholder | - -Additional commands registered **programmatically** but NOT declared in package.json: - -| Command ID | Registered in | Notes | -| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------- | -| `kilo-code.autocomplete.reload` | `src/services/autocomplete/index.ts:16` | Reloads settings and model | -| `kilo-code.autocomplete.codeActionQuickFix` | `src/services/autocomplete/index.ts:21` | No-op stub | -| `kilo-code.autocomplete.showIncompatibilityExtensionPopup` | `src/services/autocomplete/index.ts:31` | Shows Copilot conflict dialog | -| `kilo-code.autocomplete.disable` | `src/services/autocomplete/index.ts:36` | Disables autocomplete | -| `kilocode.autocomplete.inline-completion.accepted` | `src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider.ts:313` | Telemetry callback when suggestion accepted | -| `kilo-code.jetbrains.getInlineCompletions` | `src/services/autocomplete/AutocompleteJetbrainsBridge.ts:289` | JetBrains bridge | - -### 1.3 Keybindings - -From `src/package.json` `contributes.keybindings`: - -| Command | Key | Mac | When Clause | -| ---------------------------------------------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `kilo-code.autocomplete.cancelSuggestions` | `Escape` | same | `editorTextFocus && !editorTabMovesFocus && !inSnippetMode && kilocode.autocomplete.hasSuggestions` | -| `kilo-code.autocomplete.generateSuggestions` | `Ctrl+L` | `Cmd+L` | `editorTextFocus && !editorTabMovesFocus && !inSnippetMode && kilocode.autocomplete.enableSmartInlineTaskKeybinding && !github.copilot.completions.enabled` | -| `kilo-code.autocomplete.showIncompatibilityExtensionPopup` | `Ctrl+L` | `Cmd+L` | `editorTextFocus && !editorTabMovesFocus && !inSnippetMode && kilocode.autocomplete.enableSmartInlineTaskKeybinding && github.copilot.completions.enabled` | - -**Note**: The `Escape` keybinding references `kilocode.autocomplete.hasSuggestions` which is -**never set** in code via `setContext`. This means the keybinding is currently inert -(would never activate). - -### 1.4 Menus - -There are **no menu contributions** for autocomplete commands. The autocomplete commands -do not appear in any editor/context, view/title, or other menu. - -### 1.5 Configuration Settings - -There are **no VSCode `configuration` contributions** for autocomplete in `package.json`. -Autocomplete settings are stored entirely in VSCode global state via `ContextProxy` under -the key `ghostServiceSettings`, not as workspace/user settings. - -### 1.6 Code Actions - -From `src/package.json`: - -```jsonc -"codeActions": [{ - "languages": ["*"], - "providedCodeActionKinds": ["vscode.CodeActionKind.QuickFix"] -}] -``` - -This is a general declaration. The autocomplete-specific code action provider is registered -programmatically in `src/services/autocomplete/index.ts:42-46`: - -```typescript -vscode.languages.registerCodeActionsProvider("*", autocompleteManager.codeActionProvider, { - providedCodeActionKinds: Object.values(autocompleteManager.codeActionProvider.providedCodeActionKinds), -}) -``` - -The `AutocompleteCodeActionProvider` (`src/services/autocomplete/AutocompleteCodeActionProvider.ts`) -provides a QuickFix action that triggers `kilo-code.autocomplete.generateSuggestions`. - ---- - -## 2. Extension Activation & Service Initialization - -### 2.1 Extension activation flow (`src/extension.ts`) - -1. **Import**: `registerAutocompleteProvider` imported from `./services/autocomplete` (line 49) -2. **First-install defaults** (lines 400-414): On first install, autocomplete is enabled: - ```typescript - const currentAutocompleteSettings = contextProxy.getValue("ghostServiceSettings") - await contextProxy.setValue("ghostServiceSettings", { - ...currentAutocompleteSettings, - enableAutoTrigger: !kiloCodeWrapperJetbrains, // disabled for JetBrains - enableSmartInlineTaskKeybinding: true, - }) - ``` -3. **Registration** (lines 512-520): Autocomplete is registered unless running as CLI: - ```typescript - if (kiloCodeWrapperCode !== "cli") { - registerAutocompleteProvider(context, provider) - } - ``` - -### 2.2 `registerAutocompleteProvider` (`src/services/autocomplete/index.ts`) - -This function: - -1. Creates `AutocompleteServiceManager` singleton -2. Registers JetBrains bridge via `registerAutocompleteJetbrainsBridge` -3. Registers 5 commands (reload, codeActionQuickFix, generateSuggestions, showIncompatibilityExtensionPopup, disable) -4. Registers `CodeActionsProvider` for all languages (`"*"`) - -### 2.3 `AutocompleteServiceManager` initialization - -On construction (`src/services/autocomplete/AutocompleteServiceManager.ts:37-61`): - -1. Creates `AutocompleteModel` for provider/model management -2. Creates `AutocompleteCodeActionProvider` for QuickFix code actions -3. Creates `AutocompleteInlineCompletionProvider` for inline completions -4. Calls `this.load()` to initialize - -### 2.4 `load()` method - -On load (`src/services/autocomplete/AutocompleteServiceManager.ts:70-99`): - -1. Reads `ghostServiceSettings` from `ContextProxy` -2. Sets context key `kilocode.autocomplete.enableSmartInlineTaskKeybinding` via `setContext` -3. Registers/unregisters `InlineCompletionItemProvider` based on `enableAutoTrigger` state -4. Updates status bar -5. Writes enriched settings (with provider/model info) back to `ContextProxy` -6. Posts state to webview - ---- - -## 3. Context Keys (setContext) - -| Context Key | Where Set | Purpose | -| ------------------------------------------------------- | ----------------------------------------------------------------- | -------------------------------------------------------- | -| `kilocode.autocomplete.enableSmartInlineTaskKeybinding` | `AutocompleteServiceManager.updateGlobalContext()` (line 286-290) | Controls whether `Cmd+L` / `Ctrl+L` keybinding is active | -| `kilocode.autocomplete.hasSuggestions` | ❌ Never set | Would control `Escape` keybinding — currently dead code | - ---- - -## 4. Webview State Integration - -### 4.1 State passing to webview (`src/core/webview/ClineProvider.ts`) - -The `ghostServiceSettings` is destructured from global state and included in the -state object sent to the webview at: - -- Line 2284: `ghostServiceSettings` extracted from state values -- Line 2480: `ghostServiceSettings: ghostServiceSettings` included in state to webview -- Line 2758: `ghostServiceSettings: stateValues.ghostServiceSettings` included in full state - -### 4.2 Webview message handlers (`src/core/webview/webviewMessageHandler.ts`) - -Three autocomplete-related message types are handled: - -1. **`ghostServiceSettings`** (lines 1972-1982): - - ```typescript - case "ghostServiceSettings": - const validatedSettings = autocompleteServiceSettingsSchema.parse(message.values) - await updateGlobalState("ghostServiceSettings", validatedSettings) - await provider.postStateToWebview() - vscode.commands.executeCommand("kilo-code.autocomplete.reload") - ``` - - This is the primary way the webview UI writes autocomplete settings. - -2. **`snoozeAutocomplete`** (lines 1983-1989): - - ```typescript - case "snoozeAutocomplete": - if (typeof message.value === "number" && message.value > 0) { - await AutocompleteServiceManager.getInstance()?.snooze(message.value) - } else { - await AutocompleteServiceManager.getInstance()?.unsnooze() - } - ``` - -3. **`requestChatCompletion`** (lines 3969-3975): Handles chat textarea FIM autocomplete. -4. **`chatCompletionAccepted`** (lines 3977-3979): Handles chat completion acceptance telemetry. - -### 4.3 Autocomplete reload triggered from webview - -The `kilo-code.autocomplete.reload` command is also triggered when API profiles change: - -- `saveApiConfiguration` (line 2231) -- `upsertApiConfiguration` (lines 2294, 2303) -- `renameApiConfiguration` (line 2330) -- `deleteApiConfiguration` (line 2407) - ---- - -## 5. Global State / ContextProxy - -### 5.1 State key - -The autocomplete feature uses a single global state key: - -``` -ghostServiceSettings: AutocompleteServiceSettings -``` - -Defined in `packages/types/src/global-settings.ts:230`: - -```typescript -ghostServiceSettings: autocompleteServiceSettingsSchema -``` - -### 5.2 Schema (`packages/types/src/kilocode/kilocode.ts:9-19`) - -```typescript -export const autocompleteServiceSettingsSchema = z - .object({ - enableAutoTrigger: z.boolean().optional(), - enableSmartInlineTaskKeybinding: z.boolean().optional(), - enableChatAutocomplete: z.boolean().optional(), - provider: z.string().optional(), - model: z.string().optional(), - snoozeUntil: z.number().optional(), - hasKilocodeProfileWithNoBalance: z.boolean().optional(), - }) - .optional() -``` - -### 5.3 Read/write patterns - -- **Read**: `ContextProxy.instance.getGlobalState("ghostServiceSettings")` -- **Write**: `ContextProxy.instance.setValues({ ghostServiceSettings: ... })` -- **WebView write**: sends `{ type: "ghostServiceSettings", values: ... }` message - -### 5.4 VSCode global state references - -The key `ghostServiceSettings` is listed as a valid global state key for webview -communication in `packages/types/src/vscode-extension-host.ts:546` and `795`. - ---- - -## 6. VSCode API Providers Registered - -| Provider Type | Registration | Scope | -| ------------------------------ | ------------------------------------------------------------------------- | ---------------------------------------------------- | -| `InlineCompletionItemProvider` | `AutocompleteServiceManager.updateInlineCompletionProviderRegistration()` | `{ scheme: "file" }` — only for file-based documents | -| `CodeActionsProvider` | `src/services/autocomplete/index.ts:42` | `"*"` — all languages | - -The inline completion provider is conditionally registered/disposed based on -`enableAutoTrigger` and snooze state. - ---- - -## 7. Status Bar - -`AutocompleteStatusBar` (`src/services/autocomplete/AutocompleteStatusBar.ts`): - -- Alignment: `vscode.StatusBarAlignment.Right`, priority 100 -- Shows/hides based on `enableAutoTrigger` setting -- Displays completion count, cost, provider info, and snoozed state -- Uses `$(kilo-logo)` codicon (custom icon font) - ---- - -## 8. i18n / Localization - -### 8.1 Package NLS keys (`src/package.nls.json` and locale variants) - -Keys used in `package.json` command titles: - -| Key | English Value | -| ---------------------------------------------- | ---------------------------------------------- | -| `autocomplete.commands.generateSuggestions` | Generate Suggested Edits | -| `autocomplete.commands.displaySuggestions` | Display Suggested Edits | -| `autocomplete.commands.cancelSuggestions` | Cancel Suggested Edits | -| `autocomplete.commands.applyCurrentSuggestion` | Apply Current Suggested Edit | -| `autocomplete.commands.applyAllSuggestions` | Apply All Suggested Edits | -| `autocomplete.commands.goToNextSuggestion` | Go To Next Suggestion | -| `autocomplete.commands.goToPreviousSuggestion` | Go To Previous Suggestion | -| `autocomplete.input.title` | Press 'Enter' to confirm or 'Escape' to cancel | -| `autocomplete.input.placeholder` | Describe what you want to do... | - -Translated in 20+ locale files: `src/package.nls.{de,fr,es,it,ja,ko,nl,pl,pt-BR,ru,sk,cs,uk,zh-CN,zh-TW,ar,ca,hi,id,th,tr,vi}.json`. - -### 8.2 Runtime i18n keys (src/i18n/locales/en/kilocode.json) - -Namespace: `kilocode:autocomplete.*` - -```jsonc -{ - "autocomplete": { - "statusBar": { - "enabled": "$(kilo-logo) Autocomplete", - "snoozed": "snoozed", - "warning": "$(warning) Autocomplete", - "tooltip": { - "basic": "Kilo Code Autocomplete", - "disabled": "Kilo Code Autocomplete (disabled)", - "noCredits": "...", - "noUsableProvider": "...", - "sessionTotal": "Session total cost:", - "provider": "Provider:", - "model": "Model:", - "profile": "Profile: ", - "defaultProfile": "Default", - "completionSummary": "Performed {{count}} completions between {{startTime}} and {{endTime}}, for a total cost of {{cost}}.", - "providerInfo": "Autocompletions provided by {{model}} via {{provider}}.", - }, - "cost": { - "zero": "$0.00", - "lessThanCent": "<$0.01", - }, - }, - "toggleMessage": "Kilo Code Autocomplete {{status}}", - "progress": { - "title": "Kilo Code", - "analyzing": "Analyzing your code...", - "generating": "Generating suggested edits...", - "processing": "Processing suggested edits...", - "showing": "Displaying suggested edits...", - }, - "input": { - "title": "Kilo Code: Quick Task", - "placeholder": "e.g., 'refactor this function to be more efficient'", - }, - "commands": { - "generateSuggestions": "Kilo Code: Generate Suggested Edits", - "displaySuggestions": "Display Suggested Edits", - "cancelSuggestions": "Cancel Suggested Edits", - "applyCurrentSuggestion": "Apply Current Suggested Edit", - "applyAllSuggestions": "Apply All Suggested Edits", - "category": "Kilo Code", - }, - "codeAction": { - "title": "Kilo Code: Suggested Edits", - }, - "chatParticipant": { - "fullName": "Kilo Code Agent", - "name": "Agent", - "description": "I can help you with quick tasks and suggested edits.", - }, - "incompatibilityExtensionPopup": { - "message": "The Kilo Code Autocomplete is being blocked by a conflict with GitHub Copilot. To fix this, you must disable Copilot's inline suggestions.", - "disableCopilot": "Disable Copilot", - "disableInlineAssist": "Disable Autocomplete", - }, - }, -} -``` - -Translated in all locale files under `src/i18n/locales/{locale}/kilocode.json`. - ---- - -## 9. Telemetry Events - -| Event | Where Used | -| -------------------------------------------- | -------------------------------------------------------------------- | -| `TelemetryEventName.INLINE_ASSIST_AUTO_TASK` | `AutocompleteServiceManager.codeSuggestion()` | -| `TelemetryEventName.GHOST_SERVICE_DISABLED` | `AutocompleteServiceManager.disable()` | -| Accept suggestion telemetry | `AutocompleteInlineCompletionProvider` via accepted command callback | - ---- - -## 10. Dependencies on Host Extension - -The autocomplete service depends on: - -1. **`ClineProvider`** — for `providerSettingsManager` (API provider configs), `postStateToWebview()` -2. **`ContextProxy`** — singleton for global state read/write -3. **`vscode.ExtensionContext`** — for `subscriptions` (disposable management), `globalState` -4. **Webview messaging** — bidirectional communication for settings changes -5. **Custom icon font** — `$(kilo-logo)` codicon from `assets/icons/kilo-icon-font.woff2` - ---- - -## 11. Legacy: Ghost Service - -The code refers to `ghostServiceSettings` and `GhostServiceManager` in -`src/services/ghost/` — this appears to be the original/predecessor copy. -The current active autocomplete uses `src/services/autocomplete/` which is -a refactored version. The `ghost` name persists in the global state key -`ghostServiceSettings` for backwards compatibility. - ---- - -## 12. Summary: What a New Extension Would Need - -To recreate the autocomplete as a standalone extension: - -1. **package.json**: 6 declared commands + keybindings + code action declaration -2. **Activation**: `onLanguage` + `onStartupFinished`, register providers on activate -3. **Providers**: `InlineCompletionItemProvider` (file scheme), `CodeActionsProvider` (all langs) -4. **Context keys**: `kilocode.autocomplete.enableSmartInlineTaskKeybinding` (via setContext) -5. **Status bar**: Right-aligned status bar item with custom icon -6. **State**: Single `ghostServiceSettings` object in global state (or a new key) -7. **Webview communication**: Message types `ghostServiceSettings`, `snoozeAutocomplete`, `requestChatCompletion`, `chatCompletionAccepted` -8. **i18n**: ~10 NLS keys in package.nls.json + ~30 runtime keys in kilocode.json -9. **Telemetry**: 2 primary event types diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/ar.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/ar.ts deleted file mode 100644 index 0d82dce70d6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/ar.ts +++ /dev/null @@ -1,49 +0,0 @@ -// ar runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "متوقف مؤقتاً", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (معطل)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**لم يتم تكوين نموذج الإكمال التلقائي**\n\nلتمكين الإكمال التلقائي، أضف ملفًا شخصيًا مع أحد هذه المزودين المدعومين: {{providers}}.\n\n[فتح الإعدادات]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "إجمالي تكلفة الجلسة:", - "kilocode:autocomplete.statusBar.tooltip.provider": "المزود:", - "kilocode:autocomplete.statusBar.tooltip.model": "النموذج:", - "kilocode:autocomplete.statusBar.tooltip.profile": "الملف الشخصي: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "افتراضي", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "تم إجراء {{count}} إكمال بين {{startTime}} و {{endTime}}، بتكلفة إجمالية {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "يتم توفير الإكمال التلقائي بواسطة {{model}} عبر {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "تحليل الكود الخاص بك...", - "kilocode:autocomplete.progress.generating": "إنشاء التعديلات المقترحة...", - "kilocode:autocomplete.progress.processing": "معالجة التعديلات المقترحة...", - "kilocode:autocomplete.progress.showing": "عرض التعديلات المقترحة...", - "kilocode:autocomplete.input.title": "Kilo Code: مهمة سريعة", - "kilocode:autocomplete.input.placeholder": "مثال، 'أعد هيكلة هذه الدالة لتكون أكثر كفاءة'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: إنشاء التعديلات المقترحة", - "kilocode:autocomplete.commands.displaySuggestions": "عرض التعديلات المقترحة", - "kilocode:autocomplete.commands.cancelSuggestions": "إلغاء التعديلات المقترحة", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "تطبيق التعديل المقترح الحالي", - "kilocode:autocomplete.commands.applyAllSuggestions": "تطبيق جميع التعديلات المقترحة", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: التعديلات المقترحة", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "يمكنني مساعدتك في المهام السريعة والتعديلات المقترحة.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "يتم حظر Kilo Code Autocomplete بسبب تعارض مع GitHub Copilot. لإصلاح هذا، يجب عليك تعطيل اقتراحات Copilot المضمنة.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "تعطيل Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "تعطيل الإكمال التلقائي", - "kilocode:autocomplete.creditsExhausted.message": - "تم إيقاف Kilo Code Autocomplete مؤقتًا لأن حسابك لا يحتوي على رصيد متبقٍ. أضف رصيدًا لاستئناف الإكمال التلقائي.", - "kilocode:autocomplete.creditsExhausted.addCredits": "إضافة رصيد", - "kilocode:autocomplete.authError.message": - "تم إيقاف Kilo Code Autocomplete مؤقتًا بسبب خطأ في المصادقة. يرجى تسجيل الدخول مرة أخرى.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/ca.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/ca.ts deleted file mode 100644 index 8fd2ed6ef49..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/ca.ts +++ /dev/null @@ -1,49 +0,0 @@ -// ca runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pausat", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (desactivat)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**No s'ha configurat cap model d'autocompletat**\n\nPer habilitar l'autocompletat, afegeix un perfil amb un d'aquests proveïdors compatibles: {{providers}}.\n\n[Obrir Configuració]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Cost total de la sessió:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Proveïdor:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Perfil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Per defecte", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "S'han realitzat {{count}} completacions entre {{startTime}} i {{endTime}}, amb un cost total de {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Les completacions automàtiques són proporcionades per {{model}} via {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analitzant el teu codi...", - "kilocode:autocomplete.progress.generating": "Generant edicions suggerides...", - "kilocode:autocomplete.progress.processing": "Processant edicions suggerides...", - "kilocode:autocomplete.progress.showing": "Mostrant edicions suggerides...", - "kilocode:autocomplete.input.title": "Kilo Code: Tasca Ràpida", - "kilocode:autocomplete.input.placeholder": "p. ex., 'refactoritza aquesta funció per ser més eficient'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Generar Edicions Suggerides", - "kilocode:autocomplete.commands.displaySuggestions": "Mostrar Edicions Suggerides", - "kilocode:autocomplete.commands.cancelSuggestions": "Cancel·lar Edicions Suggerides", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Aplicar Edició Suggerida Actual", - "kilocode:autocomplete.commands.applyAllSuggestions": "Aplicar Totes les Edicions Suggerides", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Edicions Suggerides", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Puc ajudar-te amb tasques ràpides i edicions suggerides.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "El Kilo Code Autocomplete està sent bloquejat per un conflicte amb GitHub Copilot. Per solucionar això, has de desactivar els suggeriments en línia de Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Desactivar Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Desactivar Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete s'ha pausat perquè el teu compte no té crèdits restants. Afegeix crèdits per reprendre l'autocompletat.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Afegir crèdits", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete s'ha pausat a causa d'un error d'autenticació. Si us plau, torna a iniciar sessió.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/cs.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/cs.ts deleted file mode 100644 index 4d0871c75ff..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/cs.ts +++ /dev/null @@ -1,49 +0,0 @@ -// cs runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pozastaveno", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (zakázáno)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Není nakonfigurován žádný model automatického doplňování**\n\nPro povolení automatického doplňování přidej profil s jedním z těchto podporovaných poskytovatelů: {{providers}}.\n\n[Otevřít Nastavení]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Celkové náklady relace:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Poskytovatel:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Výchozí", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Provedeno {{count}} dokončení mezi {{startTime}} a {{endTime}}, s celkovými náklady {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Automatické dokončování poskytuje {{model}} přes {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analyzuji tvůj kód...", - "kilocode:autocomplete.progress.generating": "Generuji navrhované úpravy...", - "kilocode:autocomplete.progress.processing": "Zpracovávám navrhované úpravy...", - "kilocode:autocomplete.progress.showing": "Zobrazuji navrhované úpravy...", - "kilocode:autocomplete.input.title": "Kilo Code: Rychlý úkol", - "kilocode:autocomplete.input.placeholder": "např. 'refaktoruj tuto funkci, aby byla efektivnější'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Generovat navrhované úpravy", - "kilocode:autocomplete.commands.displaySuggestions": "Zobrazit navrhované úpravy", - "kilocode:autocomplete.commands.cancelSuggestions": "Zrušit navrhované úpravy", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Použít aktuální navrhovanou úpravu", - "kilocode:autocomplete.commands.applyAllSuggestions": "Použít všechny navrhované úpravy", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Navrhované úpravy", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Mohu ti pomoci s rychlými úkoly a navrženými úpravami.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete je blokováno konfliktem s GitHub Copilot. Pro vyřešení tohoto problému musíš zakázat inline návrhy Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Zakázat Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Zakázat Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete bylo pozastaveno, protože na tvém účtu nezbyly žádné kredity. Přidej kredity pro obnovení automatického doplňování.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Přidat kredity", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete bylo pozastaveno kvůli chybě ověření. Prosím, přihlas se znovu.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/de.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/de.ts deleted file mode 100644 index 79a96f7183f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/de.ts +++ /dev/null @@ -1,50 +0,0 @@ -// de runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pausiert", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (deaktiviert)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Kein Autocomplete-Modell konfiguriert**\n\nUm Autocomplete zu aktivieren, füge ein Profil mit einem dieser unterstützten Anbieter hinzu: {{providers}}.\n\n[Einstellungen öffnen]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Sitzungsgesamtkosten:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Anbieter:", - "kilocode:autocomplete.statusBar.tooltip.model": "Modell:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Standard", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{count}} Vervollständigungen zwischen {{startTime}} und {{endTime}} durchgeführt, für Gesamtkosten von {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Autovervollständigungen bereitgestellt von {{model}} über {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analysiere deinen Code...", - "kilocode:autocomplete.progress.generating": "Generiere Bearbeitungsvorschläge...", - "kilocode:autocomplete.progress.processing": "Verarbeite Bearbeitungsvorschläge...", - "kilocode:autocomplete.progress.showing": "Zeige Bearbeitungsvorschläge...", - "kilocode:autocomplete.input.title": "Kilo Code: Schnellaufgabe", - "kilocode:autocomplete.input.placeholder": "z.B. 'refaktoriere diese Funktion für mehr Effizienz'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Bearbeitungsvorschläge generieren", - "kilocode:autocomplete.commands.displaySuggestions": "Bearbeitungsvorschläge anzeigen", - "kilocode:autocomplete.commands.cancelSuggestions": "Bearbeitungsvorschläge abbrechen", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Aktuellen Bearbeitungsvorschlag anwenden", - "kilocode:autocomplete.commands.applyAllSuggestions": "Alle Bearbeitungsvorschläge anwenden", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Bearbeitungsvorschläge", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Ich kann dir bei Schnellaufgaben und Bearbeitungsvorschlägen helfen.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Das Kilo Code Autocomplete wird durch einen Konflikt mit GitHub Copilot blockiert. Um dies zu beheben, musst du Copilots Inline-Vorschläge deaktivieren.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilot deaktivieren", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocomplete deaktivieren", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete wurde pausiert, weil dein Konto kein Guthaben mehr hat. Füge Guthaben hinzu, um Autocomplete fortzusetzen.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Guthaben hinzufügen", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete wurde aufgrund eines Authentifizierungsfehlers pausiert. Bitte melde dich erneut an.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/es.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/es.ts deleted file mode 100644 index 2a4f1be5f2b..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/es.ts +++ /dev/null @@ -1,49 +0,0 @@ -// es runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pausado", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (deshabilitado)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**No hay modelo de autocompletado configurado**\n\nPara habilitar el autocompletado, añade un perfil con uno de estos proveedores compatibles: {{providers}}.\n\n[Abrir Configuración]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Costo total de la sesión:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Proveedor:", - "kilocode:autocomplete.statusBar.tooltip.model": "Modelo:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Perfil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Predeterminado", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Se realizaron {{count}} completaciones entre {{startTime}} y {{endTime}}, por un costo total de {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Autocompletaciones proporcionadas por {{model}} a través de {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analizando tu código...", - "kilocode:autocomplete.progress.generating": "Generando ediciones sugeridas...", - "kilocode:autocomplete.progress.processing": "Procesando ediciones sugeridas...", - "kilocode:autocomplete.progress.showing": "Mostrando ediciones sugeridas...", - "kilocode:autocomplete.input.title": "Kilo Code: Tarea Rápida", - "kilocode:autocomplete.input.placeholder": "ej., 'refactoriza esta función para que sea más eficiente'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Generar Ediciones Sugeridas", - "kilocode:autocomplete.commands.displaySuggestions": "Mostrar Ediciones Sugeridas", - "kilocode:autocomplete.commands.cancelSuggestions": "Cancelar Ediciones Sugeridas", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Aplicar Edición Sugerida Actual", - "kilocode:autocomplete.commands.applyAllSuggestions": "Aplicar Todas las Ediciones Sugeridas", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Ediciones Sugeridas", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Puedo ayudarte con tareas rápidas y ediciones sugeridas.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "El Kilo Code Autocomplete está siendo bloqueado por un conflicto con GitHub Copilot. Para solucionarlo, debes desactivar las sugerencias en línea de Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Desactivar Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Desactivar Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete se ha pausado porque tu cuenta no tiene créditos restantes. Añade créditos para reanudar el autocompletado.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Añadir créditos", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete se ha pausado debido a un error de autenticación. Por favor, inicia sesión de nuevo.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/fr.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/fr.ts deleted file mode 100644 index 10f3ef7024d..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/fr.ts +++ /dev/null @@ -1,49 +0,0 @@ -// fr runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "en pause", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (désactivé)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Aucun modèle d'autocomplétion configuré**\n\nPour activer l'autocomplétion, ajoute un profil avec l'un de ces fournisseurs pris en charge : {{providers}}.\n\n[Ouvrir les Paramètres]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Coût total de la session :", - "kilocode:autocomplete.statusBar.tooltip.provider": "Fournisseur:", - "kilocode:autocomplete.statusBar.tooltip.model": "Modèle :", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil : ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Par défaut", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{count}} complétions effectuées entre {{startTime}} et {{endTime}}, pour un coût total de {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "Auto-complétions fournies par {{model}} via {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analyse de ton code...", - "kilocode:autocomplete.progress.generating": "Génération des modifications suggérées...", - "kilocode:autocomplete.progress.processing": "Traitement des modifications suggérées...", - "kilocode:autocomplete.progress.showing": "Affichage des modifications suggérées...", - "kilocode:autocomplete.input.title": "Kilo Code : Tâche Rapide", - "kilocode:autocomplete.input.placeholder": "ex., 'refactorise cette fonction pour plus d'efficacité'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code : Générer des Modifications Suggérées", - "kilocode:autocomplete.commands.displaySuggestions": "Afficher les Modifications Suggérées", - "kilocode:autocomplete.commands.cancelSuggestions": "Annuler les Modifications Suggérées", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Appliquer la Modification Suggérée Actuelle", - "kilocode:autocomplete.commands.applyAllSuggestions": "Appliquer Toutes les Modifications Suggérées", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code : Modifications Suggérées", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Je peux t'aider avec des tâches rapides et des modifications suggérées.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Le Kilo Code Autocomplete est bloqué par un conflit avec GitHub Copilot. Pour résoudre cela, tu dois désactiver les suggestions en ligne de Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Désactiver Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Désactiver Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete a été mis en pause car ton compte n'a plus de crédits. Ajoute des crédits pour reprendre l'autocomplétion.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Ajouter des crédits", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete a été mis en pause en raison d'une erreur d'authentification. Veuillez te reconnecter.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/hi.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/hi.ts deleted file mode 100644 index 6c8d7ad6298..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/hi.ts +++ /dev/null @@ -1,50 +0,0 @@ -// hi runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "रोका गया", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (अक्षम)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**कोई ऑटोकम्प्लीट मॉडल कॉन्फ़िगर नहीं किया गया**\n\nऑटोकम्प्लीट सक्षम करने के लिए, इन समर्थित प्रदाताओं में से एक के साथ एक प्रोफ़ाइल जोड़ें: {{providers}}।\n\n[सेटिंग्स खोलें]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "सत्र की कुल लागत:", - "kilocode:autocomplete.statusBar.tooltip.provider": "प्रदाता:", - "kilocode:autocomplete.statusBar.tooltip.model": "मॉडल:", - "kilocode:autocomplete.statusBar.tooltip.profile": "प्रोफ़ाइल: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "डिफ़ॉल्ट", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{startTime}} और {{endTime}} के बीच {{count}} पूर्णताएं की गईं, कुल लागत {{cost}}।", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "स्वत: पूर्णता {{provider}} के माध्यम से {{model}} द्वारा प्रदान की जाती है।", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "आपके कोड का विश्लेषण कर रहे हैं...", - "kilocode:autocomplete.progress.generating": "सुझाए गए संपादन बना रहे हैं...", - "kilocode:autocomplete.progress.processing": "सुझाए गए संपादन प्रोसेस कर रहे हैं...", - "kilocode:autocomplete.progress.showing": "सुझाए गए संपादन दिखा रहे हैं...", - "kilocode:autocomplete.input.title": "Kilo Code: त्वरित कार्य", - "kilocode:autocomplete.input.placeholder": "जैसे, 'इस फ़ंक्शन को अधिक कुशल बनाने के लिए रिफैक्टर करें'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: सुझाए गए संपादन जेनरेट करें", - "kilocode:autocomplete.commands.displaySuggestions": "सुझाए गए संपादन दिखाएं", - "kilocode:autocomplete.commands.cancelSuggestions": "सुझाए गए संपादन रद्द करें", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "वर्तमान सुझाए गए संपादन लागू करें", - "kilocode:autocomplete.commands.applyAllSuggestions": "सभी सुझाए गए संपादन लागू करें", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: सुझाए गए संपादन", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "मैं त्वरित कार्यों और सुझाए गए संपादनों में आपकी सहायता कर सकता हूं।", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete को GitHub Copilot के साथ संघर्ष के कारण ब्लॉक किया जा रहा है। इसे ठीक करने के लिए, आपको Copilot के इनलाइन सुझावों को अक्षम करना होगा।", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilot अक्षम करें", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocomplete अक्षम करें", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete रोक दिया गया है क्योंकि आपके खाते में शेष क्रेडिट नहीं है। ऑटोकम्प्लीट फिर से शुरू करने के लिए क्रेडिट जोड़ें।", - "kilocode:autocomplete.creditsExhausted.addCredits": "क्रेडिट जोड़ें", - "kilocode:autocomplete.authError.message": - "प्रमाणीकरण त्रुटि के कारण Kilo Code Autocomplete रोक दिया गया है। कृपया फिर से साइन इन करें।", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/id.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/id.ts deleted file mode 100644 index 30096caa196..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/id.ts +++ /dev/null @@ -1,50 +0,0 @@ -// id runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "dijeda", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (dinonaktifkan)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Tidak ada model autocomplete yang dikonfigurasi**\n\nUntuk mengaktifkan autocomplete, tambahkan profil dengan salah satu penyedia yang didukung ini: {{providers}}.\n\n[Buka Pengaturan]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Total biaya sesi:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Penyedia:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Default", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Melakukan {{count}} penyelesaian antara {{startTime}} dan {{endTime}}, dengan total biaya {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Pelengkapan otomatis disediakan oleh {{model}} melalui {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Menganalisis kode Anda...", - "kilocode:autocomplete.progress.generating": "Menghasilkan suntingan yang disarankan...", - "kilocode:autocomplete.progress.processing": "Memproses suntingan yang disarankan...", - "kilocode:autocomplete.progress.showing": "Menampilkan suntingan yang disarankan...", - "kilocode:autocomplete.input.title": "Kilo Code: Tugas Cepat", - "kilocode:autocomplete.input.placeholder": "mis., 'refaktor fungsi ini agar lebih efisien'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Hasilkan Suntingan yang Disarankan", - "kilocode:autocomplete.commands.displaySuggestions": "Tampilkan Suntingan yang Disarankan", - "kilocode:autocomplete.commands.cancelSuggestions": "Batalkan Suntingan yang Disarankan", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Terapkan Suntingan yang Disarankan Saat Ini", - "kilocode:autocomplete.commands.applyAllSuggestions": "Terapkan Semua Suntingan yang Disarankan", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Suntingan yang Disarankan", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Saya dapat membantu Anda dengan tugas cepat dan suntingan yang disarankan.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete diblokir oleh konflik dengan GitHub Copilot. Untuk memperbaiki ini, Anda harus menonaktifkan saran inline Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Nonaktifkan Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Nonaktifkan Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete telah dijeda karena akun Anda tidak memiliki sisa kredit. Tambahkan kredit untuk melanjutkan autocomplete.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Tambah Kredit", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete telah dijeda karena kesalahan autentikasi. Silakan masuk kembali.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/it.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/it.ts deleted file mode 100644 index ca0133c09ea..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/it.ts +++ /dev/null @@ -1,49 +0,0 @@ -// it runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "in pausa", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (disabilitato)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Nessun modello di autocompletamento configurato**\n\nPer abilitare l'autocompletamento, aggiungi un profilo con uno di questi provider supportati: {{providers}}.\n\n[Apri Impostazioni]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Costo totale della sessione:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Provider:", - "kilocode:autocomplete.statusBar.tooltip.model": "Modello:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profilo: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Predefinito", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Eseguiti {{count}} completamenti tra {{startTime}} e {{endTime}}, per un costo totale di {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Autocompletamenti forniti da {{model}} tramite {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analizzando il tuo codice...", - "kilocode:autocomplete.progress.generating": "Generando modifiche suggerite...", - "kilocode:autocomplete.progress.processing": "Elaborando modifiche suggerite...", - "kilocode:autocomplete.progress.showing": "Mostrando modifiche suggerite...", - "kilocode:autocomplete.input.title": "Kilo Code: Attività Rapida", - "kilocode:autocomplete.input.placeholder": "es., 'refactorizza questa funzione per renderla più efficiente'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Genera Modifiche Suggerite", - "kilocode:autocomplete.commands.displaySuggestions": "Mostra Modifiche Suggerite", - "kilocode:autocomplete.commands.cancelSuggestions": "Annulla Modifiche Suggerite", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Applica Modifica Suggerita Corrente", - "kilocode:autocomplete.commands.applyAllSuggestions": "Applica Tutte le Modifiche Suggerite", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Modifiche Suggerite", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Posso aiutarti con attività rapide e modifiche suggerite.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Il Kilo Code Autocomplete è bloccato da un conflitto con GitHub Copilot. Per risolvere questo problema, devi disabilitare i suggerimenti in linea di Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Disabilita Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Disabilita Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete è stato messo in pausa perché il tuo account non ha più crediti. Aggiungi crediti per riprendere l'autocompletamento.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Aggiungi crediti", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete è stato messo in pausa a causa di un errore di autenticazione. Effettua nuovamente l'accesso.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/ja.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/ja.ts deleted file mode 100644 index f09f6e6f4ac..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/ja.ts +++ /dev/null @@ -1,49 +0,0 @@ -// ja runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "一時停止中", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete(無効)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**オートコンプリートモデルが設定されていません**\n\nオートコンプリートを有効にするには、これらのサポートされているプロバイダーのいずれかでプロファイルを追加してください: {{providers}}。\n\n[設定を開く]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "セッション合計コスト:", - "kilocode:autocomplete.statusBar.tooltip.provider": "プロバイダー:", - "kilocode:autocomplete.statusBar.tooltip.model": "モデル:", - "kilocode:autocomplete.statusBar.tooltip.profile": "プロファイル: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "デフォルト", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{startTime}}から{{endTime}}の間に{{count}}回の補完を実行し、合計コストは{{cost}}です。", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "オートコンプリートは{{provider}}経由で{{model}}によって提供されています。", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "コードを分析中...", - "kilocode:autocomplete.progress.generating": "編集提案を生成中...", - "kilocode:autocomplete.progress.processing": "編集提案を処理中...", - "kilocode:autocomplete.progress.showing": "編集提案を表示中...", - "kilocode:autocomplete.input.title": "Kilo Code: クイックタスク", - "kilocode:autocomplete.input.placeholder": "例:「この関数をより効率的にリファクタリングして」", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: 編集提案を生成", - "kilocode:autocomplete.commands.displaySuggestions": "編集提案を表示", - "kilocode:autocomplete.commands.cancelSuggestions": "編集提案をキャンセル", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "現在の編集提案を適用", - "kilocode:autocomplete.commands.applyAllSuggestions": "すべての編集提案を適用", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: 編集提案", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "クイックタスクと編集提案でお手伝いできます。", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code AutocompleteがGitHub Copilotとの競合によってブロックされています。これを修正するには、Copilotのインライン提案を無効にする必要があります。", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilotを無効にする", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocompleteを無効にする", - "kilocode:autocomplete.creditsExhausted.message": - "アカウントのクレジットが残っていないため、Kilo Code Autocompleteが一時停止されました。オートコンプリートを再開するにはクレジットを追加してください。", - "kilocode:autocomplete.creditsExhausted.addCredits": "クレジットを追加", - "kilocode:autocomplete.authError.message": - "認証エラーのため、Kilo Code Autocompleteが一時停止されました。再度サインインしてください。", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/ko.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/ko.ts deleted file mode 100644 index 9258f8f7a5f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/ko.ts +++ /dev/null @@ -1,48 +0,0 @@ -// ko runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "일시 중지됨", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (비활성화됨)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**자동완성 모델이 구성되지 않았습니다**\n\n자동완성을 활성화하려면 다음 지원되는 제공업체 중 하나로 프로필을 추가하세요: {{providers}}.\n\n[설정 열기]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "세션 총 비용:", - "kilocode:autocomplete.statusBar.tooltip.provider": "제공업체:", - "kilocode:autocomplete.statusBar.tooltip.model": "모델:", - "kilocode:autocomplete.statusBar.tooltip.profile": "프로필: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "기본값", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{startTime}}부터 {{endTime}}까지 {{count}}회 완성을 수행했으며, 총 비용은 {{cost}}입니다.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "자동완성은 {{provider}}를 통해 {{model}}에서 제공됩니다.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "코드 분석 중...", - "kilocode:autocomplete.progress.generating": "제안된 편집 생성 중...", - "kilocode:autocomplete.progress.processing": "제안된 편집 처리 중...", - "kilocode:autocomplete.progress.showing": "제안된 편집 표시 중...", - "kilocode:autocomplete.input.title": "Kilo Code: 빠른 작업", - "kilocode:autocomplete.input.placeholder": "예: '이 함수를 더 효율적으로 리팩토링해줘'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: 제안된 편집 생성", - "kilocode:autocomplete.commands.displaySuggestions": "제안된 편집 표시", - "kilocode:autocomplete.commands.cancelSuggestions": "제안된 편집 취소", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "현재 제안된 편집 적용", - "kilocode:autocomplete.commands.applyAllSuggestions": "모든 제안된 편집 적용", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: 제안된 편집", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "빠른 작업과 제안된 편집으로 도움을 드릴 수 있습니다.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete가 GitHub Copilot과의 충돌로 인해 차단되고 있습니다. 이를 해결하려면 Copilot의 인라인 제안을 비활성화해야 합니다.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilot 비활성화", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocomplete 비활성화", - "kilocode:autocomplete.creditsExhausted.message": - "계정에 남은 크레딧이 없어 Kilo Code Autocomplete가 일시 중지되었습니다. 자동완성을 재개하려면 크레딧을 추가하세요.", - "kilocode:autocomplete.creditsExhausted.addCredits": "크레딧 추가", - "kilocode:autocomplete.authError.message": - "인증 오류로 인해 Kilo Code Autocomplete가 일시 중지되었습니다. 다시 로그인해 주세요.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/nl.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/nl.ts deleted file mode 100644 index f7859dff23b..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/nl.ts +++ /dev/null @@ -1,50 +0,0 @@ -// Dutch runtime translations for autocomplete (kilocode:autocomplete.* namespace) -// Source: src/i18n/locales/nl/kilocode.json → "autocomplete" section - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "gepauzeerd", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (uitgeschakeld)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Geen autocomplete-model geconfigureerd**\n\nVoeg een profiel toe met een van deze ondersteunde providers om autocomplete in te schakelen: {{providers}}.\n\n[Instellingen openen]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Totale sessiekosten:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Provider:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profiel: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Standaard", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{count}} aanvullingen uitgevoerd tussen {{startTime}} en {{endTime}}, voor totale kosten van {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Automatische aanvullingen geleverd door {{model}} via {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Je code analyseren...", - "kilocode:autocomplete.progress.generating": "Voorgestelde bewerkingen genereren...", - "kilocode:autocomplete.progress.processing": "Voorgestelde bewerkingen verwerken...", - "kilocode:autocomplete.progress.showing": "Voorgestelde bewerkingen weergeven...", - "kilocode:autocomplete.input.title": "Kilo Code: Snelle taak", - "kilocode:autocomplete.input.placeholder": "bijv. 'herschrijf deze functie om efficiënter te zijn'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Voorgestelde bewerkingen genereren", - "kilocode:autocomplete.commands.displaySuggestions": "Voorgestelde bewerkingen weergeven", - "kilocode:autocomplete.commands.cancelSuggestions": "Voorgestelde bewerkingen annuleren", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Huidige voorgestelde bewerking toepassen", - "kilocode:autocomplete.commands.applyAllSuggestions": "Alle voorgestelde bewerkingen toepassen", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Voorgestelde bewerkingen", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Ik kan je helpen met snelle taken en voorgestelde bewerkingen.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "De Kilo Code Autocomplete wordt geblokkeerd door een conflict met GitHub Copilot. Om dit op te lossen, moet je de inline suggesties van Copilot uitschakelen.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilot uitschakelen", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocomplete uitschakelen", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete is gepauzeerd omdat je account geen tegoed meer heeft. Voeg tegoed toe om autocomplete te hervatten.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Tegoed toevoegen", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete is gepauzeerd vanwege een authenticatiefout. Meld je opnieuw aan.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ar.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ar.ts deleted file mode 100644 index 53561ae074f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ar.ts +++ /dev/null @@ -1,13 +0,0 @@ -// ar package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "اضغط 'Enter' للتأكيد أو 'Escape' للإلغاء", - "autocomplete.input.placeholder": "صف ما تريد فعله...", - "autocomplete.commands.generateSuggestions": "Kilo Code: إنشاء التعديلات المقترحة", - "autocomplete.commands.displaySuggestions": "عرض التعديلات المقترحة", - "autocomplete.commands.cancelSuggestions": "إلغاء التعديلات المقترحة", - "autocomplete.commands.applyCurrentSuggestion": "تطبيق التعديل المقترح الحالي", - "autocomplete.commands.applyAllSuggestions": "تطبيق جميع التعديلات المقترحة", - "autocomplete.commands.goToNextSuggestion": "انتقل إلى الاقتراح التالي", - "autocomplete.commands.goToPreviousSuggestion": "انتقل إلى الاقتراح السابق", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ca.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ca.ts deleted file mode 100644 index 7b7bfdd3ebe..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ca.ts +++ /dev/null @@ -1,13 +0,0 @@ -// ca package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Premeu 'Enter' per confirmar o 'Escape' per cancel·lar", - "autocomplete.input.placeholder": "Descriviu què voleu fer...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Generar Edicions Suggerides", - "autocomplete.commands.displaySuggestions": "Mostrar Edicions Suggerides", - "autocomplete.commands.cancelSuggestions": "Cancel·lar Edicions Suggerides", - "autocomplete.commands.applyCurrentSuggestion": "Aplicar Edició Suggerida Actual", - "autocomplete.commands.applyAllSuggestions": "Aplicar Totes les Edicions Suggerides", - "autocomplete.commands.goToNextSuggestion": "Anar al Suggeriment Següent", - "autocomplete.commands.goToPreviousSuggestion": "Anar al Suggeriment Anterior", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-cs.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-cs.ts deleted file mode 100644 index d7cfeef27bd..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-cs.ts +++ /dev/null @@ -1,13 +0,0 @@ -// cs package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Stiskněte 'Enter' pro potvrzení nebo 'Escape' pro zrušení", - "autocomplete.input.placeholder": "Popište, co chcete udělat...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Generovat Navrhované Úpravy", - "autocomplete.commands.displaySuggestions": "Zobrazit Navrhované Úpravy", - "autocomplete.commands.cancelSuggestions": "Zrušit Navrhované Úpravy", - "autocomplete.commands.applyCurrentSuggestion": "Použít Aktuální Navrženou Úpravu", - "autocomplete.commands.applyAllSuggestions": "Použít Všechny Navrhované Úpravy", - "autocomplete.commands.goToNextSuggestion": "Přejít na Další Návrh", - "autocomplete.commands.goToPreviousSuggestion": "Přejít na Předchozí Návrh", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-de.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-de.ts deleted file mode 100644 index 980859a4e5b..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-de.ts +++ /dev/null @@ -1,13 +0,0 @@ -// de package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Kilo Code Geisterschreiber", - "autocomplete.input.placeholder": "Beschreiben Sie, was Sie programmieren möchten...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Vorgeschlagene Bearbeitungen Generieren", - "autocomplete.commands.displaySuggestions": "Vorgeschlagene Bearbeitungen Anzeigen", - "autocomplete.commands.cancelSuggestions": "Vorgeschlagene Bearbeitungen Abbrechen", - "autocomplete.commands.applyCurrentSuggestion": "Aktuelle Vorgeschlagene Bearbeitung Anwenden", - "autocomplete.commands.applyAllSuggestions": "Alle Vorgeschlagenen Bearbeitungen Anwenden", - "autocomplete.commands.goToNextSuggestion": "Zur Nächsten Vorgeschlagenen Bearbeitung", - "autocomplete.commands.goToPreviousSuggestion": "Zur Vorherigen Vorgeschlagenen Bearbeitung", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-en.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-en.ts deleted file mode 100644 index b87d3668e04..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-en.ts +++ /dev/null @@ -1,14 +0,0 @@ -// English package.nls translations for autocomplete (used in package.json command titles/descriptions) -// Source: src/package.nls.json → "autocomplete.*" keys - -export const dict = { - "autocomplete.input.title": "Press 'Enter' to confirm or 'Escape' to cancel", - "autocomplete.input.placeholder": "Describe what you want to do...", - "autocomplete.commands.generateSuggestions": "Generate Suggested Edits", - "autocomplete.commands.displaySuggestions": "Display Suggested Edits", - "autocomplete.commands.cancelSuggestions": "Cancel Suggested Edits", - "autocomplete.commands.applyCurrentSuggestion": "Apply Current Suggested Edit", - "autocomplete.commands.applyAllSuggestions": "Apply All Suggested Edits", - "autocomplete.commands.goToNextSuggestion": "Go To Next Suggestion", - "autocomplete.commands.goToPreviousSuggestion": "Go To Previous Suggestion", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-es.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-es.ts deleted file mode 100644 index e307b9d0b40..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-es.ts +++ /dev/null @@ -1,13 +0,0 @@ -// es package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Presiona 'Enter' para confirmar o 'Escape' para cancelar", - "autocomplete.input.placeholder": "Describe lo que quieres hacer...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Generar Ediciones Sugeridas", - "autocomplete.commands.displaySuggestions": "Mostrar Ediciones Sugeridas", - "autocomplete.commands.cancelSuggestions": "Cancelar Ediciones Sugeridas", - "autocomplete.commands.applyCurrentSuggestion": "Aplicar Edición Sugerida Actual", - "autocomplete.commands.applyAllSuggestions": "Aplicar Todas las Ediciones Sugeridas", - "autocomplete.commands.goToNextSuggestion": "Ir a la Siguiente Sugerencia", - "autocomplete.commands.goToPreviousSuggestion": "Ir a la Sugerencia Anterior", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-fr.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-fr.ts deleted file mode 100644 index cf02624704f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-fr.ts +++ /dev/null @@ -1,13 +0,0 @@ -// fr package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Écrivain fantôme Kilo Code", - "autocomplete.input.placeholder": "Décrivez ce que vous voulez coder...", - "autocomplete.commands.generateSuggestions": "Kilo Code : Générer des Modifications Suggérées", - "autocomplete.commands.displaySuggestions": "Afficher les Modifications Suggérées", - "autocomplete.commands.cancelSuggestions": "Annuler les Modifications Suggérées", - "autocomplete.commands.applyCurrentSuggestion": "Appliquer la Modification Suggérée Actuelle", - "autocomplete.commands.applyAllSuggestions": "Appliquer Toutes les Modifications Suggérées", - "autocomplete.commands.goToNextSuggestion": "Aller à la Suggestion Suivante", - "autocomplete.commands.goToPreviousSuggestion": "Aller à la Suggestion Précédente", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-hi.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-hi.ts deleted file mode 100644 index de48ca0dd53..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-hi.ts +++ /dev/null @@ -1,13 +0,0 @@ -// hi package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "पुष्टि के लिए 'Enter' दबाएं या रद्द करने के लिए 'Escape' दबाएं", - "autocomplete.input.placeholder": "वर्णन करें कि आप क्या करना चाहते हैं...", - "autocomplete.commands.generateSuggestions": "Kilo Code: सुझाए गए संपादन जेनरेट करें", - "autocomplete.commands.displaySuggestions": "सुझाए गए संपादन दिखाएं", - "autocomplete.commands.cancelSuggestions": "सुझाए गए संपादन रद्द करें", - "autocomplete.commands.applyCurrentSuggestion": "वर्तमान सुझाया गया संपादन लागू करें", - "autocomplete.commands.applyAllSuggestions": "सभी सुझाए गए संपादन लागू करें", - "autocomplete.commands.goToNextSuggestion": "अगले सुझाव पर जाएं", - "autocomplete.commands.goToPreviousSuggestion": "पिछले सुझाव पर जाएं", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-id.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-id.ts deleted file mode 100644 index 704fe5009d9..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-id.ts +++ /dev/null @@ -1,13 +0,0 @@ -// id package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Tekan 'Enter' untuk konfirmasi atau 'Escape' untuk membatalkan", - "autocomplete.input.placeholder": "Jelaskan apa yang ingin Anda lakukan...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Buat Saran Pengeditan", - "autocomplete.commands.displaySuggestions": "Tampilkan Saran Pengeditan", - "autocomplete.commands.cancelSuggestions": "Batalkan Saran Pengeditan", - "autocomplete.commands.applyCurrentSuggestion": "Terapkan Saran Pengeditan Saat Ini", - "autocomplete.commands.applyAllSuggestions": "Terapkan Semua Saran Pengeditan", - "autocomplete.commands.goToNextSuggestion": "Pergi ke Saran Berikutnya", - "autocomplete.commands.goToPreviousSuggestion": "Pergi ke Saran Sebelumnya", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-it.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-it.ts deleted file mode 100644 index 8d205775fba..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-it.ts +++ /dev/null @@ -1,13 +0,0 @@ -// it package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Scrittore Fantasma Kilo Code", - "autocomplete.input.placeholder": "Descrivi cosa vuoi programmare...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Genera Modifiche Suggerite", - "autocomplete.commands.displaySuggestions": "Visualizza Modifiche Suggerite", - "autocomplete.commands.cancelSuggestions": "Annulla Modifiche Suggerite", - "autocomplete.commands.applyCurrentSuggestion": "Applica Modifica Suggerita Corrente", - "autocomplete.commands.applyAllSuggestions": "Applica Tutte le Modifiche Suggerite", - "autocomplete.commands.goToNextSuggestion": "Vai alla Prossima Suggerimento", - "autocomplete.commands.goToPreviousSuggestion": "Vai al Suggerimento Precedente", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ja.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ja.ts deleted file mode 100644 index 263dbf53a77..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ja.ts +++ /dev/null @@ -1,13 +0,0 @@ -// ja package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Kilo Code ゴーストライター", - "autocomplete.input.placeholder": "コーディングしたい内容を説明してください...", - "autocomplete.commands.generateSuggestions": "Kilo Code: 提案された編集を生成", - "autocomplete.commands.displaySuggestions": "提案された編集を表示", - "autocomplete.commands.cancelSuggestions": "提案された編集をキャンセル", - "autocomplete.commands.applyCurrentSuggestion": "現在の提案された編集を適用", - "autocomplete.commands.applyAllSuggestions": "すべての提案された編集を適用", - "autocomplete.commands.goToNextSuggestion": "次の提案に移動", - "autocomplete.commands.goToPreviousSuggestion": "前の提案に移動", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ko.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ko.ts deleted file mode 100644 index 84e00705a44..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ko.ts +++ /dev/null @@ -1,13 +0,0 @@ -// ko package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "'Enter'를 눌러 확인하거나 'Escape'를 눌러 취소하세요", - "autocomplete.input.placeholder": "무엇을 하고 싶은지 설명해주세요...", - "autocomplete.commands.generateSuggestions": "Kilo Code: 편집 제안 생성", - "autocomplete.commands.displaySuggestions": "편집 제안 표시", - "autocomplete.commands.cancelSuggestions": "편집 제안 취소", - "autocomplete.commands.applyCurrentSuggestion": "현재 편집 제안 적용", - "autocomplete.commands.applyAllSuggestions": "모든 편집 제안 적용", - "autocomplete.commands.goToNextSuggestion": "다음 제안으로 이동", - "autocomplete.commands.goToPreviousSuggestion": "이전 제안으로 이동", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-nl.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-nl.ts deleted file mode 100644 index 9b8c240c293..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-nl.ts +++ /dev/null @@ -1,13 +0,0 @@ -// nl package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Druk op 'Enter' om te bevestigen of 'Escape' om te annuleren", - "autocomplete.input.placeholder": "Beschrijf wat je wilt doen...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Bewerkingssuggesties Genereren", - "autocomplete.commands.displaySuggestions": "Bewerkingssuggesties Weergeven", - "autocomplete.commands.cancelSuggestions": "Bewerkingssuggesties Annuleren", - "autocomplete.commands.applyCurrentSuggestion": "Huidige Bewerkingssuggestie Toepassen", - "autocomplete.commands.applyAllSuggestions": "Alle Bewerkingssuggesties Toepassen", - "autocomplete.commands.goToNextSuggestion": "Ga Naar Volgende Suggestie", - "autocomplete.commands.goToPreviousSuggestion": "Ga Naar Vorige Suggestie", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pl.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pl.ts deleted file mode 100644 index e113d8eff90..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pl.ts +++ /dev/null @@ -1,13 +0,0 @@ -// pl package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Naciśnij 'Enter' aby potwierdzić lub 'Escape' aby anulować", - "autocomplete.input.placeholder": "Opisz co chcesz zrobić...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Generuj Sugestie Edycji", - "autocomplete.commands.displaySuggestions": "Wyświetl Sugestie Edycji", - "autocomplete.commands.cancelSuggestions": "Anuluj Sugestie Edycji", - "autocomplete.commands.applyCurrentSuggestion": "Zastosuj Bieżącą Sugestię Edycji", - "autocomplete.commands.applyAllSuggestions": "Zastosuj Wszystkie Sugestie Edycji", - "autocomplete.commands.goToNextSuggestion": "Przejdź do Następnej Sugestii", - "autocomplete.commands.goToPreviousSuggestion": "Przejdź do Poprzedniej Sugestii", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pt-BR.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pt-BR.ts deleted file mode 100644 index 2fe4f35f592..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-pt-BR.ts +++ /dev/null @@ -1,13 +0,0 @@ -// pt-BR package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Pressione 'Enter' para confirmar ou 'Escape' para cancelar", - "autocomplete.input.placeholder": "Descreva o que você quer fazer...", - "autocomplete.commands.generateSuggestions": "Gerar Sugestões de Edição", - "autocomplete.commands.displaySuggestions": "Exibir Sugestões de Edição", - "autocomplete.commands.cancelSuggestions": "Cancelar Sugestões de Edição", - "autocomplete.commands.applyCurrentSuggestion": "Aplicar a Sugestão de Edição Atual", - "autocomplete.commands.applyAllSuggestions": "Aplicar Todas as Sugestões de Edição", - "autocomplete.commands.goToNextSuggestion": "Ir para a Próxima Sugestão", - "autocomplete.commands.goToPreviousSuggestion": "Voltar para a Sugestão Anterior", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ru.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ru.ts deleted file mode 100644 index 025ddcce0ed..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-ru.ts +++ /dev/null @@ -1,13 +0,0 @@ -// ru package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Нажмите 'Enter' для подтверждения или 'Escape' для отмены", - "autocomplete.input.placeholder": "Опишите, что вы хотите сделать...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Генерировать Предлагаемые Правки", - "autocomplete.commands.displaySuggestions": "Показать Предлагаемые Правки", - "autocomplete.commands.cancelSuggestions": "Отменить Предлагаемые Правки", - "autocomplete.commands.applyCurrentSuggestion": "Применить Текущую Предлагаемую Правку", - "autocomplete.commands.applyAllSuggestions": "Применить Все Предлагаемые Правки", - "autocomplete.commands.goToNextSuggestion": "Перейти к Следующему Предложению", - "autocomplete.commands.goToPreviousSuggestion": "Перейти к Предыдущему Предложению", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-sk.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-sk.ts deleted file mode 100644 index ea6dc5b7284..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-sk.ts +++ /dev/null @@ -1,13 +0,0 @@ -// sk package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Stlačte 'Enter' pre potvrdenie alebo 'Escape' pre zrušenie", - "autocomplete.input.placeholder": "Popíšte, čo chcete urobiť...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Generovať Navrhované Úpravy", - "autocomplete.commands.displaySuggestions": "Zobraziť Navrhované Úpravy", - "autocomplete.commands.cancelSuggestions": "Zrušiť Navrhované Úpravy", - "autocomplete.commands.applyCurrentSuggestion": "Použiť Aktuálnu Navrhnutú Úpravu", - "autocomplete.commands.applyAllSuggestions": "Použiť Všetky Navrhované Úpravy", - "autocomplete.commands.goToNextSuggestion": "Prejsť na Ďalší Návrh", - "autocomplete.commands.goToPreviousSuggestion": "Prejsť na Predchádzajúci Návrh", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-th.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-th.ts deleted file mode 100644 index ffa6b25c624..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-th.ts +++ /dev/null @@ -1,13 +0,0 @@ -// th package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "กด 'Enter' เพื่อยืนยันหรือ 'Escape' เพื่อยกเลิก", - "autocomplete.input.placeholder": "อธิบายสิ่งที่คุณต้องการทำ...", - "autocomplete.commands.generateSuggestions": "Kilo Code: สร้างข้อเสนอแนะการแก้ไข", - "autocomplete.commands.displaySuggestions": "แสดงข้อเสนอแนะการแก้ไข", - "autocomplete.commands.cancelSuggestions": "ยกเลิกข้อเสนอแนะการแก้ไข", - "autocomplete.commands.applyCurrentSuggestion": "ใช้ข้อเสนอแนะการแก้ไขปัจจุบัน", - "autocomplete.commands.applyAllSuggestions": "ใช้ข้อเสนอแนะการแก้ไขทั้งหมด", - "autocomplete.commands.goToNextSuggestion": "ไปยังข้อเสนอแนะถัดไป", - "autocomplete.commands.goToPreviousSuggestion": "ไปยังข้อเสนอแนะก่อนหน้า", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-tr.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-tr.ts deleted file mode 100644 index e1fc96af228..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-tr.ts +++ /dev/null @@ -1,13 +0,0 @@ -// tr package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Onaylamak için 'Enter'a, iptal etmek için 'Escape'e basın", - "autocomplete.input.placeholder": "Ne yapmak istediğinizi açıklayın...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Düzenleme Önerileri Oluştur", - "autocomplete.commands.displaySuggestions": "Düzenleme Önerilerini Göster", - "autocomplete.commands.cancelSuggestions": "Düzenleme Önerilerini İptal Et", - "autocomplete.commands.applyCurrentSuggestion": "Mevcut Düzenleme Önerisini Uygula", - "autocomplete.commands.applyAllSuggestions": "Tüm Düzenleme Önerilerini Uygula", - "autocomplete.commands.goToNextSuggestion": "Sonraki Öneriye Git", - "autocomplete.commands.goToPreviousSuggestion": "Önceki Öneriye Git", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-uk.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-uk.ts deleted file mode 100644 index 0cd82294c7a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-uk.ts +++ /dev/null @@ -1,13 +0,0 @@ -// uk package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Натисніть 'Enter' для підтвердження або 'Escape' для скасування", - "autocomplete.input.placeholder": "Опишіть, що ви хочете зробити...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Генерувати Пропозиції Редагування", - "autocomplete.commands.displaySuggestions": "Показати Пропозиції Редагування", - "autocomplete.commands.cancelSuggestions": "Скасувати Пропозиції Редагування", - "autocomplete.commands.applyCurrentSuggestion": "Застосувати Поточну Пропозицію Редагування", - "autocomplete.commands.applyAllSuggestions": "Застосувати Всі Пропозиції Редагування", - "autocomplete.commands.goToNextSuggestion": "Перейти до Наступної Пропозиції", - "autocomplete.commands.goToPreviousSuggestion": "Перейти до Попередньої Пропозиції", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-vi.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-vi.ts deleted file mode 100644 index 67db13e4a45..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-vi.ts +++ /dev/null @@ -1,13 +0,0 @@ -// vi package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Nhấn 'Enter' để xác nhận hoặc 'Escape' để hủy", - "autocomplete.input.placeholder": "Mô tả những gì bạn muốn làm...", - "autocomplete.commands.generateSuggestions": "Kilo Code: Tạo Gợi Ý Chỉnh Sửa", - "autocomplete.commands.displaySuggestions": "Hiển Thị Gợi Ý Chỉnh Sửa", - "autocomplete.commands.cancelSuggestions": "Hủy Gợi Ý Chỉnh Sửa", - "autocomplete.commands.applyCurrentSuggestion": "Áp Dụng Gợi Ý Chỉnh Sửa Hiện Tại", - "autocomplete.commands.applyAllSuggestions": "Áp Dụng Tất Cả Gợi Ý Chỉnh Sửa", - "autocomplete.commands.goToNextSuggestion": "Đi Đến Gợi Ý Tiếp Theo", - "autocomplete.commands.goToPreviousSuggestion": "Đi Đến Gợi Ý Trước Đó", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-CN.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-CN.ts deleted file mode 100644 index aaf8a7b2bca..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-CN.ts +++ /dev/null @@ -1,13 +0,0 @@ -// zh-CN package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "Kilo Code 幽灵写手", - "autocomplete.input.placeholder": "描述您想要编程的内容...", - "autocomplete.commands.generateSuggestions": "Kilo Code:生成建议编辑", - "autocomplete.commands.displaySuggestions": "显示建议编辑", - "autocomplete.commands.cancelSuggestions": "取消建议编辑", - "autocomplete.commands.applyCurrentSuggestion": "应用当前建议编辑", - "autocomplete.commands.applyAllSuggestions": "应用所有建议编辑", - "autocomplete.commands.goToNextSuggestion": "转到下一个建议", - "autocomplete.commands.goToPreviousSuggestion": "转到上一个建议", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-TW.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-TW.ts deleted file mode 100644 index 1e5285d2f88..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/package-nls-zh-TW.ts +++ /dev/null @@ -1,13 +0,0 @@ -// zh-TW package.nls translations for autocomplete - -export const dict = { - "autocomplete.input.title": "按 'Enter' 確認或按 'Escape' 取消", - "autocomplete.input.placeholder": "描述您想要做什麼...", - "autocomplete.commands.generateSuggestions": "Kilo Code: 產生編輯建議", - "autocomplete.commands.displaySuggestions": "顯示編輯建議", - "autocomplete.commands.cancelSuggestions": "取消編輯建議", - "autocomplete.commands.applyCurrentSuggestion": "套用目前編輯建議", - "autocomplete.commands.applyAllSuggestions": "套用所有編輯建議", - "autocomplete.commands.goToNextSuggestion": "前往下一個建議", - "autocomplete.commands.goToPreviousSuggestion": "前往上一個建議", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/pl.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/pl.ts deleted file mode 100644 index 68dc4fa7cac..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/pl.ts +++ /dev/null @@ -1,49 +0,0 @@ -// pl runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "wstrzymane", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (wyłączone)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Nie skonfigurowano modelu autouzupełniania**\n\nAby włączyć autouzupełnianie, dodaj profil z jednym z tych obsługiwanych dostawców: {{providers}}.\n\n[Otwórz Ustawienia]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Całkowity koszt sesji:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Dostawca:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Domyślny", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Wykonano {{count}} uzupełnień między {{startTime}} a {{endTime}}, za łączny koszt {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Autouzupełnianie zapewniane przez {{model}} za pośrednictwem {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analizuję twój kod...", - "kilocode:autocomplete.progress.generating": "Generuję sugerowane edycje...", - "kilocode:autocomplete.progress.processing": "Przetwarzam sugerowane edycje...", - "kilocode:autocomplete.progress.showing": "Wyświetlam sugerowane edycje...", - "kilocode:autocomplete.input.title": "Kilo Code: Szybkie Zadanie", - "kilocode:autocomplete.input.placeholder": "np. 'zrefaktoruj tę funkcję, aby była bardziej wydajna'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Generuj Sugerowane Edycje", - "kilocode:autocomplete.commands.displaySuggestions": "Wyświetl Sugerowane Edycje", - "kilocode:autocomplete.commands.cancelSuggestions": "Anuluj Sugerowane Edycje", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Zastosuj Bieżącą Sugerowaną Edycję", - "kilocode:autocomplete.commands.applyAllSuggestions": "Zastosuj Wszystkie Sugerowane Edycje", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Sugerowane Edycje", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Mogę pomóc ci w szybkich zadaniach i sugerowanych edycjach.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete jest blokowane przez konflikt z GitHub Copilot. Aby to naprawić, musisz wyłączyć sugestie inline Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Wyłącz Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Wyłącz Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete zostało wstrzymane, ponieważ na twoim koncie nie ma pozostałych kredytów. Dodaj kredyty, aby wznowić autouzupełnianie.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Dodaj kredyty", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete zostało wstrzymane z powodu błędu uwierzytelniania. Zaloguj się ponownie.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/pt-BR.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/pt-BR.ts deleted file mode 100644 index 067371a6fac..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/pt-BR.ts +++ /dev/null @@ -1,48 +0,0 @@ -// pt-BR runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pausado", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (desabilitado)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Nenhum modelo de autocompletar configurado**\n\nPara habilitar o autocompletar, adicione um perfil com um destes provedores suportados: {{providers}}.\n\n[Abrir Configurações]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Custo total da sessão:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Provedor:", - "kilocode:autocomplete.statusBar.tooltip.model": "Modelo:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Perfil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Padrão", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Realizadas {{count}} conclusões entre {{startTime}} e {{endTime}}, por um custo total de {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "Autocompletações fornecidas por {{model}} via {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analisando seu código...", - "kilocode:autocomplete.progress.generating": "Gerando edições sugeridas...", - "kilocode:autocomplete.progress.processing": "Processando edições sugeridas...", - "kilocode:autocomplete.progress.showing": "Exibindo edições sugeridas...", - "kilocode:autocomplete.input.title": "Kilo Code: Tarefa Rápida", - "kilocode:autocomplete.input.placeholder": "ex., 'refatore esta função para ser mais eficiente'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Gerar Edições Sugeridas", - "kilocode:autocomplete.commands.displaySuggestions": "Exibir Edições Sugeridas", - "kilocode:autocomplete.commands.cancelSuggestions": "Cancelar Edições Sugeridas", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Aplicar Edição Sugerida Atual", - "kilocode:autocomplete.commands.applyAllSuggestions": "Aplicar Todas as Edições Sugeridas", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Edições Sugeridas", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Posso te ajudar com tarefas rápidas e edições sugeridas.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "O Kilo Code Autocomplete está sendo bloqueado por um conflito com o GitHub Copilot. Para corrigir isso, você deve desabilitar as sugestões inline do Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Desabilitar Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Desabilitar Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "O Kilo Code Autocomplete foi pausado porque sua conta não tem créditos restantes. Adicione créditos para retomar o autocompletar.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Adicionar créditos", - "kilocode:autocomplete.authError.message": - "O Kilo Code Autocomplete foi pausado devido a um erro de autenticação. Por favor, faça login novamente.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/ru.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/ru.ts deleted file mode 100644 index 7fdfa0a89a6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/ru.ts +++ /dev/null @@ -1,50 +0,0 @@ -// ru runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "приостановлено", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (отключено)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Модель автодополнения не настроена**\n\nЧтобы включить автодополнение, добавьте профиль с одним из поддерживаемых провайдеров: {{providers}}.\n\n[Открыть Настройки]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Общая стоимость сессии:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Провайдер:", - "kilocode:autocomplete.statusBar.tooltip.model": "Модель:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Профиль: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "По умолчанию", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Выполнено {{count}} автодополнений между {{startTime}} и {{endTime}}, общая стоимость {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Автодополнение предоставляется {{model}} через {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Анализирую твой код...", - "kilocode:autocomplete.progress.generating": "Генерирую предлагаемые правки...", - "kilocode:autocomplete.progress.processing": "Обрабатываю предлагаемые правки...", - "kilocode:autocomplete.progress.showing": "Показываю предлагаемые правки...", - "kilocode:autocomplete.input.title": "Kilo Code: Быстрая Задача", - "kilocode:autocomplete.input.placeholder": "напр., 'рефактори эту функцию для большей эффективности'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Генерировать Предлагаемые Правки", - "kilocode:autocomplete.commands.displaySuggestions": "Показать Предлагаемые Правки", - "kilocode:autocomplete.commands.cancelSuggestions": "Отменить Предлагаемые Правки", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Применить Текущую Предлагаемую Правку", - "kilocode:autocomplete.commands.applyAllSuggestions": "Применить Все Предлагаемые Правки", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Предлагаемые Правки", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Я могу помочь тебе с быстрыми задачами и предлагаемыми правками.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete блокируется конфликтом с GitHub Copilot. Чтобы исправить это, ты должен отключить встроенные предложения Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Отключить Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Отключить Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete приостановлено, так как на твоём аккаунте не осталось кредитов. Добавь кредиты, чтобы возобновить автодополнение.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Добавить кредиты", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete приостановлено из-за ошибки аутентификации. Пожалуйста, войди снова.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/sk.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/sk.ts deleted file mode 100644 index 04b76caa5c5..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/sk.ts +++ /dev/null @@ -1,49 +0,0 @@ -// sk runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "pozastavené", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (zakázané)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Nie je nakonfigurovaný žiadny model automatického doplňovania**\n\nPre povolenie automatického doplňovania pridaj profil s jedným z týchto podporovaných poskytovateľov: {{providers}}.\n\n[Otvoriť Nastavenia]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Celkové náklady relácie:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Poskytovateľ:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Predvolený", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Vykonaných {{count}} dokončení medzi {{startTime}} a {{endTime}}, s celkovými nákladmi {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Automatické dokončovanie poskytuje {{model}} cez {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Analyzujem tvoj kód...", - "kilocode:autocomplete.progress.generating": "Generujem navrhované úpravy...", - "kilocode:autocomplete.progress.processing": "Spracovávam navrhované úpravy...", - "kilocode:autocomplete.progress.showing": "Zobrazujem navrhované úpravy...", - "kilocode:autocomplete.input.title": "Kilo Code: Rýchla úloha", - "kilocode:autocomplete.input.placeholder": "napr. 'refaktoruj túto funkciu, aby bola efektívnejšia'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Generovať navrhované úpravy", - "kilocode:autocomplete.commands.displaySuggestions": "Zobraziť navrhované úpravy", - "kilocode:autocomplete.commands.cancelSuggestions": "Zrušiť navrhované úpravy", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Použiť aktuálnu navrhnutú úpravu", - "kilocode:autocomplete.commands.applyAllSuggestions": "Použiť všetky navrhované úpravy", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Navrhované úpravy", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "Môžem ti pomôcť s rýchlymi úlohami a navrhnutými úpravami.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete je blokované konfliktom s GitHub Copilot. Pre vyriešenie tohto problému musíš zakázať inline návrhy Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Zakázať Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Zakázať Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete bolo pozastavené, pretože na tvojom účte nezostali žiadne kredity. Pridaj kredity na obnovenie automatického dopĺňania.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Pridať kredity", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete bolo pozastavené kvôli chybe overenia. Prosím, prihlás sa znova.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/th.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/th.ts deleted file mode 100644 index 4a36a3ba6f6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/th.ts +++ /dev/null @@ -1,49 +0,0 @@ -// th runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "หยุดชั่วคราว", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (ปิดใช้งาน)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**ไม่ได้กำหนดค่าโมเดลการเติมข้อความอัตโนมัติ**\n\nหากต้องการเปิดใช้งานการเติมข้อความอัตโนมัติ ให้เพิ่มโปรไฟล์กับผู้ให้บริการที่รองรับเหล่านี้: {{providers}}\n\n[เปิดการตั้งค่า]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "ค่าใช้จ่ายรวมของเซสชัน:", - "kilocode:autocomplete.statusBar.tooltip.provider": "ผู้ให้บริการ:", - "kilocode:autocomplete.statusBar.tooltip.model": "โมเดล:", - "kilocode:autocomplete.statusBar.tooltip.profile": "โปรไฟล์: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "ค่าเริ่มต้น", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "ดำเนินการเติมเต็ม {{count}} ครั้งระหว่าง {{startTime}} ถึง {{endTime}} ด้วยค่าใช้จ่ายรวม {{cost}}", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "การเติมเต็มอัตโนมัติให้บริการโดย {{model}} ผ่าน {{provider}}", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "กำลังวิเคราะห์โค้ดของคุณ...", - "kilocode:autocomplete.progress.generating": "กำลังสร้างการแก้ไขที่แนะนำ...", - "kilocode:autocomplete.progress.processing": "กำลังประมวลผลการแก้ไขที่แนะนำ...", - "kilocode:autocomplete.progress.showing": "กำลังแสดงการแก้ไขที่แนะนำ...", - "kilocode:autocomplete.input.title": "Kilo Code: งานด่วน", - "kilocode:autocomplete.input.placeholder": "เช่น 'ปรับโครงสร้างฟังก์ชันนี้ให้มีประสิทธิภาพมากขึ้น'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: สร้างการแก้ไขที่แนะนำ", - "kilocode:autocomplete.commands.displaySuggestions": "แสดงการแก้ไขที่แนะนำ", - "kilocode:autocomplete.commands.cancelSuggestions": "ยกเลิกการแก้ไขที่แนะนำ", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "ใช้การแก้ไขที่แนะนำปัจจุบัน", - "kilocode:autocomplete.commands.applyAllSuggestions": "ใช้การแก้ไขที่แนะนำทั้งหมด", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: การแก้ไขที่แนะนำ", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "ฉันสามารถช่วยคุณในงานด่วนและการแก้ไขที่แนะนำได้", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete ถูกบล็อกโดยความขัดแย้งกับ GitHub Copilot เพื่อแก้ไขปัญหานี้ คุณต้องปิดใช้งานคำแนะนำแบบอินไลน์ของ Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "ปิดใช้งาน Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "ปิดใช้งาน Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete ถูกหยุดชั่วคราวเนื่องจากบัญชีของคุณไม่มีเครดิตเหลือ เพิ่มเครดิตเพื่อใช้งานการเติมข้อความอัตโนมัติต่อ", - "kilocode:autocomplete.creditsExhausted.addCredits": "เพิ่มเครดิต", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete ถูกหยุดชั่วคราวเนื่องจากข้อผิดพลาดในการยืนยันตัวตน กรุณาเข้าสู่ระบบอีกครั้ง", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/tr.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/tr.ts deleted file mode 100644 index 56c5951178f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/tr.ts +++ /dev/null @@ -1,50 +0,0 @@ -// tr runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "duraklatıldı", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (devre dışı)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Otomatik tamamlama modeli yapılandırılmadı**\n\nOtomatik tamamlamayı etkinleştirmek için desteklenen sağlayıcılardan biriyle bir profil ekleyin: {{providers}}.\n\n[Ayarları Aç]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Oturum toplam maliyeti:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Sağlayıcı:", - "kilocode:autocomplete.statusBar.tooltip.model": "Model:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Profil: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Varsayılan", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "{{startTime}} ile {{endTime}} arasında {{count}} tamamlama gerçekleştirildi, toplam maliyet {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Otomatik tamamlamalar {{provider}} üzerinden {{model}} tarafından sağlanmaktadır.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Kodun analiz ediliyor...", - "kilocode:autocomplete.progress.generating": "Önerilen düzenlemeler oluşturuluyor...", - "kilocode:autocomplete.progress.processing": "Önerilen düzenlemeler işleniyor...", - "kilocode:autocomplete.progress.showing": "Önerilen düzenlemeler gösteriliyor...", - "kilocode:autocomplete.input.title": "Kilo Code: Hızlı Görev", - "kilocode:autocomplete.input.placeholder": "örn., 'bu fonksiyonu daha verimli olacak şekilde yeniden düzenle'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Önerilen Düzenlemeler Oluştur", - "kilocode:autocomplete.commands.displaySuggestions": "Önerilen Düzenlemeleri Göster", - "kilocode:autocomplete.commands.cancelSuggestions": "Önerilen Düzenlemeleri İptal Et", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Mevcut Önerilen Düzenlemeyi Uygula", - "kilocode:autocomplete.commands.applyAllSuggestions": "Tüm Önerilen Düzenlemeleri Uygula", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Önerilen Düzenlemeler", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Hızlı görevler ve önerilen düzenlemeler konusunda sana yardımcı olabilirim.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete, GitHub Copilot ile bir çakışma nedeniyle engelleniyor. Bunu düzeltmek için Copilot'un satır içi önerilerini devre dışı bırakmalısın.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Copilot'u Devre Dışı Bırak", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Autocomplete'i Devre Dışı Bırak", - "kilocode:autocomplete.creditsExhausted.message": - "Hesabında kalan kredin olmadığı için Kilo Code Autocomplete duraklatıldı. Otomatik tamamlamayı sürdürmek için kredi ekle.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Kredi Ekle", - "kilocode:autocomplete.authError.message": - "Bir kimlik doğrulama hatası nedeniyle Kilo Code Autocomplete duraklatıldı. Lütfen tekrar giriş yap.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/uk.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/uk.ts deleted file mode 100644 index 9478c4aa7a8..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/uk.ts +++ /dev/null @@ -1,49 +0,0 @@ -// uk runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "призупинено", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (вимкнено)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Модель автодоповнення не налаштована**\n\nЩоб увімкнути автодоповнення, додайте профіль з одним із підтримуваних провайдерів: {{providers}}.\n\n[Відкрити Налаштування]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Загальна вартість сесії:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Провайдер:", - "kilocode:autocomplete.statusBar.tooltip.model": "Модель:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Профіль: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "За замовчуванням", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Виконано {{count}} автодоповнень між {{startTime}} та {{endTime}}, загальна вартість {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "Автодоповнення надається {{model}} через {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Аналізую твій код...", - "kilocode:autocomplete.progress.generating": "Генерую запропоновані правки...", - "kilocode:autocomplete.progress.processing": "Обробляю запропоновані правки...", - "kilocode:autocomplete.progress.showing": "Показую запропоновані правки...", - "kilocode:autocomplete.input.title": "Kilo Code: Швидке Завдання", - "kilocode:autocomplete.input.placeholder": "напр., 'рефактори цю функцію для більшої ефективності'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Генерувати Запропоновані Правки", - "kilocode:autocomplete.commands.displaySuggestions": "Показати Запропоновані Правки", - "kilocode:autocomplete.commands.cancelSuggestions": "Скасувати Запропоновані Правки", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Застосувати Поточну Запропоновану Правку", - "kilocode:autocomplete.commands.applyAllSuggestions": "Застосувати Всі Запропоновані Правки", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Запропоновані Правки", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Я можу допомогти тобі зі швидкими завданнями та запропонованими правками.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete блокується конфліктом з GitHub Copilot. Щоб виправити це, ти повинен вимкнути вбудовані пропозиції Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Вимкнути Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Вимкнути Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete призупинено, оскільки на твоєму обліковому записі не залишилося кредитів. Додай кредити, щоб відновити автодоповнення.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Додати кредити", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete призупинено через помилку автентифікації. Будь ласка, увійди знову.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/vi.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/vi.ts deleted file mode 100644 index 17910b54e45..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/vi.ts +++ /dev/null @@ -1,50 +0,0 @@ -// vi runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "tạm dừng", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete (đã tắt)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**Chưa cấu hình mô hình tự động hoàn thành**\n\nĐể bật tự động hoàn thành, hãy thêm hồ sơ với một trong các nhà cung cấp được hỗ trợ sau: {{providers}}.\n\n[Mở Cài đặt]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "Tổng chi phí phiên:", - "kilocode:autocomplete.statusBar.tooltip.provider": "Nhà cung cấp:", - "kilocode:autocomplete.statusBar.tooltip.model": "Mô hình:", - "kilocode:autocomplete.statusBar.tooltip.profile": "Hồ sơ: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "Mặc định", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "Đã thực hiện {{count}} lần hoàn thành từ {{startTime}} đến {{endTime}}, với tổng chi phí {{cost}}.", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": - "Tự động hoàn thành được cung cấp bởi {{model}} thông qua {{provider}}.", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "Đang phân tích mã của bạn...", - "kilocode:autocomplete.progress.generating": "Đang tạo các chỉnh sửa được đề xuất...", - "kilocode:autocomplete.progress.processing": "Đang xử lý các chỉnh sửa được đề xuất...", - "kilocode:autocomplete.progress.showing": "Đang hiển thị các chỉnh sửa được đề xuất...", - "kilocode:autocomplete.input.title": "Kilo Code: Tác Vụ Nhanh", - "kilocode:autocomplete.input.placeholder": "ví dụ, 'tái cấu trúc hàm này để hiệu quả hơn'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: Tạo Các Chỉnh Sửa Được Đề Xuất", - "kilocode:autocomplete.commands.displaySuggestions": "Hiển Thị Các Chỉnh Sửa Được Đề Xuất", - "kilocode:autocomplete.commands.cancelSuggestions": "Hủy Các Chỉnh Sửa Được Đề Xuất", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "Áp Dụng Chỉnh Sửa Được Đề Xuất Hiện Tại", - "kilocode:autocomplete.commands.applyAllSuggestions": "Áp Dụng Tất Cả Các Chỉnh Sửa Được Đề Xuất", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: Các Chỉnh Sửa Được Đề Xuất", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": - "Tôi có thể giúp bạn với các tác vụ nhanh và chỉnh sửa được đề xuất.", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete đang bị chặn do xung đột với GitHub Copilot. Để khắc phục điều này, bạn phải tắt các gợi ý inline của Copilot.", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "Tắt Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "Tắt Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete đã bị tạm dừng vì tài khoản của bạn không còn tín dụng. Thêm tín dụng để tiếp tục sử dụng tự động hoàn thành.", - "kilocode:autocomplete.creditsExhausted.addCredits": "Thêm tín dụng", - "kilocode:autocomplete.authError.message": - "Kilo Code Autocomplete đã bị tạm dừng do lỗi xác thực. Vui lòng đăng nhập lại.", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/zh-CN.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/zh-CN.ts deleted file mode 100644 index 8098e4d0fde..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/zh-CN.ts +++ /dev/null @@ -1,47 +0,0 @@ -// zh-CN runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "已暂停", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete(已禁用)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**未配置自动补全模型**\n\n要启用自动补全,请添加一个使用以下支持的提供商的配置文件:{{providers}}。\n\n[打开设置]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "会话总费用:", - "kilocode:autocomplete.statusBar.tooltip.provider": "提供商:", - "kilocode:autocomplete.statusBar.tooltip.model": "模型:", - "kilocode:autocomplete.statusBar.tooltip.profile": "配置: ", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "默认", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "在{{startTime}}至{{endTime}}期间执行了{{count}}次补全,总费用为{{cost}}。", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "自动补全由{{model}}通过{{provider}}提供。", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "正在分析你的代码...", - "kilocode:autocomplete.progress.generating": "正在生成建议编辑...", - "kilocode:autocomplete.progress.processing": "正在处理建议编辑...", - "kilocode:autocomplete.progress.showing": "正在显示建议编辑...", - "kilocode:autocomplete.input.title": "Kilo Code: 快速任务", - "kilocode:autocomplete.input.placeholder": "例如:'重构这个函数使其更高效'", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code: 生成建议编辑", - "kilocode:autocomplete.commands.displaySuggestions": "显示建议编辑", - "kilocode:autocomplete.commands.cancelSuggestions": "取消建议编辑", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "应用当前建议编辑", - "kilocode:autocomplete.commands.applyAllSuggestions": "应用所有建议编辑", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code: 建议编辑", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "我可以帮助你完成快速任务和建议编辑。", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete 被与 GitHub Copilot 的冲突阻止。要解决此问题,你必须禁用 Copilot 的内联建议。", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "禁用 Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "禁用 Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete 已暂停,因为你的账户没有剩余额度。请添加额度以恢复自动补全。", - "kilocode:autocomplete.creditsExhausted.addCredits": "添加额度", - "kilocode:autocomplete.authError.message": "Kilo Code Autocomplete 因身份验证错误已暂停。请重新登录。", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/i18n/zh-TW.ts b/packages/kilo-vscode/src/services/autocomplete/i18n/zh-TW.ts deleted file mode 100644 index 37e0037fb30..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/i18n/zh-TW.ts +++ /dev/null @@ -1,47 +0,0 @@ -// zh-TW runtime translations for autocomplete - -export const dict = { - "kilocode:autocomplete.statusBar.enabled": "$(kilo-logo) Autocomplete", - "kilocode:autocomplete.statusBar.snoozed": "已暫停", - "kilocode:autocomplete.statusBar.warning": "$(warning) Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.basic": "Kilo Code Autocomplete", - "kilocode:autocomplete.statusBar.tooltip.disabled": "Kilo Code Autocomplete(已停用)", - "kilocode:autocomplete.statusBar.tooltip.noUsableProvider": - "**未設定 Autocomplete 模型**\n\n若要啟用 Autocomplete,請新增一個使用以下支援供應商的設定檔:{{providers}}。\n\n[開啟設定]({{command}})", - "kilocode:autocomplete.statusBar.tooltip.sessionTotal": "工作階段總費用:", - "kilocode:autocomplete.statusBar.tooltip.provider": "供應商:", - "kilocode:autocomplete.statusBar.tooltip.model": "模型:", - "kilocode:autocomplete.statusBar.tooltip.profile": "設定檔:", - "kilocode:autocomplete.statusBar.tooltip.defaultProfile": "預設", - "kilocode:autocomplete.statusBar.tooltip.completionSummary": - "在 {{startTime}} 至 {{endTime}} 之間完成了 {{count}} 次補齊,總費用為 {{cost}}。", - "kilocode:autocomplete.statusBar.tooltip.providerInfo": "Autocomplete 由 {{provider}} 的 {{model}} 提供。", - "kilocode:autocomplete.statusBar.cost.zero": "$0.00", - "kilocode:autocomplete.statusBar.cost.lessThanCent": "<$0.01", - "kilocode:autocomplete.toggleMessage": "Kilo Code Autocomplete {{status}}", - "kilocode:autocomplete.progress.title": "Kilo Code", - "kilocode:autocomplete.progress.analyzing": "正在分析程式碼...", - "kilocode:autocomplete.progress.generating": "正在產生建議編輯...", - "kilocode:autocomplete.progress.processing": "正在處理建議編輯...", - "kilocode:autocomplete.progress.showing": "正在顯示建議編輯...", - "kilocode:autocomplete.input.title": "Kilo Code:快速任務", - "kilocode:autocomplete.input.placeholder": "例如「重構此函式以提升效率」", - "kilocode:autocomplete.commands.generateSuggestions": "Kilo Code:產生建議編輯", - "kilocode:autocomplete.commands.displaySuggestions": "顯示建議編輯", - "kilocode:autocomplete.commands.cancelSuggestions": "取消建議編輯", - "kilocode:autocomplete.commands.applyCurrentSuggestion": "套用目前的建議編輯", - "kilocode:autocomplete.commands.applyAllSuggestions": "套用所有建議編輯", - "kilocode:autocomplete.commands.category": "Kilo Code", - "kilocode:autocomplete.codeAction.title": "Kilo Code:建議編輯", - "kilocode:autocomplete.chatParticipant.fullName": "Kilo Code Agent", - "kilocode:autocomplete.chatParticipant.name": "Agent", - "kilocode:autocomplete.chatParticipant.description": "可以協助處理快速任務和建議編輯。", - "kilocode:autocomplete.incompatibilityExtensionPopup.message": - "Kilo Code Autocomplete 因與 GitHub Copilot 衝突而被封鎖。若要修正此問題,必須停用 Copilot 的行內建議。", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableCopilot": "停用 Copilot", - "kilocode:autocomplete.incompatibilityExtensionPopup.disableInlineAssist": "停用 Autocomplete", - "kilocode:autocomplete.creditsExhausted.message": - "Kilo Code Autocomplete 已暫停,因為你的帳戶沒有剩餘額度。請新增額度以恢復自動補齊。", - "kilocode:autocomplete.creditsExhausted.addCredits": "新增額度", - "kilocode:autocomplete.authError.message": "Kilo Code Autocomplete 因驗證錯誤已暫停。請重新登入。", -} From 845978c170acd3c39e65a21632c05c3d0633322f Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:43:21 +0000 Subject: [PATCH 2/5] refactor(vscode): remove unused chat autocomplete handlers --- .../ChatTextAreaAutocomplete.ts | 13 +++++- .../handleChatCompletionAccepted.ts | 29 ------------- .../handleChatCompletionRequest.ts | 43 ------------------- 3 files changed, 11 insertions(+), 74 deletions(-) delete mode 100644 packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionAccepted.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionRequest.ts diff --git a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts index 690f0e1261a..bb4e52f000d 100644 --- a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts +++ b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/ChatTextAreaAutocomplete.ts @@ -1,15 +1,24 @@ import * as vscode from "vscode" import { AutocompleteModel } from "../AutocompleteModel" -import { AutocompleteContext, VisibleCodeContext } from "../types" +import type { AutocompleteContext, VisibleCodeContext } from "../types" import { removePrefixOverlap } from "../continuedev/core/autocomplete/postprocessing/removePrefixOverlap.js" import { AutocompleteTelemetry } from "../classic-auto-complete/AutocompleteTelemetry" import { postprocessAutocompleteSuggestion } from "../classic-auto-complete/uselessSuggestionFilter" import { VisibleCodeTracker } from "../context/VisibleCodeTracker" import { FileIgnoreController } from "../shims/FileIgnoreController" import type { KiloConnectionService } from "../../cli-backend" -import type { ChatCompletionRequestMessage, ChatCompletionResponseSender } from "./handleChatCompletionRequest" import { finalizeChatSuggestion, buildChatPrefix } from "./chat-autocomplete-utils" +interface ChatCompletionRequestMessage { + type: "requestChatCompletion" + text: string + requestId: string +} + +interface ChatCompletionResponseSender { + postMessage(message: { type: "chatCompletionResult"; text: string; requestId: string }): void +} + /** * Chat textarea autocomplete with cached per-request objects. * diff --git a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionAccepted.ts b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionAccepted.ts deleted file mode 100644 index 9bb9a153bd1..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionAccepted.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { AutocompleteTelemetry } from "../classic-auto-complete/AutocompleteTelemetry" - -export interface ChatCompletionAcceptedMessage { - type: "chatCompletionAccepted" - suggestionLength?: number -} - -// Singleton telemetry instance for chat-textarea autocomplete -// This ensures we use the same instance across requests and acceptance events -let telemetryInstance: AutocompleteTelemetry | null = null - -/** - * Get or create the telemetry instance for chat-textarea autocomplete - */ -export function getChatAutocompleteTelemetry(): AutocompleteTelemetry { - if (!telemetryInstance) { - telemetryInstance = new AutocompleteTelemetry("chat-textarea") - } - return telemetryInstance -} - -/** - * Handles a chat completion accepted event from the webview. - * Captures telemetry when the user accepts a suggestion via Tab or ArrowRight. - */ -export function handleChatCompletionAccepted(message: ChatCompletionAcceptedMessage): void { - const telemetry = getChatAutocompleteTelemetry() - telemetry.captureAcceptSuggestion(message.suggestionLength) -} diff --git a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionRequest.ts b/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionRequest.ts deleted file mode 100644 index eeac049683e..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/chat-autocomplete/handleChatCompletionRequest.ts +++ /dev/null @@ -1,43 +0,0 @@ -import * as vscode from "vscode" -import { VisibleCodeTracker } from "../context/VisibleCodeTracker" -import { FileIgnoreController } from "../shims/FileIgnoreController" -import { ChatTextAreaAutocomplete } from "./ChatTextAreaAutocomplete" -import type { KiloConnectionService } from "../../cli-backend" - -export interface ChatCompletionRequestMessage { - type: "requestChatCompletion" - text?: string - requestId?: string -} - -export interface ChatCompletionResponseSender { - postMessage(message: { type: "chatCompletionResult"; text: string; requestId: string }): void -} - -/** - * Handles a chat completion request from the webview. - * Captures visible code context and generates an autocomplete suggestion. - */ -export async function handleChatCompletionRequest( - message: ChatCompletionRequestMessage, - responseSender: ChatCompletionResponseSender, - connectionService: KiloConnectionService, -): Promise { - const userText = message.text || "" - const requestId = message.requestId || "" - - const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? "" - - const ignoreController = new FileIgnoreController(workspacePath) - await ignoreController.initialize() - - const tracker = new VisibleCodeTracker(workspacePath, ignoreController) - const visibleContext = await tracker.captureVisibleCode() - - const autocomplete = new ChatTextAreaAutocomplete(connectionService) - const { suggestion } = await autocomplete.getCompletion(userText, visibleContext) - - responseSender.postMessage({ type: "chatCompletionResult", text: suggestion, requestId }) - - ignoreController.dispose() -} From b0d77fe9d742a1cd653ce6ed9da081c851ef54a9 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:43:43 +0000 Subject: [PATCH 3/5] refactor(vscode): remove dormant autocomplete provider pipeline --- .../core/autocomplete/CompletionProvider.ts | 272 --- .../core/autocomplete/MinimalConfig.ts | 126 - .../classification/shouldCompleteMultiline.ts | 37 - .../StreamTransformPipeline.ts | 82 - .../streamTransforms/charStream.test.ts | 192 -- .../filtering/streamTransforms/charStream.ts | 96 - .../filtering/streamTransforms/lineStream.ts | 53 +- .../test/NEGATIVE_TEST_CASES/QWEN_JSON.txt | 60 - .../NEGATIVE_TEST_CASES/QWEN_TYPESCRIPT.txt | 128 - .../NEGATIVE_TEST_CASES/STARCODER_JSON.txt | 20 - .../NEGATIVE_TEST_CASES/STARCODER_PYTHON.TXT | 29 - .../NEGATIVE_TEST_CASES/STARCODER_RUBY.TXT | 41 - .../NEGATIVE_TEST_CASES/STARCODER_RUST.TXT | 73 - .../filtering/test/filter.test.ts | 37 - .../autocomplete/filtering/test/testCases.ts | 2175 ----------------- .../core/autocomplete/filtering/test/util.ts | 81 - .../generation/CompletionStreamer.ts | 79 - .../generation/GeneratorReuseManager.test.ts | 208 -- .../generation/GeneratorReuseManager.ts | 70 - .../generation/ListenableGenerator.test.ts | 148 -- .../generation/ListenableGenerator.ts | 84 - .../autocomplete/generation/utils.test.ts | 126 - .../core/autocomplete/generation/utils.ts | 25 - .../core/autocomplete/prefiltering/index.ts | 57 - .../templating/__tests__/renderPrompt.test.ts | 262 -- .../autocomplete/templating/formatting.ts | 90 - .../autocomplete/templating/getStopTokens.ts | 28 - .../core/autocomplete/templating/index.ts | 205 -- .../util/AutocompleteDebouncer.ts | 32 - .../util/AutocompleteLoggingService.ts | 93 - .../util/AutocompleteLruCacheInMem.test.ts | 247 -- .../util/AutocompleteLruCacheInMem.ts | 77 - .../util/completionTestUtils.test.ts | 63 - .../autocomplete/util/completionTestUtils.ts | 94 - .../util/processSingleLineCompletion.test.ts | 96 - .../util/processSingleLineCompletion.ts | 80 - .../core/autocomplete/util/types.ts | 25 +- .../continuedev/core/test/fixtures.ts | 4 - .../continuedev/core/test/testDir.ts | 32 +- .../continuedev/core/util/parameters.ts | 4 +- 40 files changed, 5 insertions(+), 5726 deletions(-) delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/CompletionProvider.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/MinimalConfig.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/classification/shouldCompleteMultiline.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_JSON.txt delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_TYPESCRIPT.txt delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_JSON.txt delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_PYTHON.TXT delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUBY.TXT delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUST.TXT delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/filter.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/testCases.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/util.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/CompletionStreamer.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/prefiltering/index.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/__tests__/renderPrompt.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/formatting.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/getStopTokens.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/index.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteDebouncer.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLoggingService.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.ts diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/CompletionProvider.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/CompletionProvider.ts deleted file mode 100644 index 8871fc5e0fb..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/CompletionProvider.ts +++ /dev/null @@ -1,272 +0,0 @@ -import { MinimalConfigProvider } from "./MinimalConfig.js" -import { IDE, ILLM } from "../index.js" -import { DEFAULT_AUTOCOMPLETE_OPTS } from "../util/parameters.js" -import { shouldCompleteMultiline } from "./classification/shouldCompleteMultiline.js" -import { ContextRetrievalService } from "./context/ContextRetrievalService.js" -import { isSecurityConcern } from "../indexing/ignore.js" -import { BracketMatchingService } from "./filtering/BracketMatchingService.js" -import { CompletionStreamer } from "./generation/CompletionStreamer.js" -import { postprocessCompletion } from "./postprocessing/index.js" -import { shouldPrefilter } from "./prefiltering/index.js" -import { getAllSnippetsWithoutRace } from "./snippets/index.js" -import { renderPromptWithTokenLimit } from "./templating/index.js" -import { GetLspDefinitionsFunction } from "./types.js" -import { AutocompleteDebouncer } from "./util/AutocompleteDebouncer.js" -import { AutocompleteLoggingService } from "./util/AutocompleteLoggingService.js" -import { AutocompleteLruCacheInMem } from "./util/AutocompleteLruCacheInMem.js" -import { HelperVars } from "./util/HelperVars.js" -import { AutocompleteInput, AutocompleteOutcome } from "./util/types.js" - -// Errors that can be expected on occasion even during normal functioning should not be shown. -// Not worth disrupting the user to tell them that a single autocomplete request didn't go through -const ERRORS_TO_IGNORE = [ - // From Ollama - "unexpected server status", - "operation was aborted", -] - -export class CompletionProvider { - private autocompleteCache = AutocompleteLruCacheInMem.get() - public errorsShown: Set = new Set() - private bracketMatchingService = new BracketMatchingService() - private debouncer = new AutocompleteDebouncer() - private completionStreamer: CompletionStreamer - private loggingService = new AutocompleteLoggingService() - private contextRetrievalService: ContextRetrievalService - - constructor( - private readonly configHandler: MinimalConfigProvider, - private readonly ide: IDE, - private readonly _injectedGetLlm: () => Promise, - private readonly _onError: (e: unknown) => void, - private readonly getDefinitionsFromLsp: GetLspDefinitionsFunction, - ) { - this.completionStreamer = new CompletionStreamer(this.onError.bind(this)) - this.contextRetrievalService = new ContextRetrievalService(this.ide) - } - - private async _prepareLlm(): Promise { - const llm = await this._injectedGetLlm() - - if (!llm) { - return undefined - } - - // Temporary fix for JetBrains autocomplete bug as described in https://github.com/continuedev/continue/pull/3022 - if (llm.model === undefined && llm.completionOptions?.model !== undefined) { - llm.model = llm.completionOptions.model - } - - // Ignore empty API keys for Mistral since we currently write - // a template provider without one during onboarding - if (llm.providerName === "mistral" && llm.apiKey === "") { - return undefined - } - - // Set temperature (but don't override) - if (llm.completionOptions.temperature === undefined) { - llm.completionOptions.temperature = 0.01 - } - - return llm - } - - private onError(e: unknown) { - if ( - ERRORS_TO_IGNORE.some((err) => (typeof e === "string" ? e.includes(err) : (e as Error)?.message?.includes(err))) - ) { - return - } - - console.warn("Error generating autocompletion: ", e) - const errorMessage = e instanceof Error ? e.message : String(e) - if (!this.errorsShown.has(errorMessage)) { - this.errorsShown.add(errorMessage) - this._onError(e) - } - } - - public cancel() { - this.loggingService.cancel() - } - - public accept(completionId: string) { - const outcome = this.loggingService.accept(completionId) - if (!outcome) { - return - } - this.bracketMatchingService.handleAcceptedCompletion(outcome.completion, outcome.filepath) - } - - public markDisplayed(completionId: string, outcome: AutocompleteOutcome) { - this.loggingService.markDisplayed(completionId, outcome) - } - - private async _getAutocompleteOptions(llm: ILLM) { - const { config } = await this.configHandler.loadConfig() - const options = { - ...DEFAULT_AUTOCOMPLETE_OPTS, - ...config?.tabAutocompleteOptions, - ...llm.autocompleteOptions, - } - - // Enable static contextualization if defined. - if (config?.experimental?.enableStaticContextualization) { - options.experimental_enableStaticContextualization = false - } - - return options - } - - public async provideInlineCompletionItems( - input: AutocompleteInput, - token: AbortSignal | undefined, - force?: boolean, - ): Promise { - try { - // Create abort signal if not given - if (!token) { - const controller = this.loggingService.createAbortController(input.completionId) - token = controller.signal - } - const startTime = Date.now() - - const llm = await this._prepareLlm() - if (!llm) { - return undefined - } - - if (isSecurityConcern(input.filepath)) { - return undefined - } - - const options = await this._getAutocompleteOptions(llm) - - // Debounce - if (!force) { - if (await this.debouncer.delayAndShouldDebounce(options.debounceDelay)) { - return undefined - } - } - - const helper = await HelperVars.create(input, options, llm.model, this.ide) - - if (await shouldPrefilter(helper, await this.ide.getWorkspaceDirs())) { - return undefined - } - - const [snippetPayload, workspaceDirs] = await Promise.all([ - getAllSnippetsWithoutRace({ - helper, - ide: this.ide, - getDefinitionsFromLsp: this.getDefinitionsFromLsp, - contextRetrievalService: this.contextRetrievalService, - }), - this.ide.getWorkspaceDirs(), - ]) - - const { prompt, prefix, suffix, completionOptions } = renderPromptWithTokenLimit({ - snippetPayload, - workspaceDirs, - helper, - llm, - }) - - // Completion - let completion: string | undefined = "" - - const cache = await this.autocompleteCache - const cachedCompletion = helper.options.useCache ? await cache.get(helper.prunedPrefix) : undefined - let cacheHit = false - if (cachedCompletion) { - // Cache - cacheHit = true - completion = cachedCompletion - } else { - const multiline = !helper.options.transform || shouldCompleteMultiline(helper) - - const completionStream = this.completionStreamer.streamCompletionWithFilters( - token, - llm, - prefix, - suffix, - prompt, - multiline, - completionOptions, - helper, - ) - - for await (const update of completionStream) { - completion += update - } - - // Don't postprocess if aborted - if (token.aborted) { - return undefined - } - - const processedCompletion = helper.options.transform - ? postprocessCompletion({ - completion, - prefix: helper.prunedPrefix, - suffix: helper.prunedSuffix, - llm, - }) - : completion - - completion = processedCompletion - } - - if (!completion) { - return undefined - } - - const outcome: AutocompleteOutcome = { - time: Date.now() - startTime, - completion, - prefix, - suffix, - prompt, - modelProvider: llm.underlyingProviderName, - modelName: llm.model, - completionOptions, - cacheHit, - filepath: helper.filepath, - numLines: completion.split("\n").length, - completionId: helper.input.completionId, - gitRepo: "fake-placeholder", //MINIMAL_REPO - came from git - uniqueId: await this.ide.getUniqueId(), - timestamp: new Date().toISOString(), - profileType: this.configHandler.currentProfile?.profileDescription.profileType, - ...helper.options, - } - - if (options.experimental_enableStaticContextualization) { - outcome.enabledStaticContextualization = true - } - - ////////// - // Save to cache - if (!outcome.cacheHit && helper.options.useCache) { - ;(await this.autocompleteCache) - .put(outcome.prefix, outcome.completion) - .catch((e) => console.warn(`Failed to save to cache: ${e.message}`)) - } - - // When using the JetBrains extension, Mark as displayed - const ideType = (await this.ide.getIdeInfo()).ideType - if (ideType === "jetbrains") { - this.markDisplayed(input.completionId, outcome) - } - - return outcome - } catch (e: unknown) { - this.onError(e) - return undefined - } finally { - this.loggingService.deleteAbortController(input.completionId) - } - } -} - -export default CompletionProvider diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/MinimalConfig.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/MinimalConfig.ts deleted file mode 100644 index c834949ff15..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/MinimalConfig.ts +++ /dev/null @@ -1,126 +0,0 @@ -/** - * Minimal configuration for autocomplete features. - * This replaces the complex ConfigHandler system with simple hardcoded defaults. - * - * Analysis of ConfigHandler usage: - * - CompletionProvider needs: config.tabAutocompleteOptions, config.experimental.enableStaticContextualization, currentProfile.profileType - * - * The profileType is only used for logging/telemetry, so we can set it to undefined for a minimal extraction. - */ - -import { ILLM, TabAutocompleteOptions } from "../index.js" -import { DEFAULT_AUTOCOMPLETE_OPTS } from "../util/parameters.js" - -interface MinimalConfig { - tabAutocompleteOptions?: TabAutocompleteOptions - experimental?: { - enableStaticContextualization?: boolean - } - // Minimal model selection support for NextEdit context fetching - modelsByRole?: { - autocomplete?: ILLM[] - } - selectedModelByRole?: { - autocomplete?: ILLM - edit?: ILLM - chat?: ILLM - rerank?: ILLM - } - rules?: unknown[] -} - -interface MinimalProfile { - profileDescription: { - profileType?: "control-plane" | "local" | "platform" - } -} - -/** - * Default configuration with hardcoded values suitable for autocomplete/NextEdit. - * Uses the same defaults from DEFAULT_AUTOCOMPLETE_OPTS. - */ -const DEFAULT_MINIMAL_CONFIG: MinimalConfig = { - tabAutocompleteOptions: { - ...DEFAULT_AUTOCOMPLETE_OPTS, - }, - experimental: { - enableStaticContextualization: false, - }, - modelsByRole: { - autocomplete: [], - }, - selectedModelByRole: { - autocomplete: undefined, - }, -} - -/** - * Simple config provider that replaces ConfigHandler for autocomplete/NextEdit. - * Returns hardcoded configuration without dependencies on control-plane. - */ -export class MinimalConfigProvider { - private config: MinimalConfig - public currentProfile: MinimalProfile | undefined - - constructor(config?: Partial) { - this.config = { - ...DEFAULT_MINIMAL_CONFIG, - ...config, - tabAutocompleteOptions: { - ...DEFAULT_AUTOCOMPLETE_OPTS, - ...config?.tabAutocompleteOptions, - } as TabAutocompleteOptions, - experimental: { - ...DEFAULT_MINIMAL_CONFIG.experimental, - ...config?.experimental, - }, - } - - // Set a minimal profile for logging purposes - // In a minimal extraction, we don't have a control-plane profile - this.currentProfile = undefined - } - - /** - * Returns the config in the same shape as ConfigHandler.loadConfig() - * This maintains API compatibility with existing code. - */ - async loadConfig(): Promise<{ config: MinimalConfig }> { - return { config: this.config } - } - - /** - * Get autocomplete options directly - */ - getAutocompleteOptions(): TabAutocompleteOptions { - return this.config.tabAutocompleteOptions || DEFAULT_AUTOCOMPLETE_OPTS - } - - /** - * Check if static contextualization is enabled - */ - isStaticContextualizationEnabled(): boolean { - return this.config.experimental?.enableStaticContextualization ?? false - } - - /** - * Reload config (stub for compatibility) - */ - async reloadConfig(..._args: unknown[]): Promise { - // No-op for minimal config - } - - /** - * Register config update handler (stub for compatibility) - */ - onConfigUpdate(_handler: (event: { config: MinimalConfig; configLoadInterrupted: boolean }) => void): void { - // No-op for minimal config - } - - /** - * Register custom context provider (stub for compatibility) - */ - registerCustomContextProvider(_provider: unknown): void { - // No-op for minimal config - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/classification/shouldCompleteMultiline.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/classification/shouldCompleteMultiline.ts deleted file mode 100644 index e24b7008402..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/classification/shouldCompleteMultiline.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { AutocompleteLanguageInfo } from "../constants/AutocompleteLanguageInfo" -import { HelperVars } from "../util/HelperVars" - -function shouldCompleteMultilineBasedOnLanguage(language: AutocompleteLanguageInfo, prefix: string, suffix: string) { - return language.useMultiline?.({ prefix, suffix }) ?? true -} - -export function shouldCompleteMultiline(helper: HelperVars) { - switch (helper.options.multilineCompletions) { - case "always": - return true - case "never": - return false - default: - break - } - - // Always single-line if an intellisense option is selected - if (helper.input.selectedCompletionInfo) { - return true - } - - // // Don't complete multi-line if you are mid-line - // if (isMidlineCompletion(helper.fullPrefix, helper.fullSuffix)) { - // return false; - // } - - // Don't complete multi-line for single-line comments - if ( - helper.lang.singleLineComment && - helper.fullPrefix.split("\n").slice(-1)[0]?.trimStart().startsWith(helper.lang.singleLineComment) - ) { - return false - } - - return shouldCompleteMultilineBasedOnLanguage(helper.lang, helper.prunedPrefix, helper.prunedSuffix) -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts deleted file mode 100644 index 28bedc73429..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/StreamTransformPipeline.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { streamLines } from "../../../diff/util" -import { HelperVars } from "../../util/HelperVars" - -import { stopAtStartOf, stopAtStopTokens } from "./charStream" -import { - avoidEmptyComments, - avoidPathLine, - noDoubleNewLine, - showWhateverWeHaveAtXMs, - skipPrefixes, - stopAtLines, - stopAtLinesExact, - stopAtRepeatingLines, - stopAtSimilarLine, - streamWithNewLines, -} from "./lineStream" - -const STOP_AT_PATTERNS = ["diff --git"] - -export class StreamTransformPipeline { - async *transform( - generator: AsyncGenerator, - prefix: string, - suffix: string, - multiline: boolean, - stopTokens: string[], - fullStop: () => void, - helper: HelperVars, - ): AsyncGenerator { - let charGenerator = generator - - charGenerator = stopAtStopTokens(generator, [...stopTokens, ...STOP_AT_PATTERNS]) - charGenerator = stopAtStartOf(charGenerator, suffix) - for (const charFilter of helper.lang.charFilters ?? []) { - charGenerator = charFilter({ - chars: charGenerator, - prefix, - suffix, - filepath: helper.filepath, - multiline, - }) - } - - let lineGenerator = streamLines(charGenerator) - - lineGenerator = stopAtLines(lineGenerator, fullStop) - const lineBelowCursor = this.getLineBelowCursor(helper) - if (lineBelowCursor.trim() !== "") { - lineGenerator = stopAtLinesExact(lineGenerator, fullStop, [lineBelowCursor]) - } - lineGenerator = stopAtRepeatingLines(lineGenerator, fullStop) - lineGenerator = avoidEmptyComments(lineGenerator, helper.lang.singleLineComment) - lineGenerator = avoidPathLine(lineGenerator, helper.lang.singleLineComment) - lineGenerator = skipPrefixes(lineGenerator) - lineGenerator = noDoubleNewLine(lineGenerator) - - for (const lineFilter of helper.lang.lineFilters ?? []) { - lineGenerator = lineFilter({ lines: lineGenerator, fullStop }) - } - - lineGenerator = stopAtSimilarLine(lineGenerator, this.getLineBelowCursor(helper), fullStop) - - const timeoutValue = helper.options.modelTimeout - - lineGenerator = showWhateverWeHaveAtXMs(lineGenerator, timeoutValue!) - - const finalGenerator = streamWithNewLines(lineGenerator) - for await (const update of finalGenerator) { - yield update - } - } - - private getLineBelowCursor(helper: HelperVars): string { - let lineBelowCursor = "" - let i = 1 - while (lineBelowCursor.trim() === "" && helper.pos.line + i <= helper.fileLines.length - 1) { - lineBelowCursor = helper.fileLines[Math.min(helper.pos.line + i, helper.fileLines.length - 1)] - i++ - } - return lineBelowCursor - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.test.ts deleted file mode 100644 index 488798b60f8..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.test.ts +++ /dev/null @@ -1,192 +0,0 @@ -import { describe, expect, it } from "vitest" -import { stopAtStartOf, stopAtStopTokens } from "./charStream" - -async function* createMockStream(chunks: string[]): AsyncGenerator { - for (const chunk of chunks) { - yield chunk - } -} - -async function streamToString(stream: AsyncGenerator): Promise { - let result = "" - for await (const chunk of stream) { - result += chunk - } - return result -} - -describe("stopAtStopTokens", () => { - it("should yield characters until a stop token is encountered", async () => { - const mockStream = createMockStream(["Hello", " world", "! Stop", "here"]) - const stopTokens = ["Stop"] - const result = stopAtStopTokens(mockStream, stopTokens) - - const output = [] - for await (const char of result) { - output.push(char) - } - - expect(output.join("")).toBe("Hello world! ") - }) - - it("should handle multiple stop tokens", async () => { - const mockStream = createMockStream(["This", " is a ", "test. END", " of stream"]) - const stopTokens = ["END", "STOP", "HALT"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("This is a test. ") - }) - - it("should handle stop tokens split across chunks", async () => { - const mockStream = createMockStream(["Hello", " wo", "r", "ld! ST", "OP now"]) - const stopTokens = ["STOP"] - const result = stopAtStopTokens(mockStream, stopTokens) - - const output = [] - for await (const char of result) { - output.push(char) - } - - expect(output.join("")).toBe("Hello world! ") - }) - - it("should yield all characters if no stop token is encountered", async () => { - const mockStream = createMockStream(["This", " is ", "a complete", " stream"]) - const stopTokens = ["END"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("This is a complete stream") - }) - - it("should handle empty chunks", async () => { - const mockStream = createMockStream(["Hello", "", " world", "", "! STOP"]) - const stopTokens = ["STOP"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("Hello world! ") - }) - - it("should handle stop token at the beginning of the stream", async () => { - const mockStream = createMockStream(["STOP", "Hello world"]) - const stopTokens = ["STOP"] - const result = stopAtStopTokens(mockStream, stopTokens) - - const output = [] - for await (const char of result) { - output.push(char) - } - - expect(output.join("")).toBe("") - }) - - it("should handle stop token at the end of the stream", async () => { - const mockStream = createMockStream(["Hello world", "STOP"]) - const stopTokens = ["STOP"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("Hello world") - }) - - it("should handle multiple stop tokens of different lengths", async () => { - const mockStream = createMockStream(["This is a ", "test with ", "multiple STOP", " tokens END"]) - const stopTokens = ["STOP", "END", "HALT"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("This is a test with multiple ") - }) - - it("should handle an empty stream", async () => { - const mockStream = createMockStream([]) - const stopTokens = ["STOP"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("") - }) - - it("should handle an empty stop tokens array", async () => { - const mockStream = createMockStream(["Hello", " world!"]) - const stopTokens: string[] = [] - const result = stopAtStopTokens(mockStream, stopTokens) - - const output = [] - for await (const char of result) { - output.push(char) - } - - expect(output.join("")).toBe("Hello world!") - }) - - it("should handle stop token when remaining buffer is smaller than maximum stop token length", async () => { - const mockStream = createMockStream(["Hello world!STOP"]) - const stopTokens: string[] = ["STOP", "STOP_TOKEN_THAT_IS_LARGER_THAN_BUFFER"] - const result = stopAtStopTokens(mockStream, stopTokens) - - expect(await streamToString(result)).toBe("Hello world!") - }) -}) - -describe("stopAtStartOf", () => { - const sampleCode = ` { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: \`Bearer \${this.workOsAccessToken}\`, - }, - }, - ); - const data = await response.json(); - return data.items; - } - - async getContextItems( - query: string, - extras: ContextProviderExtras, - ): Promise { - const response = await extras.fetch( - new URL( - \`/proxy/context/\${this.options.id}/retrieve\`, - controlPlaneEnv.CONTROL_PLANE_URL, - ), -` - - /* Some LLMs, such as Codestral, repeat the suffix of the query. To test our filtering, we cut the sample code at random positions, remove a part of the input -and construct a response, containing the removed part and the suffix. The goal of the stopAtStartOf() method is to detect the start of the suffix in the response */ - it("should stop if the start of the suffix is reached", async () => { - const suffix = ` - const data = await response.json(); - return data.items; -}` - const mockStream = createMockStream(sampleCode.split(/(?! )/g)) - const result = stopAtStartOf(mockStream, suffix) - - const resultStr = await streamToString(result) - expect(resultStr).toBe(` { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: \`Bearer \${this.workOsAccessToken}\`, - }, - }, - ); - `) - }) - it("should stop if the start of the suffix is reached, even if the suffix has a prefix", async () => { - const suffix = ` - xxxconst data = await response.json(); - return data.items; -}` - const mockStream = createMockStream(sampleCode.split(/(?! )/g)) - const result = stopAtStartOf(mockStream, suffix) - - const resultStr = await streamToString(result) - expect(resultStr).toBe(` { - method: "GET", - headers: { - "Content-Type": "application/json", - Authorization: \`Bearer \${this.workOsAccessToken}\`, - }, - }, - ); - `) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.ts deleted file mode 100644 index d19bed609ca..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/charStream.ts +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Asynchronously yields characters from the input stream, stopping if a stop token is encountered. - * - * @param {AsyncGenerator} stream - The input stream of characters. - * @param {string[]} stopTokens - Array of tokens that signal when to stop yielding. - * @yields {string} Characters from the input stream. - * @returns {AsyncGenerator} An async generator that yields characters until a stop condition is met. - * @description - * 1. If no stop tokens are provided, yields all characters from the stream. - * 2. Otherwise, buffers incoming chunks and checks for stop tokens. - * 3. Yields characters one by one if no stop token is found at the start of the buffer. - * 4. Stops yielding and returns if a stop token is encountered. - * 5. After the stream ends, filters encountered stop tokens in remaining buffer. - * 6. Yields any remaining buffered characters. - */ -export async function* stopAtStopTokens(stream: AsyncGenerator, stopTokens: string[]): AsyncGenerator { - if (stopTokens.length === 0) { - for await (const char of stream) { - yield char - } - return - } - - const maxStopTokenLength = Math.max(...stopTokens.map((token) => token.length)) - let buffer = "" - - for await (const chunk of stream) { - buffer += chunk - - while (buffer.length >= maxStopTokenLength) { - let found = false - for (const stopToken of stopTokens) { - if (buffer.startsWith(stopToken)) { - found = true - return - } - } - - if (!found) { - yield buffer[0] - buffer = buffer.slice(1) - } - } - } - // Filter out the possible stop tokens from remaining buffer - stopTokens.forEach((token) => { - buffer = buffer.replace(token, "") - }) - - // Yield any remaining characters in the buffer - for (const char of buffer) { - yield char - } -} - -/** - * Asynchronously yields characters from the input stream. - * Stops if the beginning of the suffix is detected in the stream. - */ -export async function* stopAtStartOf( - stream: AsyncGenerator, - suffix: string, - sequenceLength: number = 20, -): AsyncGenerator { - if (suffix.length < sequenceLength) { - for await (const chunk of stream) { - yield chunk - } - return - } - // We use sequenceLength * 1.5 as a heuristic to make sure we don't miss the sequence if the - // stream is not perfectly aligned with the sequence (small whitespace differences etc). - const targetPart = suffix.trimStart().slice(0, Math.floor(sequenceLength * 1.5)) - - let buffer = "" - - for await (const chunk of stream) { - buffer += chunk - - // Check if the targetPart contains contains the buffer at any point - if (buffer.length >= sequenceLength && targetPart.includes(buffer)) { - return // Stop processing when the sequence is found - } - - // Yield chunk by chunk, ensuring not to exceed sequenceLength in the buffer - while (buffer.length > sequenceLength) { - yield buffer[0] - buffer = buffer.slice(1) - } - } - - // Yield the remaining buffer if it is not contained in the `targetPart` - if (buffer.length > 0) { - yield buffer - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/lineStream.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/lineStream.ts index 2a0be704a67..a4cc5e15265 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/lineStream.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/streamTransforms/lineStream.ts @@ -1,4 +1,4 @@ -import { LineStream } from "../../../diff/util" +import type { LineStream } from "../../../diff/util" import { lineIsRepeated } from "../../util/textSimilarity" export { lineIsRepeated } @@ -177,19 +177,6 @@ export async function* stopAtLines( } } -/** - * Yield until an exact stop line is encountered, then call fullStop. - */ -export async function* stopAtLinesExact(stream: LineStream, fullStop: () => void, linesToStopAt: string[]): LineStream { - for await (const line of stream) { - if (linesToStopAt.some((stopAt) => line === stopAt)) { - fullStop() - break - } - yield line - } -} - /** * On the first line only, strip any configured prefix (e.g. ""). */ @@ -230,41 +217,3 @@ export async function* stopAtRepeatingLines(lines: LineStream, fullStop: () => v previousLine = line } } - -/** - * Pass through lines, but if the stream takes longer than ms after we have at least one non-empty line, stop early. - */ -export async function* showWhateverWeHaveAtXMs(lines: LineStream, ms: number): LineStream { - const startTime = Date.now() - let firstNonWhitespaceLineYielded = false - - for await (const line of lines) { - yield line - - if (!firstNonWhitespaceLineYielded && line.trim() !== "") { - firstNonWhitespaceLineYielded = true - } - - const isTakingTooLong = Date.now() - startTime > ms - if (isTakingTooLong && firstNonWhitespaceLineYielded) { - break - } - } -} - -/** - * Yield lines until the first blank line after some content; then stop. - */ -export async function* noDoubleNewLine(lines: LineStream): LineStream { - let isFirstLine = true - - for await (const line of lines) { - if (line.trim() === "" && !isFirstLine) { - return - } - - isFirstLine = false - - yield line - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_JSON.txt b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_JSON.txt deleted file mode 100644 index ff0ba3cb39a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_JSON.txt +++ /dev/null @@ -1,60 +0,0 @@ -##### Prompt ##### -{ - "active": true, - "department": "Product Development", - "location": { - "country": "USA", - "state": "California", - "city": "San BERNARDINO", - "coordinates": { - - } - }, - "employees": [ - { - "name": "John Doe", - "age": 30, - "position": "Developer", - "skills": ["JavaScript", "React", "Node.js"], - "remote": false, - "salary": { - "currency": "USD", - "amount": 95000 - } - }, - { - "name": "Jane Smith", - "age": 25, - "position": "Designer", - "skills": ["Photoshop", "Illustrator"], - "remote": true, - "salary": { - "currency": "USD", - "amount": 70000 - } - }, - { - "name": "Emily Johnson", - "age": 35, - "position": "Manager", - "teamSize": 8, - "remote": true, - "skills": ["Leadership", "Project Management"],========================================================================== -========================================================================== -Completion: - - "latitude": 34.10834, - "longitude": -117.28977 - } - }, - "employeeCount": 2, - "averageAge": 30, - "remoteFriendly": true, - "salaryRange": { - "min": 70000, - "max": 95000, - "currency": "USD" - }, - "skills": { - "required": ["JavaScript", "React", "Node.js", "Leadership", "Project Management"], - "optional": ["Photoshop", "Illustrator"] \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_TYPESCRIPT.txt b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_TYPESCRIPT.txt deleted file mode 100644 index 241d141f28b..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/QWEN_TYPESCRIPT.txt +++ /dev/null @@ -1,128 +0,0 @@ -##### Prompt ##### - }`, - }, - { - description: "Should autocomplete Vue computed property", - filename: "UserComponent.vue", - input: ` - - -`, - llmOutput: `() { - return this.firstName + ' ' + this.lastName; - }`, - expectedCompletion: `() { - return this.firstName + ' ' + this.lastName; - }`, - }, - { - description: "Should autocomplete Vue method using props", - filename: "TodoItem.vue", - input: ` - - -`, - llmOutput: `this.completed`, - expectedCompletion: `this.completed`, - }, - { - description: "Should autocomplete Svelte reactive statement", - filename: "Counter.svelte", - input: ` - - - -`, - llmOutput: `doubledCount = count * 2`, - expectedCompletion: `doubledCount = count * 2`, - }, - - { - description: "Should autocomplete Svelte component inside HTML", - filename: "NestedComponent.svelte", - input: ` - - -
-

Hello Svelte

- /> -
-`, - llmOutput: `name="World"`, - expectedCompletion: `name="World"`, - }, - - { - description: "Should handle autocomplete in Svelte each block", - filename: "List.svelte", - input: ` - - -
    - {#each items as item} -
  • {item}
  • - {/each<|fim|> -
-`, - llmOutput: `}`, - expectedCompletion: `}`, - }, - -]; -========================================================================== -========================================================================== -Completion: - - - -export default { - components: { - ChildComponent, - }, \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_JSON.txt b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_JSON.txt deleted file mode 100644 index a50bd2fb4c1..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_JSON.txt +++ /dev/null @@ -1,20 +0,0 @@ -##### Prompt ##### -{ - "employees": [ - { "name": "John Doe", "age": 30, "position": "Developer" }, - { "name": "Jane Smith", "age": 25, "position": "Designer" }, - { "name": "Emily Johnson", "age": 35, "position": "Manager" } - ], - "active": true -} -========================================================================== -========================================================================== -Completion: - - -} - -{ - "employees": [ - { "name": "John Doe", "age": 30 }, - { "name": "Jane Smith", "age": 25 } \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_PYTHON.TXT b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_PYTHON.TXT deleted file mode 100644 index c4aaf43ec1f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_PYTHON.TXT +++ /dev/null @@ -1,29 +0,0 @@ -##### Prompt ##### -class Calculator: - def __init__(self): - self.result = 0 - - def add(self, number): - self.result += number - return self - - def divid - - def subtract(self, number): - self.result -= number - return self - - def reset(self): - self.result = 0 - return self - - def get_result(self): - return self.result - - -========================================================================== -========================================================================== -Completion: - -self.result /= number - return self \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUBY.TXT b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUBY.TXT deleted file mode 100644 index df8c2011fba..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUBY.TXT +++ /dev/null @@ -1,41 +0,0 @@ -##### Prompt ##### -class Calculator - attr_accessor :result - - def initialize - @result = 0 - end - - def add(number) - @result += number - self - end - - def subtract(number) - @result -= number - self - end - - def power(ne - - def get_result - @result - end - - def reset - @result = 0 - self - end -end - -calc = Calculator.new -calc.add(5).subtract(3) -puts "Result: #{calc.get_result}" -========================================================================== -========================================================================== -Completion: - - - @result ** number - self - end \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUST.TXT b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUST.TXT deleted file mode 100644 index 582ae5f364d..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/NEGATIVE_TEST_CASES/STARCODER_RUST.TXT +++ /dev/null @@ -1,73 +0,0 @@ -##### Prompt ##### -use std::io; - -fn main() { - println!("Welcome to the Calculator!"); - - loop { - println!("Please enter an operator (+, -, *, /) or 'q' to quit:"); - let operator = read_input(); - - if operator == "q" { - break; - } - - println!("Please enter the first number:"); - let num1 = read_input().parse::().unwrap(); - - println!("Please enter the second number:"); - let num2 = read_input().parse::().unwrap(); - - let result = match operator.as_str() { - "+" => num1 + num2, - "-" => num1 - num2, - "*" => num1 * num2, - "/" => num1 / num2, - - _ => { - println!("Invalid operator. Please try again."); - continue; - } - }; - - println!("Result: {}", result); - } -} - -fn read_input() -> String { - let mut input = String::new(); - io::stdin() - .read_line(&mut input) - .expect("Failed to read input"); - input.trim().to_string() -} -========================================================================== -========================================================================== -Completion: - - => { - println!("Invalid operator. Please try again."); - continue; - } - }; - - println!("Result: {}", result); - } - - println!("Goodbye!"); -} - - -fn main2() { - println!("Welcome to the Calculator!"); - - loop { - println!("Please enter an operator (+, -, *, /) or 'q' to quit:"); - let operator = read_input(); - - if operator == "q" { - break; - } - - match operator.as_str() { - "+" | "-" | "*" | "/" => (), \ No newline at end of file diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/filter.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/filter.test.ts deleted file mode 100644 index 9f3a1d68e9a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/filter.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { afterAll, beforeAll, describe, it } from "vitest" -import { addToTestDir, setUpTestDir, tearDownTestDir } from "../../../test/testDir" - -import { TEST_CASES_WITH_DIFF, TEST_CASES_WITHOUT_DIFF } from "./testCases" -import { AutocompleteFileringTestInput, testAutocompleteFiltering } from "./util" - -const filterTestCases = (tests: AutocompleteFileringTestInput[]) => { - if (tests.some((test) => test.options?.only)) { - return tests.filter((test) => test.options?.only) - } - - return tests -} - -describe("Autocomplete filtering tests", () => { - beforeAll(async () => { - tearDownTestDir() - setUpTestDir() - addToTestDir([".continueignore"]) - }) - - afterAll(async () => { - tearDownTestDir() - }) - - describe("Should return unmodified LLM output", () => { - it.each(filterTestCases(TEST_CASES_WITHOUT_DIFF))("$description", async (testCase) => { - await testAutocompleteFiltering(testCase) - }) - }) - - describe("Should return modified LLM output", () => { - it.each(filterTestCases(TEST_CASES_WITH_DIFF))("$description", async (testCase) => { - await testAutocompleteFiltering(testCase) - }) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/testCases.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/testCases.ts deleted file mode 100644 index 909cb0a2b03..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/testCases.ts +++ /dev/null @@ -1,2175 +0,0 @@ -import { dedent } from "../../../util" - -import { AutocompleteFileringTestInput } from "./util" - -export const TEST_CASES_WITH_DIFF: AutocompleteFileringTestInput[] = [ - { - description: "Should handle python multi-line string", - filename: "test.py", - input: `def create_greeting(name): - greeting = """Hello, """ + name + """! -Welcome to our community. We hope you have a great time here. -If you have any questions, feel free to reach out.""" - return greeting - -message = create_greeting("Alice") -print(message) - -multi_line_message = """<|fim|> -print(multi_line_message) -`, - llmOutput: `This is a multi-line message. -It continues across multiple lines, -which allows for easy reading and formatting. -""" -`, - expectedCompletion: `This is a multi-line message. -It continues across multiple lines, -which allows for easy reading and formatting. -"""`, - }, - { - description: "Should autocomplete Rust match arms", - filename: "main.rs", - input: ` -fn get_status_code_description(code: u16) -> &'static str { - match code { - 200 => "OK", - 404 => "Not Found", - 500 => "Internal Server Error", - <|fim|> - } -} -`, - llmOutput: `403 => "Forbidden", - 401 => "Unauthorized", - _ => "Unknown Status", -`, - expectedCompletion: `403 => "Forbidden", - 401 => "Unauthorized", - _ => "Unknown Status",`, - }, - { - description: "Should complete a Markdown code block", - filename: "test.md", - input: ` -Here is a sample JavaScript function: - -\`\`\`javascript -function sayHello() { - console.log("Hello, <|fim|> -} -\`\`\` -`, - llmOutput: `world!"); -`, - expectedCompletion: 'world!");', - }, - { - description: "Should autocomplete Java when inside a block", - filename: "Main.java", - input: ` -public class Main { - public static void main(String[] args) { - for (int i = 0; i < 10; i++) { - if (i % 2 == 0) { - System.out.println("Even: " + i); - } else { -<|fim|> - } - } - } -}`, - llmOutput: ` - System.out.println("Odd: " + i); -`, - expectedCompletion: ` - System.out.println("Odd: " + i);`, - }, - { - description: "Should autocomplete a Markdown heading and preserve formatting", - filename: "test.md", - input: `# My Document - -## Introduction -This is a sample document for testing. - -## <|fim|> -### Conclusion -Thank you for reading. -`, - llmOutput: `Features -Here is a list of features: -- Feature 1 -- Feature 2 -`, - expectedCompletion: `Features -Here is a list of features: -- Feature 1 -- Feature 2`, - }, - { - // options: { only: true }, - description: "Should autocomplete a Java method within a class", - filename: "Calculator.java", - input: ` -public class Calculator { - private double result; - - public Calculator() { - this.result = 0.0; - } - - public void add(double number) { - result += number; -<|fim|>`, - llmOutput: ` - } - - public void subtract(double number) { - result -= number; - } -`, - expectedCompletion: ` - }`, - }, - { - description: "Should filter out consecutive, repeated YAML keys", - filename: "test.yaml", - input: ` - version: '3' - services: - db: - image: postgres - environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: pass<|fim|> - `, - llmOutput: ` - POSTGRES_DB: mydb - POSTGRES_DB: mydb - `, - expectedCompletion: ` - POSTGRES_DB: mydb`, - }, - { - description: "Should enforce bracket matching in JSON files", - filename: "test.json", - input: `{ - "active": true, - "department": "Product Development", - "location": { - "country": "USA", - "state": "California", - "city": "San BERNARDINO", - "coordinates": { - <|fim|> - } - }, - "employees": [ - { - "name": "John Doe", - "age": 30, - "position": "Developer", - "skills": ["JavaScript", "React", "Node.js"], - "remote": false, - "salary": { - "currency": "USD", - "amount": 95000 - } - }, - { - "name": "Jane Smith", - "age": 25, - "position": "Designer", - "skills": ["Photoshop", "Illustrator"], - "remote": true, - "salary": { - "currency": "USD", - "amount": 70000 - } - }, - { - "name": "Emily Johnson", - "age": 35, - "position": "Manager", - "teamSize": 8, - "remote": true, - "skills": ["Leadership", "Project Management"],`, - llmOutput: `"latitude": 34.10834, - "longitude": -117.28977 - } - }, - "employeeCount": 2, - "averageAge": 30, - "remoteFriendly": true, - "salaryRange": { - "min": 70000, - "max": 95000, - "currency": "USD" - }, - "skills": { - "required": ["JavaScript", "React", "Node.js", "Leadership", "Project Management"], - "optional": ["Photoshop", "Illustrator"]`, - expectedCompletion: `"latitude": 34.10834, - "longitude": -117.28977`, - }, - { - description: "Should return nothing when output is duplicated lines in TypeScript", - filename: "file.ts", - input: ` -async getContextForPath( - filepath: string, - astPath: AstPatt, - language: LanguageName, - options: ContextOptions = {}, -<|fim|> - ): Promise { - const snippets: AutocompleteCodeSnippet[] = []; - let parentKey = filepath; -`, - llmOutput: ` ): Promise { - const snippets: AutocompleteCodeSnippet[] = []; - `, - expectedCompletion: undefined, - }, - { - description: "Should return partial result when output is duplicated lines in TypeScript", - filename: "file.ts", - input: ` -async getContextForPath( - filepath: string, - astPath: AstPatt, - language: LanguageName, - options: ContextOptions = {}, -<|fim|> - ): Promise { - const snippets: AutocompleteCodeSnippet[] = []; - let parentKey = filepath; -`, - llmOutput: `console.log('TEST'); - ): Promise { - const snippets: AutocompleteCodeSnippet[] = []; - `, - expectedCompletion: `console.log('TEST');`, - }, - { - description: "Should autocomplete React effect hook", - input: `import React, { useState, useEffect } from "react"; - -export const Timer = () => { - const [seconds, setSeconds] = useState(0); - - useEffect(() => { - const interval = setInterval(() => { - setSeconds(seconds + 1); - }, 1000); - - <|fim|>; - - return () => clearInterval(interval); - }, [seconds]); - - return ( -
-

{seconds} seconds have passed.

-
- ); -};`, - llmOutput: "return () => clearInterval(interval);", - expectedCompletion: undefined, - filename: "Timer.tsx", - }, - { - description: "Should autocomplete simple return statement in TypeScript", - filename: "file.ts", - input: ` - multiply(number) { - this.result *= number; - return <|fim|> - } - - divide(number) { - if (number === 0) { - throw new Error("Cannot divide by zero"); - } - this.result /= number; - return this; - } -`, - llmOutput: ` this;`, - expectedCompletion: `this;`, - }, - { - description: "Should complete YAML list item and preserve structure", - filename: "test.yaml", - input: ` - services: - - name: web - image: nginx - - name: app<|fim|> - volumes: - - volume1 - - volume2 - `, - llmOutput: ` - image: node - `, - expectedCompletion: ` - image: node`, - }, - { - description: "Should complete YAML key-value pair inside a nested structure", - filename: "test.yaml", - input: ` - version: '3' - services: - db: - image: postgres - environment: - POSTGRES_USER: user - POSTGRES_PASSWORD: pass - POSTGRES_DB: mydb<|fim|> - `, - llmOutput: ` - PGDATA: /var/lib/postgresql/data/pgdata - `, - expectedCompletion: ` - PGDATA: /var/lib/postgresql/data/pgdata`, - }, - { - description: "Should complete YAML block within an existing block", - filename: "test.yaml", - input: ` - pipelines: - branches: - master: - - step: - name: Build and Test - script: - - npm install - - npm run test - - step: - name: Deploy<|fim|> - `, - llmOutput: ` - script: - - npm run deploy - `, - expectedCompletion: ` - script: - - npm run deploy`, - }, - { - description: "Should autocomplete SQL query with subquery and alias in SELECT clause", - filename: "complex_query.sql", - input: `SELECT u.id, - u.name, - (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count - FROM users u - WHERE u.active = 1 - <|fim|>`, - llmOutput: " AND EXISTS (SELECT 1 FROM transactions t WHERE t.user_id = u.id AND t.amount > 100)", - expectedCompletion: "AND EXISTS (SELECT 1 FROM transactions t WHERE t.user_id = u.id AND t.amount > 100)", - }, -] - -export const TEST_CASES_WITHOUT_DIFF: AutocompleteFileringTestInput[] = [ - { - description: "should pass", - filename: "test.js", - input: "console.log('Hello <|fim|>!');", - llmOutput: "World", - expectedCompletion: "World", - }, - { - description: "Should preserve closing brackets when the opening bracket is not a part of the completion.", - filename: "test.js", - input: dedent` - class Calculator { - constructor() { - this.result = 0; - } - - add(number) { - this.result += number; - return this; - } - - subtract(number) { - this.result -= number; - return this; - } - - multiply(number) { - this.result *= number; - return this; - } - - divide(number) { - <|fim|> - - getResult() { - return this.result; - } - - reset() { - this.result = 0; - return this; - } - } - `, - llmOutput: dedent`if (number === 0) { - throw new Error("Cannot divide by zero"); - } - this.result /= number; - return this; - }`, - expectedCompletion: dedent`if (number === 0) { - throw new Error("Cannot divide by zero"); - } - this.result /= number; - return this; - }`, - }, - { - description: "Should multiline-autocomplete CSS blocks", - input: `body { - font-family: Arial, sans-serif; - font-size: 16px; - color: #333333; -} - -h1 { - font-size: 24px; - font-weight: bold; - color: #000000; -} - -h4<|fim|> - -a { - text-decoration: none; - color: #007bff; -} - -.container { - width: 100%; - max-width: 1200px; - margin: 0 auto; - padding: 20px; -} - -.button { - display: inline-block; - padding: 10px 20px; - background-color: #007bff; - color: #ffffff;`, - llmOutput: ` { - font-size: 18px; - font-weight: bold; - color: #000000; -}`, - expectedCompletion: ` { - font-size: 18px; - font-weight: bold; - color: #000000; -}`, - filename: "test.css", - }, - { - description: "Should complete CSS rules inside a nested selector", - filename: "styles.css", - input: ` -.container { - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100vh; - - .inner { - <|fim|> - } -} -`, - llmOutput: `width: 50%; - height: 50%; - background-color: #f0f0f0;`, - expectedCompletion: `width: 50%; - height: 50%; - background-color: #f0f0f0;`, - }, - - { - description: "Should complete a CSS rule when the property is partially typed", - filename: "styles.css", - input: ` -button { - border: 2px solid #000; - border-radius<|fim|> -}`, - llmOutput: ": 5px;", - expectedCompletion: ": 5px;", - }, - - { - description: "Should handle CSS autocomplete with a single bracket present", - filename: "styles.css", - input: ` -.card { - box-shadow: 0 4px 8px rgba(0,0,0,0.2); - transition: 0.3s; - padding: 16px; - border-bottom-left-radius: <|fim|>px; - border-bottom-right-radius: 8px; -} -`, - llmOutput: "8", - expectedCompletion: "8", - }, - - { - description: "Should autocomplete CSS pseudoclass", - filename: "pseudoClass.css", - input: ` -input:focus { - outline: none; - border: 2px solid <|fim|>; -} -`, - llmOutput: "#4CAF50;", - expectedCompletion: "#4CAF50;", - }, - - { - description: "Should handle CSS variable syntax", - filename: "variables.css", - input: ` -:root { - --primary-color: #3498db; - --padding: 10px; -} - -.section { - background-color: var(<|fim|>); - padding: var(--padding); -} -`, - llmOutput: "--primary-color", - expectedCompletion: "--primary-color", - }, - { - description: "Should complete CSS grid template columns", - filename: "grid.css", - input: ` -.grid-container { - display: grid; - grid-template-columns: repeat(<|fim|>); - grid-gap: 10px; -} -`, - llmOutput: "3, 1fr", - expectedCompletion: "3, 1fr", - }, - - { - description: "Should complete PHP function inside a class with comments", - input: `name = $name; - $this->email = $email; - } - - public function <|fim|> - - public function setEmail($email) { - $this->email = $email; - } -}`, - llmOutput: `getDetails() { - return "Name: " . $this->name . ", Email: " . $this->email; - }`, - expectedCompletion: `getDetails() { - return "Name: " . $this->name . ", Email: " . $this->email; - }`, - filename: "User.php", - }, - - { - description: "Should autocomplete PHP function with inline logic", - input: ` -} - -echo calculateArea(5, 3);`, - llmOutput: "return $length * $width;", - expectedCompletion: "return $length * $width;", - filename: "areaCalculator.php", - }, - - { - description: "Should handle PHP completion in the middle of an array", - input: `); - -echo "First color is: " . $colors[0];`, - llmOutput: '"Blue"', - expectedCompletion: '"Blue"', - filename: "colors.php", - }, - { - description: "Should autocomplete React return statements (jsx)", - input: `import React from "react"; - -export const Button = ({ - onClick, - children, -}: { - children: React.ReactNode; - onClick: () => void; -}) => { - return ( -<|fim|> - ); -};`, - llmOutput: ``, - expectedCompletion: ``, - filename: "Button.tsx", - }, - { - description: "Should autocomplete React state initialization", - input: `import React, { useState } from "react"; - -export const Counter = () => { - const [count, setCount] = useState(<|fim|>); - - return ( -
-

You clicked {count} times

- -
- ); -};`, - llmOutput: "0", - expectedCompletion: "0", - filename: "Counter.tsx", - }, - { - description: "Should autocomplete React component methods", - input: `import React from "react"; - -class Form extends React.Component { - constructor(props) { - super(props); - this.state = { name: '' }; - } - - handleChange = (event) => { - <|fim|> - } - - handleSubmit = (event) => { - event.preventDefault(); - alert('A name was submitted: ' + this.state.name); - } - - render() { - return ( -
- - -
- ); - } -}`, - llmOutput: "this.setState({ name: event.target.value });", - expectedCompletion: "this.setState({ name: event.target.value });", - filename: "Form.tsx", - }, - { - description: "Should autocomplete Python function definition", - filename: "test.py", - input: `def calculate_area(length, width): - area = length * width - return area - -def calculate_perimeter(length, width): - <|fim|> -`, - llmOutput: `perimeter = 2 * (length + width) - return perimeter`, - expectedCompletion: `perimeter = 2 * (length + width) - return perimeter`, - }, - { - description: "Should complete Python class method with self", - filename: "test.py", - input: `class BankAccount: - def __init__(self, owner, balance=0): - self.owner = owner - self.balance = balance - - def deposit(self, amount): - self.balance += amount - return self.balance - - def withdraw(self, amount): - <|fim|> -`, - llmOutput: `if amount > self.balance: - return "Insufficient funds" - self.balance -= amount - return self.balance`, - expectedCompletion: `if amount > self.balance: - return "Insufficient funds" - self.balance -= amount - return self.balance`, - }, - { - description: "Should autocomplete Python list comprehension", - filename: "test.py", - input: `squares = [x**2 for x in range(10)] -even_squares = [x for x in squares if x % 2 == 0] -print(even_squares) - -odd_squares = [<|fim|> -print(odd_squares) -`, - llmOutput: "x for x in squares if x % 2 != 0", - expectedCompletion: "x for x in squares if x % 2 != 0", - }, - { - description: "Should autocomplete a simple Go function declaration", - filename: "simpleFunction.go", - input: `package main - -import ( - "fmt" -) - -func main() { - fmt.Println("Hello, World!") -} - -func calculateArea<|fim|>`, - llmOutput: `(length float64, width float64) float64 { - return length * width -}`, - expectedCompletion: `(length float64, width float64) float64 { - return length * width -}`, - }, - - { - description: "Should handle autocomplete in the middle of a Go struct definition", - filename: "structDefinition.go", - input: `package main - -type Person struct { - FirstName string - LastName string - Age int - Address Address -} - -type Address struct { - Street string - City <|fim|> -} - -func main() {}`, - llmOutput: `string - State string - ZipCode string -}`, - expectedCompletion: `string - State string - ZipCode string`, - }, - - { - description: "Should autocomplete a missing Go function body bracket", - filename: "missingBracket.go", - input: `package main - -func add(a int, b int) int { - return a + b<|fim|> - -func multiply(a int, b int) int { - return a * b -} - -func main() { - result1 := add(2, 3) - result2 := multiply(4, 5) - println(result1, result2) -}`, - llmOutput: ` -}`, - expectedCompletion: ` -}`, - }, - { - description: "Should autocomplete SQL query with nested functions and missing bracket", - filename: "_nested_function.sql", - input: `SELECT name, ROUND(AVG(rating), 2) as avg_rating - FROM movies - WHERE release_year > 2000 AND director = 'Christopher Nolan' - GROUP BY name - HAVING avg_rating > <|fim|>`, - llmOutput: "8.5)", - expectedCompletion: "8.5)", - }, - { - description: "Should autocomplete SQL script with employee and product tables", - filename: "database.sql", - input: ` - CREATE TABLE employees ( - id INT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(100) NOT NULL, - age INT NOT NULL, - position VARCHAR(100) - ); - - CREATE TABLE products ( - id INT AUTO_INCREMENT PRIMARY KEY, - name VARCHAR(100), - price DECIMAL(8,2) NOT NULL<|fim|> '0.00', - quantity INT NOT NULL DEFAULT '0' - ); - - INSERT INTO employees (name, age, position) VALUES ('John Doe', 30, 'Developer'); - INSERT INTO products (name, price, quantity) VALUES ('Apple', '1.99', '47'); - - SELECT * FROM products ORDER BY name DESC LIMIT 3; - SELECT * FROM products WHERE price > '0'; - SELECT * FROM products WHERE quantity > '100'; - SELECT * FROM employees WHERE age > 25; - `, - llmOutput: " DEFAULT", - expectedCompletion: " DEFAULT", - }, - { - description: "Should autocomplete multi-line SQL query with CASE statements", - filename: "case_statement.sql", - input: `SELECT order_id, - order_date, - CASE - WHEN status = 'shipped' THEN 'Completed' - WHEN status = 'pending' THEN 'Pending Approval' - <|fim|> - ELSE 'Unknown' - END as order_status - FROM orders`, - llmOutput: "WHEN status = 'cancelled' THEN 'Cancelled'", - expectedCompletion: "WHEN status = 'cancelled' THEN 'Cancelled'", - }, - { - description: "Should autocomplete HTML paragraph content", - input: ` - - Document - - -

<|fim|>

- -`, - llmOutput: "This is a paragraph with some sample text.", - expectedCompletion: "This is a paragraph with some sample text.", - filename: "test.html", - }, - { - description: "Should autocomplete HTML attributes within a tag", - input: `
- > -
-

Title

-

Description text.

-
-
`, - llmOutput: 'alt="Description of image"', - expectedCompletion: 'alt="Description of image"', - filename: "test.html", - }, - { - description: "Should autocomplete HTML nested tags", - input: `
    -
  • Item 1
  • -
  • Item 2
  • -
  • Item 3
  • -
`, - llmOutput: ">Item 4", - expectedCompletion: ">Item 4", - filename: "test.html", - }, - - { - description: "Should complete a class method in Ruby", - input: ` -class Greeter - def initialize(name) - @name = name - end - - def greet - puts "Hello, <|fim|> - end -end - -g = Greeter.new("World") -g.greet -`, - llmOutput: "#{@name}!", - expectedCompletion: "#{@name}!", - filename: "greeter.rb", - }, - { - description: "Should complete Ruby if-else block", - input: ` -number = 10 - -if number > 5 - puts "Number is greater than 5" -<|fim|> -end -`, - llmOutput: `else - puts "Number is 5 or less"`, - expectedCompletion: `else - puts "Number is 5 or less"`, - filename: "conditional.rb", - }, - { - description: "Should complete Ruby array method", - input: ` -numbers = [1, 2, 3, 4, 5] -squared_numbers = numbers.<|fim|> -`, - llmOutput: "map { |n| n ** 2 }", - expectedCompletion: "map { |n| n ** 2 }", - filename: "array_methods.rb", - }, - { - description: "Should autocomplete Java within a string", - filename: "App.java", - input: ` -public class App { - public static void main(String[] args) { - String message = "Hello, <|fim|>"; - System.out.println(message); - } -}`, - llmOutput: "World", - expectedCompletion: "World", - }, - { - description: "Should autocomplete a C++ class definition with a constructor", - filename: "test.cpp", - input: "class Vehicle { public: Vehicle(<|fim|>); };", - llmOutput: "int wheels, double weight", - expectedCompletion: "int wheels, double weight", - }, - { - description: "Should complete a C++ method declaration inside a class", - filename: "test.cpp", - input: "class Calculator { public: int add(int a, int b); int subtract(int a, int b);<|fim|> };", - llmOutput: " int multiply(int a, int b);", - expectedCompletion: " int multiply(int a, int b);", - }, - { - description: "Should autocomplete C++ for loop syntax", - filename: "test.cpp", - input: ` - int sum = 0; - for (int i = 0; i < 10; <|fim|>) { - sum += i; - } - `, - llmOutput: "i++", - expectedCompletion: "i++", - }, - { - description: "Should autocomplete JSON object inside an array", - filename: "data.json", - input: `{ - "users": [ - { "id": 1, "name": "Alice" }, - { "id": 2, "name": "Bob" } - <|fim|> - ] -}`, - llmOutput: ', { "id": 3, "name": "Charlie" }', - expectedCompletion: ', { "id": 3, "name": "Charlie" }', - }, - { - description: "Should autocomplete within a CSV record", - filename: "test.csv", - input: `Name, Age, City -John Doe, 30, New York -Jane Smith<|fim|>`, - llmOutput: ", 25, Los Angeles", - expectedCompletion: ", 25, Los Angeles", - }, - { - description: "Should complete CSV record when starting in the middle of a word", - filename: "test.csv", - input: `Product, Price, Quantity -Laptop, 1200, 5 -Smart<|fim|>`, - llmOutput: "phone, 800, 10", - expectedCompletion: "phone, 800, 10", - }, - { - description: "Should complete CSV structure adding closing brackets", - filename: "test.csv", - input: `ID, Name, JoiningDate -1, Alice, 2023-01-10 -2, B<|fim|>`, - llmOutput: "ob, 2023-02-10", - expectedCompletion: "ob, 2023-02-10", - }, - { - description: "Should autocomplete a Rust function implementation inside a struct", - filename: "main.rs", - input: ` -struct Calculator { - result: f64, -} - -impl Calculator { - fn new() -> Self { - Calculator { result: 0.0 } - } - - fn add(&mut self, number: f64) { - self.result += number; - } - - fn subtract(&mut self, number: f64) { - self.result -= number; - } - - fn multiply(&mut self, number: f64) { - self.result *= number; - } - - fn divide(&mut self, number: f64) { - if number != 0.0 { - self.result /= number; - } else { - println!("Cannot divide by zero."); - } - } - - fn reset(&mut self) { - self.result = 0.0; - } - - fn get_result(&self) -> f64 { - self.result - } - - fn<|fim|> -} -`, - llmOutput: ` divide(&mut self, number: f64) { - if number != 0.0 { - self.result /= number; - } else { - println!("Cannot divide by zero."); - } -}`, - expectedCompletion: ` divide(&mut self, number: f64) { - if number != 0.0 { - self.result /= number; - } else { - println!("Cannot divide by zero."); - }`, - }, - { - description: "Should autocomplete Rust struct definition", - filename: "main.rs", - input: ` -struct User { - id: u32, - username: String, - email: String, - is_active: bool, - <|fim|> -} - -impl User { - fn new(id: u32, username: String, email: String) -> Self { - User { - id, - username, - email, - is_active: true, - } - } -} -`, - llmOutput: `created_at: String, - updated_at: String,`, - expectedCompletion: `created_at: String, - updated_at: String,`, - }, - { - description: "Haskell: Nested pattern matching with let bindings", - filename: "NestedPattern.hs", - input: `module NestedPattern where - -data Tree a = Leaf a | Node (Tree a) (Tree a) - -sumTree :: Num a => Tree a -> a -sumTree (Leaf x) = x -sumTree (Node left right) = - let leftSum = <|fim|> - rightSum = sumTree right - in leftSum + rightSum`, - llmOutput: "sumTree left", - expectedCompletion: "sumTree left", - }, - { - description: "Haskell: Complex function with where clause and guards", - filename: "QuadraticSolver.hs", - input: `module QuadraticSolver where - -solveQuadratic :: (Ord a, Floating a) => a -> a -> a -> Maybe (a, a) -solveQuadratic a b c - | discriminant < 0 = Nothing - | otherwise = Just (x1, x2) - where - discriminant = b^2 - 4*a*c - sqrtD = sqrt discriminant - x1 = (-b + sqrtD) / (2*a) - <|fim|> = (-b - sqrtD) / (2*a)`, - llmOutput: "x2", - expectedCompletion: "x2", - }, - { - description: "Haskell: List comprehension with complex filter", - filename: "PrimeNumbers.hs", - input: `module PrimeNumbers where - -primesUpTo :: Int -> [Int] -primesUpTo n = [x | x <- [2..n], isPrime x] - where isPrime num = <|fim|> && all (\\d -> num \`mod\` d /= 0) [2..(floor . sqrt $ fromIntegral num)]`, - llmOutput: "num > 1", - expectedCompletion: "num > 1", - }, - { - description: "Should autocomplete Dart class methods", - filename: "calculator.dart", - input: ` -class Calculator { - double result = 0.0; - - void add(double number) { - result += number; - } - - void multiply(double number) { - result *= number; - } - - <|fim|> - - double getResult() { - return result; - } -}`, - llmOutput: `void subtract(double number) { - result -= number; - }`, - expectedCompletion: `void subtract(double number) { - result -= number; - }`, - }, - { - description: "Should handle string interpolation in Dart", - filename: "greetings.dart", - input: ` -void main() { - var name = "World"; - print('Hello, <|fim|>!'); -}`, - llmOutput: "${name}", - expectedCompletion: "${name}", - }, - { - description: "Should autocomplete within a Dart function body", - filename: "counter.dart", - input: ` -class Counter { - int count = 0; - - void increment() { - count++; - } - - void decrement() { - <|fim|> - - void reset() { - count = 0; - } -}`, - llmOutput: "count--;", - expectedCompletion: "count--;", - }, - { - description: "Should autocomplete Clojure function definition with missing closing parenthesis", - input: `(defn calculate-sum [a b] - (let [sum (+ a b)] - (println "The sum is" sum) - sum<|fim|>`, - llmOutput: "))", - expectedCompletion: "))", - filename: "test.clj", - }, - { - description: "Should autocomplete missing part of a Clojure map within a function", - input: `(defn get-user [] - {:username "johndoe" - :email "johndoe@example.com" - :age 30 - <|fim|> - (println "User information loaded"))`, - llmOutput: ':location "Unknown"}', - expectedCompletion: ':location "Unknown"}', - filename: "test.clj", - }, - { - description: "Should autocomplete inside a Clojure vector within a looping construct", - input: `(defn odd-numbers [] - (loop [nums [1 3 5<|fim|> 9 11]] - (when (seq nums) - (println (first nums)) - (recur (rest nums)))))`, - llmOutput: " 7,", - expectedCompletion: " 7,", - filename: "test.clj", - }, - { - description: "Should autocomplete R function definition", - filename: "calculate.R", - input: ` -calculate_mean <- function(numbers) { - total <- sum(numbers) - <|fim|> -}`, - llmOutput: `mean_value <- total / length(numbers) - return(mean_value)`, - expectedCompletion: `mean_value <- total / length(numbers) - return(mean_value)`, - }, - { - description: "Should complete R loop and print statement", - filename: "loopPrint.R", - input: ` -numbers <- c(1, 2, 3, 4, 5) -for (number in numbers) { - print(<|fim|>) -}`, - llmOutput: "number)", - expectedCompletion: "number)", - }, - { - description: "Should autocomplete R data frame creation", - filename: "dataFrame.R", - input: ` -data <- data.frame( - Name = c("Alice", "Bob", "Charlie"), - Age = c(25, 30, 35), - <|fim|> -)`, - llmOutput: "Height = c(165, 180, 175)", - expectedCompletion: "Height = c(165, 180, 175)", - }, - { - description: "Should autocomplete R if-else statement", - filename: "condition.R", - input: ` -grade <- 85 -if (grade >= 90) { - print("A") -} else if (grade >= 80) { - <|fim|> -} else { - print("C") -}`, - llmOutput: 'print("B")', - expectedCompletion: 'print("B")', - }, - { - description: "Should autocomplete R ggplot2 plot structure", - filename: "plot.R", - input: ` -library(ggplot2) - -ggplot(data=mtcars, aes(x=wt, y=mpg)) + - geom_point() + - <|fim|>`, - llmOutput: "geom_smooth(method='lm', se=FALSE)", - expectedCompletion: "geom_smooth(method='lm', se=FALSE)", - }, - { - description: "Should autocomplete Scala class with a method", - filename: "Person.scala", - input: `class Person(val name: String, val age: Int) { - def greet(): String = { - <|fim|> - } - }`, - llmOutput: 's"Hello, my name is $name and I am $age years old."', - expectedCompletion: 's"Hello, my name is $name and I am $age years old."', - }, - - { - description: "Should handle Scala case class with a missing field", - filename: "Person.scala", - input: `case class Address(city: String, postalCode: String) - case class Person(name: String, age: Int, address: Address) - - val alice = Person("Alice", 30, Address("Wonderland", <|fim|>))`, - llmOutput: '"12345")', - expectedCompletion: '"12345")', - }, - - { - description: "Should autocomplete Scala function with missing body bracket", - filename: "Math.scala", - input: `object MathUtils { - def add(a: Int, b: Int): Int = { - a + b<|fim|> - - def multiply(a: Int, b: Int): Int = { - a * b - } - } - - object Main extends App { - println(MathUtils.add(3, 5)) - println(MathUtils.multiply(4, 6)) - }`, - llmOutput: ` - }`, - expectedCompletion: ` - }`, - }, - { - description: "Should autocomplete C function definition", - filename: "math_utils.c", - input: `#include - -int add(int a, int b) { - return a + b; -} - -int multiply(int a, int b) { - return a * b; -} - -int subtract(int a, int b) { - <|fim|> -} - -int main() { - printf("Result: %d", add(2, 3)); - return 0; -}`, - llmOutput: "return a - b;", - expectedCompletion: "return a - b;", - }, - - { - description: "Should handle C struct with missing field initialization", - filename: "person.c", - input: `#include - -typedef struct { - char name[50]; - int age; - float height; -} Person; - -int main() { - Person alice = {"Alice", 30, <|fim|>}; - printf("Name: %s, Age: %d, Height: %.2f", alice.name, alice.age, alice.height); - return 0; -}`, - llmOutput: "5.5", - expectedCompletion: "5.5", - }, - - { - description: "Should autocomplete C function with missing body bracket", - filename: "area.c", - input: `#include - -double calculateCircleArea(double radius) { - const double pi = 3.14159; - return pi * radius * radius;<|fim|> - -double calculateRectangleArea(double length, double width) { - return length * width; -} - -int main() { - printf("Circle Area: %.2f", calculateCircleArea(5.0)); - printf("Rectangle Area: %.2f", calculateRectangleArea(4.0, 6.0)); - return 0; -}`, - llmOutput: ` -}`, - expectedCompletion: ` -}`, - }, - { - description: "Should autocomplete a simple Kotlin function declaration", - filename: "simpleFunction.kt", - input: ` -fun main() { - println("Hello, World!") -} - -fun calculateArea(length: Double, width: Double): Double <|fim|>`, - llmOutput: `{ - return length * width -}`, - expectedCompletion: `{ - return length * width -}`, - }, - { - description: "Should handle autocomplete inside a Kotlin data class", - filename: "dataClass.kt", - input: ` -data class User( - val id: Int, - val name: String, - val email: String, - <|fim|> -)`, - llmOutput: "val age: Int", - expectedCompletion: "val age: Int", - }, - { - description: "Should complete Kotlin if-else structure with missing brackets", - filename: "controlStructure.kt", - input: ` -fun getMax(a: Int, b: Int): Int { - if (a > b<|fim|> - } else { - return b - } -}`, - llmOutput: `) { - return a`, - expectedCompletion: `) { - return a`, - }, - { - description: "Should autocomplete Solidity function definition", - filename: "SimpleStorage.sol", - input: ` -pragma solidity ^0.8.0; - -contract SimpleStorage { - uint private data; - - function set(uint x) public { - data = x; - } - - function get() public view returns (uint) { - <|fim|> - } -} - `, - llmOutput: "return data;", - expectedCompletion: "return data;", - }, - - { - description: "Should autocomplete Solidity event with parameters", - filename: "EventExample.sol", - input: ` -pragma solidity ^0.8.0; - -contract EventExample { - event DataStored(uint indexed id, string content); - - function storeData(uint id, string memory content) public { - emit DataStored(<|fim|>); - } -} - `, - llmOutput: "id, content", - expectedCompletion: "id, content", - }, - - { - description: "Should handle Solidity struct definition completion", - filename: "StructDefinition.sol", - input: ` -pragma solidity ^0.8.0; - -contract StructExample { - struct Person { - string name; - uint age; - address wallet; - } - - Person[] private people; - - function addPerson(string memory name, uint age, address wallet) public { - people.push(Person(name, age, wallet)); - } - - function getFirstPerson<|fim|> -} - `, - llmOutput: `() public view returns (string memory, uint, address) { - if (people.length > 0) { - Person storage person = people[0]; - return (person.name, person.age, person.wallet); - } - return ("", 0, address(0)); - }`, - expectedCompletion: `() public view returns (string memory, uint, address) { - if (people.length > 0) { - Person storage person = people[0]; - return (person.name, person.age, person.wallet); - } - return ("", 0, address(0)); - }`, - }, - { - description: "Should autocomplete TypeScript interface properties", - filename: "User.ts", - input: ` -interface User { - id: number; - name: string; - e<|fim|> -} -`, - llmOutput: `mail: string; - age: number; -}`, - expectedCompletion: `mail: string; - age: number;`, - }, - { - description: "Should autocomplete TypeScript interface declarations", - filename: "autocomplete.ts", - input: `interface AutocompleteDiffSnippet extends BaseAutocompleteSnippet {} - -interface AutocompleteCodeSnippet`, - llmOutput: ` extends BaseAutocompleteSnippet { - filepath: string; -}`, - expectedCompletion: ` extends BaseAutocompleteSnippet { - filepath: string; -}`, - }, - { - description: "Should autocomplete a TypeScript arrow function inside a variable assignment", - filename: "mathOperations.ts", - input: ` -const addNumbers = (a: number, b: number): number => { - return a + b; -}; - -const multiplyNumbers = (a: number, b: number): number => { - re<|fim|> -} - -console.log(multiplyNumbers(2, 3)); -`, - llmOutput: "turn a * b;", - expectedCompletion: "turn a * b;", - }, - - // TODO - // { - // description: - // "Should handle autocomplete inside a nested TypeScript class method", - // filename: "Account.ts", - // input: ` - // class Account { - // private balance: number = 0; - - // deposit(amount: number) { - // this.balance += amount; - // return this.balance; - // } - - // withdraw(amount: number) { - // if (amount > this.balance) { - // throw new Error("Insufficient funds"); - // } - // this.balance -= amount; - // return thi<|fim|> - // } - // } - // `, - // llmOutput: `s.balance;`, - // expectedCompletion: `s.balance;`, - // }, - - // TODO - // { - // description: "Should autocomplete a TypeScript generic function", - // filename: "GenericFunction.ts", - // input: ` - // function identity(arg: T): T { - // return ar<|fim|> - // } - - // console.log(identity(5)); - // `, - // llmOutput: `g;`, - // expectedCompletion: `g;`, - // }, - - // TODO - // { - // description: - // "Should autocomplete a TypeScript promise within an asynchronous function", - // filename: "asyncFunction.ts", - // input: ` - // async function fetchData(url: string): Promise { - // const response = await fetch(url); - // <|fim|> - // return data; - // } - - // fetchData('https://api.example.com/data'); - // `, - // llmOutput: `const data = await response.json();`, - // expectedCompletion: `const data = await response.json();`, - // }, - - { - description: "Should autocomplete a C# class with a constructor and property", - filename: "Person.cs", - input: `using System; - -public class Person -{ - public string Name { get; set; } - public int Age { get; set; } - - public Person(string name, int <|fim|> -}`, - llmOutput: `age) - { - Name = name; - Age = age; - }`, - expectedCompletion: `age) - { - Name = name; - Age = age; - }`, - }, - { - description: "Should autocomplete a C# interface method", - filename: "IGreetable.cs", - input: `public interface IGreetable -{ - void <|fim|> -}`, - llmOutput: "Greet();", - expectedCompletion: "Greet();", - }, - { - description: "Should autocomplete inside C# method with if condition", - filename: "Calculator.cs", - input: `using System; - -public class Calculator -{ - public int Add(int a, int b) - { - if(<|fim|>) - { - return a + b; - } - return 0; - } -}`, - llmOutput: "a > 0 && b > 0", - expectedCompletion: "a > 0 && b > 0", - }, - { - description: "Should complete a simple Julia function", - filename: "simpleFunction.jl", - input: `function calculate_area(length, width) - <|fim|> -end -`, - llmOutput: "return length * width", - expectedCompletion: "return length * width", - }, - { - description: "Should autocomplete Julia for loop", - filename: "loop.jl", - input: `numbers = [1, 2, 3, 4, 5] -squared_numbers = [] - -for num in numbers - <|fim|> -end - -println(squared_numbers) -`, - llmOutput: "push!(squared_numbers, num^2)", - expectedCompletion: "push!(squared_numbers, num^2)", - }, - { - description: "Should complete a Julia struct definition", - filename: "structDefinition.jl", - input: `struct Person - first_name::String - last_name::String - age::Int - address::Address -end - -struct Address - street::String - city::String - <|fim|> -end -`, - llmOutput: `state::String - zip_code::String`, - expectedCompletion: `state::String - zip_code::String`, - }, - { - description: "Should complete a Julia dictionary access", - filename: "dictionary.jl", - input: `grades = Dict("Alice" => 90, "Bob" => 85, "Eve" => 88) - -function get_grade(student_name) - return grades[<|fim|>] -end - -println(get_grade("Alice")) # Should print 90 -`, - llmOutput: "student_name", - expectedCompletion: "student_name", - }, - { - description: "Should complete a Julia module declaration", - filename: "moduleDeclaration.jl", - input: `module MathOperations - -export add, subtract - -function add(a, b) - return a + b -end - -function subtract(a, b) - return a - b -end - -<|fim|> -`, - llmOutput: "end", - expectedCompletion: "end", - }, - { - description: "Should complete F# let-binding with function definition", - filename: "mathModule.fs", - input: `module MathModule - -let calculateArea length width = - <|fim|>`, - llmOutput: "length * width", - expectedCompletion: "length * width", - }, - - { - description: "Should complete incomplete F# type definition", - filename: "personType.fs", - input: `type Person = { - FirstName: string - LastName: string - Age: int<|fim|> -} - -let john = { FirstName = "John"; LastName = "Doe"; Age = 30 }`, - llmOutput: ` - Address: string -}`, - expectedCompletion: ` - Address: string`, - }, - - { - description: "Should complete F# pattern matching expression", - filename: "patternMatching.fs", - input: `let describeNumber number = - match number with - | 0 -> "Zero" - | 1 -> "One" - | <|fim|>`, - llmOutput: `2 -> "Two" - | _ -> "Other"`, - expectedCompletion: `2 -> "Two" - | _ -> "Other"`, - }, - - { - description: "Should complete F# list comprehension expression", - filename: "listComprehension.fs", - input: `let squares = [ for x in 1..10 -> x * x ] -let evenSquares = [ for x in squares do if x % 2 = 0 then yield x ] -let oddSquares = [<|fim|>]`, - llmOutput: " for x in squares do if x % 2 <> 0 then yield x ]", - expectedCompletion: " for x in squares do if x % 2 <> 0 then yield x ]", - }, - { - description: "Should complete an F# recursive function", - filename: "recursiveFunctions.fs", - input: `let rec factorial n = - if n <= 1 then 1 - else n <|fim|> factorial (n - 1)`, - llmOutput: "*", - expectedCompletion: "*", - }, - { - description: "Should complete F# member method inside a class type", - filename: "bankAccount.fs", - input: `type BankAccount(owner: string, initialBalance: float) = - let mutable balance = initialBalance - - member this.Deposit amount = - balance <- balance + amount - this - <|fim|>`, - llmOutput: ` - member this.Withdraw amount = - if amount > balance then - failwith "Insufficient funds" - balance <- balance - amount - this`, - expectedCompletion: ` - member this.Withdraw amount = - if amount > balance then - failwith "Insufficient funds" - balance <- balance - amount - this`, - }, - - { - description: "Should complete F# async workflow function", - filename: "asyncWorkflow.fs", - input: `let fetchDataAsync url = - async { - use client = new System.Net.Http.HttpClient() - <|fim|> - }`, - llmOutput: `let! response = client.GetStringAsync(url) - return response`, - expectedCompletion: `let! response = client.GetStringAsync(url) - return response`, - }, - { - description: "Should autocomplete SCSS nested class starting inside a rule", - filename: "styles.scss", - input: `nav { - display: flex; - justify-content: space-between; - .logo { - font-size: 1.5rem; - color: #333; - - .brand<|fim|> - } - - ul { - list-style: none; - display: flex; - gap: 1rem; - } -}`, - llmOutput: `-name { - font-weight: bold; - text-transform: uppercase; -}`, - expectedCompletion: `-name { - font-weight: bold; - text-transform: uppercase; -}`, - }, - - { - description: "Should handle SCSS mixin within a class", - filename: "styles.scss", - input: `.card { - border: 1px solid #ccc; - padding: 10px; - - @include<|fim|> - - &:hover { - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); - } -}`, - llmOutput: " transition(all 0.3s ease);", - expectedCompletion: " transition(all 0.3s ease);", - }, - - { - description: "Should autocomplete SCSS variable in the middle of a statement", - filename: "styles.scss", - input: `$primary-color: #007bff; -$secondary-color: #6c757d; - -.button { - background-color: <|fim|> color; - padding: 10px 15px; - border: none; - color: #fff; - border-radius: 4px; -}`, - llmOutput: "$primary-", - expectedCompletion: "$primary-", - }, - { - description: "Should autocomplete Vue component method", - filename: "MyComponent.vue", - input: ` - - -`, - llmOutput: `() { - this.count = 0; - }`, - expectedCompletion: `() { - this.count = 0; - }`, - }, - { - description: "Should autocomplete Vue computed property", - filename: "UserComponent.vue", - input: ` - - -`, - llmOutput: `() { - return this.firstName + ' ' + this.lastName; - }`, - expectedCompletion: `() { - return this.firstName + ' ' + this.lastName; - }`, - }, - { - description: "Should autocomplete Vue method using props", - filename: "TodoItem.vue", - input: ` - - -`, - llmOutput: "this.completed", - expectedCompletion: "this.completed", - }, - { - description: "Should autocomplete Svelte reactive statement", - filename: "Counter.svelte", - input: ` - - - -`, - llmOutput: "doubledCount = count * 2", - expectedCompletion: "doubledCount = count * 2", - }, - - { - description: "Should autocomplete Svelte component inside HTML", - filename: "NestedComponent.svelte", - input: ` - - -
-

Hello Svelte

- /> -
-`, - llmOutput: 'name="World"', - expectedCompletion: 'name="World"', - }, - - { - description: "Should handle autocomplete in Svelte each block", - filename: "List.svelte", - input: ` - - -
    - {#each items as item} -
  • {item}
  • - {/each<|fim|> -
-`, - llmOutput: "}", - expectedCompletion: "}", - }, - { - description: "Should handle autocomplete in two similar TypeScript functions", - filename: "List.svelte", - input: ` -import { createClient, RedisClientType } from "redis"; -import { IKeyValueStore } from "./index.js"; - -export class RedisKeyValueStore implements IKeyValueStore { - private client: RedisClientType; - - constructor(redisUrl: string) { - this.client = createClient({ - url: redisUrl - .replace("https://", "redis://") - .replace("http://", "redis://"), - }); - this.client.on("connect", () => console.log("Redis Connected")); - this.client.on("error", (err) => console.log("Redis Client Error", err)); - this.client.connect(); - } - public async has(tableName: string, key: string): Promise { - return (await this.client.exists(this._getKey(tableName, key))) > 0; - } - - public async keys(tableName: string): Promise { - const keys = await this.client.keys(this._getTableKey(tableName)); - return keys.map((key) => key.split("::")[1]); - } - - public async put( - tableName: string, - key: string, - value: string, - ): Promise { - await this.client.set(this._getKey(tableName, key), value); - } - - public async get( - tableName: string, - key: string, - ): Promise { - const value = await this.client.get(this._getKey(tableName, key)); - return value ?? undefined; - } - - public async deleteAll(tableName: string): Promise { - await this.client.del(this._getTableKey(tableName)); - } - -<|fim|> - - - public async remove(tableName: string, key: string): Promise { - const result = await this.client.del(this._getKey(tableName, key)); - return result > 0; - } -} -`, - llmOutput: ` public async delete(tableName: string, key: string): Promise { - await this.client.del(this._getKey(tableName, key)); - }`, - expectedCompletion: ` public async delete(tableName: string, key: string): Promise { - await this.client.del(this._getKey(tableName, key)); - }`, - }, -] diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/util.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/util.ts deleted file mode 100644 index e07a53cd125..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/filtering/test/util.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { expect } from "vitest" -import { MockLLM } from "../../../llm/llms/Mock" -import { testMinimalConfigProvider, testIde } from "../../../test/fixtures" -import { joinPathsToUri } from "../../../util/uri" -import { CompletionProvider } from "../../CompletionProvider" -import { AutocompleteInput } from "../../util/types" - -const FIM_DELIMITER = "<|fim|>" - -function parseFimExample(text: string): { prefix: string; suffix: string } { - const [prefix, suffix] = text.split(FIM_DELIMITER) - return { prefix, suffix } -} - -export interface AutocompleteFileringTestInput { - description: string - filename: string - input: string - llmOutput: string - expectedCompletion: string | null | undefined - options?: { - only?: boolean - } -} - -export async function testAutocompleteFiltering(test: AutocompleteFileringTestInput) { - // Normalize line endings to LF for cross-platform compatibility (Windows Git may check out CRLF) - const normalizedInput = test.input.replace(/\r\n/g, "\n") - const normalizedLlmOutput = test.llmOutput.replace(/\r\n/g, "\n") - - const { prefix } = parseFimExample(normalizedInput) - - // Setup necessary objects - const llm = new MockLLM({ - model: "mock", - }) - llm.completion = normalizedLlmOutput - const ide = testIde - const configHandler = testMinimalConfigProvider - - // Create a real file - const [workspaceDir] = await ide.getWorkspaceDirs() - const fileUri = joinPathsToUri(workspaceDir, test.filename) - await ide.writeFile(fileUri, normalizedInput.replace(FIM_DELIMITER, "")) - - // Prepare completion input and provider - const completionProvider = new CompletionProvider( - configHandler, - ide, - async () => llm, - () => {}, - async () => [], - ) - - const line = prefix.split("\n").length - 1 - const character = prefix.split("\n")[line].length - const autocompleteInput: AutocompleteInput = { - isUntitledFile: false, - completionId: "test-completion-id", - filepath: fileUri, - pos: { - line, - character, - }, - recentlyEditedRanges: [], - recentlyVisitedRanges: [], - } - - // Generate a completion - const result = await completionProvider.provideInlineCompletionItems( - autocompleteInput, - undefined, - true, // force=true to skip debounce in tests - ) - - // Ensure that we return the text that is wanted to be displayed - // Normalize line endings for cross-platform compatibility - const normalizeLineEndings = (str: string | null | undefined) => str?.replace(/\r\n/g, "\n") - - expect(normalizeLineEndings(result?.completion)).toEqual(normalizeLineEndings(test.expectedCompletion)) -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/CompletionStreamer.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/CompletionStreamer.ts deleted file mode 100644 index 6ceedf7f291..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/CompletionStreamer.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { CompletionOptions, ILLM } from "../.." -import { StreamTransformPipeline } from "../filtering/streamTransforms/StreamTransformPipeline" -import { HelperVars } from "../util/HelperVars" - -import { GeneratorReuseManager } from "./GeneratorReuseManager" -import { stopAfterMaxProcessingTime } from "./utils" - -export class CompletionStreamer { - private streamTransformPipeline = new StreamTransformPipeline() - private generatorReuseManager: GeneratorReuseManager - - constructor(onError: (err: unknown) => void) { - this.generatorReuseManager = new GeneratorReuseManager(onError) - } - - async *streamCompletionWithFilters( - token: AbortSignal, - llm: ILLM, - prefix: string, - suffix: string, - prompt: string, - multiline: boolean, - completionOptions: Partial | undefined, - helper: HelperVars, - ) { - // Full stop means to stop the LLM's generation, instead of just truncating the displayed completion - const fullStop = () => this.generatorReuseManager.currentGenerator?.cancel() - - // Try to reuse pending requests if what the user typed matches start of completion - const generator = this.generatorReuseManager.getGenerator( - prefix, - (abortSignal: AbortSignal) => { - const generator = llm.supportsFim() - ? llm.streamFim(prefix, suffix, abortSignal, completionOptions) - : llm.streamComplete(prompt, abortSignal, { - ...completionOptions, - raw: true, - }) - - /** - * This transformer applies even on reused generator. We are deliberately - * not using streamTransformPipeline because we want to capture and stop - * the request even if the generator is being reused. - */ - return helper.options.transform - ? stopAfterMaxProcessingTime(generator, helper.options.modelTimeout * 2.5, fullStop) - : generator - }, - multiline, - ) - - // LLM - const generatorWithCancellation = async function* () { - for await (const update of generator) { - if (token.aborted) { - return - } - yield update - } - } - - const initialGenerator = generatorWithCancellation() - const transformedGenerator = helper.options.transform - ? this.streamTransformPipeline.transform( - initialGenerator, - prefix, - suffix, - multiline, - completionOptions?.stop || [], - fullStop, - helper, - ) - : initialGenerator - - for await (const update of transformedGenerator) { - yield update - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.test.ts deleted file mode 100644 index a30399957dd..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.test.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { afterEach, beforeEach, describe, expect, Mock, test, vi } from "vitest" -import { GeneratorReuseManager } from "./GeneratorReuseManager" - -function createMockGenerator(data: string[], delay: number = 0): (abortSignal: AbortSignal) => AsyncGenerator { - const mockGenerator = async function* () { - for (const chunk of data) { - yield chunk - - if (delay > 0) { - await new Promise((resolve) => setTimeout(resolve, delay)) - } - } - } - const newGenerator = vi.fn<() => AsyncGenerator>().mockReturnValue(mockGenerator()) - - return newGenerator -} - -describe("GeneratorReuseManager", () => { - let reuseManager: GeneratorReuseManager - let onErrorMock: Mock - - beforeEach(() => { - onErrorMock = vi.fn() - reuseManager = new GeneratorReuseManager(onErrorMock) - }) - - afterEach(() => { - vi.clearAllMocks() - }) - - test("creates new generator when there is no current generator", async () => { - const data = ["hello ", "world"] - const newGenerator = createMockGenerator(data) - - const prefix = "" - - const generator = reuseManager.getGenerator(prefix, newGenerator, true) - - const output: string[] = [] - for await (const chunk of generator) { - output.push(chunk) - } - - expect(output).toEqual(data) - expect(newGenerator).toHaveBeenCalledTimes(1) - }) - - test("reuses generator when prefix matches pending completion", async () => { - const newGenerator = createMockGenerator(["llo ", "world"]) - - // First call with initial prefix - const prefix1 = "he" - const generator1 = reuseManager.getGenerator(prefix1, newGenerator, true) - - const output1: string[] = [] - for await (const chunk of generator1) { - output1.push(chunk) - } - - expect(output1).toEqual(["llo ", "world"]) - - // Second call with extended prefix that matches pending completion - const prefix2 = "hello " - const generator2 = reuseManager.getGenerator(prefix2, newGenerator, true) - - const output2: string[] = [] - for await (const chunk of generator2) { - output2.push(chunk) - } - - expect(output2).toEqual(["world"]) - - // Ensure generator was reused (newGenerator should be called only once) - expect(newGenerator).toHaveBeenCalledTimes(1) - }) - - test("creates new generator when prefix does not match pending completion", async () => { - const data = ["goodbye ", "world"] - const newGenerator = createMockGenerator(data) - - // Initial generator with different prefix - reuseManager.pendingGeneratorPrefix = "hello " - reuseManager.pendingCompletion = "world" - - const prefix = "good" - const generator = reuseManager.getGenerator(prefix, newGenerator, true) - - const output: string[] = [] - for await (const chunk of generator) { - output.push(chunk) - } - - expect(output).toEqual(data) - // Ensure a new generator was created - expect(newGenerator).toHaveBeenCalledTimes(1) - }) - - test("handles multiline=false by stopping at newline", async () => { - const data = ["first line\n", "second line"] - const newGenerator = createMockGenerator(data) - - const prefix = "" - const generator = reuseManager.getGenerator(prefix, newGenerator, false) - - const output: string[] = [] - for await (const chunk of generator) { - output.push(chunk) - } - - expect(output).toEqual(["first line"]) - // Ensure it stops after the first newline - }) - - test("handles multiline=true by not stopping at newline", async () => { - const data = ["first line\n", "second line"] - const newGenerator = createMockGenerator(data) - - const prefix = "" - const generator = reuseManager.getGenerator(prefix, newGenerator, true) - - const output: string[] = [] - for await (const chunk of generator) { - output.push(chunk) - } - - expect(output).toEqual(data) - }) - - test("cancels previous generator when creating a new one", async () => { - const data1 = ["data from generator 1", "not generated"] - const data2 = ["data from generator 2"] - - const newGenerator1 = createMockGenerator(data1, 1000) // Delay so we have the chance to cancel it - const newGenerator2 = createMockGenerator(data2) - - const prefix1 = "prefix1" - const prefix2 = "prefix2" - - // First generator - const generator1 = reuseManager.getGenerator(prefix1, newGenerator1, true) - const output1: string[] = [] - for await (const chunk of generator1) { - output1.push(chunk) - // Simulate the generator being canceled before completing - reuseManager.currentGenerator?.cancel() - } - - expect(output1.length).toEqual(1) - expect(output1[0]).toEqual(data1[0]) - - // Second generator - const generator2 = reuseManager.getGenerator(prefix2, newGenerator2, true) - const output2: string[] = [] - for await (const chunk of generator2) { - output2.push(chunk) - } - - expect(output2).toEqual(data2) - }) - - test("calls onError when generator throws an error", async () => { - const error = new Error("Generator error") - const mockGenerator = async function* () { - throw error - } - const newGenerator = vi.fn<() => AsyncGenerator>().mockReturnValue(mockGenerator()) - - const prefix = "" - const generator = reuseManager.getGenerator(prefix, newGenerator, true) - - const output: string[] = [] - await expect(async () => { - for await (const chunk of generator) { - output.push(chunk) - } - }).not.toThrow() // getGenerator handles errors internally - - expect(onErrorMock).toHaveBeenCalledWith(error) - expect(output).toEqual([]) - }) - - test("handles backspacing by creating new generator when prefix is shorter", async () => { - const data = ["hello world"] - const newGenerator1 = createMockGenerator(data) - const newGenerator2 = createMockGenerator(data) - - // First prefix - const prefix1 = "hello world" - const generator1 = reuseManager.getGenerator(prefix1, newGenerator1, true) - const output1: string[] = [] - for await (const chunk of generator1) { - output1.push(chunk) - } - - // Simulate backspace (prefix is shorter) - const prefix2 = "hello worl" - const generator2 = reuseManager.getGenerator(prefix2, newGenerator2, true) - const output2: string[] = [] - for await (const chunk of generator2) { - output2.push(chunk) - } - - // Ensure a new generator was created - expect(newGenerator1).toHaveBeenCalledTimes(1) - expect(newGenerator2).toHaveBeenCalledTimes(1) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.ts deleted file mode 100644 index 37d29f6e0c3..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/GeneratorReuseManager.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { ListenableGenerator } from "./ListenableGenerator" - -export class GeneratorReuseManager { - currentGenerator: ListenableGenerator | undefined - pendingGeneratorPrefix: string | undefined - pendingCompletion = "" - - constructor(private readonly onError: (err: unknown) => void) {} - - private _createListenableGenerator(abortController: AbortController, gen: AsyncGenerator, prefix: string) { - this.currentGenerator?.cancel() - - const listenableGen = new ListenableGenerator(gen, this.onError, abortController) - listenableGen.listen((chunk) => (this.pendingCompletion += chunk ?? "")) - - this.pendingGeneratorPrefix = prefix - this.pendingCompletion = "" - this.currentGenerator = listenableGen - } - - private shouldReuseExistingGenerator(prefix: string): boolean { - return ( - !!this.currentGenerator && - !!this.pendingGeneratorPrefix && - (this.pendingGeneratorPrefix + this.pendingCompletion).startsWith(prefix) && - // for e.g. backspace - this.pendingGeneratorPrefix?.length <= prefix?.length - ) - } - - async *getGenerator( - prefix: string, - newGenerator: (abortSignal: AbortSignal) => AsyncGenerator, - multiline: boolean, - ): AsyncGenerator { - // If we can't reuse, then create a new generator - if (!this.shouldReuseExistingGenerator(prefix)) { - // Create a wrapper over the current generator to fix the prompt - const abortController = new AbortController() - this._createListenableGenerator(abortController, newGenerator(abortController.signal), prefix) - } - - // Already typed characters are those that are new in the prefix from the old generator - let typedSinceLastGenerator = prefix.slice(this.pendingGeneratorPrefix?.length) || "" - for await (let chunk of this.currentGenerator?.tee() ?? []) { - if (!chunk) { - continue - } - - // Ignore already typed characters in the completion - while (chunk.length && typedSinceLastGenerator.length) { - if (chunk[0] === typedSinceLastGenerator[0]) { - typedSinceLastGenerator = typedSinceLastGenerator.slice(1) - chunk = chunk.slice(1) - } else { - break - } - } - - // Break at newline unless we are in multiline mode - const newLineIndex = chunk.indexOf("\n") - if (newLineIndex >= 0 && !multiline) { - yield chunk.slice(0, newLineIndex) - break - } else if (chunk !== "") { - yield chunk - } - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.test.ts deleted file mode 100644 index 35cdc207a1e..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.test.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { describe, expect, it, vi } from "vitest" - -import { ListenableGenerator } from "./ListenableGenerator" - -describe("ListenableGenerator", () => { - // Helper function to create an async generator - async function* asyncGenerator(values: T[]) { - for (const value of values) { - // Yield on next event loop iteration to ensure async behavior - await new Promise(setImmediate) - yield value - } - } - - it("should yield values from the source generator via tee()", async () => { - const values = [1, 2, 3] - const source = asyncGenerator(values) - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const result: number[] = [] - for await (const value of lg.tee()) { - result.push(value) - } - - expect(result).toEqual(values) - expect(onError).not.toHaveBeenCalled() - }) - - it("should allow listeners to receive values", async () => { - const values = [1, 2, 3] - const source = asyncGenerator(values) - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const listener = vi.fn() - - // Add listener after yielding starts (next event loop iteration) - await new Promise(setImmediate) - lg.listen(listener) - - // Wait for generator to actually finish - await lg.waitForCompletion() - - expect(listener).toHaveBeenCalledWith(1) - expect(listener).toHaveBeenCalledWith(2) - expect(listener).toHaveBeenCalledWith(3) - // Listener should receive null at the end - expect(listener).toHaveBeenCalledWith(null) - }) - - it("should buffer values for listeners added after some values have been yielded", async () => { - const values = [1, 2, 3] - const source = asyncGenerator(values) - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const initialListener = vi.fn() - - lg.listen(initialListener) - - // Wait for the first value to be yielded (next event loop iteration) - await new Promise(setImmediate) - - // Add a second listener after first value has been yielded - const newListener = vi.fn() - lg.listen(newListener) - - // Wait for generator to actually finish - await lg.waitForCompletion() - - // Both listeners should have received all values - ;[initialListener, newListener].forEach((listener) => { - expect(listener).toHaveBeenCalledWith(1) - expect(listener).toHaveBeenCalledWith(2) - expect(listener).toHaveBeenCalledWith(3) - expect(listener).toHaveBeenCalledWith(null) - }) - }) - - it("should handle cancellation", async () => { - const values = [1, 2, 3, 4, 5] - const source = asyncGenerator(values) - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const result: number[] = [] - const teeIterator = lg.tee() - - const consume = async () => { - for await (const value of teeIterator) { - result.push(value) - if (value === 3) { - lg.cancel() - } - } - } - - await consume() - - expect(result).toEqual([1, 2, 3]) - expect(lg["_isEnded"]).toBe(true) - }) - - it("should call onError when the source generator throws an error", async () => { - async function* errorGenerator() { - yield 1 - throw new Error("Test error") - } - - const source = errorGenerator() - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const result: number[] = [] - for await (const value of lg.tee()) { - result.push(value) - } - - expect(result).toEqual([1]) - expect(onError).toHaveBeenCalledTimes(1) - expect(onError).toHaveBeenCalledWith(new Error("Test error")) - }) - - it("should notify listeners when the generator ends", async () => { - const values = [1, 2, 3] - const source = asyncGenerator(values) - const onError = vi.fn() - - const lg = new ListenableGenerator(source, onError, new AbortController()) - - const listener = vi.fn() - lg.listen(listener) - - // Wait for the generator to actually finish - await lg.waitForCompletion() - - expect(listener).toHaveBeenCalledWith(1) - expect(listener).toHaveBeenCalledWith(2) - expect(listener).toHaveBeenCalledWith(3) - expect(listener).toHaveBeenCalledWith(null) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.ts deleted file mode 100644 index 4005b13023a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/ListenableGenerator.ts +++ /dev/null @@ -1,84 +0,0 @@ -export class ListenableGenerator { - private _source: AsyncGenerator - private _buffer: T[] = [] - private _listeners: Set<(value: T) => void> = new Set() - private _isEnded = false - private _abortController: AbortController - private _completionPromise: Promise - - constructor( - source: AsyncGenerator, - private readonly onError: (e: unknown) => void, - abortController: AbortController, - ) { - this._source = source - this._abortController = abortController - this._completionPromise = this._start().catch((e) => console.log(`Listenable generator failed: ${e.message}`)) - } - - public cancel() { - this._abortController.abort() - this._isEnded = true - } - - public waitForCompletion(): Promise { - return this._completionPromise - } - - private async _start() { - try { - for await (const value of this._source) { - if (this._isEnded) { - break - } - this._buffer.push(value) - for (const listener of this._listeners) { - listener(value) - } - } - } catch (e) { - this.onError(e) - } finally { - this._isEnded = true - for (const listener of this._listeners) { - listener(null as any) - } - } - } - - listen(listener: (value: T) => void) { - this._listeners.add(listener) - for (const value of this._buffer) { - listener(value) - } - if (this._isEnded) { - listener(null as any) - } - } - - async *tee(): AsyncGenerator { - try { - let i = 0 - while (i < this._buffer.length) { - yield this._buffer[i++] - } - while (!this._isEnded) { - let resolve: (value: T) => void - const promise = new Promise((res) => { - resolve = res - this._listeners.add(resolve!) - }) - await promise - this._listeners.delete(resolve!) - - // Possible timing caused something to slip in between - // timers so we iterate over the buffer - while (i < this._buffer.length) { - yield this._buffer[i++] - } - } - } finally { - // this._listeners.delete(resolve!); - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.test.ts deleted file mode 100644 index 87dba5f97db..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.test.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" -import { stopAfterMaxProcessingTime } from "./utils" - -describe("stopAfterMaxProcessingTime", () => { - beforeEach(() => { - vi.useFakeTimers() - }) - - afterEach(() => { - vi.useRealTimers() - }) - - async function* createMockStream(chunks: string[]): AsyncGenerator { - for (const chunk of chunks) { - yield chunk - } - } - - async function streamToString(stream: AsyncGenerator): Promise { - let result = "" - for await (const chunk of stream) { - result += chunk - } - return result - } - - it("should yield all chunks when maxTimeMs is not reached", async () => { - const mockStream = createMockStream(["Hello", " world", "!"]) - const fullStop = vi.fn() - const result = stopAfterMaxProcessingTime(mockStream, 1000, fullStop) - - const output = await streamToString(result) - - expect(output).toBe("Hello world!") - expect(fullStop).not.toHaveBeenCalled() - }) - - it("should stop processing after max time is reached", async () => { - // Mock implementation of Date.now - let currentTime = 0 - const originalDateNow = Date.now - Date.now = vi.fn(() => currentTime) - - // Create a generator that we can control - async function* controlledGenerator(): AsyncGenerator { - for (let i = 0; i < 100; i++) { - // After yielding 10 chunks, simulate time passing beyond our limit - if (i === 10) { - currentTime = 1000 // This exceeds our 500ms limit - } - yield `chunk-${i}` - } - } - - const fullStop = vi.fn() - const maxTimeMs = 500 - - const transformedGenerator = stopAfterMaxProcessingTime(controlledGenerator(), maxTimeMs, fullStop) - - // Consume the generator and collect outputs - const outputs: string[] = [] - for await (const chunk of transformedGenerator) { - outputs.push(chunk) - } - - // We expect: - // 1. Not all chunks were processed (less than 100) - // 2. fullStop was called - // 3. We processed at least the chunks before time was exceeded - expect(outputs.length).toBeLessThan(100) - expect(outputs.length).toBeGreaterThanOrEqual(10) // We should get at least the first 10 chunks - expect(fullStop).toHaveBeenCalled() - - // Restore Date.now - Date.now = originalDateNow - }) - - it("should check time only periodically based on checkInterval", async () => { - const chunks = Array(100).fill("x") - const mockStream = createMockStream(chunks) - const fullStop = vi.fn() - - // Spy on Date.now to count how many times it's called - const dateSpy = vi.spyOn(Date, "now") - - // Stream should complete normally (not hitting the timeout) - await streamToString(stopAfterMaxProcessingTime(mockStream, 10000, fullStop)) - - // The first call is to set startTime, then once every checkInterval (10) chunks - // So for 100 chunks, we expect startTime + ~10 checks = ~11 calls - // We use a range because implementation details might vary slightly - expect(dateSpy.mock.calls.length).toBeGreaterThanOrEqual(1) - expect(dateSpy.mock.calls.length).toBeLessThanOrEqual(15) - - dateSpy.mockRestore() - }) - - it("should handle empty stream gracefully", async () => { - const mockStream = createMockStream([]) - const fullStop = vi.fn() - const result = stopAfterMaxProcessingTime(mockStream, 1000, fullStop) - - const output = await streamToString(result) - - expect(output).toBe("") - expect(fullStop).not.toHaveBeenCalled() - }) - - it("should pass through all chunks if there's no timeout", async () => { - const chunks = Array(100).fill("test chunk") - const mockStream = createMockStream(chunks) - const fullStop = vi.fn() - - // Use undefined as timeout to simulate no timeout - const result = stopAfterMaxProcessingTime(mockStream, undefined as any, fullStop) - - // Process the stream - const processedChunks = [] - for await (const chunk of result) { - processedChunks.push(chunk) - } - - expect(processedChunks.length).toBe(chunks.length) - expect(fullStop).not.toHaveBeenCalled() - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.ts deleted file mode 100644 index 131a791b732..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/generation/utils.ts +++ /dev/null @@ -1,25 +0,0 @@ -export async function* stopAfterMaxProcessingTime( - stream: AsyncGenerator, - maxTimeMs: number, - fullStop: () => void, -): AsyncGenerator { - const startTime = Date.now() - /** - * Check every 10 chunks to avoid performance overhead. - */ - const checkInterval = 10 - let chunkCount = 0 - - for await (const chunk of stream) { - yield chunk - - chunkCount++ - - if (chunkCount % checkInterval === 0) { - if (Date.now() - startTime > maxTimeMs) { - fullStop() - return - } - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/prefiltering/index.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/prefiltering/index.ts deleted file mode 100644 index 02866d092b9..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/prefiltering/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import ignore from "ignore" -import { getConfigJsonPath } from "../../util/paths" -import { findUriInDirs } from "../../util/uri" -import { HelperVars } from "../util/HelperVars" - -async function isDisabledForFile( - currentFilepath: string, - disableInFiles: string[] | undefined, - workspaceDirs: string[], -) { - if (disableInFiles) { - // Relative path needed for `ignore` - const { relativePathOrBasename } = findUriInDirs(currentFilepath, workspaceDirs) - - const pattern = ignore().add(disableInFiles) - if (pattern.ignores(relativePathOrBasename)) { - return true - } - } - return false -} - -export async function shouldPrefilter(helper: HelperVars, workspaceDirs: string[]): Promise { - // Allow disabling autocomplete from config.json - if (helper.options.disable) { - return true - } - - // Check whether we're in the continue config.json file - if (helper.filepath === getConfigJsonPath()) { - return true - } - - // Check whether autocomplete is disabled for this file - const disableInFiles = [ - ...(helper.options.disableInFiles ?? []), - "*.prompt", - // "some-example-ignored-file", //MINIMAL_REPO - was configurable - ] - if (await isDisabledForFile(helper.filepath, disableInFiles, workspaceDirs)) { - return true - } - - // Don't offer completions when we have no information (untitled file and no file contents) - if (helper.filepath.includes("Untitled") && helper.fileContents.trim() === "") { - return true - } - - // if ( - // helper.options.transform && - // (await shouldLanguageSpecificPrefilter(helper)) - // ) { - // return true; - // } - - return false -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/__tests__/renderPrompt.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/__tests__/renderPrompt.test.ts deleted file mode 100644 index 8ef9281d8d1..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/__tests__/renderPrompt.test.ts +++ /dev/null @@ -1,262 +0,0 @@ -import { afterEach, describe, expect, it, vi } from "vitest" - -// ---------- Module mocks ---------- - -// Simple Handlebars mock that does naive placeholder substitution -vi.mock("handlebars", () => { - return { - default: { - compile: (template: string) => (ctx: Record) => { - return template - .replace(/{{prefix}}/g, ctx.prefix) - .replace(/{{suffix}}/g, ctx.suffix) - .replace(/{{filename}}/g, ctx.filename ?? "") - .replace(/{{reponame}}/g, ctx.reponame ?? "") - .replace(/{{language}}/g, ctx.language ?? "") - }, - }, - } -}) - -// Token utilities – we map 1 char = 1 token for simplicity -vi.mock("../../../llm/countTokens", () => { - const countTokens = (str: string) => str.length - const pruneLinesFromTop = (str: string, allowed: number) => str.slice(Math.max(0, str.length - allowed)) - const pruneLinesFromBottom = (str: string, allowed: number) => str.slice(0, allowed) - const getTokenCountingBufferSafety = () => 0 - - return { - countTokens, - pruneLinesFromTop, - pruneLinesFromBottom, - getTokenCountingBufferSafety, - } -}) - -// Snippet selection – configurable via constant return value -vi.mock("../filtering", () => ({ - getSnippets: () => [], -})) - -// Snippet formatting -const FORMATTED_SNIPPETS = "[FORMATTED_SNIPPETS]" -vi.mock("../formatting", () => ({ - formatSnippets: () => FORMATTED_SNIPPETS, -})) - -// Stop tokens helper – we expose a variable so each test can override it -let stopTokenReturn: string[] = [""] -vi.mock("../getStopTokens", () => ({ - getStopTokens: () => stopTokenReturn, -})) - -// AutocompleteTemplate – provide overridable template + compiler + completionOptions -let templateOverride: any = (prefix: string, suffix: string) => `${prefix}|${suffix}` -let compileFnOverride: ((...args: any[]) => [string, string]) | undefined -let completionOptionsOverride: Record | undefined -vi.mock("../AutocompleteTemplate", () => ({ - getTemplateForModel: () => ({ - template: templateOverride, - compilePrefixSuffix: compileFnOverride, - completionOptions: completionOptionsOverride ?? {}, - }), -})) - -// ---------- Imports after mocks ---------- -import { renderPrompt, renderPromptWithTokenLimit } from ".." -import { AutocompleteLanguageInfo } from "../../constants/AutocompleteLanguageInfo" -import { SnippetPayload } from "../../snippets" -import { HelperVars } from "../../util/HelperVars" - -// ---------- Helper builders ---------- - -const tsLang: AutocompleteLanguageInfo = { - name: "TypeScript", - topLevelKeywords: [], - singleLineComment: "//", - endOfLine: [";"], -} - -const emptySnippetPayload: SnippetPayload = { - rootPathSnippets: [], - importDefinitionSnippets: [], - ideSnippets: [], - recentlyEditedRangeSnippets: [], - recentlyVisitedRangesSnippets: [], - diffSnippets: [], - clipboardSnippets: [], - recentlyOpenedFileSnippets: [], - staticSnippet: [], -} - -function makeHelper() { - return { - input: { - filepath: "file:///test.ts", - pos: { line: 0, character: 0 }, - recentlyEditedRanges: [], - recentlyVisitedRanges: [], - }, - prunedPrefix: "PRUNED_PREFIX", - prunedSuffix: "PRUNED_SUFFIX", - lang: tsLang, - modelName: "test-model", - filepath: "file:///test.ts", - workspaceUris: [], - options: { - maxPromptTokens: 2048, - prefixPercentage: 0.5, - maxSuffixPercentage: 0.5, - experimental_includeClipboard: false, - useRecentlyOpened: false, - experimental_includeRecentlyVisitedRanges: false, - experimental_includeRecentlyEditedRanges: false, - experimental_includeDiff: false, - onlyMyCode: false, - }, - } as unknown as HelperVars -} - -afterEach(() => { - // reset overridable mocks - templateOverride = (prefix: string, suffix: string) => `${prefix}|${suffix}` - compileFnOverride = undefined - completionOptionsOverride = undefined - stopTokenReturn = [""] - vi.restoreAllMocks() -}) - -// ---------- Test suite ---------- - -describe("renderPrompt prefix/suffix selection", () => { - it("uses manuallyPassPrefix when provided", () => { - const helper = makeHelper() - helper.input.manuallyPassPrefix = "MANUAL" - const { prefix, suffix } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(suffix).toBe("\n") - expect(prefix.endsWith("MANUAL")).toBe(true) - }) - - it("falls back to prunedPrefix when no manual prefix", () => { - const helper = makeHelper() - - const { prefix } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(prefix.includes("PRUNED_PREFIX")).toBe(true) - }) -}) - -describe("template rendering paths", () => { - it("handles function template", () => { - templateOverride = (p: string, s: string, _filepath: string, _reponame: string) => `FUNC:${p}|${s}` - - const helper = makeHelper() - - const { prompt } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(prompt.startsWith("FUNC:")).toBe(true) - expect(prompt.includes("PRUNED_PREFIX")).toBe(true) - }) -}) - -describe("compilePrefixSuffix vs snippet formatting", () => { - it("applies compilePrefixSuffix when provided", () => { - compileFnOverride = (p: string, s: string) => [`COMP_${p}`, `COMP_${s}`] - templateOverride = (prefix: string, suffix: string) => `${prefix}|${suffix}` - const helper = makeHelper() - - const { prefix: compiledPrefix } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(compiledPrefix.startsWith("COMP_PRUNED_PREFIX")).toBe(true) - }) - - it("prepends formatted snippets when no compiler present", () => { - const helper = makeHelper() - - const { prefix: compiledPrefix } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(compiledPrefix.startsWith(`${FORMATTED_SNIPPETS}\n`)).toBe(true) - }) -}) - -describe("renderPromptWithTokenLimit parity & pruning", () => { - it("matches renderPrompt when llm is undefined", () => { - const helper = makeHelper() - - const res1 = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - const res2 = renderPromptWithTokenLimit({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - llm: undefined, - }) - - expect(res2).toEqual(res1) - }) - - it("prunes prefix/suffix to respect small context length", () => { - const longPrefix = "A".repeat(300) - - const helper = makeHelper() - ;(helper as any).prunedPrefix = longPrefix - - const llmStub = { - contextLength: 120, - completionOptions: { maxTokens: 10 }, - model: "test-model", - } as any - - const { prefix: compiledPrefix } = renderPromptWithTokenLimit({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - llm: llmStub, - }) - - expect(compiledPrefix.length).toBeLessThan(120) - }) -}) - -describe("stop-token merging", () => { - it("returns stop tokens from getStopTokens", () => { - stopTokenReturn = ["LANG_STOP", "TEMPLATE_STOP"] - completionOptionsOverride = { stop: ["TEMPLATE_STOP"] } - templateOverride = (prefix: string, suffix: string) => `${prefix}|${suffix}` - - const helper = makeHelper() - - const { completionOptions } = renderPrompt({ - snippetPayload: emptySnippetPayload, - workspaceDirs: ["file:///workspace"], - helper, - }) - - expect(completionOptions?.stop).toEqual(stopTokenReturn) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/formatting.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/formatting.ts deleted file mode 100644 index 5aba7208e98..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/formatting.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { getLastNUriRelativePathParts } from "../../util/uri" -import { - AutocompleteClipboardSnippet, - AutocompleteCodeSnippet, - AutocompleteDiffSnippet, - AutocompleteSnippet, - AutocompleteSnippetType, - AutocompleteStaticSnippet, -} from "../types" -import { HelperVars } from "../util/HelperVars" - -const getCommentMark = (helper: HelperVars) => { - return helper.lang.singleLineComment -} - -const addCommentMarks = (text: string, helper: HelperVars) => { - const commentMark = getCommentMark(helper) - return text - .trim() - .split("\n") - .map((line) => `${commentMark} ${line}`) - .join("\n") -} - -const formatClipboardSnippet = ( - snippet: AutocompleteClipboardSnippet, - workspaceDirs: string[], -): AutocompleteCodeSnippet => { - return formatCodeSnippet( - { - filepath: "file:///Untitled.txt", - content: snippet.content, - type: AutocompleteSnippetType.Code, - }, - workspaceDirs, - ) -} - -const formatCodeSnippet = (snippet: AutocompleteCodeSnippet, workspaceDirs: string[]): AutocompleteCodeSnippet => { - return { - ...snippet, - content: `Path: ${getLastNUriRelativePathParts(workspaceDirs, snippet.filepath, 2)}\n${snippet.content}`, - } -} - -const formatDiffSnippet = (snippet: AutocompleteDiffSnippet): AutocompleteDiffSnippet => { - return snippet -} - -const formatStaticSnippet = (snippet: AutocompleteStaticSnippet): AutocompleteStaticSnippet => { - return snippet -} - -const commentifySnippet = (helper: HelperVars, snippet: AutocompleteSnippet): AutocompleteSnippet => { - return { - ...snippet, - content: addCommentMarks(snippet.content, helper), - } -} - -export const formatSnippets = ( - helper: HelperVars, - snippets: AutocompleteSnippet[], - workspaceDirs: string[], -): string => { - const currentFilepathComment = addCommentMarks( - getLastNUriRelativePathParts(workspaceDirs, helper.filepath, 2), - helper, - ) - - return ( - snippets - .map((snippet) => { - switch (snippet.type) { - case AutocompleteSnippetType.Code: - return formatCodeSnippet(snippet, workspaceDirs) - case AutocompleteSnippetType.Diff: - return formatDiffSnippet(snippet) - case AutocompleteSnippetType.Clipboard: - return formatClipboardSnippet(snippet, workspaceDirs) - case AutocompleteSnippetType.Static: - return formatStaticSnippet(snippet) - } - }) - .map((item) => { - return commentifySnippet(helper, item).content - }) - .join("\n") + `\n${currentFilepathComment}` - ) -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/getStopTokens.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/getStopTokens.ts deleted file mode 100644 index cbaa9f3d867..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/getStopTokens.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { CompletionOptions } from "../.." -import { AutocompleteLanguageInfo } from "../constants/AutocompleteLanguageInfo" - -// TODO: Do we want to stop completions when reaching a `/src/` string? -const SRC_DIRECTORY = "/src/" -// Starcoder2 tends to output artifacts starting with the letter "t" -const STARCODER2_T_ARTIFACTS = ["t.", "\nt", ""] -const PYTHON_ENCODING = "#- coding: utf-8" -const CODE_BLOCK_END = "```" - -// const multilineStops: string[] = [DOUBLE_NEWLINE, WINDOWS_DOUBLE_NEWLINE]; -const commonStops = [SRC_DIRECTORY, PYTHON_ENCODING, CODE_BLOCK_END] - -export function getStopTokens( - completionOptions: Partial | undefined, - _lang: AutocompleteLanguageInfo, - model: string, -): string[] { - const stopTokens = [ - ...(completionOptions?.stop || []), - // ...multilineStops, - ...commonStops, - ...(model.toLowerCase().includes("starcoder2") ? STARCODER2_T_ARTIFACTS : []), - // ...lang.topLevelKeywords.map((word) => `\n${word}`), - ] - - return stopTokens -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/index.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/index.ts deleted file mode 100644 index 43516dfb9ed..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/templating/index.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { CompletionOptions } from "../.." -import { HelperVars } from "../util/HelperVars" - -import { ILLM } from "../../index.js" -import { DEFAULT_MAX_TOKENS } from "../../llm/constants.js" -import { - countTokens, - getTokenCountingBufferSafety, - pruneLinesFromBottom, - pruneLinesFromTop, -} from "../../llm/countTokens" -import { getUriPathBasename } from "../../util/uri" -import { SnippetPayload } from "../snippets" -import { AutocompleteSnippet } from "../types" -import { AutocompleteTemplate, getTemplateForModel } from "./AutocompleteTemplate" -import { getSnippets } from "./filtering" -import { formatSnippets } from "./formatting" -import { getStopTokens } from "./getStopTokens" - -function getTemplate(helper: HelperVars): AutocompleteTemplate { - return getTemplateForModel(helper.modelName) -} - -/** Consolidates shared setup between renderPrompt and renderPromptWithTokenLimit. */ -function preparePromptContext({ - snippetPayload, - workspaceDirs, - helper, -}: { - snippetPayload: SnippetPayload - workspaceDirs: string[] - helper: HelperVars -}): { - prefix: string - suffix: string - reponame: string - template: AutocompleteTemplate["template"] - compilePrefixSuffix: AutocompleteTemplate["compilePrefixSuffix"] | undefined - completionOptions: Partial | undefined - snippets: AutocompleteSnippet[] -} { - // Determine base prefix/suffix, accounting for any manually supplied prefix. - const prefix = helper.input.manuallyPassPrefix || helper.prunedPrefix - let suffix = helper.input.manuallyPassPrefix ? "" : helper.prunedSuffix - if (suffix === "") { - suffix = "\n" - } - - const reponame = getUriPathBasename(workspaceDirs[0] ?? "myproject") - - const { template, compilePrefixSuffix, completionOptions } = getTemplate(helper) - - const snippets = getSnippets(helper, snippetPayload) - - return { - prefix, - suffix, - reponame, - template, - compilePrefixSuffix, - completionOptions, - snippets, - } -} - -export function renderPrompt({ - snippetPayload, - workspaceDirs, - helper, -}: { - snippetPayload: SnippetPayload - workspaceDirs: string[] - helper: HelperVars -}): { - prompt: string - prefix: string - suffix: string - completionOptions: Partial | undefined -} { - const { prefix, suffix, reponame, template, compilePrefixSuffix, completionOptions, snippets } = preparePromptContext( - { snippetPayload, workspaceDirs, helper }, - ) - - // Delegate prompt construction to buildPrompt to avoid duplication. - const { - prompt, - prefix: compiledPrefix, - suffix: compiledSuffix, - } = buildPrompt(template, compilePrefixSuffix, prefix, suffix, helper, snippets, workspaceDirs, reponame) - - const stopTokens = getStopTokens(completionOptions, helper.lang, helper.modelName) - - return { - prompt, - prefix: compiledPrefix, - suffix: compiledSuffix, - completionOptions: { - ...completionOptions, - stop: stopTokens, - }, - } -} - -/** Builds the final prompt by applying prefix/suffix compilation or snippet formatting, then rendering the template. */ -function buildPrompt( - template: AutocompleteTemplate["template"], - compilePrefixSuffix: AutocompleteTemplate["compilePrefixSuffix"] | undefined, - prefix: string, - suffix: string, - helper: HelperVars, - snippets: AutocompleteSnippet[], - workspaceDirs: string[], - reponame: string, -): { prompt: string; prefix: string; suffix: string } { - if (compilePrefixSuffix) { - ;[prefix, suffix] = compilePrefixSuffix(prefix, suffix, helper.filepath, reponame, snippets, helper.workspaceUris) - } else { - const formatted = formatSnippets(helper, snippets, workspaceDirs) - prefix = [formatted, prefix].join("\n") - } - const prompt = template(prefix, suffix, helper.filepath, reponame, helper.lang.name, snippets, helper.workspaceUris) - return { prompt, prefix, suffix } -} - -function pruneLength(llm: ILLM, prompt: string): number { - const contextLength = llm.contextLength - const reservedTokens = llm.completionOptions.maxTokens ?? DEFAULT_MAX_TOKENS - const safetyBuffer = getTokenCountingBufferSafety(contextLength) - const maxAllowedPromptTokens = contextLength - reservedTokens - safetyBuffer - const promptTokenCount = countTokens(prompt, llm.model) - return promptTokenCount - maxAllowedPromptTokens -} - -export function renderPromptWithTokenLimit({ - snippetPayload, - workspaceDirs, - helper, - llm, -}: { - snippetPayload: SnippetPayload - workspaceDirs: string[] - helper: HelperVars - llm: ILLM | undefined -}): { - prompt: string - prefix: string - suffix: string - completionOptions: Partial | undefined -} { - const { - prefix: initialPrefix, - suffix: initialSuffix, - reponame, - template, - compilePrefixSuffix, - completionOptions, - snippets, - } = preparePromptContext({ snippetPayload, workspaceDirs, helper }) - - // We'll mutate prefix/suffix during pruning, so copy them. - let prefix = initialPrefix - let suffix = initialSuffix - - let { - prompt, - prefix: compiledPrefix, - suffix: compiledSuffix, - } = buildPrompt(template, compilePrefixSuffix, prefix, suffix, helper, snippets, workspaceDirs, reponame) - - // Truncate prefix and suffix if prompt tokens exceed maxAllowedPromptTokens - if (llm) { - const prune = pruneLength(llm, prompt) - if (prune > 0) { - const tokensToDrop = prune - const prefixTokenCount = countTokens(prefix, helper.modelName) - const suffixTokenCount = countTokens(suffix, helper.modelName) - const totalContextTokens = prefixTokenCount + suffixTokenCount - if (totalContextTokens > 0) { - const dropPrefix = Math.ceil(tokensToDrop * (prefixTokenCount / totalContextTokens)) - const dropSuffix = Math.ceil(tokensToDrop - dropPrefix) - const allowedPrefixTokens = Math.max(0, prefixTokenCount - dropPrefix) - const allowedSuffixTokens = Math.max(0, suffixTokenCount - dropSuffix) - prefix = pruneLinesFromTop(prefix, allowedPrefixTokens, helper.modelName) - suffix = pruneLinesFromBottom(suffix, allowedSuffixTokens, helper.modelName) - } - ;({ - prompt, - prefix: compiledPrefix, - suffix: compiledSuffix, - } = buildPrompt(template, compilePrefixSuffix, prefix, suffix, helper, snippets, workspaceDirs, reponame)) - } - } - - const stopTokens = getStopTokens(completionOptions, helper.lang, helper.modelName) - - return { - prompt, - prefix: compiledPrefix, - suffix: compiledSuffix, - completionOptions: { - ...completionOptions, - stop: stopTokens, - }, - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteDebouncer.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteDebouncer.ts deleted file mode 100644 index 6bfb8a654ad..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteDebouncer.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { randomUUID } from "node:crypto" - -export class AutocompleteDebouncer { - private debounceTimeout: NodeJS.Timeout | undefined = undefined - private currentRequestId: string | undefined = undefined - - async delayAndShouldDebounce(debounceDelay: number): Promise { - // Generate a unique ID for this request - const requestId = randomUUID() - this.currentRequestId = requestId - - // Clear any existing timeout - if (this.debounceTimeout) { - clearTimeout(this.debounceTimeout) - } - - // Create a new promise that resolves after the debounce delay - return new Promise((resolve) => { - this.debounceTimeout = setTimeout(() => { - // When the timeout completes, check if this is still the most recent request - const shouldDebounce = this.currentRequestId !== requestId - - // If this is the most recent request, it shouldn't be debounced - if (!shouldDebounce) { - this.currentRequestId = undefined - } - - resolve(shouldDebounce) - }, debounceDelay) - }) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLoggingService.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLoggingService.ts deleted file mode 100644 index 83a8cf43ee4..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLoggingService.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { COUNT_COMPLETION_REJECTED_AFTER } from "../../util/parameters" -import { AutocompleteOutcome } from "./types" - -export class AutocompleteLoggingService { - // Key is completionId - private _abortControllers = new Map() - private _logRejectionTimeouts = new Map() - private _outcomes = new Map() - _lastDisplayedCompletion: { id: string; displayedAt: number } | undefined = undefined - - public createAbortController(completionId: string): AbortController { - const abortController = new AbortController() - this._abortControllers.set(completionId, abortController) - return abortController - } - - public deleteAbortController(completionId: string) { - this._abortControllers.delete(completionId) - } - - public cancel() { - this._abortControllers.forEach((abortController) => { - abortController.abort() - }) - this._abortControllers.clear() - } - - public accept(completionId: string): AutocompleteOutcome | undefined { - if (this._logRejectionTimeouts.has(completionId)) { - clearTimeout(this._logRejectionTimeouts.get(completionId)) - this._logRejectionTimeouts.delete(completionId) - } - - if (this._outcomes.has(completionId)) { - const outcome = this._outcomes.get(completionId)! - outcome.accepted = true - this.logAutocompleteOutcome(outcome) - this._outcomes.delete(completionId) - return outcome - } - return undefined - } - - public cancelRejectionTimeout(completionId: string) { - if (this._logRejectionTimeouts.has(completionId)) { - clearTimeout(this._logRejectionTimeouts.get(completionId)!) - this._logRejectionTimeouts.delete(completionId) - } - - if (this._outcomes.has(completionId)) { - this._outcomes.delete(completionId) - } - } - - public markDisplayed(completionId: string, outcome: AutocompleteOutcome) { - const logRejectionTimeout = setTimeout(() => { - // Wait 10 seconds, then assume it wasn't accepted - outcome.accepted = false - this.logAutocompleteOutcome(outcome) - this._logRejectionTimeouts.delete(completionId) - }, COUNT_COMPLETION_REJECTED_AFTER) - this._outcomes.set(completionId, outcome) - this._logRejectionTimeouts.set(completionId, logRejectionTimeout) - - // If the previously displayed completion is still waiting for rejection, - // and this one is a continuation of that (the outcome.completion is the same modulo prefix) - // then we should cancel the rejection timeout - const previous = this._lastDisplayedCompletion - const now = Date.now() - if (previous && this._logRejectionTimeouts.has(previous.id)) { - const previousOutcome = this._outcomes.get(previous.id) - const c1 = previousOutcome?.completion.split("\n")[0] ?? "" - const c2 = outcome.completion.split("\n")[0] - if (previousOutcome && (c1.endsWith(c2) || c2.endsWith(c1) || c1.startsWith(c2) || c2.startsWith(c1))) { - this.cancelRejectionTimeout(previous.id) - } else if (now - previous.displayedAt < 500) { - // If a completion isn't shown for more than - this.cancelRejectionTimeout(previous.id) - } - } - - this._lastDisplayedCompletion = { - id: completionId, - displayedAt: now, - } - } - - private logAutocompleteOutcome(outcome: AutocompleteOutcome) { - if (!process.env.VITEST) { - console.log(outcome) - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.test.ts deleted file mode 100644 index 216a979749b..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.test.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { describe, it, expect, beforeEach } from "vitest" -import { AutocompleteLruCacheInMem } from "./AutocompleteLruCacheInMem" - -describe("AutoCompleteLruCacheInMem", () => { - let cache: AutocompleteLruCacheInMem - - beforeEach(async () => { - cache = await AutocompleteLruCacheInMem.get() - }) - - describe("basic operations", () => { - it("should store and retrieve a value", async () => { - await cache.put("hello", "world") - const result = await cache.get("hello") - expect(result).toBe("world") - }) - - it("should return undefined for non-existent key", async () => { - const result = await cache.get("nonexistent") - expect(result).toBeUndefined() - }) - - it("should update existing value", async () => { - await cache.put("key", "value1") - await cache.put("key", "value2") - const result = await cache.get("key") - expect(result).toBe("value2") - }) - }) - - describe("exact key matching", () => { - it("should match exact key and return value", async () => { - await cache.put("hello", "world") - const result = await cache.get("hello") - expect(result).toBe("world") - }) - - it("should return undefined when key doesn't match exactly", async () => { - await cache.put("hello", "world") - const result = await cache.get("goodbye") - expect(result).toBeUndefined() - }) - - it("should return undefined for partial key match", async () => { - await cache.put("hello", "world") - const result = await cache.get("hel") - expect(result).toBeUndefined() - }) - - it("should be case sensitive", async () => { - await cache.put("Hello", "World") - const result1 = await cache.get("Hello") - const result2 = await cache.get("hello") - expect(result1).toBe("World") - expect(result2).toBeUndefined() - }) - }) - - describe("fuzzy matching", () => { - it("should return completion when prefix extends a cached key", async () => { - // Cache "c" -> "ontinue" - await cache.put("c", "ontinue") - // Query "co" should return "ntinue" (completion minus what we already have) - const result = await cache.get("co") - expect(result).toBe("ntinue") - }) - - it("should prefer longest matching key", async () => { - // Cache multiple overlapping keys - await cache.put("h", "ello world") - await cache.put("he", "llo world") - await cache.put("hel", "lo world") - - // Query "hello" should match "hel" (longest key) - // User typed "hello" = "hel" + "lo", cached completion is "lo world" - // So return " world" (the part not yet typed) - const result = await cache.get("hello") - expect(result).toBe(" world") - }) - - it("should validate cached completion starts correctly", async () => { - // Cache "c" -> "ontinue" - await cache.put("c", "ontinue") - // Query "cx" doesn't match the completion pattern, should return undefined - const result = await cache.get("cx") - expect(result).toBeUndefined() - }) - - it("should return exact match if available", async () => { - // Cache both exact and partial keys - await cache.put("co", "mplete") - await cache.put("c", "ontinue") - - // Exact match should be preferred - const result = await cache.get("co") - expect(result).toBe("mplete") - }) - - it("should handle multiple partial matches correctly", async () => { - // Cache overlapping prefixes - await cache.put("fun", "ction") - await cache.put("f", "unction") - - // Query "func" should match "fun" (longest) and return "ction" - const result = await cache.get("func") - expect(result).toBe("tion") - }) - - it("should return undefined when no fuzzy match exists", async () => { - await cache.put("hello", "world") - // "goodbye" doesn't start with "hello" - const result = await cache.get("goodbye") - expect(result).toBeUndefined() - }) - - it("should handle empty cache for fuzzy matching", async () => { - const result = await cache.get("anyprefix") - expect(result).toBeUndefined() - }) - }) - - describe("LRU eviction", () => { - it("should evict oldest entry when capacity is reached", async () => { - // Create a fresh cache for this test - const testCache = await AutocompleteLruCacheInMem.get() - - // Fill cache to capacity (100 entries) - for (let i = 0; i < 100; i++) { - await testCache.put(`key${i}`, `value${i}`) - } - - // Add one more entry to trigger eviction - await testCache.put("newkey", "newvalue") - - // First entry should be evicted (oldest timestamp) - const result = await testCache.get("key0") - expect(result).toBeUndefined() - - // New entry should exist - const newResult = await testCache.get("newkey") - expect(newResult).toBe("newvalue") - }) - - it("should update timestamp on cache hit", async () => { - // Create a fresh cache for this test - const testCache = await AutocompleteLruCacheInMem.get() - - // Fill to capacity - for (let i = 0; i < 100; i++) { - await testCache.put(`key${i}`, `value${i}`) - } - - // Access an early entry to refresh its timestamp - const refreshedValue = await testCache.get("key5") - expect(refreshedValue).toBe("value5") - - // Add new entries to trigger evictions - await testCache.put("new1", "newvalue1") - await testCache.put("new2", "newvalue2") - - // key5 should still exist (refreshed timestamp) - const key5Result = await testCache.get("key5") - expect(key5Result).toBe("value5") - - // key0 should be evicted (oldest timestamp, never accessed) - const key0Result = await testCache.get("key0") - expect(key0Result).toBeUndefined() - }) - }) - - describe("edge cases", () => { - it("should handle empty strings", async () => { - const testCache = await AutocompleteLruCacheInMem.get() - await testCache.put("", "empty") - const result = await testCache.get("") - expect(result).toBe("empty") - }) - - it("should handle very long strings", async () => { - const testCache = await AutocompleteLruCacheInMem.get() - const longString = "a".repeat(10000) - await testCache.put(longString, "completion") - const result = await testCache.get(longString) - expect(result).toBe("completion") - }) - - it("should handle special characters", async () => { - await cache.put("const x = {", "foo: 'bar'}") - const result = await cache.get("const x = {") - expect(result).toBe("foo: 'bar'}") - }) - - it("should handle unicode characters", async () => { - await cache.put("emoji 🚀", "rocket") - const result = await cache.get("emoji 🚀") - expect(result).toBe("rocket") - }) - }) - - describe("concurrent operations", () => { - it("should handle concurrent put operations", async () => { - const promises = [] - for (let i = 0; i < 10; i++) { - promises.push(cache.put(`concurrent${i}`, `value${i}`)) - } - await Promise.all(promises) - - // All values should be stored - for (let i = 0; i < 10; i++) { - const result = await cache.get(`concurrent${i}`) - expect(result).toBe(`value${i}`) - } - }) - - it("should handle concurrent get operations", async () => { - await cache.put("shared", "value") - - const promises = [] - for (let i = 0; i < 10; i++) { - promises.push(cache.get("shared")) - } - const results = await Promise.all(promises) - - // All gets should return the same value - results.forEach((result) => { - expect(result).toBe("value") - }) - }) - }) - - describe("multiple cache instances", () => { - it("should create separate cache instances", async () => { - const cache1 = await AutocompleteLruCacheInMem.get() - const cache2 = await AutocompleteLruCacheInMem.get() - - await cache1.put("test", "value1") - await cache2.put("test", "value2") - - const result1 = await cache1.get("test") - const result2 = await cache2.get("test") - - // Each instance should have its own data - expect(result1).toBe("value1") - expect(result2).toBe("value2") - }) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.ts deleted file mode 100644 index 3cad96a860a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/AutocompleteLruCacheInMem.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { LRUCache } from "lru-cache" - -const MAX_PREFIX_LENGTH = 50000 - -function truncatePrefix(input: string, safety: number = 100): string { - const maxBytes = MAX_PREFIX_LENGTH - safety - let bytes = 0 - let startIndex = 0 - - // Count bytes from the end, keeping the most recent typing - for (let i = input.length - 1; i >= 0; i--) { - bytes += new TextEncoder().encode(input[i]).length - if (bytes > maxBytes) { - startIndex = i + 1 - break - } - } - - return input.substring(startIndex) -} - -export class AutocompleteLruCacheInMem { - private static capacity = 100 - private cache: LRUCache - - private constructor() { - this.cache = new LRUCache({ - max: AutocompleteLruCacheInMem.capacity, - }) - } - - static async get(): Promise { - return new AutocompleteLruCacheInMem() - } - - async get(prefix: string): Promise { - const truncated = truncatePrefix(prefix) - - // First try exact match (faster) - const exactMatch = this.cache.get(truncated) - if (exactMatch !== undefined) { - return exactMatch - } - - // Then try fuzzy matching - find keys where prefix starts with the key - // If the query is "co" and we have "c" -> "ontinue" in the cache, - // we should return "ntinue" as the completion. - // Have to make sure we take the key with longest length for best match - let bestMatch: { key: string; value: string } | null = null - let longestKeyLength = 0 - - for (const [key, value] of this.cache.entries()) { - // Check if truncated prefix starts with this key - if (truncated.startsWith(key) && key.length > longestKeyLength) { - bestMatch = { key, value } - longestKeyLength = key.length - } - } - - if (bestMatch) { - // Validate that the cached completion is a valid completion for the prefix - if (bestMatch.value.startsWith(truncated.slice(bestMatch.key.length))) { - // Update LRU timestamp for the matched key by accessing it - this.cache.get(bestMatch.key) - // Return the portion of the value that extends beyond the current prefix - return bestMatch.value.slice(truncated.length - bestMatch.key.length) - } - } - - return undefined - } - - async put(prefix: string, completion: string) { - const truncated = truncatePrefix(prefix) - this.cache.set(truncated, completion) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.test.ts deleted file mode 100644 index 045f3995b28..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { describe, expect, it } from "vitest" -import { processTestCase, type CompletionTestCase } from "./completionTestUtils" - -describe("processTestCase utility", () => { - it("processes simple console.log completion", () => { - const testCase: CompletionTestCase = { - original: "console.log(|cur||till|)", - completion: '"foo,", bar', - } - - expect(processTestCase(testCase)).toEqual({ - input: { - lastLineOfCompletionText: '"foo,", bar', - currentText: ")", - cursorPosition: "console.log(".length, - }, - expectedResult: { - completionText: '"foo,", bar', - }, - }) - }) - - it("processes simple console.log completion with overwriting", () => { - const testCase: CompletionTestCase = { - original: "console.log(|cur|)|till|", - completion: '"foo,", bar);', - } - - expect(processTestCase(testCase)).toEqual({ - input: { - lastLineOfCompletionText: '"foo,", bar);', - currentText: ")", - cursorPosition: "console.log(".length, - }, - expectedResult: { - completionText: '"foo,", bar);', - range: { - start: "console.log(".length, - end: "console.log()".length, - }, - }, - }) - }) - - it("partially applying completion", () => { - const testCase: CompletionTestCase = { - original: '|cur||till|fetch("https://example.com");', - completion: 'await fetch("https://example.com");', - appliedCompletion: "await ", - } - - expect(processTestCase(testCase)).toEqual({ - input: { - lastLineOfCompletionText: 'await fetch("https://example.com");', - currentText: 'fetch("https://example.com");', - cursorPosition: 0, - }, - expectedResult: { - completionText: "await ", - }, - }) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.ts deleted file mode 100644 index 9dfbc6c63c5..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/completionTestUtils.ts +++ /dev/null @@ -1,94 +0,0 @@ -export interface CompletionTestCase { - original: string // Text with |cur| and |till| markers - completion: string // Text to insert/overwrite - appliedCompletion?: string | null - cursorMarker?: string - tillMarker?: string -} - -interface ProcessedTestCase { - input: { - lastLineOfCompletionText: string - currentText: string - cursorPosition: number - } - expectedResult: { - completionText: string - range?: { - start: number - end: number - } - } -} - -/** - * Transforms human-readable test case into input and expected results. - * - * - `original`: Your original text with |cur| marking where the cursor is before completion, - * and |till| marking where the cursor should be after accepting completion (and this is - * the end of the actual applied completion) - * - `completion`: LLM completion output - * - `appliedCompletion` (optional): part of the LLM completion output that is actually applied - * (written between |cur| and |till| in the original) - * - * For example, you have this line: - * - * console.log(""); - * - * and expect it to be completed this way: - * - * console.log("foo: ", bar); - * - * with your completion coming from LLM being: `'foo: ", bar);'` - * - * Your input to this function should be: - * - original: `'console.log("|cur|"|till|);'` - * - completion: `'foo: ", bar);'` - * - appliedCompletion: `'foo: ", bar'` - * - * Output: input and expected output of {@link core/autocomplete/util/processSingleLineCompletion/processSingleLineCompletion|processSingleLineCompletion()} - * - */ -export function processTestCase({ - original, - completion, - appliedCompletion = null, - cursorMarker = "|cur|", - tillMarker = "|till|", -}: CompletionTestCase): ProcessedTestCase { - // Validate cursor marker - if (!original.includes(cursorMarker)) { - throw new Error("Cursor marker not found in original text") - } - - const cursorPos = original.indexOf(cursorMarker) - original = original.replace(cursorMarker, "") - - let tillPos = original.indexOf(tillMarker) - if (tillPos < 0) { - tillPos = cursorPos - } else { - original = original.replace(tillMarker, "") - } - - // Calculate currentText based on what's between cursor and till marker - const currentText = original.substring(cursorPos) - - return { - input: { - lastLineOfCompletionText: completion, - currentText, - cursorPosition: cursorPos, - }, - expectedResult: { - completionText: appliedCompletion || completion, - range: - cursorPos === tillPos - ? undefined - : { - start: cursorPos, - end: tillPos, - }, - }, - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.test.ts deleted file mode 100644 index df60fd5123a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.test.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { describe, expect, it } from "vitest" -import { processTestCase } from "./completionTestUtils" -import { processSingleLineCompletion } from "./processSingleLineCompletion" - -describe("processSingleLineCompletion", () => { - it("should handle simple end of line completion", () => { - const testCase = processTestCase({ - original: "console.log(|cur|", - completion: '"Hello, world!")', - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) - - it("should handle midline insert repeating the end of line", () => { - const testCase = processTestCase({ - original: "console.log(|cur|);|till|", - completion: '"Hello, world!");', - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) - - it("should handle midline insert repeating the end of line plus adding a semicolon", () => { - const testCase = processTestCase({ - original: "console.log(|cur|)|till|", - completion: '"Hello, world!");', - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) - - it("should handle simple midline insert", () => { - const testCase = processTestCase({ - original: "console.log(|cur|)", - completion: '"Hello, world!"', - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) - - it("should handle complex dif with addition in the beginning", () => { - const testCase = processTestCase({ - original: 'console.log(|cur||till|, "param1", )', // TODO - completion: '"Hello world!", "param1", param1);', - appliedCompletion: '"Hello world!"', - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) - - it("should handle simple insertion even with random equality", () => { - const testCase = processTestCase({ - original: 'print(f"Foobar length: |cur||till|")', - completion: "{len(foobar)}", - }) - - const result = processSingleLineCompletion( - testCase.input.lastLineOfCompletionText, - testCase.input.currentText, - testCase.input.cursorPosition, - ) - - expect(result).toEqual(testCase.expectedResult) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.ts deleted file mode 100644 index f4642295472..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/processSingleLineCompletion.ts +++ /dev/null @@ -1,80 +0,0 @@ -import * as Diff from "diff" - -interface SingleLineCompletionResult { - completionText: string - range?: { - start: number - end: number - } -} - -interface DiffType { - count?: number - added?: boolean - removed?: boolean - value: string -} - -function diffPatternMatches(diffs: DiffType[], pattern: DiffPartType[]): boolean { - if (diffs.length !== pattern.length) { - return false - } - - for (let i = 0; i < diffs.length; i++) { - const diff = diffs[i] - const diffPartType: DiffPartType = !diff.added && !diff.removed ? "=" : diff.added ? "+" : "-" - - if (diffPartType !== pattern[i]) { - return false - } - } - - return true -} - -type DiffPartType = "+" | "-" | "=" - -export function processSingleLineCompletion( - lastLineOfCompletionText: string, - currentText: string, - cursorPosition: number, -): SingleLineCompletionResult | undefined { - const diffs: DiffType[] = Diff.diffWords(currentText, lastLineOfCompletionText) - - if (diffPatternMatches(diffs, ["+"])) { - // Just insert, we're already at the end of the line - return { - completionText: lastLineOfCompletionText, - } - } - - if (diffPatternMatches(diffs, ["+", "="]) || diffPatternMatches(diffs, ["+", "=", "+"])) { - // The model repeated the text after the cursor to the end of the line - return { - completionText: lastLineOfCompletionText, - range: { - start: cursorPosition, - end: currentText.length + cursorPosition, - }, - } - } - - if (diffPatternMatches(diffs, ["+", "-"]) || diffPatternMatches(diffs, ["-", "+"])) { - // We are midline and the model just inserted without repeating to the end of the line - return { - completionText: lastLineOfCompletionText, - } - } - - // For any other diff pattern, just use the first added part if available - if (diffs[0]?.added) { - return { - completionText: diffs[0].value, - } - } - - // Default case: treat as simple insertion - return { - completionText: lastLineOfCompletionText, - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/types.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/types.ts index 815bb4a66a6..1b11559f8a0 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/types.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/util/types.ts @@ -1,5 +1,5 @@ -import { Position, Range, RangeInFile, TabAutocompleteOptions } from "../.." -import { AutocompleteCodeSnippet } from "../types" +import type { Position, Range, RangeInFile } from "../.." +import type { AutocompleteCodeSnippet } from "../types" export type RecentlyEditedRange = RangeInFile & { timestamp: number @@ -24,24 +24,3 @@ export interface AutocompleteInput { } injectDetails?: string } - -export interface AutocompleteOutcome extends TabAutocompleteOptions { - accepted?: boolean - time: number - prefix: string - suffix: string - prompt: string - completion: string - modelProvider: string - modelName: string - completionOptions: any - cacheHit: boolean - numLines: number - filepath: string - gitRepo?: string - completionId: string - uniqueId: string - timestamp: string - enabledStaticContextualization?: boolean - profileType?: "local" | "platform" | "control-plane" -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/fixtures.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/fixtures.ts index 1f9b83c756f..8131afe46db 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/fixtures.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/fixtures.ts @@ -1,9 +1,5 @@ -import { MinimalConfigProvider } from "../autocomplete/MinimalConfig" import { FileSystemIde } from "../util/filesystem" import { TEST_DIR } from "./testDir" export const testIde = new FileSystemIde(TEST_DIR) - -// For autocomplete/nextEdit tests, use MinimalConfigProvider -export const testMinimalConfigProvider = new MinimalConfigProvider() diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/testDir.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/testDir.ts index c0386c7b3ca..8873a01d432 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/testDir.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/testDir.ts @@ -1,7 +1,7 @@ import fs from "fs" import os from "os" import path from "path" -import { localPathOrUriToPath, localPathToUri } from "../util/pathToUri" +import { localPathToUri } from "../util/pathToUri" // Want this outside of the git repository so we can change branches in tests const TEST_DIR_PATH = path.join(os.tmpdir(), "testWorkspaceDir") @@ -29,33 +29,3 @@ export function tearDownTestDir() { }) } } - -/* - accepts array of items in 3 formats, e.g. - "index/" creates index directory - "index/index.ts" creates an empty index/index.ts - ["index/index.ts", "hello"] creates index/index.ts with contents "hello" -*/ -export function addToTestDir(pathsOrUris: (string | [string, string])[]) { - // Allow tests to use URIs or local paths - const paths = pathsOrUris.map((val) => { - if (Array.isArray(val)) { - return [localPathOrUriToPath(val[0]), val[1]] - } else { - return localPathOrUriToPath(val) - } - }) - - for (const p of paths) { - const filepath = path.join(TEST_DIR_PATH, Array.isArray(p) ? p[0] : p) - fs.mkdirSync(path.dirname(filepath), { recursive: true }) - - if (Array.isArray(p)) { - fs.writeFileSync(filepath, p[1]) - } else if (p.endsWith("/")) { - fs.mkdirSync(filepath, { recursive: true }) - } else { - fs.writeFileSync(filepath, "") - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/parameters.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/parameters.ts index e79407947d0..18ee68de274 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/parameters.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/parameters.ts @@ -1,4 +1,4 @@ -import { TabAutocompleteOptions } from "../index.js" +import type { TabAutocompleteOptions } from "../index.js" export const DEFAULT_AUTOCOMPLETE_OPTS: TabAutocompleteOptions = { disable: false, @@ -28,5 +28,3 @@ export const DEFAULT_AUTOCOMPLETE_OPTS: TabAutocompleteOptions = { experimental_includeDiff: true, experimental_enableStaticContextualization: false, } - -export const COUNT_COMPLETION_REJECTED_AFTER = 10_000 From b4323414716c1be85addb0c2c7d8193821c66173 Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:43:53 +0000 Subject: [PATCH 4/5] refactor(vscode): remove unused continuedev support utilities --- .../continuedev/core/diff/myers.test.ts | 634 ----------------- .../continuedev/core/diff/myers.ts | 204 ------ .../continuedev/core/diff/streamDiff.test.ts | 317 --------- .../continuedev/core/diff/streamDiff.ts | 76 -- .../continuedev/core/diff/util.ts | 95 +-- .../continuedev/core/fetch/stream.ts | 138 ---- .../continuedev/core/llm/constants.ts | 10 - .../continuedev/core/llm/countTokens.ts | 233 +----- .../continuedev/core/llm/index.ts | 664 ------------------ .../continuedev/core/llm/llms/Mock.ts | 66 -- .../continuedev/core/llm/messages.ts | 31 - .../continuedev/core/llm/model-info/index.ts | 22 - .../core/llm/model-info/providers/openai.ts | 139 ---- .../continuedev/core/llm/model-info/types.ts | 58 -- .../core/llm/openaiTypeConverters.ts | 108 --- .../continuedev/core/llm/templates/edit.ts | 253 ------- .../core/llm/templates/edit/gpt.ts | 72 -- .../core/test/FakeConfigHandler.ts | 87 --- .../continuedev/core/test/FakeIDE.ts | 150 ---- .../core/test/vitest.global-setup.ts | 11 - .../continuedev/core/test/vitest.setup.ts | 11 - .../continuedev/core/util/CodeRenderer.ts | 34 - .../core/util/TokensBatchingService.ts | 82 --- .../continuedev/core/util/index.ts | 51 -- .../continuedev/core/util/logger.ts | 35 - .../continuedev/core/util/merge.ts | 58 -- .../continuedev/core/util/paths.ts | 34 - .../autocomplete/continuedev/core/util/uri.ts | 24 - 28 files changed, 12 insertions(+), 3685 deletions(-) delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.test.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/fetch/stream.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/constants.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/index.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/llms/Mock.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/messages.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/index.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/providers/openai.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/types.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/openaiTypeConverters.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit/gpt.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeConfigHandler.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeIDE.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.global-setup.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.setup.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/CodeRenderer.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/TokensBatchingService.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/index.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/logger.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/merge.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/paths.ts diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.test.ts deleted file mode 100644 index 40011c37992..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.test.ts +++ /dev/null @@ -1,634 +0,0 @@ -import { describe, expect, test } from "vitest" - -import { dedent } from "../util" - -import { myersCharDiff, myersDiff } from "./myers" - -describe("Test myers diff function", () => { - test("should ...", () => { - const linesA = dedent` - A - B - C - D - E - ` - const linesB = dedent` - A - B - C' - D' - E - ` - const diffLines = myersDiff(linesA, linesB) - expect(diffLines).toEqual([ - { type: "same", line: "A" }, - { type: "same", line: "B" }, - { type: "old", line: "C" }, - { type: "old", line: "D" }, - { type: "new", line: "C'" }, - { type: "new", line: "D'" }, - { type: "same", line: "E" }, - ]) - }) - - test("should ignore newline differences at end", () => { - const linesA = "A\nB\nC\n" - const linesB = "A\nB\nC" - - const diffLines = myersDiff(linesA, linesB) - expect(diffLines).toEqual([ - { type: "same", line: "A" }, - { type: "same", line: "B" }, - { type: "same", line: "C" }, - ]) - }) - - test("should ignore single-line whitespace-only differences", () => { - const linesA = "A\n B\nC\n" - const linesB = "A\nB\nC" - - const diffLines = myersDiff(linesA, linesB) - expect(diffLines).toEqual([ - { type: "same", line: "A" }, - { type: "same", line: " B" }, - { type: "same", line: "C" }, - ]) - }) -}) - -describe("Test myersCharDiff function on the same line", () => { - test("should differentiate character changes", () => { - const oldContent = "hello world" - const newContent = "hello earth" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "hello ", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "wo", - oldIndex: 6, - oldCharIndexInLine: 6, - oldLineIndex: 0, - }, - { - type: "new", - char: "ea", - newIndex: 6, - newCharIndexInLine: 6, - newLineIndex: 0, - }, - { - type: "same", - char: "r", - oldIndex: 8, - newIndex: 8, - oldCharIndexInLine: 8, - newCharIndexInLine: 8, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "ld", - oldIndex: 9, - oldCharIndexInLine: 9, - oldLineIndex: 0, - }, - { - type: "new", - char: "th", - newIndex: 9, - newCharIndexInLine: 9, - newLineIndex: 0, - }, - ]) - }) - - test("should handle insertions", () => { - const oldContent = "abc" - const newContent = "abxyzc" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "ab", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "new", - char: "xyz", - newIndex: 2, - newCharIndexInLine: 2, - newLineIndex: 0, - }, - { - type: "same", - char: "c", - oldIndex: 2, - newIndex: 5, - oldCharIndexInLine: 2, - newCharIndexInLine: 5, - oldLineIndex: 0, - newLineIndex: 0, - }, - ]) - }) - - test("should handle deletions", () => { - const oldContent = "abxyzc" - const newContent = "abc" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "ab", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "xyz", - oldIndex: 2, - oldCharIndexInLine: 2, - oldLineIndex: 0, - }, - { - type: "same", - char: "c", - oldIndex: 5, - newIndex: 2, - oldCharIndexInLine: 5, - newCharIndexInLine: 2, - oldLineIndex: 0, - newLineIndex: 0, - }, - ]) - }) - - test("should handle empty strings", () => { - const oldContent = "" - const newContent = "abc" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "new", - char: "abc", - newIndex: 0, - newCharIndexInLine: 0, - newLineIndex: 0, - }, - ]) - }) - - test("should handle identical strings", () => { - const content = "no changes here" - - const diffChars = myersCharDiff(content, content) - expect(diffChars).toEqual([ - { - type: "same", - char: "no changes here", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - ]) - }) - - test("should handle whitespace changes", () => { - const oldContent = "hello world" - const newContent = "hello world" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "hello ", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "new", - char: " ", - newIndex: 6, - newCharIndexInLine: 6, - newLineIndex: 0, - }, - { - type: "same", - char: "world", - oldIndex: 6, - newIndex: 7, - oldCharIndexInLine: 6, - newCharIndexInLine: 7, - oldLineIndex: 0, - newLineIndex: 0, - }, - ]) - }) - - test("should handle complex changes", () => { - const oldContent = "The quick brown fox jumps over the lazy dog" - const newContent = "The fast brown fox leaps over the sleeping dog" - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "The ", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "quick", - oldIndex: 4, - oldCharIndexInLine: 4, - oldLineIndex: 0, - }, - { - type: "new", - char: "fast", - newIndex: 4, - newCharIndexInLine: 4, - newLineIndex: 0, - }, - { - type: "same", - char: " brown fox ", - oldIndex: 9, - newIndex: 8, - oldCharIndexInLine: 9, - newCharIndexInLine: 8, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "jum", - oldIndex: 20, - oldCharIndexInLine: 20, - oldLineIndex: 0, - }, - { - type: "new", - char: "lea", - newIndex: 19, - newCharIndexInLine: 19, - newLineIndex: 0, - }, - { - type: "same", - char: "ps over the ", - oldIndex: 23, - newIndex: 22, - oldCharIndexInLine: 23, - newCharIndexInLine: 22, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "new", - char: "s", - newIndex: 34, - newCharIndexInLine: 34, - newLineIndex: 0, - }, - { - type: "same", - char: "l", - oldIndex: 35, - newIndex: 35, - oldCharIndexInLine: 35, - newCharIndexInLine: 35, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "azy", - oldIndex: 36, - oldCharIndexInLine: 36, - oldLineIndex: 0, - }, - { - type: "new", - char: "eeping", - newIndex: 36, - newCharIndexInLine: 36, - newLineIndex: 0, - }, - { - type: "same", - char: " dog", - oldIndex: 39, - newIndex: 42, - oldCharIndexInLine: 39, - newCharIndexInLine: 42, - oldLineIndex: 0, - newLineIndex: 0, - }, - ]) - }) -}) - -describe("Test myersCharDiff function on different lines", () => { - test("should track line indices for multi-line changes", () => { - const oldContent = ["Line one", "Line two", "Line three"].join("\n") - - const newContent = ["Line one", "Modified line", "Line three"].join("\n") - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "Line one", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "same", - char: "\n", - oldIndex: 8, - newIndex: 8, - oldCharIndexInLine: 8, - newCharIndexInLine: 8, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "L", - oldIndex: 9, - oldCharIndexInLine: 0, - oldLineIndex: 1, - }, - { - type: "new", - char: "Mod", - newIndex: 9, - newCharIndexInLine: 0, - newLineIndex: 1, - }, - { - char: "i", - newCharIndexInLine: 3, - newIndex: 12, - newLineIndex: 1, - oldCharIndexInLine: 1, - oldIndex: 10, - oldLineIndex: 1, - type: "same", - }, - { - char: "n", - oldCharIndexInLine: 2, - oldIndex: 11, - oldLineIndex: 1, - type: "old", - }, - { - char: "fi", - newCharIndexInLine: 4, - newIndex: 13, - newLineIndex: 1, - type: "new", - }, - { - char: "e", - newCharIndexInLine: 6, - newIndex: 15, - newLineIndex: 1, - oldCharIndexInLine: 3, - oldIndex: 12, - oldLineIndex: 1, - type: "same", - }, - { - char: "d", - newCharIndexInLine: 7, - newIndex: 16, - newLineIndex: 1, - type: "new", - }, - { - char: " ", - newCharIndexInLine: 8, - newIndex: 17, - newLineIndex: 1, - oldCharIndexInLine: 4, - oldIndex: 13, - oldLineIndex: 1, - type: "same", - }, - { - type: "old", - char: "two", - oldCharIndexInLine: 5, - oldIndex: 14, - oldLineIndex: 1, - }, - { - type: "new", - char: "line", - newCharIndexInLine: 9, - newIndex: 18, - newLineIndex: 1, - }, - { - type: "same", - char: "\n", - oldIndex: 17, - oldCharIndexInLine: 8, - oldLineIndex: 1, - newIndex: 22, - newCharIndexInLine: 13, - newLineIndex: 1, - }, - { - type: "same", - char: "Line three", - oldIndex: 18, - newIndex: 23, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 2, - newLineIndex: 2, - }, - ]) - }) - - test("should track line indices when adding new lines", () => { - const oldContent = ["First line", "Last line"].join("\n") - - const newContent = ["First line", "Middle line", "Another middle", "Last line"].join("\n") - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "First line", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "same", - char: "\n", - oldIndex: 10, - newIndex: 10, - oldCharIndexInLine: 10, - newCharIndexInLine: 10, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "new", - char: "Middle line", - newIndex: 11, - newCharIndexInLine: 0, - newLineIndex: 1, - }, - { - type: "new", - char: "\n", - newIndex: 22, - newCharIndexInLine: 11, - newLineIndex: 1, - }, - { - type: "new", - char: "Another middle", - newCharIndexInLine: 0, - newIndex: 23, - newLineIndex: 2, - }, - { - type: "new", - char: "\n", - newCharIndexInLine: 14, - newIndex: 37, - newLineIndex: 2, - }, - { - type: "same", - char: "Last line", - oldIndex: 11, - oldCharIndexInLine: 0, - oldLineIndex: 1, - newIndex: 38, - newCharIndexInLine: 0, - newLineIndex: 3, - }, - ]) - }) - - test("should track line indices when removing lines", () => { - const oldContent = ["Start", "Line to remove", "Another to remove", "End"].join("\n") - - const newContent = ["Start", "End"].join("\n") - - const diffChars = myersCharDiff(oldContent, newContent) - expect(diffChars).toEqual([ - { - type: "same", - char: "Start", - oldIndex: 0, - newIndex: 0, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "same", - char: "\n", - oldIndex: 5, - newIndex: 5, - oldCharIndexInLine: 5, - newCharIndexInLine: 5, - oldLineIndex: 0, - newLineIndex: 0, - }, - { - type: "old", - char: "Line to remove", - oldIndex: 6, - oldCharIndexInLine: 0, - oldLineIndex: 1, - }, - { - type: "old", - char: "\n", - oldCharIndexInLine: 14, - oldIndex: 20, - oldLineIndex: 1, - }, - { - type: "old", - char: "Another to remove", - oldCharIndexInLine: 0, - oldIndex: 21, - oldLineIndex: 2, - }, - { - type: "old", - char: "\n", - oldCharIndexInLine: 17, - oldIndex: 38, - oldLineIndex: 2, - }, - { - type: "same", - char: "End", - oldIndex: 39, - newIndex: 6, - oldCharIndexInLine: 0, - newCharIndexInLine: 0, - oldLineIndex: 3, - newLineIndex: 1, - }, - ]) - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.ts deleted file mode 100644 index 1d61d26d769..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/myers.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { diffChars, diffLines, type Change } from "diff" - -import { DiffChar, DiffLine } from ".." - -function convertMyersChangeToDiffLines(change: Change): DiffLine[] { - const type: DiffLine["type"] = change.added ? "new" : change.removed ? "old" : "same" - const lines = change.value.split("\n") - - // Ignore the \n at the end of the final line, if there is one - if (lines[lines.length - 1] === "") { - lines.pop() - } - - return lines.map((line) => ({ type, line })) -} - -// The interpretation of lines in oldContent and newContent is the same as jsdiff -// Lines are separated by \n, with the exception that a trailing \n does *not* -// represent an empty line. -// -// The default for jsdiff is that "foo" and "foo\n" are *different* single-line -// contents, but we can't represent that: to avoid a diff -// [ { type: "old", line: "foo" }, { type: "new", line: "foo" } ], we -// pass ignoreNewlineAtEof: true. -export function myersDiff(oldContent: string, newContent: string): DiffLine[] { - const theirFormat = diffLines(oldContent, newContent, { - ignoreNewlineAtEof: true, - }) - const ourFormat = theirFormat.flatMap(convertMyersChangeToDiffLines) - - // Combine consecutive old/new pairs that are identical after trimming - for (let i = 0; i < ourFormat.length - 1; i++) { - if ( - ourFormat[i]?.type === "old" && - ourFormat[i + 1]?.type === "new" && - ourFormat[i].line.trim() === ourFormat[i + 1].line.trim() - ) { - ourFormat[i] = { type: "same", line: ourFormat[i].line } - ourFormat.splice(i + 1, 1) - } - } - - // Remove trailing empty old lines - while ( - ourFormat.length > 0 && - ourFormat[ourFormat.length - 1].type === "old" && - ourFormat[ourFormat.length - 1].line === "" - ) { - ourFormat.pop() - } - - return ourFormat -} - -export function myersCharDiff(oldContent: string, newContent: string): DiffChar[] { - // Process the content character by character. - // We will handle newlines separately, - // because diffChars does not have an option to ignore eol newlines. - const theirFormat = diffChars(oldContent, newContent) - - // Track indices as we process the diff. - let oldIndex = 0 - let newIndex = 0 - let oldLineIndex = 0 - let newLineIndex = 0 - let oldCharIndexInLine = 0 - let newCharIndexInLine = 0 - - const result: DiffChar[] = [] - - for (const change of theirFormat) { - // Split the change value by newlines to handle them separately. - if (change.value.includes("\n")) { - const parts = change.value.split(/(\n)/g) // This keeps the newlines as separate entries. - - for (let i = 0; i < parts.length; i++) { - const part = parts[i] - if (part === "") continue - - if (part === "\n") { - // Handle newline. - if (change.added) { - result.push({ - type: "new", - char: part, - newIndex: newIndex, - newLineIndex: newLineIndex, - newCharIndexInLine: newCharIndexInLine, - }) - newIndex += part.length - newLineIndex++ - newCharIndexInLine = 0 // Reset when moving to a new line. - } else if (change.removed) { - result.push({ - type: "old", - char: part, - oldIndex: oldIndex, - oldLineIndex: oldLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - }) - oldIndex += part.length - oldLineIndex++ - oldCharIndexInLine = 0 // Reset when moving to a new line. - } else { - result.push({ - type: "same", - char: part, - oldIndex: oldIndex, - newIndex: newIndex, - oldLineIndex: oldLineIndex, - newLineIndex: newLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - newCharIndexInLine: newCharIndexInLine, - }) - oldIndex += part.length - newIndex += part.length - oldLineIndex++ - newLineIndex++ - oldCharIndexInLine = 0 - newCharIndexInLine = 0 - } - } else { - // Handle regular text. - if (change.added) { - result.push({ - type: "new", - char: part, - newIndex: newIndex, - newLineIndex: newLineIndex, - newCharIndexInLine: newCharIndexInLine, - }) - newIndex += part.length - newCharIndexInLine += part.length - } else if (change.removed) { - result.push({ - type: "old", - char: part, - oldIndex: oldIndex, - oldLineIndex: oldLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - }) - oldIndex += part.length - oldCharIndexInLine += part.length - } else { - result.push({ - type: "same", - char: part, - oldIndex: oldIndex, - newIndex: newIndex, - oldLineIndex: oldLineIndex, - newLineIndex: newLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - newCharIndexInLine: newCharIndexInLine, - }) - oldIndex += part.length - newIndex += part.length - oldCharIndexInLine += part.length - newCharIndexInLine += part.length - } - } - } - } else { - // No newlines, handle as a simple change. - if (change.added) { - result.push({ - type: "new", - char: change.value, - newIndex: newIndex, - newLineIndex: newLineIndex, - newCharIndexInLine: newCharIndexInLine, - }) - newIndex += change.value.length - newCharIndexInLine += change.value.length - } else if (change.removed) { - result.push({ - type: "old", - char: change.value, - oldIndex: oldIndex, - oldLineIndex: oldLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - }) - oldIndex += change.value.length - oldCharIndexInLine += change.value.length - } else { - result.push({ - type: "same", - char: change.value, - oldIndex: oldIndex, - newIndex: newIndex, - oldLineIndex: oldLineIndex, - newLineIndex: newLineIndex, - oldCharIndexInLine: oldCharIndexInLine, - newCharIndexInLine: newCharIndexInLine, - }) - oldIndex += change.value.length - newIndex += change.value.length - oldCharIndexInLine += change.value.length - newCharIndexInLine += change.value.length - } - } - } - - return result -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.test.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.test.ts deleted file mode 100644 index c02e427472a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.test.ts +++ /dev/null @@ -1,317 +0,0 @@ -import fs from "node:fs" -import path from "node:path" - -import { describe, expect, test } from "vitest" - -// @ts-expect-error no typings available -import { changed, diff as myersDiff } from "myers-diff" -import { streamDiff } from "../diff/streamDiff.js" -import { DiffLine, DiffType } from "../index.js" -import { generateLines } from "./util.js" - -// "modification" is an extra type used to represent an "old" + "new" diff line -type MyersDiffTypes = Extract | "modification" - -const UNIFIED_DIFF_SYMBOLS = { - same: "", - new: "+", - old: "-", -} - -async function collectDiffs( - oldLines: string[], - newLines: string[], -): Promise<{ streamDiffs: DiffLine[]; myersDiffs: any }> { - const streamDiffs: DiffLine[] = [] - - for await (const diffLine of streamDiff(oldLines, generateLines(newLines))) { - streamDiffs.push(diffLine) - } - - const myersDiffs = myersDiff(oldLines.join("\n"), newLines.join("\n")) - - return { streamDiffs, myersDiffs } -} - -function getMyersDiffType(diff: any): MyersDiffTypes | undefined { - if (changed(diff.rhs) && !changed(diff.lhs)) { - return "new" - } - - if (!changed(diff.rhs) && changed(diff.lhs)) { - return "old" - } - - if (changed(diff.rhs) && changed(diff.lhs)) { - return "modification" - } - - return undefined -} - -function displayDiff(diff: DiffLine[]) { - return diff.map(({ type, line }) => `${UNIFIED_DIFF_SYMBOLS[type]} ${line}`).join("\n") -} - -async function expectDiff(file: string) { - const testFilePath = path.join(__dirname, "test-examples", file + ".diff") - const testFileContents = fs.readFileSync(testFilePath, "utf-8") - const normalized = testFileContents.replace(/\r\n/g, "\n") - - const [oldText, newText, expectedDiff] = normalized.split("\n---\n").map((s) => s.replace(/^\n+/, "").trimEnd()) - const oldLines = oldText.split("\n") - const newLines = newText.split("\n") - const { streamDiffs } = await collectDiffs(oldLines, newLines) - const displayedDiff = displayDiff(streamDiffs) - - if (!expectedDiff || expectedDiff.trim() === "") { - console.log("Expected diff was empty. Writing computed diff to the test file") - // Persist with LF to keep fixtures stable cross-platform - fs.writeFileSync(testFilePath, `${oldText}\n\n---\n\n${newText}\n\n---\n\n${displayedDiff}`) - - throw new Error("Expected diff is empty") - } - - expect(displayedDiff).toEqual(expectedDiff) -} - -// We use a longer `)` string here to not get -// caught by the fuzzy matcher -describe("streamDiff(", () => { - test("no changes", async () => { - const oldLines = ["first item", "second arg", "third param"] - const newLines = ["first item", "second arg", "third param"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "same", line: "second arg" }, - { type: "same", line: "third param" }, - ]) - - expect(myersDiffs).toEqual([]) - }) - - test("add new line", async () => { - const oldLines = ["first item", "second arg"] - const newLines = ["first item", "second arg", "third param"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "same", line: "second arg" }, - { type: "new", line: "third param" }, - ]) - - expect(myersDiffs.length).toEqual(1) - expect(getMyersDiffType(myersDiffs[0])).toBe("new") - }) - - test("remove line", async () => { - const oldLines = ["first item", "second arg", "third param"] - const newLines = ["first item", "third param"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "old", line: "second arg" }, - { type: "same", line: "third param" }, - ]) - - expect(myersDiffs.length).toEqual(1) - expect(getMyersDiffType(myersDiffs[0])).toBe("old") - }) - - test("modify line", async () => { - const oldLines = ["first item", "second arg", "third param"] - const newLines = ["first item", "modified second arg", "third param"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "old", line: "second arg" }, - { type: "new", line: "modified second arg" }, - { type: "same", line: "third param" }, - ]) - - expect(myersDiffs.length).toEqual(1) - expect(getMyersDiffType(myersDiffs[0])).toBe("modification") - }) - - test("add multiple lines", async () => { - const oldLines = ["first item", "fourth val"] - const newLines = ["first item", "second arg", "third param", "fourth val"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "new", line: "second arg" }, - { type: "new", line: "third param" }, - { type: "same", line: "fourth val" }, - ]) - - // Multi-line addition - expect(myersDiffs[0].rhs.add).toEqual(2) - expect(getMyersDiffType(myersDiffs[0])).toBe("new") - }) - - test("remove multiple lines", async () => { - const oldLines = ["first item", "second arg", "third param", "fourth val"] - const newLines = ["first item", "fourth val"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item" }, - { type: "old", line: "second arg" }, - { type: "old", line: "third param" }, - { type: "same", line: "fourth val" }, - ]) - - // Multi-line deletion - expect(myersDiffs[0].lhs.del).toEqual(2) - expect(getMyersDiffType(myersDiffs[0])).toBe("old") - }) - - test("empty old lines", async () => { - const oldLines: string[] = [] - const newLines = ["first item", "second arg"] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "new", line: "first item" }, - { type: "new", line: "second arg" }, - ]) - - // Multi-line addition - expect(myersDiffs[0].rhs.add).toEqual(2) - expect(getMyersDiffType(myersDiffs[0])).toBe("new") - }) - - test("empty new lines", async () => { - const oldLines = ["first item", "second arg"] - const newLines: string[] = [] - - const { streamDiffs, myersDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "old", line: "first item" }, - { type: "old", line: "second arg" }, - ]) - - // Multi-line deletion - expect(myersDiffs[0].lhs.del).toEqual(2) - expect(getMyersDiffType(myersDiffs[0])).toBe("old") - }) - - test("tabs vs. spaces differences are ignored", async () => { - await expectDiff("fastapi-tabs-vs-spaces.py") - }) - - test("trailing whitespaces should match ", async () => { - const oldLines = ["first item ", "second arg ", "third param "] - - const newLines = ["first item", "second arg", "third param "] - - const { streamDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "first item " }, - { type: "same", line: "second arg " }, - { type: "same", line: "third param " }, - ]) - }) - - //indentation and whitespace handling - test.each([false, true])( - "ignores indentation changes for sufficiently long lines (trailingWhitespace: %s)", - async (trailingWhitespace) => { - let oldLines = [" short", " middle", " a long enough line", " short2", "indented line", "final line"] - - const newLines = ["short", "middle", "a long enough line", "short2", " indented line", "final line"] - - if (trailingWhitespace) { - oldLines = oldLines.map((line) => line + " ") - } - - const { streamDiffs } = await collectDiffs(oldLines, newLines) - const expected = trailingWhitespace - ? [ - { type: "old", line: " short " }, - { type: "new", line: "short" }, - { type: "old", line: " middle " }, - { type: "new", line: "middle" }, - { type: "same", line: " a long enough line " }, - { type: "same", line: " short2 " }, - { type: "same", line: "indented line " }, - { type: "same", line: "final line " }, - ] - : [ - { type: "old", line: " short" }, - { type: "new", line: "short" }, - { type: "old", line: " middle" }, - { type: "new", line: "middle" }, - { type: "same", line: " a long enough line" }, - { type: "same", line: " short2" }, - { type: "same", line: "indented line" }, - { type: "same", line: "final line" }, - ] - - expect(streamDiffs).toEqual(expected) - }, - ) - - test("preserves original lines for minor reindentation in simple block", async () => { - const oldLines = ["if (checkValueOf(x)) {", " doSomethingWith(x);", "}"] - const newLines = ["if (checkValueOf(x)) {", " doSomethingWith(x);", "}"] - - const { streamDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "if (checkValueOf(x)) {" }, - { type: "same", line: " doSomethingWith(x);" }, - { type: "same", line: "}" }, - ]) - }) - - test("uses new lines for nested reindentation changes", async () => { - const oldLines = ["if (checkValueOf(x)) {", " doSomethingWith(x);", "}"] - const newLines = [ - "if (checkValueOf(x)) {", - " if (reallyCheckValueOf(x)) {", - " doSomethingElseWith(x);", - " }", - "}", - ] - - const { streamDiffs } = await collectDiffs(oldLines, newLines) - - expect(streamDiffs).toEqual([ - { type: "same", line: "if (checkValueOf(x)) {" }, - { type: "new", line: " if (reallyCheckValueOf(x)) {" }, - { type: "old", line: " doSomethingWith(x);" }, - { type: "new", line: " doSomethingElseWith(x);" }, - { type: "old", line: "}" }, - { type: "new", line: " }" }, - { type: "new", line: "}" }, - ]) - }) - - test("FastAPI example", async () => { - await expectDiff("fastapi.py") - }) - - test("FastAPI comments", async () => { - await expectDiff("add-comments.py") - }) - - test("Mock LLM example", async () => { - await expectDiff("mock-llm.ts") - }) -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.ts deleted file mode 100644 index 8c3407de13c..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/streamDiff.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { DiffLine, DiffType } from "../index.js" - -import { LineStream, matchLine } from "./util.js" - -/** - * https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/ - * Invariants: - * - new + same = newLines.length - * - old + same = oldLinesCopy.length - * ^ (above two guarantee that all lines get represented) - * - Lines are always output in order, at least among old and new separately - * - Old lines in a hunk are always output before the new lines - */ -export async function* streamDiff(oldLines: string[], newLines: LineStream): AsyncGenerator { - const oldLinesCopy = [...oldLines] - - // If one indentation mistake is made, others are likely. So we are more permissive about matching - let seenIndentationMistake = false - - let newLineResult = await newLines.next() - - while (oldLinesCopy.length > 0 && !newLineResult.done) { - const { matchIndex, isPerfectMatch, newLine } = matchLine(newLineResult.value, oldLinesCopy, seenIndentationMistake) - - if (!seenIndentationMistake && newLineResult.value !== newLine) { - seenIndentationMistake = true - } - - let type: DiffType - - const isNewLine = matchIndex === -1 - - if (isNewLine) { - type = "new" - } else { - // Insert all deleted lines before match - for (let i = 0; i < matchIndex; i++) { - yield { type: "old", line: oldLinesCopy.shift()! } - } - type = isPerfectMatch ? "same" : "old" - } - - switch (type) { - case "new": - yield { type, line: newLine } - break - - case "same": - yield { type, line: oldLinesCopy.shift()! } - break - - case "old": - yield { type, line: oldLinesCopy.shift()! } - yield { type: "new", line: newLine } - break - - default: - console.error(`Error streaming diff, unrecognized diff type: ${type}`) - } - newLineResult = await newLines.next() - } - - // Once at the edge, only one choice - if (newLineResult.done && oldLinesCopy.length > 0) { - for (const oldLine of oldLinesCopy) { - yield { type: "old", line: oldLine } - } - } - - if (!newLineResult.done && oldLinesCopy.length === 0) { - yield { type: "new", line: newLineResult.value } - for await (const newLine of newLines) { - yield { type: "new", line: newLine } - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/util.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/util.ts index 90a5ced95a4..d5da1720c3c 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/util.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/diff/util.ts @@ -1,94 +1,8 @@ -import { distance } from "fastest-levenshtein" - -import { ChatMessage } from "../index.js" +import type { ChatMessage } from "../index.js" import { renderChatMessage } from "../util/messageContent.js" export type LineStream = AsyncGenerator -type MatchLineResult = { - /** - * -1 if it's a new line, otherwise the index of the first match - * in the old lines. - */ - matchIndex: number - isPerfectMatch: boolean - newLine: string -} - -function linesMatchPerfectly(lineA: string, lineB: string): boolean { - return lineA === lineB && lineA !== "" -} - -const END_BRACKETS = ["}", "});", "})"] - -function linesMatch(lineA: string, lineB: string, linesBetween = 0): boolean { - // Require a perfect (without padding) match for these lines - // Otherwise they are edit distance 1 from empty lines and other single char lines (e.g. each other) - if (["}", "*", "});", "})"].includes(lineA.trim())) { - return lineA.trim() === lineB.trim() - } - - const d = distance(lineA, lineB) - - return ( - // Should be more unlikely for lines to fuzzy match if they are further away - (d / Math.max(lineA.length, lineB.length) <= Math.max(0, 0.48 - linesBetween * 0.06) || - lineA.trim() === lineB.trim()) && - lineA.trim() !== "" - ) -} - -/** - * Used to find a match for a new line in an array of old lines. - * - * Return the index of the first match and whether it is a perfect match - * Also return a version of the line with correct indentation if needs fixing - */ -export function matchLine(newLine: string, oldLines: string[], permissiveAboutIndentation = false): MatchLineResult { - // Only match empty lines if it's the next one: - if (newLine.trim() === "" && oldLines[0]?.trim() === "") { - return { - matchIndex: 0, - isPerfectMatch: true, - newLine: newLine.trim(), - } - } - - const isEndBracket = END_BRACKETS.includes(newLine.trim()) - - for (let i = 0; i < oldLines.length; i++) { - // trims trailing whitespaces from the lines before comparison - //this ensures trailing spaces don't affect matching. - const oldLineTrimmed = oldLines[i].trimEnd() - const newLineTrimmed = newLine.trimEnd() - - // Don't match end bracket lines if too far away - if (i > 4 && isEndBracket) { - return { matchIndex: -1, isPerfectMatch: false, newLine } - } - - if (linesMatchPerfectly(newLineTrimmed, oldLineTrimmed)) { - return { matchIndex: i, isPerfectMatch: true, newLine } - } - if (linesMatch(newLineTrimmed, oldLineTrimmed, i)) { - // This is a way to fix indentation, but only for sufficiently long lines to avoid matching whitespace or short lines - if ( - newLineTrimmed.trimStart() === oldLineTrimmed.trimStart() && - (permissiveAboutIndentation || newLine.trim().length > 8) - ) { - return { - matchIndex: i, - isPerfectMatch: true, - newLine: oldLines[i], - } - } - return { matchIndex: i, isPerfectMatch: false, newLine } - } - } - - return { matchIndex: -1, isPerfectMatch: false, newLine } -} - /** * Convert a stream of arbitrary chunks to a stream of lines */ @@ -97,7 +11,6 @@ export async function* streamLines( log: boolean = false, ): LineStream { const allLines = [] - let buffer = "" try { @@ -110,11 +23,6 @@ export async function* streamLines( yield line allLines.push(line) } - - // if (buffer === "" && chunk.endsWith("\n")) { - // yield ""; - // allLines.push(""); - // } } if (buffer.length > 0) { yield buffer @@ -130,6 +38,5 @@ export async function* streamLines( export async function* generateLines(lines: T[]): AsyncGenerator { for (const line of lines) { yield line - // await new Promise((resolve, reject) => setTimeout(() => resolve(null), 50)); } } diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/fetch/stream.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/fetch/stream.ts deleted file mode 100644 index 74cace737ba..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/fetch/stream.ts +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Parses a single line from an SSE (Server-Sent Events) stream. - */ -function parseSseLine(line: string): { done: boolean; data: unknown } { - if (line.startsWith("data:[DONE]") || line.startsWith("data: [DONE]")) { - return { done: true, data: undefined } - } - if (line.startsWith("data:")) { - const jsonStr = line.slice(5).trim() - try { - return { done: false, data: JSON.parse(jsonStr) } - } catch { - return { done: false, data: undefined } - } - } - if (line.startsWith(": ping")) { - return { done: true, data: undefined } - } - return { done: false, data: undefined } -} - -/** - * Streams a Response body as UTF-8 text chunks. - * - * Modern implementation using native ReadableStream and TextDecoderStream APIs. - * Requires Node.js 18+ or modern browsers. - */ -export async function* streamResponse(response: Response): AsyncGenerator { - // Handle client-side cancellation - if (response.status === 499) { - return - } - - // Check for error responses - if (response.status !== 200) { - throw new Error(await response.text()) - } - - if (!response.body) { - throw new Error("No response body returned.") - } - - let chunks = 0 - - try { - // Modern API: Use TextDecoderStream to decode the response body - const textStream = response.body.pipeThrough(new TextDecoderStream("utf-8")) - const reader = textStream.getReader() - - try { - while (true) { - const { done, value } = await reader.read() - if (done) break - yield value - chunks++ - } - } finally { - reader.releaseLock() - } - } catch (e) { - if (e instanceof Error) { - // Handle graceful cancellation - if (e.name.startsWith("AbortError")) { - return - } - - // Handle premature close errors - if (e.message.toLowerCase().includes("premature close")) { - if (chunks === 0) { - throw new Error("Stream was closed before any data was received. Try again. (Premature Close)") - } else { - throw new Error("The response was cancelled mid-stream. Try again. (Premature Close).") - } - } - } - throw e - } -} -/** - * Streams Server-Sent Events (SSE) from a Response. - * Parses SSE format and yields parsed data objects. - */ -export async function* streamSse(response: Response): AsyncGenerator { - let buffer = "" - - for await (const value of streamResponse(response)) { - buffer += value - - let position: number - while ((position = buffer.indexOf("\n")) >= 0) { - const line = buffer.slice(0, position) - buffer = buffer.slice(position + 1) - - const { done, data } = parseSseLine(line) - if (done) { - break - } - if (data) { - yield data - } - } - } - - // Process any remaining buffered content - if (buffer.length > 0) { - const { done, data } = parseSseLine(buffer) - if (!done && data) { - yield data - } - } -} - -/** - * Streams newline-delimited JSON from a Response. - * Each line should be a complete JSON object. - */ -export async function* streamJSON(response: Response): AsyncGenerator { - let buffer = "" - - for await (const value of streamResponse(response)) { - buffer += value - - let position: number - while ((position = buffer.indexOf("\n")) >= 0) { - const line = buffer.slice(0, position) - buffer = buffer.slice(position + 1) - - if (line.trim()) { - try { - const data = JSON.parse(line) - yield data - } catch { - throw new Error(`Malformed JSON sent from server: ${line}`) - } - } - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/constants.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/constants.ts deleted file mode 100644 index b0e2a8528ad..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -const DEFAULT_MAX_TOKENS = 4096 -const DEFAULT_CONTEXT_LENGTH = 32_768 -const DEFAULT_PRUNING_LENGTH = 128000 - -export enum NEXT_EDIT_MODELS { - MERCURY_CODER = "mercury-coder", - INSTINCT = "instinct", -} - -export { DEFAULT_CONTEXT_LENGTH, DEFAULT_MAX_TOKENS, DEFAULT_PRUNING_LENGTH } diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/countTokens.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/countTokens.ts index f37012aaa3a..2bc58aad0de 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/countTokens.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/countTokens.ts @@ -1,8 +1,7 @@ import { Tiktoken, encodingForModel as _encodingForModel } from "js-tiktoken" -import { ChatMessage, CompiledMessagesResult, MessageContent } from "../index.js" -import { addSpaceToAnyEmptyMessages, chatMessageIsEmpty } from "./messages.js" -import { DEFAULT_PRUNING_LENGTH } from "./constants.js" +import type { MessageContent } from "../index.js" import { llamaTokenizer } from "./llamaTokenizer.js" + interface Encoding { encode: Tiktoken["encode"] decode: Tiktoken["decode"] @@ -47,7 +46,7 @@ export function encodingForModel(modelName: string): Encoding { return (gptEncoding ??= _encodingForModel("gpt-4")) } -function countTokens( +export function countTokens( content: MessageContent, // defaults to llama2 because the tokenizer tends to produce more tokens modelName = "llama2", @@ -57,58 +56,21 @@ function countTokens( return content.reduce((acc, part) => { return acc + encoding.encode(part.text ?? "", "all", []).length }, 0) - } else { - return encoding.encode(content ?? "", "all", []).length } + return encoding.encode(content ?? "", "all", []).length } -function countChatMessageTokens(modelName: string, chatMessage: ChatMessage): number { - // Doing simpler, safer version of what is here: - // https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb - // every message follows <|im_start|>{role/name}\n{content}<|end|>\n - const BASE_TOKENS = 4 - let tokens = BASE_TOKENS - - if (chatMessage.content) { - tokens += countTokens(chatMessage.content, modelName) - } - - return tokens -} - -/** - * Extracts and validates the user message from the end of a message array. - * - * @param messages - Array of chat messages (will be modified by popping messages) - * @returns Array of messages that form the tool sequence - */ -function extractToolSequence(messages: ChatMessage[]): ChatMessage[] { - const lastMsg = messages.pop() - if (!lastMsg || lastMsg.role !== "user") { - throw new Error("Error parsing chat history: no user message found") - } - - const toolSequence: ChatMessage[] = [lastMsg] - - return toolSequence -} - -function pruneLinesFromTop(prompt: string, maxTokens: number, modelName: string): string { +export function pruneLinesFromTop(prompt: string, maxTokens: number, modelName: string): string { const lines = prompt.split("\n") - // Preprocess tokens for all lines and cache them. const lineTokens = lines.map((line) => countTokens(line, modelName)) let totalTokens = lineTokens.reduce((sum, tokens) => sum + tokens, 0) let start = 0 const currentLines = lines.length - // Calculate initial token count including newlines - totalTokens += Math.max(0, currentLines - 1) // Add tokens for joining newlines + totalTokens += Math.max(0, currentLines - 1) - // Using indexes instead of array modifications. - // Remove lines from the top until the token count is within the limit. while (totalTokens > maxTokens && start < currentLines) { - totalTokens -= lineTokens[start] - // Decrement token count for the removed line and its preceding/joining newline (if not the last line) + totalTokens -= lineTokens[start] ?? 0 if (currentLines - start > 1) { totalTokens-- } @@ -118,21 +80,17 @@ function pruneLinesFromTop(prompt: string, maxTokens: number, modelName: string) return lines.slice(start).join("\n") } -function pruneLinesFromBottom(prompt: string, maxTokens: number, modelName: string): string { +export function pruneLinesFromBottom(prompt: string, maxTokens: number, modelName: string): string { const lines = prompt.split("\n") const lineTokens = lines.map((line) => countTokens(line, modelName)) let totalTokens = lineTokens.reduce((sum, tokens) => sum + tokens, 0) let end = lines.length - // Calculate initial token count including newlines - totalTokens += Math.max(0, end - 1) // Add tokens for joining newlines + totalTokens += Math.max(0, end - 1) - // Reverse traversal to avoid array modification - // Remove lines from the bottom until the token count is within the limit. while (totalTokens > maxTokens && end > 0) { end-- - totalTokens -= lineTokens[end] - // Decrement token count for the removed line and its following/joining newline (if not the first line) + totalTokens -= lineTokens[end] ?? 0 if (end > 0) { totalTokens-- } @@ -141,180 +99,11 @@ function pruneLinesFromBottom(prompt: string, maxTokens: number, modelName: stri return lines.slice(0, end).join("\n") } -function pruneStringFromBottom(modelName: string, maxTokens: number, prompt: string): string { +export function pruneStringFromBottom(modelName: string, maxTokens: number, prompt: string): string { const encoding = encodingForModel(modelName) - const tokens = encoding.encode(prompt, "all", []) if (tokens.length <= maxTokens) { return prompt } - return encoding.decode(tokens.slice(0, maxTokens)) } - -function pruneStringFromTop(modelName: string, maxTokens: number, prompt: string): string { - const encoding = encodingForModel(modelName) - - const tokens = encoding.encode(prompt, "all", []) - if (tokens.length <= maxTokens) { - return prompt - } - - return encoding.decode(tokens.slice(tokens.length - maxTokens)) -} - -const MAX_TOKEN_SAFETY_BUFFER = 1000 -const TOKEN_SAFETY_PROPORTION = 0.02 -export function getTokenCountingBufferSafety(contextLength: number) { - return Math.min(MAX_TOKEN_SAFETY_BUFFER, contextLength * TOKEN_SAFETY_PROPORTION) -} - -const MIN_RESPONSE_TOKENS = 1000 - -function pruneRawPromptFromTop( - modelName: string, - contextLength: number, - prompt: string, - tokensForCompletion: number, -): string { - const maxTokens = contextLength - tokensForCompletion - getTokenCountingBufferSafety(contextLength) - return pruneStringFromTop(modelName, maxTokens, prompt) -} - -/** - * Reconciles chat messages with available context length by intelligently pruning older messages - * while preserving critical conversation elements. - * - * Core Guidelines: - * - Always preserve the last user/tool message sequence (including any associated assistant message with tool calls) - * - Always preserve the system message and tools - * - Never allow orphaned tool responses without their corresponding tool calls - * - Remove older messages first when pruning is necessary - * - Maintain conversation coherence by flattening adjacent similar messages - * - * Process: - * 1. Handle image content conversion for models that don't support images - * 2. Extract and preserve system message - * 3. Filter out empty messages and trailing non-user/tool messages - * 4. Extract the complete tool sequence from the end (user message or assistant + tool responses) - * 5. Calculate token requirements for non-negotiable elements (system, tools, last sequence) - * 6. Prune older messages until within available token budget - * 7. Reassemble with proper ordering and flatten adjacent similar messages - * - * @param params - Configuration object containing: - * - modelName: LLM model name for token counting - * - msgs: Array of chat messages to process - * - contextLength: Maximum context length supported by the model - * - maxTokens: Maximum tokens to reserve for the response - * @returns Processed array of chat messages that fit within context constraints - * @throws Error if non-negotiable elements exceed available context - */ -function compileChatMessages({ - modelName, - msgs, - knownContextLength, - maxTokens, -}: { - modelName: string - msgs: ChatMessage[] - knownContextLength: number | undefined - maxTokens: number -}): CompiledMessagesResult { - let didPrune = false - - let msgsCopy: ChatMessage[] = msgs.map((m) => ({ ...m })) - - // Extract system message - const systemMsg = msgsCopy.find((msg) => msg.role === "system") - msgsCopy = msgsCopy.filter((msg) => msg.role !== "system") - - // Remove any empty messages or non-user/tool trailing messages - msgsCopy = msgsCopy.filter((msg) => !chatMessageIsEmpty(msg)) - - msgsCopy = addSpaceToAnyEmptyMessages(msgsCopy) - - // Extract the tool sequence from the end of the message array - const toolSequence = extractToolSequence(msgsCopy) - - // Count tokens for all messages in the tool sequence - let lastMessagesTokens = 0 - for (const msg of toolSequence) { - lastMessagesTokens += countChatMessageTokens(modelName, msg) - } - - // System message - let systemMsgTokens = 0 - if (systemMsg) { - systemMsgTokens = countChatMessageTokens(modelName, systemMsg) - } - - const contextLength = knownContextLength ?? DEFAULT_PRUNING_LENGTH - const countingSafetyBuffer = getTokenCountingBufferSafety(contextLength) - const minOutputTokens = Math.min(MIN_RESPONSE_TOKENS, maxTokens) - - let inputTokensAvailable = contextLength - - // Leave space for output/safety - inputTokensAvailable -= countingSafetyBuffer - inputTokensAvailable -= minOutputTokens - - // Non-negotiable messages - inputTokensAvailable -= systemMsgTokens - inputTokensAvailable -= lastMessagesTokens - - // Make sure there's enough context for the non-excludable items - if (knownContextLength !== undefined && inputTokensAvailable < 0) { - throw new Error( - `Not enough context available to include the system message, last user message, and tools. - There must be at least ${minOutputTokens} tokens remaining for output. - Request had the following token counts: - - contextLength: ${knownContextLength} - - counting safety buffer: ${countingSafetyBuffer} - - system message: ~${systemMsgTokens} - - max output tokens: ${maxTokens}`, - ) - } - - // Now remove messages till we're under the limit - let currentTotal = 0 - const historyWithTokens = msgsCopy.map((message) => { - const tokens = countChatMessageTokens(modelName, message) - currentTotal += tokens - return { - ...message, - tokens, - } - }) - - while (historyWithTokens.length > 0 && currentTotal > inputTokensAvailable) { - const message = historyWithTokens.shift()! - currentTotal -= message.tokens - didPrune = true - } - - // Now reassemble - const reassembled: ChatMessage[] = [] - if (systemMsg) { - reassembled.push(systemMsg) - } - reassembled.push(...historyWithTokens.map(({ tokens: _tokens, ...rest }) => rest)) - reassembled.push(...toolSequence) - - const inputTokens = currentTotal + systemMsgTokens + lastMessagesTokens - const availableTokens = contextLength - countingSafetyBuffer - minOutputTokens - const contextPercentage = inputTokens / availableTokens - return { - compiledChatMessages: reassembled, - didPrune, - contextPercentage, - } -} - -export { - compileChatMessages, - countTokens, - pruneLinesFromBottom, - pruneLinesFromTop, - pruneRawPromptFromTop, - pruneStringFromBottom, -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/index.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/index.ts deleted file mode 100644 index 6d6fef85ba6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/index.ts +++ /dev/null @@ -1,664 +0,0 @@ -import { findLlmInfo } from "./model-info" -import { ChatCompletionCreateParams } from "openai/resources/index" - -import { - ChatMessage, - Chunk, - CompletionOptions, - ILLM, - LLMFullCompletionOptions, - LLMOptions, - MessageOption, - ModelCapability, - PromptLog, - TabAutocompleteOptions, - Usage, -} from "../index.js" -import type { CacheBehavior, ILLMInteractionLog, ILLMLogger } from "../index.js" -import { mergeJson } from "../util/merge.js" -import { renderChatMessage } from "../util/messageContent.js" -import { TokensBatchingService } from "../util/TokensBatchingService.js" - -import { DEFAULT_CONTEXT_LENGTH, DEFAULT_MAX_TOKENS } from "./constants.js" -import { compileChatMessages, countTokens, pruneRawPromptFromTop } from "./countTokens.js" -import { - fromChatCompletionChunk, - fromChatResponse, - LlmApiRequestType, - toChatBody, - toCompleteBody, - toFimBody, -} from "./openaiTypeConverters.js" - -type InteractionStatus = "in_progress" | "success" | "error" | "cancelled" - -export abstract class BaseLLM implements ILLM { - static providerName: string - - get providerName(): string { - return (this.constructor as typeof BaseLLM).providerName - } - - /** - * This exists because for the continue-proxy, sometimes we want to get the value of the underlying provider that is used on the server - * For example, the underlying provider should always be sent with dev data - */ - get underlyingProviderName(): string { - return this.providerName - } - - autocompleteOptions?: Partial - - supportsFim(): boolean { - return false - } - - supportsCompletions(): boolean { - if (["openai", "azure"].includes(this.providerName)) { - if ( - this.apiBase?.includes("api.groq.com") || - this.apiBase?.includes("api.mistral.ai") || - this.apiBase?.includes(":1337") || - this.apiBase?.includes("integrate.api.nvidia.com") || - this._llmOptions.useLegacyCompletionsEndpoint?.valueOf() === false - ) { - // Jan + Groq + Mistral don't support completions : ( - // Seems to be going out of style... - return false - } - } - if (["groq", "mistral", "deepseek"].includes(this.providerName)) { - return false - } - return true - } - - uniqueId: string - model: string - - title?: string - _contextLength: number | undefined - maxStopWords?: number | undefined - completionOptions: CompletionOptions - templateMessages?: (messages: ChatMessage[]) => string - logger?: ILLMLogger - llmRequestHook?: (model: string, prompt: string) => any - apiKey?: string - apiBase?: string - cacheBehavior?: CacheBehavior - capabilities?: ModelCapability - - lastRequestId: string | undefined - - private _llmOptions: LLMOptions - - protected openaiAdapter?: any - - constructor(_options: LLMOptions) { - this._llmOptions = _options - this.lastRequestId = undefined - - // Set default options - const options = { - title: (this.constructor as typeof BaseLLM).providerName, - ..._options, - } - - this.model = options.model - // Use ../llm-info package to autodetect certain parameters - const modelSearchString = - this.providerName === "continue-proxy" ? this.model?.split("/").pop() || this.model : this.model - const llmInfo = findLlmInfo(modelSearchString, this.underlyingProviderName) - - this.title = options.title - this.uniqueId = options.uniqueId ?? "None" - this._contextLength = options.contextLength ?? llmInfo?.contextLength - this.maxStopWords = options.maxStopWords ?? this.maxStopWords - this.completionOptions = { - ...options.completionOptions, - model: options.model || "gpt-4", - maxTokens: - options.completionOptions?.maxTokens ?? - (llmInfo?.maxCompletionTokens - ? Math.min( - llmInfo.maxCompletionTokens, - // Even if the model has a large maxTokens, we don't want to use that every time, - // because it takes away from the context length - this.contextLength / 4, - ) - : DEFAULT_MAX_TOKENS), - } - - this.apiKey = options.apiKey - this.apiBase = options.apiBase - if (this.apiBase && !this.apiBase.endsWith("/")) { - this.apiBase = `${this.apiBase}/` - } - this.capabilities = options.capabilities - - this.autocompleteOptions = options.autocompleteOptions - } - - get contextLength() { - return this._contextLength ?? DEFAULT_CONTEXT_LENGTH - } - - private _templatePromptLikeMessages(prompt: string): string { - if (!this.templateMessages) { - return prompt - } - - // NOTE system message no longer supported here - - const msgs: ChatMessage[] = [{ role: "user", content: prompt }] - - return this.templateMessages(msgs) - } - - private _logEnd( - model: string, - prompt: string, - completion: string, - interaction: ILLMInteractionLog | undefined, - usage: Usage | undefined, - error?: any, - ): InteractionStatus { - const promptTokens = this.countTokens(prompt) - const generatedTokens = this.countTokens(completion) - - TokensBatchingService.getInstance().addTokens(model, this.providerName, promptTokens, generatedTokens) - - console.log("tokensGenerated", { - model: model, - provider: this.underlyingProviderName, - promptTokens: promptTokens, - generatedTokens: generatedTokens, - }) - - if (typeof error === "undefined") { - interaction?.logItem({ - kind: "success", - promptTokens, - generatedTokens, - usage, - }) - return "success" - } else { - if (error === "cancel" || error?.name?.includes("AbortError")) { - interaction?.logItem({ - kind: "cancel", - promptTokens, - generatedTokens, - usage, - }) - return "cancelled" - } else { - console.log(error) - interaction?.logItem({ - kind: "error", - name: error.name, - message: error.message, - promptTokens, - generatedTokens, - usage, - }) - return "error" - } - } - } - - private parseCompletionOptions(options: LLMFullCompletionOptions) { - const log = options.log ?? true - const raw = options.raw ?? false - options.log = undefined - - const completionOptions: CompletionOptions = mergeJson(this.completionOptions, options) - - return { completionOptions, logEnabled: log, raw } - } - - private formatChatMessages(messages: ChatMessage[]): string { - const msgsCopy = messages ? messages.map((msg) => ({ ...msg })) : [] - let formatted = "" - for (const msg of msgsCopy) { - formatted += this._formatChatMessage(msg) - } - return formatted - } - - private _formatChatMessage(msg: ChatMessage): string { - let contentToShow = renderChatMessage(msg) - - return `<${msg.role}>\n${contentToShow}\n\n` - } - - protected async *_streamFim( - _prefix: string, - _suffix: string, - _signal: AbortSignal, - _options: CompletionOptions, - ): AsyncGenerator { - throw new Error("Not implemented") - } - - protected useOpenAIAdapterFor: (LlmApiRequestType | "*")[] = [] - - private shouldUseOpenAIAdapter(requestType: LlmApiRequestType) { - return this.useOpenAIAdapterFor.includes(requestType) || this.useOpenAIAdapterFor.includes("*") - } - - async *streamFim( - prefix: string, - suffix: string, - signal: AbortSignal, - options: LLMFullCompletionOptions = {}, - ): AsyncGenerator { - this.lastRequestId = undefined - const { completionOptions, logEnabled } = this.parseCompletionOptions(options) - const interaction = logEnabled ? this.logger?.createInteractionLog() : undefined - let status: InteractionStatus = "in_progress" - - const fimLog = `Prefix: ${prefix}\nSuffix: ${suffix}` - if (logEnabled) { - interaction?.logItem({ - kind: "startFim", - prefix, - suffix, - options: completionOptions, - provider: this.providerName, - }) - if (this.llmRequestHook) { - this.llmRequestHook(completionOptions.model, fimLog) - } - } - - let completion = "" - try { - if (this.shouldUseOpenAIAdapter("streamFim") && this.openaiAdapter) { - const stream = this.openaiAdapter.fimStream(toFimBody(prefix, suffix, completionOptions), signal) - for await (const chunk of stream) { - if (!this.lastRequestId && typeof (chunk as any).id === "string") { - this.lastRequestId = (chunk as any).id - } - const result = fromChatCompletionChunk(chunk) - if (result) { - const content = renderChatMessage(result) - const formattedContent = this._formatChatMessage(result) - interaction?.logItem({ - kind: "chunk", - chunk: formattedContent, - }) - - completion += formattedContent - yield content - } - } - } else { - for await (const chunk of this._streamFim(prefix, suffix, signal, completionOptions)) { - interaction?.logItem({ - kind: "chunk", - chunk, - }) - - completion += chunk - yield chunk - } - } - - status = this._logEnd(completionOptions.model, fimLog, completion, interaction, undefined) - } catch (e) { - console.error(e as Error, { - context: "llm_stream_fim", - model: completionOptions.model, - provider: this.providerName, - useOpenAIAdapter: this.shouldUseOpenAIAdapter("streamFim"), - }) - - status = this._logEnd(completionOptions.model, fimLog, completion, interaction, undefined, e) - throw e - } finally { - if (status === "in_progress") { - this._logEnd(completionOptions.model, fimLog, completion, interaction, undefined, "cancel") - } - } - - return { - prompt: fimLog, - completion, - completionOptions, - } - } - - async *streamComplete(_prompt: string, signal: AbortSignal, options: LLMFullCompletionOptions = {}) { - this.lastRequestId = undefined - const { completionOptions, logEnabled, raw } = this.parseCompletionOptions(options) - const interaction = logEnabled ? this.logger?.createInteractionLog() : undefined - let status: InteractionStatus = "in_progress" - - let prompt = pruneRawPromptFromTop( - completionOptions.model, - this.contextLength, - _prompt, - completionOptions.maxTokens ?? DEFAULT_MAX_TOKENS, - ) - - if (!raw) { - prompt = this._templatePromptLikeMessages(prompt) - } - - if (logEnabled) { - interaction?.logItem({ - kind: "startComplete", - prompt, - options: completionOptions, - provider: this.providerName, - }) - if (this.llmRequestHook) { - this.llmRequestHook(completionOptions.model, prompt) - } - } - - let completion = "" - try { - if (this.shouldUseOpenAIAdapter("streamComplete") && this.openaiAdapter) { - if (completionOptions.stream === false) { - // Stream false - const response = await this.openaiAdapter.completionNonStream( - { ...toCompleteBody(prompt, completionOptions), stream: false }, - signal, - ) - this.lastRequestId = response.id ?? this.lastRequestId - completion = response.choices[0]?.text ?? "" - yield completion - } else { - // Stream true - for await (const chunk of this.openaiAdapter.completionStream( - { - ...toCompleteBody(prompt, completionOptions), - stream: true, - }, - signal, - )) { - if (!this.lastRequestId && typeof (chunk as any).id === "string") { - this.lastRequestId = (chunk as any).id - } - const content = chunk.choices[0]?.text ?? "" - completion += content - interaction?.logItem({ - kind: "chunk", - chunk: content, - }) - yield content - } - } - } else { - for await (const chunk of this._streamComplete(prompt, signal, completionOptions)) { - completion += chunk - interaction?.logItem({ - kind: "chunk", - chunk, - }) - yield chunk - } - } - status = this._logEnd(completionOptions.model, prompt, completion, interaction, undefined) - } catch (e) { - console.error(e as Error, { - context: "llm_stream_complete", - model: completionOptions.model, - provider: this.providerName, - useOpenAIAdapter: this.shouldUseOpenAIAdapter("streamComplete"), - streamEnabled: completionOptions.stream !== false, - }) - - status = this._logEnd(completionOptions.model, prompt, completion, interaction, undefined, e) - throw e - } finally { - if (status === "in_progress") { - this._logEnd(completionOptions.model, prompt, completion, interaction, undefined, "cancel") - } - } - - return { - modelTitle: this.title ?? completionOptions.model, - modelProvider: this.underlyingProviderName, - prompt, - completion, - completionOptions, - } - } - - async chat(messages: ChatMessage[], signal: AbortSignal, options: LLMFullCompletionOptions = {}) { - let completion = "" - for await (const message of this.streamChat(messages, signal, options)) { - completion += renderChatMessage(message) - } - return { role: "assistant" as const, content: completion } - } - - compileChatMessages(message: ChatMessage[], options: LLMFullCompletionOptions) { - let { completionOptions } = this.parseCompletionOptions(options) - completionOptions = this._modifyCompletionOptions(completionOptions) - - return compileChatMessages({ - modelName: completionOptions.model, - msgs: message, - knownContextLength: this._contextLength, - maxTokens: completionOptions.maxTokens ?? DEFAULT_MAX_TOKENS, - }) - } - - protected modifyChatBody(body: ChatCompletionCreateParams): ChatCompletionCreateParams { - return body - } - - private _modifyCompletionOptions(completionOptions: CompletionOptions): CompletionOptions { - // As of 01/14/25 streaming is currently not available with o1 - // See these threads: - // - https://github.com/continuedev/continue/issues/3698 - // - https://community.openai.com/t/streaming-support-for-o1-o1-2024-12-17-resulting-in-400-unsupported-value/1085043 - if (completionOptions.model === "o1") { - completionOptions.stream = false - } - - return completionOptions - } - - async *streamChat( - _messages: ChatMessage[], - signal: AbortSignal, - options: LLMFullCompletionOptions = {}, - messageOptions?: MessageOption, - ): AsyncGenerator { - this.lastRequestId = undefined - let { completionOptions } = this.parseCompletionOptions(options) - const { logEnabled } = this.parseCompletionOptions(options) - const interaction = logEnabled ? this.logger?.createInteractionLog() : undefined - let status: InteractionStatus = "in_progress" - - completionOptions = this._modifyCompletionOptions(completionOptions) - - let messages = _messages - - // If not precompiled, compile the chat messages - if (!messageOptions?.precompiled) { - const { compiledChatMessages } = compileChatMessages({ - modelName: completionOptions.model, - msgs: _messages, - knownContextLength: this._contextLength, - maxTokens: completionOptions.maxTokens ?? DEFAULT_MAX_TOKENS, - }) - - messages = compiledChatMessages - } - - const prompt = this.templateMessages ? this.templateMessages(messages) : this.formatChatMessages(messages) - if (logEnabled) { - interaction?.logItem({ - kind: "startChat", - messages, - options: completionOptions, - provider: this.providerName, - }) - if (this.llmRequestHook) { - this.llmRequestHook(completionOptions.model, prompt) - } - } - - let completion = "" - let usage: Usage | undefined = undefined - - try { - if (this.templateMessages) { - for await (const chunk of this._streamComplete(prompt, signal, completionOptions)) { - completion += chunk - interaction?.logItem({ - kind: "chunk", - chunk: chunk, - }) - yield { role: "assistant", content: chunk } - } - } else { - if (this.shouldUseOpenAIAdapter("streamChat") && this.openaiAdapter) { - let body = toChatBody(messages, completionOptions) - body = this.modifyChatBody(body) - - if (completionOptions.stream === false) { - // Stream false - const response = await this.openaiAdapter.chatCompletionNonStream({ ...body, stream: false }, signal) - this.lastRequestId = response.id ?? this.lastRequestId - const msg = fromChatResponse(response) - yield msg - completion = this._formatChatMessage(msg) - interaction?.logItem({ - kind: "message", - message: msg, - }) - } else { - // Stream true - const stream = this.openaiAdapter.chatCompletionStream( - { - ...body, - stream: true, - }, - signal, - ) - for await (const chunk of stream) { - if (!this.lastRequestId && typeof (chunk as any).id === "string") { - this.lastRequestId = (chunk as any).id - } - const result = fromChatCompletionChunk(chunk) - if (result) { - completion += this._formatChatMessage(result) - interaction?.logItem({ - kind: "message", - message: result, - }) - yield result - } - } - } - } else { - for await (const chunk of this._streamChat(messages, signal, completionOptions)) { - if (chunk.role === "assistant") { - completion += this._formatChatMessage(chunk) - } - - interaction?.logItem({ - kind: "message", - message: chunk, - }) - - if (chunk.role === "assistant" && chunk.usage) { - usage = chunk.usage - } - - yield chunk - } - } - } - status = this._logEnd(completionOptions.model, prompt, completion, interaction, usage) - } catch (e) { - console.error(e as Error, { - context: "llm_stream_chat", - model: completionOptions.model, - provider: this.providerName, - useOpenAIAdapter: this.shouldUseOpenAIAdapter("streamChat"), - streamEnabled: completionOptions.stream !== false, - templateMessages: !!this.templateMessages, - }) - - status = this._logEnd(completionOptions.model, prompt, completion, interaction, usage, e) - throw e - } finally { - if (status === "in_progress") { - this._logEnd(completionOptions.model, prompt, completion, interaction, usage, "cancel") - } - } - - return { - modelTitle: this.title ?? completionOptions.model, - modelProvider: this.underlyingProviderName, - prompt, - completion, - } - } - - async rerank(query: string, chunks: Chunk[]): Promise { - if (this.shouldUseOpenAIAdapter("rerank") && this.openaiAdapter) { - const results = await this.openaiAdapter.rerank({ - model: this.model, - query, - documents: chunks.map((chunk) => chunk.content), - }) - - // Standard OpenAI format - if (results.data && Array.isArray(results.data)) { - return results.data - .sort((a: { index: number }, b: { index: number }) => a.index - b.index) - .map((result: { relevance_score: number }) => result.relevance_score) - } - - throw new Error( - `Unexpected rerank response format from ${this.providerName}. ` + - `Expected 'data' array but got: ${JSON.stringify(Object.keys(results))}`, - ) - } - - throw new Error(`Reranking is not supported for provider type ${this.providerName}`) - } - - protected async *_streamComplete( - _prompt: string, - _signal: AbortSignal, - _options: CompletionOptions, - ): AsyncGenerator { - throw new Error("Not implemented") - } - - protected async *_streamChat( - messages: ChatMessage[], - signal: AbortSignal, - options: CompletionOptions, - ): AsyncGenerator { - if (!this.templateMessages) { - throw new Error("You must either implement templateMessages or _streamChat") - } - - for await (const chunk of this._streamComplete(this.templateMessages(messages), signal, options)) { - yield { role: "assistant", content: chunk } - } - } - - protected async _complete(prompt: string, signal: AbortSignal, options: CompletionOptions) { - let completion = "" - for await (const chunk of this._streamComplete(prompt, signal, options)) { - completion += chunk - } - return completion - } - - countTokens(text: string): number { - return countTokens(text, this.model) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/llms/Mock.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/llms/Mock.ts deleted file mode 100644 index 38e9a6f3836..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/llms/Mock.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ChatMessage, CompletionOptions, LLMOptions } from "../../index.js" -import { BaseLLM } from "../index.js" - -type MockMessage = ChatMessage | "REPEAT_LAST_MSG" | "REPEAT_SYSTEM_MSG" | "ERROR" - -class MockLLM extends BaseLLM { - public completion: string = "Test Completion" - public chatStreams: MockMessage[][] | undefined - static override providerName = "mock" - - constructor(options: LLMOptions) { - super(options) - this.templateMessages = undefined - this.chatStreams = options.chatStreams - } - - protected override async *_streamComplete( - _prompt: string, - _signal: AbortSignal, - _options: CompletionOptions, - ): AsyncGenerator { - yield this.completion - } - - protected override async *_streamChat( - messages: ChatMessage[], - _signal: AbortSignal, - _options: CompletionOptions, - ): AsyncGenerator { - if (this.chatStreams) { - const chatStream = this.chatStreams?.[messages.filter((m) => m.role === "user").length - 1] - if (chatStream) { - for (const message of chatStream) { - switch (message) { - case "REPEAT_LAST_MSG": - yield { - role: "assistant", - content: messages[messages.length - 1].content, - } - break - case "REPEAT_SYSTEM_MSG": - yield { - role: "assistant", - content: messages.find((m) => m.role === "system")?.content || "", - } - break - case "ERROR": - throw new Error("Intentional error") - default: - yield message - } - } - } - return - } - - for (const char of this.completion) { - yield { - role: "assistant", - content: char, - } - } - } -} - -export { MockLLM } diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/messages.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/messages.ts deleted file mode 100644 index 3433699dc21..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/messages.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { ChatMessage } from ".." - -function messageIsEmpty(message: ChatMessage): boolean { - if (typeof message.content === "string") { - return message.content.trim() === "" - } - if (Array.isArray(message.content)) { - return message.content.every((item) => item.type === "text" && item.text?.trim() === "") - } - return false -} - -// some providers don't support empty messages -export function addSpaceToAnyEmptyMessages(messages: ChatMessage[]): ChatMessage[] { - return messages.map((message) => { - if (messageIsEmpty(message)) { - message.content = " " - } - return message - }) -} - -export function chatMessageIsEmpty(message: ChatMessage): boolean { - switch (message.role) { - case "system": - case "user": - return typeof message.content === "string" && message.content.trim() === "" - case "assistant": - return typeof message.content === "string" && message.content.trim() === "" - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/index.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/index.ts deleted file mode 100644 index 7f32ff6a0ce..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { OpenAi } from "./providers/openai.js" -import { LlmInfoWithProvider, ModelProvider } from "./types.js" - -const allModelProviders: ModelProvider[] = [OpenAi] - -const allLlms: LlmInfoWithProvider[] = allModelProviders.flatMap((provider) => - provider.models.map((model) => ({ ...model, provider: provider.id })), -) - -export function findLlmInfo(model: string, preferProviderId?: string): LlmInfoWithProvider | undefined { - if (preferProviderId) { - const provider = allModelProviders.find((p) => p.id === preferProviderId) - const info = provider?.models.find((llm) => (llm.regex ? llm.regex.test(model) : llm.model === model)) - if (info) { - return { - ...info, - provider: preferProviderId, - } - } - } - return allLlms.find((llm) => (llm.regex ? llm.regex.test(model) : llm.model === model)) -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/providers/openai.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/providers/openai.ts deleted file mode 100644 index 21f7f9e33c9..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/providers/openai.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { ModelProvider } from "../types.js" - -export const OpenAi: ModelProvider = { - models: [ - { - model: "gpt-3.5-turbo", - displayName: "GPT-3.5 Turbo", - contextLength: 16385, - maxCompletionTokens: 4096, - }, - { - model: "gpt-3.5-turbo-0613", - displayName: "GPT-3.5 Turbo", - contextLength: 16385, - maxCompletionTokens: 4096, - }, - { - model: "gpt-3.5-turbo-16k", - displayName: "GPT-3.5 Turbo 16K", - contextLength: 16384, - maxCompletionTokens: 4096, - }, - { - model: "gpt-35-turbo-16k", - displayName: "GPT-3.5 Turbo 16K", - contextLength: 16384, - maxCompletionTokens: 4096, - }, - { - model: "gpt-35-turbo-0613", - displayName: "GPT-3.5 Turbo (0613)", - contextLength: 4096, - maxCompletionTokens: 4096, - }, - { - model: "gpt-35-turbo", - displayName: "GPT-3.5 Turbo", - contextLength: 4096, - maxCompletionTokens: 4096, - }, - // gpt-4 - { - model: "gpt-4", - displayName: "GPT-4", - contextLength: 8192, - maxCompletionTokens: 8192, - }, - { - model: "gpt-4-32k", - displayName: "GPT-4 32K", - contextLength: 32000, - maxCompletionTokens: 8192, - }, - { - model: "gpt-4-turbo-preview", - displayName: "GPT-4 Turbo Preview", - contextLength: 128000, - maxCompletionTokens: 4096, - }, - { - model: "gpt-4-vision", - displayName: "GPT-4 Vision", - contextLength: 128000, - maxCompletionTokens: 4096, - }, - { - model: "gpt-4-0125-preview", - displayName: "GPT-4 (0125 Preview)", - contextLength: 128000, - maxCompletionTokens: 4096, - }, - { - model: "gpt-4-1106-preview", - displayName: "GPT-4 (1106 Preview)", - contextLength: 128000, - maxCompletionTokens: 4096, - }, - // gpt-5 - { - model: "gpt-5", - displayName: "GPT-5", - contextLength: 400000, - maxCompletionTokens: 128000, - regex: /gpt-5/, - recommendedFor: ["chat"], - }, - // gpt-4o - { - model: "gpt-4o", - displayName: "GPT-4o", - contextLength: 128000, - recommendedFor: ["chat"], - }, - { - model: "gpt-4o-mini", - displayName: "GPT-4o Mini", - contextLength: 128000, - recommendedFor: ["chat"], - }, - // o1 - { - model: "o1-preview", - displayName: "o1 Preview", - contextLength: 128000, - maxCompletionTokens: 32768, - recommendedFor: ["chat"], - }, - { - model: "o1-mini", - displayName: "o1 Mini", - contextLength: 128000, - maxCompletionTokens: 65536, - recommendedFor: ["chat"], - }, - { - model: "o3-mini", - displayName: "o3 Mini", - contextLength: 128000, - maxCompletionTokens: 65536, - recommendedFor: ["chat"], - }, - // embed - { - model: "text-embedding-3-large", - displayName: "Text Embedding 3-Large", - recommendedFor: ["embed"], - }, - { - model: "text-embedding-3-small", - displayName: "Text Embedding 3-Small", - }, - { - model: "text-embedding-ada-002", - displayName: "Text Embedding Ada-002", - }, - ], - id: "openai", - displayName: "OpenAI", -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/types.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/types.ts deleted file mode 100644 index e516fa45419..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/model-info/types.ts +++ /dev/null @@ -1,58 +0,0 @@ -type UseCase = "chat" | "autocomplete" | "rerank" | "embed" - -type ParameterType = "string" | "number" | "boolean" - -interface Parameter { - key: string - required: boolean - valueType: ParameterType - displayName?: string - description?: string - defaultValue?: any -} - -enum ChatTemplate { - None = "none", - // TODO -} - -interface LlmInfo { - model: string - // providers: string[]; // TODO: uncomment and deal with the consequences - displayName?: string - description?: string - contextLength?: number - maxCompletionTokens?: number - regex?: RegExp - chatTemplate?: ChatTemplate - - /** If not set, assumes "text" only */ - mediaTypes?: MediaType[] - recommendedFor?: UseCase[] - - /** Any additional parameters required to configure the model */ - extraParameters?: Parameter[] -} - -export type LlmInfoWithProvider = LlmInfo & { - provider: string -} - -enum MediaType { - Text = "text", - Image = "image", - Audio = "audio", - Video = "video", -} - -export interface ModelProvider { - id: string - displayName: string - models: Omit[] - - /** Any additional parameters required to configure the model - * - * (other than apiKey, apiBase, which are assumed always. And of course model and provider always required) - */ - extraParameters?: Parameter[] -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/openaiTypeConverters.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/openaiTypeConverters.ts deleted file mode 100644 index 4ae6c57a017..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/openaiTypeConverters.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { - ChatCompletion, - ChatCompletionChunk, - ChatCompletionCreateParams, - ChatCompletionMessageParam, - CompletionCreateParams, -} from "openai/resources/index" - -import { ChatMessage, CompletionOptions, TextMessagePart } from ".." - -function toChatMessage(message: ChatMessage): ChatCompletionMessageParam { - if (message.role === "system") { - return { - role: "system", - content: message.content, - } - } - - if (message.role === "assistant") { - return { - role: "assistant", - content: - typeof message.content === "string" - ? message.content || " " // LM Studio (and other providers) don't accept empty content - : message.content.filter((part) => part.type === "text").map((part) => part as TextMessagePart), // can remove with newer typescript version - } - } else { - if (typeof message.content === "string") { - return { - role: "user", - content: message.content ?? " ", // LM Studio (and other providers) don't accept empty content - } - } - - // Extract text from message parts - return { - role: "user", - content: message.content.map((item) => (item as TextMessagePart).text).join("") || " ", - } - } -} - -export function toChatBody(messages: ChatMessage[], options: CompletionOptions): ChatCompletionCreateParams { - return { - messages: messages.map(toChatMessage), - model: options.model, - max_tokens: options.maxTokens, - temperature: options.temperature, - top_p: options.topP, - frequency_penalty: options.frequencyPenalty, - presence_penalty: options.presencePenalty, - stream: options.stream ?? true, - stop: options.stop, - } -} - -export function toCompleteBody(prompt: string, options: CompletionOptions): CompletionCreateParams { - return { - prompt, - model: options.model, - max_tokens: options.maxTokens, - temperature: options.temperature, - top_p: options.topP, - frequency_penalty: options.frequencyPenalty, - presence_penalty: options.presencePenalty, - stream: options.stream ?? true, - stop: options.stop, - } -} - -export function toFimBody(prefix: string, suffix: string, options: CompletionOptions): Record { - return { - model: options.model, - prompt: prefix, - suffix, - max_tokens: options.maxTokens, - temperature: options.temperature, - top_p: options.topP, - frequency_penalty: options.frequencyPenalty, - presence_penalty: options.presencePenalty, - stop: options.stop, - stream: true, - } as any -} - -export function fromChatResponse(response: ChatCompletion): ChatMessage { - const message = response.choices[0].message - - return { - role: "assistant", - content: message.content ?? "", - } -} - -export function fromChatCompletionChunk(chunk: ChatCompletionChunk): ChatMessage | undefined { - const delta = chunk.choices?.[0]?.delta - - if (delta?.content) { - return { - role: "assistant", - content: delta.content, - } - } - - return undefined -} - -export type LlmApiRequestType = "chat" | "streamChat" | "streamComplete" | "streamFim" | "rerank" diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit.ts deleted file mode 100644 index 963bbece826..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { ChatMessage, PromptTemplate } from "../../index.js" -import { gptEditPrompt } from "./edit/gpt.js" - -const simplifiedEditPrompt = `Consider the following code: -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` -Edit the code to perfectly satisfy the following user request: -{{{userInput}}} -Output nothing except for the code. No code block, no English explanation, no start/end tags.` - -const simplestEditPrompt = `Here is the code before editing: -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -Here is the edit requested: -"{{{userInput}}}" - -Here is the code after editing:` - -const codellamaInfillEditPrompt = "{{filePrefix}}{{fileSuffix}}" - -const START_TAG = "" -const osModelsEditPrompt: PromptTemplate = (history, otherData) => { - // "No sufix" means either there is no suffix OR - // it's a clean break at end of function or something - // (what we're trying to avoid is just the language model trying to complete the closing brackets of a function or something) - const firstCharOfFirstLine = otherData.suffix?.split("\n")[0]?.[0]?.trim() - const isSuffix = - otherData.suffix?.trim() !== "" && - // First character of first line is whitespace - // Otherwise we assume it's a clean break - !firstCharOfFirstLine - const suffixTag = isSuffix ? "" : "" - const suffixExplanation = isSuffix ? ' When you get to "", end your response.' : "" - - // If neither prefilling nor /v1/completions are supported, we have to use a chat prompt without putting words in the model's mouth - if (otherData.supportsCompletions !== "true" && otherData.supportsPrefill !== "true") { - return gptEditPrompt(history, otherData) - } - - // Use a different prompt when there's neither prefix nor suffix - if (otherData.prefix?.trim() === "" && otherData.suffix?.trim() === "") { - return [ - { - role: "user", - content: `\`\`\`${otherData.language} -${otherData.codeToEdit} -${suffixTag} -\`\`\` - -Please rewrite the entire code block above in order to satisfy the following request: "${otherData.userInput}". You should rewrite the entire code block without leaving placeholders, even if the code is the same as before.${suffixExplanation}`, - }, - { - role: "assistant", - content: `Sure! Here's the entire rewritten code block: -\`\`\`${otherData.language} -`, - }, - ] - } - - return [ - { - role: "user", - content: `\`\`\`${otherData.language} -${otherData.prefix}${START_TAG} -${otherData.codeToEdit} -${suffixTag} -\`\`\` - -Please rewrite the entire code block above, editing the portion below "${START_TAG}" in order to satisfy the following request: "${otherData.userInput}". You should rewrite the entire code block without leaving placeholders, even if the code is the same as before.${suffixExplanation} -`, - }, - { - role: "assistant", - content: `Sure! Here's the entire code block, including the rewritten portion: -\`\`\`${otherData.language} -${otherData.prefix}${START_TAG} -`, - }, - ] -} - -const mistralEditPrompt = `[INST] You are a helpful code assistant. Your task is to rewrite the following code with these instructions: "{{{userInput}}}" -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -Just rewrite the code without explanations: [/INST] -\`\`\`{{{language}}}` - -const alpacaEditPrompt = `Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. - -### Instruction: Rewrite the code to satisfy this request: "{{{userInput}}}" - -### Input: - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -### Response: - -Sure! Here's the code you requested: -\`\`\`{{{language}}} -` - -const phindEditPrompt = `### System Prompt -You are an expert programmer and write code on the first attempt without any errors or fillers. - -### User Message: -Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -### Assistant: -Sure! Here's the code you requested: - -\`\`\`{{{language}}} -` - -const deepseekEditPrompt = `### System Prompt -You are an AI programming assistant, utilizing the DeepSeek Coder model, developed by DeepSeek Company, and your role is to assist with questions related to computer science. For politically sensitive questions, security and privacy issues, and other non-computer science questions, you will not answer. -### Instruction: -Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\`<|EOT|> -### Response: -Sure! Here's the code you requested: - -\`\`\`{{{language}}} -` - -const zephyrEditPrompt = `<|system|> -You are an expert programmer and write code on the first attempt without any errors or fillers. -<|user|> -Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` -<|assistant|> -Sure! Here's the code you requested: - -\`\`\`{{{language}}} -` - -const openchatEditPrompt = `GPT4 Correct User: You are an expert programmer and personal assistant. You are asked to rewrite the following code in order to {{{userInput}}}. -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` -Please only respond with code and put it inside of a markdown code block. Do not give any explanation, but your code should perfectly satisfy the user request.<|end_of_turn|>GPT4 Correct Assistant: Sure thing! Here is the rewritten code that you requested: -\`\`\`{{{language}}} -` - -const xWinCoderEditPrompt = `: You are an AI coding agent that helps people with programming. Write a response that appropriately completes the user's request. -: Please rewrite the following code with these instructions: "{{{userInput}}}" -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -Just rewrite the code without explanations: -: -\`\`\`{{{language}}}` - -const neuralChatEditPrompt = `### System: -You are an expert programmer and write code on the first attempt without any errors or fillers. -### User: -Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` -### Assistant: -Sure! Here's the code you requested: - -\`\`\`{{{language}}} -` - -const codeLlama70bEditPrompt = `Source: system\n\n You are an expert programmer and write code on the first attempt without any errors or fillers. Source: user\n\n Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` Source: assistant\nDestination: user\n\n ` - -const claudeEditPrompt: PromptTemplate = (history: ChatMessage[], otherData: Record) => [ - { - role: "user", - content: `\ -\`\`\`${otherData.language} -${otherData.codeToEdit} -\`\`\` - -You are an expert programmer. You will rewrite the above code to do the following: - -${otherData.userInput} - -Output only a code block with the rewritten code: -`, - }, - { - role: "assistant", - content: `Sure! Here is the rewritten code: -\`\`\`${otherData.language}`, - }, -] - -const llama3EditPrompt: PromptTemplate = `<|begin_of_text|><|start_header_id|>user<|end_header_id|> -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` - -Rewrite the above code to satisfy this request: "{{{userInput}}}"<|eot_id|><|start_header_id|>assistant<|end_header_id|> -Sure! Here's the code you requested: -\`\`\`{{{language}}}` - -const gemmaEditPrompt = `user -You are an expert programmer and write code on the first attempt without any errors or fillers. Rewrite the code to satisfy this request: "{{{userInput}}}" - -\`\`\`{{{language}}} -{{{codeToEdit}}} -\`\`\` -model -Sure! Here's the code you requested: - -\`\`\`{{{language}}} -` - -export { - alpacaEditPrompt, - claudeEditPrompt, - codeLlama70bEditPrompt, - codellamaInfillEditPrompt, - deepseekEditPrompt, - gemmaEditPrompt, - gptEditPrompt, - llama3EditPrompt, - mistralEditPrompt, - neuralChatEditPrompt, - openchatEditPrompt, - osModelsEditPrompt, - phindEditPrompt, - simplestEditPrompt, - simplifiedEditPrompt, - xWinCoderEditPrompt, - zephyrEditPrompt, -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit/gpt.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit/gpt.ts deleted file mode 100644 index d13cdc8d0f5..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/llm/templates/edit/gpt.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { PromptTemplateFunction } from "../../.." -import { dedent } from "../../../util" - -const gptInsertionEditPrompt: PromptTemplateFunction = (_, otherData) => { - return dedent` - \`\`\`${otherData.language} - ${otherData.prefix}[BLANK]${otherData.codeToEdit}${otherData.suffix} - \`\`\` - - Above is the file of code that the user is currently editing in. Their cursor is located at the "[BLANK]". They have requested that you fill in the "[BLANK]" with code that satisfies the following request: - - "${otherData.userInput}" - - Please generate this code. Your output will be only the code that should replace the "[BLANK]", without repeating any of the prefix or suffix, without any natural language explanation, and without messing up indentation. Here is the code that will replace the "[BLANK]":` -} - -const gptFullFileEditPrompt: PromptTemplateFunction = (_, otherData) => { - return dedent` - \`\`\`${otherData.language} - ${otherData.codeToEdit} - \`\`\` - - Please rewrite the above file to address the following request: - - ${otherData.userInput} - - You should rewrite the entire file without any natural language explanation. DO NOT surround the code in a code block and DO NOT explain yourself.` -} - -export const gptEditPrompt: PromptTemplateFunction = (history, otherData) => { - if (otherData?.codeToEdit?.trim().length === 0) { - return gptInsertionEditPrompt(history, otherData) - } else if (otherData?.prefix?.trim().length === 0 && otherData?.suffix?.trim().length === 0) { - return gptFullFileEditPrompt(history, otherData) - } - - const paragraphs = ["The user has requested a section of code in a file to be rewritten."] - - if (otherData.prefix?.trim().length > 0) { - paragraphs.push(dedent` - This is the prefix of the file: - \`\`\`${otherData.language} - ${otherData.prefix} - \`\`\``) - } - - if (otherData.suffix?.trim().length > 0) { - paragraphs.push(dedent` - This is the suffix of the file: - \`\`\`${otherData.language} - ${otherData.suffix} - \`\`\``) - } - - paragraphs.push(dedent` - This is the code to rewrite: - \`\`\`${otherData.language} - ${otherData.codeToEdit} - \`\`\` - - The user's request is: "${otherData.userInput}" - - DO NOT output any natural language, only output the code changes. - - Here is the rewritten code:`) - - return paragraphs.join("\n\n") -} - -export const defaultApplyPrompt: PromptTemplateFunction = (history, otherData) => { - return `${otherData.original_code}\n\nThe following code was suggested as an edit:\n\`\`\`\n${otherData.new_code}\n\`\`\`\nPlease apply it to the previous code.` -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeConfigHandler.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeConfigHandler.ts deleted file mode 100644 index c071f588265..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeConfigHandler.ts +++ /dev/null @@ -1,87 +0,0 @@ -import type { ILLM, TabAutocompleteOptions } from "../index.js" -import { MinimalConfigProvider } from "../autocomplete/MinimalConfig.js" - -/** - * Minimal config structure for testing. - * Matches the shape of config returned by MinimalConfigProvider.loadConfig() - */ -interface MinimalTestConfig { - modelsByRole?: { - autocomplete?: ILLM[] - } - selectedModelByRole?: { - autocomplete?: ILLM - edit?: ILLM - chat?: ILLM - rerank?: ILLM - } - rules?: unknown[] -} - -/** - * Options for customizing FakeConfigHandler behavior. - * All options are optional and will use sensible defaults if not provided. - */ -interface FakeConfigHandlerOptions { - /** Configuration to return from loadConfig() */ - config?: Partial - - /** Autocomplete model to use (shorthand for setting selectedModelByRole.autocomplete) */ - autocompleteModel?: ILLM - - /** Whether static contextualization is enabled */ - enableStaticContextualization?: boolean - - /** Tab autocomplete options */ - tabAutocompleteOptions?: TabAutocompleteOptions - - /** Profile type for logging */ - profileType?: "control-plane" | "local" | "platform" -} - -export class FakeConfigHandler extends MinimalConfigProvider { - /** Track calls to onConfigUpdate for assertions */ - public configUpdateCallbacks: Array<(event: { config: MinimalTestConfig; configLoadInterrupted: boolean }) => void> = - [] - - constructor(options: FakeConfigHandlerOptions = {}) { - // Build config from options - const autocompleteModel = options.autocompleteModel - - const config = { - tabAutocompleteOptions: options.tabAutocompleteOptions, - experimental: { - enableStaticContextualization: options.enableStaticContextualization ?? false, - }, - modelsByRole: { - autocomplete: autocompleteModel ? [autocompleteModel] : [], - }, - selectedModelByRole: { - autocomplete: autocompleteModel, - }, - ...options.config, - } - - // Call parent constructor with merged config - super(config) - - // Set profile if provided - if (options.profileType) { - this.currentProfile = { - profileDescription: { - profileType: options.profileType, - }, - } - } - } - - /** - * Register config update handler - * Overrides parent to track callbacks for test assertions - */ - override onConfigUpdate( - handler: (event: { config: MinimalTestConfig; configLoadInterrupted: boolean }) => void, - ): void { - this.configUpdateCallbacks.push(handler) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeIDE.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeIDE.ts deleted file mode 100644 index a99e458b971..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/FakeIDE.ts +++ /dev/null @@ -1,150 +0,0 @@ -import type { - DocumentSymbol, - FileStatsMap, - IDE, - IdeInfo, - Location, - Range, - RangeInFile, - SignatureHelp, -} from "../index.js" - -/** - * Options for customizing FakeIDE behavior. - * All options are optional and will use sensible defaults if not provided. - */ -interface FakeIDEOptions { - /** File contents to return for readFile calls. Maps filepath -> content */ - fileContents?: Map - - /** Workspace directories to return */ - workspaceDirs?: string[] - - /** IDE info to return */ - ideInfo?: IdeInfo - - /** Open files to return */ - openFiles?: string[] - - /** Current file to return */ - currentFile?: { - isUntitled: boolean - path: string - contents: string - } - - /** Clipboard content to return */ - clipboardContent?: { text: string; copiedAt: string } - - /** Unique ID to return */ - uniqueId?: string -} - -export class FakeIDE implements IDE { - private options: FakeIDEOptions - - /** Track calls to onDidChangeActiveTextEditor for assertions */ - public activeTextEditorCallbacks: Array<(fileUri: string) => void> = [] - - constructor(options: FakeIDEOptions = {}) { - this.options = options - } - - async getIdeInfo(): Promise { - return ( - this.options.ideInfo ?? { - ideType: "vscode", - } - ) - } - - async getClipboardContent(): Promise<{ text: string; copiedAt: string }> { - return ( - this.options.clipboardContent ?? { - text: "", - copiedAt: new Date().toISOString(), - } - ) - } - - async getUniqueId(): Promise { - return this.options.uniqueId ?? "fake-unique-id" - } - - async getWorkspaceDirs(): Promise { - return this.options.workspaceDirs ?? ["/workspace"] - } - - async fileExists(fileUri: string): Promise { - if (this.options.fileContents) { - return this.options.fileContents.has(fileUri) - } - return false - } - - async writeFile(_path: string, _contents: string): Promise { - // No-op by default, tests can override if needed - } - - async saveFile(_fileUri: string): Promise { - // No-op by default, tests can override if needed - } - - async readFile(fileUri: string): Promise { - if (this.options.fileContents) { - return this.options.fileContents.get(fileUri) ?? "" - } - return "" - } - - async readRangeInFile(_fileUri: string, _range: Range): Promise { - // Simplified implementation - tests can override if needed - return "" - } - - async getOpenFiles(): Promise { - return this.options.openFiles ?? [] - } - - async getCurrentFile(): Promise< - | undefined - | { - isUntitled: boolean - path: string - contents: string - } - > { - return this.options.currentFile - } - - async getFileStats(_files: string[]): Promise { - // Return empty map by default - return {} - } - - // LSP methods - return empty arrays by default - async gotoDefinition(_location: Location): Promise { - return [] - } - - async gotoTypeDefinition(_location: Location): Promise { - return [] - } - - async getSignatureHelp(_location: Location): Promise { - return null - } - - async getReferences(_location: Location): Promise { - return [] - } - - async getDocumentSymbols(_textDocumentIdentifier: string): Promise { - return [] - } - - // Callbacks - onDidChangeActiveTextEditor(callback: (fileUri: string) => void): void { - this.activeTextEditorCallbacks.push(callback) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.global-setup.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.global-setup.ts deleted file mode 100644 index 160ea036ace..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.global-setup.ts +++ /dev/null @@ -1,11 +0,0 @@ -import fs from "fs" -import path from "path" - -// Sets up the GLOBAL directory for testing - equivalent to ~/.continue -// IMPORTANT: the CONTINUE_GLOBAL_DIR environment variable is used in utils/paths for getting all local paths -export default async function () { - process.env.CONTINUE_GLOBAL_DIR = path.join(__dirname, ".continue-test") - if (fs.existsSync(process.env.CONTINUE_GLOBAL_DIR)) { - fs.rmSync(process.env.CONTINUE_GLOBAL_DIR, { recursive: true }) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.setup.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.setup.ts deleted file mode 100644 index 4169ec45ee6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/test/vitest.setup.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { TextDecoder, TextEncoder } from "util" -import { beforeAll } from "vitest" - -beforeAll(async () => { - const g: any = globalThis - - // Node 20+ provides global fetch/Request/Response natively - // Set up TextEncoder/TextDecoder for tests - g.TextEncoder = TextEncoder - g.TextDecoder = TextDecoder -}) diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/CodeRenderer.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/CodeRenderer.ts deleted file mode 100644 index ce6a2fc7122..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/CodeRenderer.ts +++ /dev/null @@ -1,34 +0,0 @@ -// Minimal stub for removed codeRenderer functionality -import type { DiffLine, DiffChar } from "../index.js" -export class CodeRenderer { - private static instance: CodeRenderer - - static getInstance(): CodeRenderer { - if (!CodeRenderer.instance) { - CodeRenderer.instance = new CodeRenderer() - } - return CodeRenderer.instance - } - - async setTheme(_theme: string): Promise { - // No-op stub - } - - async getDataUri( - _text: string, - _languageId: string, - _options: { - imageType: "svg" - fontSize: number - fontFamily: string - dimensions: { width: number; height: number } - lineHeight: number - }, - _currLineOffsetFromTop: number, - _newDiffLines: DiffLine[], - _diffChars: DiffChar[], - ): Promise { - // Return empty data URI as stub - return "data:image/svg+xml;base64," - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/TokensBatchingService.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/TokensBatchingService.ts deleted file mode 100644 index 3091f5e564c..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/TokensBatchingService.ts +++ /dev/null @@ -1,82 +0,0 @@ -interface TokenBatch { - model: string - provider: string - count: number - totalPromptTokens: number - totalGeneratedTokens: number - lastEventTime: number -} - -export class TokensBatchingService { - private static instance: TokensBatchingService - private batches = new Map() - private flushTimer: NodeJS.Timeout | null = null - - private readonly BATCH_SIZE_LIMIT = 25 - private readonly FLUSH_INTERVAL_MS = 10 * 60 * 1000 // 10 minutes - - static getInstance(): TokensBatchingService { - if (!TokensBatchingService.instance) { - TokensBatchingService.instance = new TokensBatchingService() - } - return TokensBatchingService.instance - } - - private constructor() { - this.startFlushTimer() - } - - addTokens(model: string, provider: string, promptTokens: number, generatedTokens: number): void { - const key = `${provider}:${model}` - - if (!this.batches.has(key)) { - this.batches.set(key, { - model, - provider, - count: 0, - totalPromptTokens: 0, - totalGeneratedTokens: 0, - lastEventTime: Date.now(), - }) - } - - const batch = this.batches.get(key)! - batch.count++ - batch.totalPromptTokens += promptTokens - batch.totalGeneratedTokens += generatedTokens - batch.lastEventTime = Date.now() - - // Flush if batch is full - if (batch.count >= this.BATCH_SIZE_LIMIT) { - this.flushBatch(key, batch) - } - } - - private flushBatch(key: string, batch: TokenBatch): void { - if (batch.count === 0) return - this.batches.delete(key) - } - - private startFlushTimer(): void { - this.flushTimer = setInterval(() => { - this.flushAllBatches() - }, this.FLUSH_INTERVAL_MS) - // Allow the process to exit if this timer is the only thing keeping it alive - // This prevents test hangs and allows graceful shutdown - this.flushTimer.unref() - } - - private flushAllBatches(): void { - for (const [key, batch] of this.batches.entries()) { - this.flushBatch(key, batch) - } - } - - shutdown(): void { - if (this.flushTimer) { - clearInterval(this.flushTimer) - this.flushTimer = null - } - this.flushAllBatches() - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/index.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/index.ts deleted file mode 100644 index 2ceb627a76f..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -export function dedent(strings: TemplateStringsArray, ...values: unknown[]) { - let raw = "" - for (let i = 0; i < strings.length; i++) { - raw += strings[i] - - // Handle the value if it exists - if (i < values.length) { - let value = String(values[i]) - // If the value contains newlines, we need to adjust the indentation - if (value.includes("\n")) { - // Find the indentation level of the last line in strings[i] - const lines = strings[i].split("\n") - const lastLine = lines[lines.length - 1] - const match = lastLine.match(/(^|\n)([^\S\n]*)$/) - const indent = match ? match[2] : "" - // Add indentation to all lines except the first line of value - let valueLines = value.split("\n") - valueLines = valueLines.map((line, index) => (index === 0 ? line : indent + line)) - value = valueLines.join("\n") - } - raw += value - } - } - - // Now dedent the full string - const result = raw.replace(/^\n/, "").replace(/\n\s*$/, "") - let lines = result.split("\n") - - // Remove leading/trailing blank lines - while (lines.length > 0 && lines[0].trim() === "") { - lines.shift() - } - while (lines.length > 0 && lines[lines.length - 1].trim() === "") { - lines.pop() - } - - // Calculate minimum indentation (excluding empty lines) - const minIndent = lines.reduce((min: number | null, line: string) => { - if (line.trim() === "") return min - const match = line.match(/^(\s*)/) - const indent = match ? match[1].length : 0 - return min === null ? indent : Math.min(min, indent) - }, null) - - if (minIndent !== null && minIndent > 0) { - // Remove the minimum indentation from each line - lines = lines.map((line) => line.slice(minIndent)) - } - - return lines.join("\n") -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/logger.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/logger.ts deleted file mode 100644 index 845ecfc643a..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/logger.ts +++ /dev/null @@ -1,35 +0,0 @@ -function getIconFromLevel(level: string): string { - switch (level) { - case "debug": - return "🔵" - case "info": - return "🟢" - case "warn": - return "🟡" - case "error": - return "🔴" - } - return "X" -} - -export class Logger { - constructor( - private filename: string, - private includeFilename = false, - ) {} - #formatMessage(level: string, message: string): string { - return `${getIconFromLevel(level)} ${this.includeFilename ? `[${this.filename}] ` : ""}${message}` - } - debug(message: string, ...args: any[]) { - console.debug(this.#formatMessage("debug", message), ...args) - } - info(message: string, ...args: any[]) { - console.info(this.#formatMessage("info", message), ...args) - } - warn(message: string, ...args: any[]) { - console.info(this.#formatMessage("warn", message), ...args) - } - error(message: string, ...args: any[]) { - console.info(this.#formatMessage("error", message), ...args) - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/merge.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/merge.ts deleted file mode 100644 index 0c36693e785..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/merge.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { ConfigMergeType } from "../index.js" - -// Allow any JSON-compatible value, including complex objects -export function mergeJson>( - first: T, - second: Partial, - mergeBehavior?: ConfigMergeType, - mergeKeys?: { [key: string]: (a: unknown, b: unknown) => boolean }, -): T { - const copyOfFirst = JSON.parse(JSON.stringify(first)) - - try { - for (const key in second) { - const secondValue = second[key] - - if (!(key in copyOfFirst) || mergeBehavior === "overwrite") { - // New value - copyOfFirst[key] = secondValue - continue - } - - const firstValue = copyOfFirst[key] - if (Array.isArray(secondValue) && Array.isArray(firstValue)) { - // Array - if (mergeKeys?.[key]) { - // Merge keys are used to determine whether an item form the second object should override one from the first - const keptFromFirst: unknown[] = [] - firstValue.forEach((item: unknown) => { - if (!secondValue.some((item2: unknown) => mergeKeys[key](item, item2))) { - keptFromFirst.push(item) - } - }) - copyOfFirst[key] = [...keptFromFirst, ...secondValue] - } else { - copyOfFirst[key] = [...firstValue, ...secondValue] - } - } else if ( - typeof secondValue === "object" && - secondValue !== null && - typeof firstValue === "object" && - firstValue !== null - ) { - // Object - copyOfFirst[key] = mergeJson(firstValue, secondValue, mergeBehavior) - } else { - // Other (boolean, number, string) - copyOfFirst[key] = secondValue - } - } - return copyOfFirst - } catch (e) { - console.error("Error merging JSON", e, copyOfFirst, second) - return { - ...copyOfFirst, - ...second, - } - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/paths.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/paths.ts deleted file mode 100644 index 18bdcfb2a53..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/paths.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as fs from "fs" -import * as os from "os" -import * as path from "path" - -const CONTINUE_GLOBAL_DIR = (() => { - const configPath = process.env.CONTINUE_GLOBAL_DIR - if (configPath) { - // Convert relative path to absolute paths based on current working directory - return path.isAbsolute(configPath) ? configPath : path.resolve(process.cwd(), configPath) - } - return path.join(os.homedir(), ".continue") -})() - -function getContinueGlobalPath(): string { - // This is ~/.continue on mac/linux - const continuePath = CONTINUE_GLOBAL_DIR - if (!fs.existsSync(continuePath)) { - fs.mkdirSync(continuePath) - } - return continuePath -} - -function getIndexFolderPath(): string { - const indexPath = path.join(getContinueGlobalPath(), "index") - if (!fs.existsSync(indexPath)) { - fs.mkdirSync(indexPath) - } - return indexPath -} - -export function getConfigJsonPath(): string { - const p = path.join(getContinueGlobalPath(), "config.json") - return p -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/uri.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/uri.ts index f3be4702cd8..9901aca6a25 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/uri.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/util/uri.ts @@ -1,18 +1,3 @@ -/** Converts any OS path to cleaned up URI path segment format with no leading/trailing slashes - e.g. \path\to\folder\ -> path/to/folder - \this\is\afile.ts -> this/is/afile.ts - is/already/clean -> is/already/clean - **/ -function pathToUriPathSegment(path: string) { - let clean = path.replace(/[\\]/g, "/") // backslashes -> forward slashes - clean = clean.replace(/^\//, "") // remove start slash - clean = clean.replace(/\/$/, "") // remove end slash - return clean - .split("/") - .map((part) => encodeURIComponent(part)) - .join("/") -} - function getCleanUriPath(uri: string) { // Handle both URIs and plain paths let path: string @@ -106,15 +91,6 @@ export function getLastNUriRelativePathParts(dirUriCandidates: string[], uri: st return getLastNPathParts(relativePathOrBasename, n) } -export function joinPathsToUri(uri: string, ...pathSegments: string[]) { - let baseUri = uri - if (baseUri.at(-1) !== "/") { - baseUri += "/" - } - const segments = pathSegments.map((segment) => pathToUriPathSegment(segment)) - return new URL(segments.join("/"), baseUri).toString() -} - export function getShortestUniqueRelativeUriPaths( uris: string[], dirUriCandidates: string[], From 0f11988203ace4e020e8d9f8979a46c86f027f2b Mon Sep 17 00:00:00 2001 From: "kiloconnect[bot]" <240665456+kiloconnect[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:44:02 +0000 Subject: [PATCH 5/5] chore(vscode): enforce autocomplete dead code checks --- packages/kilo-vscode/knip.json | 1 - .../files/typescript/arrowFunctions.ts | 29 ------ .../files/typescript/classMethods.ts | 35 ------- .../__fixtures__/files/typescript/classes.ts | 9 -- .../files/typescript/functions.ts | 33 ------- .../files/typescript/generators.ts | 33 ------- .../__test-cases__/python.ts | 95 ------------------- .../src/services/autocomplete/types.ts | 72 +------------- 8 files changed, 5 insertions(+), 302 deletions(-) delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/arrowFunctions.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classMethods.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classes.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/functions.ts delete mode 100644 packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/generators.ts diff --git a/packages/kilo-vscode/knip.json b/packages/kilo-vscode/knip.json index 7d3bb0ffadb..3e718495627 100644 --- a/packages/kilo-vscode/knip.json +++ b/packages/kilo-vscode/knip.json @@ -12,7 +12,6 @@ "script/*.ts" ], "project": ["src/**/*.ts", "webview-ui/**/*.{ts,tsx}"], - "ignore": ["src/services/autocomplete/**"], "ignoreExportsUsedInFile": true, "exclude": ["dependencies", "devDependencies", "optionalPeerDependencies", "unlisted", "unresolved", "binaries"] } diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/arrowFunctions.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/arrowFunctions.ts deleted file mode 100644 index cb853ef39b6..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/arrowFunctions.ts +++ /dev/null @@ -1,29 +0,0 @@ -// @ts-nocheck - -const getAddress = (person: Person): Address => { - // TODO -} - -const logPerson = (person: Person) => { - // TODO -} - -const getHardcodedAddress = (): Address => { - // TODO -} - -const getAddresses = (people: Person[]): Address[] => { - // TODO -} - -const logPersonWithAddres = (person: Person
): Person
=> { - // TODO -} - -const logPersonOrAddress = (person: Person | Address): Person | Address => { - // TODO -} - -const logPersonAndAddress = (person: Person, address: Address) => { - // TODO -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classMethods.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classMethods.ts deleted file mode 100644 index 08f7506a70e..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classMethods.ts +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-nocheck - -class Group { - getPersonAddress(person: Person): Address { - // TODO - } - - getHardcodedAddress(): Address { - // TODO - } - - addPerson(person: Person) { - // TODO - } - - addPeople(people: Person[]) { - // TODO - } - - getAddresses(people: Person[]): Address[] { - // TODO - } - - logPersonWithAddress(person: Person
): Person
{ - // TODO - } - - logPersonOrAddress(person: Person | Address): Person | Address { - // TODO - } - - logPersonAndAddress(person: Person, address: Address) { - // TODO - } -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classes.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classes.ts deleted file mode 100644 index 8bb8299868e..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/classes.ts +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-nocheck - -class Group extends BaseClass {} - -class Group implements FirstInterface {} - -class Group extends BaseClass implements FirstInterface, SecondInterface {} - -class Group extends BaseClass implements FirstInterface {} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/functions.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/functions.ts deleted file mode 100644 index bb9d39c85d9..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/functions.ts +++ /dev/null @@ -1,33 +0,0 @@ -// @ts-nocheck - -function getAddress(person: Person): Address { - // TODO -} - -function getFirstAddress(people: Person[]): Address { - // TODO -} - -function logPerson(person: Person) { - // TODO -} - -function getHardcodedAddress(): Address { - // TODO -} - -function getAddresses(people: Person[]): Address[] { - // TODO -} - -function logPersonWithAddress(person: Person
): Person
{ - // TODO -} - -function logPersonOrAddress(person: Person | Address): Person | Address { - // TODO -} - -function logPersonAndAddress(person: Person, address: Address) { - // TODO -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/generators.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/generators.ts deleted file mode 100644 index 79811b47873..00000000000 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__fixtures__/files/typescript/generators.ts +++ /dev/null @@ -1,33 +0,0 @@ -// @ts-nocheck - -function* getAddress(person: Person): Address { - // TODO -} - -function* getFirstAddress(people: Person[]): Address { - // TODO -} - -function* logPerson(person: Person) { - // TODO -} - -function* getHardcodedAddress(): Address { - // TODO -} - -function* getAddresses(people: Person[]): Address[] { - // TODO -} - -function* logPersonWithAddress(person: Person
): Person
{ - // TODO -} - -function* logPersonOrAddress(person: Person | Address): Person | Address { - // TODO -} - -function* logPersonAndAddress(person: Person, address: Address) { - // TODO -} diff --git a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__test-cases__/python.ts b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__test-cases__/python.ts index 68a29efbfa1..cb1c48318c1 100644 --- a/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__test-cases__/python.ts +++ b/packages/kilo-vscode/src/services/autocomplete/continuedev/core/autocomplete/context/root-path-context/__test-cases__/python.ts @@ -1,98 +1,3 @@ -export const FUNCTIONS = [ - { - nodeType: "function_definition with argument and return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 15, character: 8 }, - definitionPositions: [ - { row: 14, column: 30 }, // Person - { row: 14, column: 42 }, // Address - ], - }, - { - nodeType: "function_definition with generic argument and generic return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 18, character: 8 }, - definitionPositions: [ - { row: 17, column: 35 }, // Group - { row: 17, column: 42 }, // Person - { row: 17, column: 53 }, // Group - { row: 17, column: 61 }, // Address - ], - }, - { - nodeType: "function_definition with single argument and None return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 21, character: 8 }, - definitionPositions: [ - { row: 20, column: 29 }, // Person - ], - }, - { - nodeType: "function_definition with no arguments and single return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 24, character: 8 }, - definitionPositions: [ - { row: 23, column: 38 }, // Address - ], - }, - { - nodeType: "function_definition with Union arguments and Union return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 27, character: 8 }, - definitionPositions: [ - { row: 26, column: 45 }, // Person - { row: 26, column: 54 }, // Address - { row: 26, column: 72 }, // Person - { row: 26, column: 81 }, // Address - ], - }, - { - nodeType: "function_definition with multiple arguments and None return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 30, character: 8 }, - definitionPositions: [ - { row: 29, column: 41 }, // Person - { row: 29, column: 59 }, // Address - ], - }, - { - nodeType: "function_definition with one argument and Generator return type", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 33, character: 9 }, - definitionPositions: [ - { row: 32, column: 40 }, // Person - { row: 32, column: 62 }, // Address - ], - }, - { - nodeType: "function_definition inside a class", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 38, character: 12 }, - definitionPositions: [ - { row: 37, column: 51 }, // Person - { row: 37, column: 69 }, // Address - ], - }, - { - nodeType: "function_definition of an async function", - fileName: "python/functions.py", - language: "Python", - cursorPosition: { line: 41, character: 8 }, - definitionPositions: [ - { row: 40, column: 37 }, // Address - { row: 40, column: 48 }, // Person - ], - }, -] - export const CLASSES = [ { nodeType: "class_definition with multiple superclasses", diff --git a/packages/kilo-vscode/src/services/autocomplete/types.ts b/packages/kilo-vscode/src/services/autocomplete/types.ts index a8f736f22d3..ecbae591dc1 100644 --- a/packages/kilo-vscode/src/services/autocomplete/types.ts +++ b/packages/kilo-vscode/src/services/autocomplete/types.ts @@ -1,15 +1,10 @@ import * as vscode from "vscode" import type { AutocompleteCodeSnippet } from "./continuedev/core/autocomplete/types" -import type { - Position, - Range, - RangeInFile, - TabAutocompleteOptions as CoreTabAutocompleteOptions, -} from "./continuedev/core" -import { FileIgnoreController } from "./shims/FileIgnoreController" -import { ContextRetrievalService } from "./continuedev/core/autocomplete/context/ContextRetrievalService" -import { VsCodeIde } from "./continuedev/core/vscode-test-harness/src/VSCodeIde" -import { AutocompleteModel } from "./AutocompleteModel" +import type { Position, Range, RangeInFile } from "./continuedev/core" +import type { FileIgnoreController } from "./shims/FileIgnoreController" +import type { ContextRetrievalService } from "./continuedev/core/autocomplete/context/ContextRetrievalService" +import type { VsCodeIde } from "./continuedev/core/vscode-test-harness/src/VSCodeIde" +import type { AutocompleteModel } from "./AutocompleteModel" export interface ResponseMetaData { cost: number @@ -26,15 +21,6 @@ export interface AutocompleteSuggestionContext { recentlyEditedRanges?: RecentlyEditedRange[] } -export interface AutocompleteTabExtensions { - template?: string - useOtherFiles?: boolean - recentlyEditedSimilarityThreshold?: number - maxSnippetTokens?: number -} - -export type TabAutocompleteOptions = Partial & AutocompleteTabExtensions - export interface RecentlyEditedRange extends RangeInFile { timestamp: number lines: string[] @@ -59,35 +45,6 @@ export interface AutocompleteInput { injectDetails?: string } -export interface AutocompleteOutcome extends TabAutocompleteOptions { - accepted?: boolean - time: number - prefix: string - suffix: string - prompt: string - completion: string - modelProvider: string - modelName: string - completionOptions: Record - cacheHit: boolean - numLines: number - filepath: string - gitRepo?: string - completionId: string - uniqueId: string - timestamp: string - enabledStaticContextualization?: boolean - profileType?: "local" | "platform" | "control-plane" -} - -export interface PromptResult { - systemPrompt: string - userPrompt: string - prefix: string - suffix: string - completionId: string -} - // ============================================================================ // FIM Completion Types // ============================================================================ @@ -214,25 +171,6 @@ export interface VisibleCodeContext { editors: VisibleEditorInfo[] } -// ============================================================================ -// Chat Text Area Autocomplete Types -// ============================================================================ - -/** - * Request for chat text area completion - */ -export interface ChatCompletionRequest { - text: string -} - -/** - * Result of chat text area completion (distinct from code editor ChatCompletionResult) - */ -export interface ChatTextCompletionResult { - suggestion: string - requestId: string -} - // ============================================================================ // Conversion Utilities // ============================================================================