diff --git a/core/config/load.ts b/core/config/load.ts index a109482103..0e405301e3 100644 --- a/core/config/load.ts +++ b/core/config/load.ts @@ -215,7 +215,10 @@ async function serializedToIntermediateConfig( promptFiles.push(...readAllGlobalPromptFiles()); for (const file of promptFiles) { - slashCommands.push(slashCommandFromPromptFile(file.path, file.content)); + const slashCommand = slashCommandFromPromptFile(file.path, file.content); + if (slashCommand) { + slashCommands.push(slashCommand); + } } } diff --git a/core/config/promptFile.ts b/core/config/promptFile.ts index ba7a039de4..aa19f3b0c7 100644 --- a/core/config/promptFile.ts +++ b/core/config/promptFile.ts @@ -3,13 +3,19 @@ import path from "path"; import Handlebars from "handlebars"; import * as YAML from "yaml"; -import { BaseContextProvider } from "../context"; import { walkDir } from "../indexing/walkDir"; import { stripImages } from "../llm/images"; import { renderTemplatedString } from "../promptFiles/v1/renderTemplatedString"; import { getBasename } from "../util/index"; -import type { ChatHistory, ChatHistoryItem, ChatMessage, ContextItem, ContinueSDK, IContextProvider, IDE, SlashCommand } from ".."; +import type { + ChatMessage, + ContextItem, + ContinueSDK, + IContextProvider, + IDE, + SlashCommand, +} from ".."; export const DEFAULT_PROMPTS_FOLDER = ".prompts"; @@ -93,12 +99,16 @@ export async function createNewPromptFile( export function slashCommandFromPromptFile( path: string, content: string, -): SlashCommand { - const { name, description, systemMessage, prompt } = parsePromptFile( +): SlashCommand | null { + const { name, description, systemMessage, prompt, version } = parsePromptFile( path, content, ); + if (version !== 1) { + return null; + } + return { name, description, @@ -134,6 +144,7 @@ function parsePromptFile(path: string, content: string) { const preamble = YAML.parse(preambleRaw) ?? {}; const name = preamble.name ?? getBasename(path).split(".prompt")[0]; const description = preamble.description ?? name; + const version = preamble.version ?? 2; let systemMessage: string | undefined = undefined; if (prompt.includes("")) { @@ -141,7 +152,7 @@ function parsePromptFile(path: string, content: string) { prompt = prompt.split("")[1].trim(); } - return { name, description, systemMessage, prompt }; + return { name, description, systemMessage, prompt, version }; } function extractUserInput(input: string, commandName: string): string { @@ -151,7 +162,11 @@ function extractUserInput(input: string, commandName: string): string { return input; } -async function renderPrompt(prompt: string, context: ContinueSDK, userInput: string) { +async function renderPrompt( + prompt: string, + context: ContinueSDK, + userInput: string, +) { const helpers = getContextProviderHelpers(context); // A few context providers that don't need to be in config.json to work in .prompt files diff --git a/core/indexing/docs/DocsService.ts b/core/indexing/docs/DocsService.ts index 979af63d08..46fedf9d08 100644 --- a/core/indexing/docs/DocsService.ts +++ b/core/indexing/docs/DocsService.ts @@ -362,11 +362,16 @@ export default class DocsService { isPreIndexedDoc: !!preIndexedDocs[startUrl], }); - const docs: LanceDbDocsRow[] = await table - .search(vector) - .limit(nRetrieve) - .where(`starturl = '${startUrl}'`) - .execute(); + let docs: LanceDbDocsRow[] = []; + try { + docs = await table + .search(vector) + .limit(nRetrieve) + .where(`starturl = '${startUrl}'`) + .execute(); + } catch (e: any) { + console.error("Error retrieving chunks from LanceDB", e); + } const hasIndexedDoc = await this.hasIndexedDoc(startUrl); @@ -553,9 +558,8 @@ export default class DocsService { private async getLanceTableNameFromEmbeddingsProvider( isPreIndexedDoc: boolean, ) { - const embeddingsProvider = await this.getEmbeddingsProvider( - isPreIndexedDoc, - ); + const embeddingsProvider = + await this.getEmbeddingsProvider(isPreIndexedDoc); const tableName = this.sanitizeLanceTableName( `${DocsService.lanceTableName}${embeddingsProvider.id}`, diff --git a/core/indexing/docs/preIndexedDocs.ts b/core/indexing/docs/preIndexedDocs.ts index 48b777b21f..01935af9e0 100644 --- a/core/indexing/docs/preIndexedDocs.ts +++ b/core/indexing/docs/preIndexedDocs.ts @@ -325,6 +325,11 @@ const preIndexedDocs: Record< rootUrl: "https://awscli.amazonaws.com/v2/documentation/api/latest/", faviconUrl: "https://docs.aws.amazon.com/favicon.ico", }, + "https://llama-stack.readthedocs.io/": { + title: "Llama Stack", + startUrl: "https://llama-stack.readthedocs.io/", + rootUrl: "https://llama-stack.readthedocs.io/", + }, }; export default preIndexedDocs; diff --git a/core/promptFiles/v2/createNewPromptFile.ts b/core/promptFiles/v2/createNewPromptFile.ts index 8f85baf55c..a8ea871092 100644 --- a/core/promptFiles/v2/createNewPromptFile.ts +++ b/core/promptFiles/v2/createNewPromptFile.ts @@ -66,11 +66,14 @@ export async function createNewPromptFileV2( counter++; } while (await ide.fileExists(promptFilePath)); + const globalContext = new GlobalContext(); const PROMPT_FILE = - new GlobalContext().get("hasAlreadyCreatedAPromptFile") === true + globalContext.get("hasAlreadyCreatedAPromptFile") === true ? DEFAULT_PROMPT_FILE : FIRST_TIME_DEFAULT_PROMPT_FILE; + globalContext.update("hasAlreadyCreatedAPromptFile", true); + await ide.writeFile(promptFilePath, PROMPT_FILE); await ide.openFile(promptFilePath); } diff --git a/extensions/vscode/package-lock.json b/extensions/vscode/package-lock.json index 3f6ace66fa..3f4123969e 100644 --- a/extensions/vscode/package-lock.json +++ b/extensions/vscode/package-lock.json @@ -1,12 +1,12 @@ { "name": "continue", - "version": "0.9.226", + "version": "0.9.228", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "continue", - "version": "0.9.226", + "version": "0.9.228", "license": "Apache-2.0", "dependencies": { "@electron/rebuild": "^3.2.10", diff --git a/extensions/vscode/package.json b/extensions/vscode/package.json index eeb7124abb..30828f3009 100644 --- a/extensions/vscode/package.json +++ b/extensions/vscode/package.json @@ -2,7 +2,7 @@ "name": "continue", "icon": "media/icon.png", "author": "Continue Dev, Inc", - "version": "0.9.227", + "version": "0.9.228", "repository": { "type": "git", "url": "https://github.com/continuedev/continue" diff --git a/extensions/vscode/src/lang-server/promptFileCompletions.ts b/extensions/vscode/src/lang-server/promptFileCompletions.ts index 4dfd1a9efd..ef873b44dc 100644 --- a/extensions/vscode/src/lang-server/promptFileCompletions.ts +++ b/extensions/vscode/src/lang-server/promptFileCompletions.ts @@ -141,6 +141,12 @@ class YamlKeysCompletionItemProvider implements vscode.CompletionItemProvider { const lineText = document.lineAt(position).text; const textBeforeCursor = lineText.substring(0, position.character); + // 0. If no delimiter in the file, return no completions + const fullContent = document.getText(); + if (!fullContent.includes("---")) { + return undefined; + } + // 1. Check if the cursor is in YAML section (before --- delimiter) const beforeDelimiter = isCursorBeforeDelimiter(document, position); @@ -160,7 +166,7 @@ class YamlKeysCompletionItemProvider implements vscode.CompletionItemProvider { vscode.CompletionItemKind.Property, ); item.documentation = new vscode.MarkdownString(key.description); - item.insertText = key + ": "; + item.insertText = key.key + ": "; return item; }); diff --git a/gui/src/pages/edit.tsx b/gui/src/pages/edit.tsx index b2a7e4e773..9faf015781 100644 --- a/gui/src/pages/edit.tsx +++ b/gui/src/pages/edit.tsx @@ -1,6 +1,7 @@ import { ArrowLeftIcon } from "@heroicons/react/24/outline"; import { Editor, JSONContent } from "@tiptap/core"; import { InputModifiers } from "core"; +import { stripImages } from "core/llm/images"; import { getBasename } from "core/util"; import { usePostHog } from "posthog-js/react"; import { useContext, useEffect, useState } from "react"; @@ -71,7 +72,17 @@ const EditHistoryDiv = styled.div` } `; -const EDIT_ALLOWS_CONTEXT_PROVIDERS = ["file", "code"]; +const EDIT_DISALLOWED_CONTEXT_PROVIDERS = [ + "codebase", + "tree", + "open", + "web", + "diff", + "folder", + "search", + "debugger", + "repo-map", +]; function Edit() { const posthog = usePostHog(); @@ -174,7 +185,7 @@ function Edit() { border={`1px solid #aa0`} availableContextProviders={availableContextProviders.filter( (provider) => - EDIT_ALLOWS_CONTEXT_PROVIDERS.includes(provider.title), + !EDIT_DISALLOWED_CONTEXT_PROVIDERS.includes(provider.title), )} historyKey="edit" availableSlashCommands={[]} @@ -184,15 +195,21 @@ function Edit() { modifiers: InputModifiers, editor: Editor, ): Promise { - const [_, __, prompt] = await resolveEditorContent( - editorState, - { - noContext: true, - useCodebase: false, - }, - ideMessenger, - [], - ); + const [contextItems, __, userInstructions] = + await resolveEditorContent( + editorState, + { + noContext: true, + useCodebase: false, + }, + ideMessenger, + [], + ); + + const prompt = [ + ...contextItems.map((item) => item.content), + stripImages(userInstructions), + ].join("\n\n"); ideMessenger.request("edit/sendPrompt", { prompt, range: editModeState.highlightedCode,