diff --git a/core/commands/index.ts b/core/commands/index.ts index f4a0084da9..72719d832f 100644 --- a/core/commands/index.ts +++ b/core/commands/index.ts @@ -10,7 +10,7 @@ export function slashFromCustomCommand( return { name: customCommand.name, description: customCommand.description ?? "", - run: async function* ({ input, llm, history, ide }) { + run: async function* ({ input, llm, history, ide, completionOptions }) { // Remove slash command prefix from input let userInput = input; if (userInput.startsWith(`/${customCommand.name}`)) { @@ -20,11 +20,16 @@ export function slashFromCustomCommand( } // Render prompt template - const promptUserInput = await renderTemplatedString( - customCommand.prompt, - ide.readFile.bind(ide), - { input: userInput }, - ); + let promptUserInput: string; + if (customCommand.prompt.includes("{{{ input }}}")) { + promptUserInput = await renderTemplatedString( + customCommand.prompt, + ide.readFile.bind(ide), + { input: userInput }, + ); + } else { + promptUserInput = customCommand.prompt + "\n\n" + userInput; + } const messages = [...history]; // Find the last chat message with this slash command and replace it with the user input @@ -67,6 +72,7 @@ export function slashFromCustomCommand( for await (const chunk of llm.streamChat( messages, new AbortController().signal, + completionOptions, )) { yield renderChatMessage(chunk); } diff --git a/core/core.ts b/core/core.ts index dbadb82c0b..28e3af79a2 100644 --- a/core/core.ts +++ b/core/core.ts @@ -20,6 +20,8 @@ import { recentlyEditedFilesCache } from "./context/retrieval/recentlyEditedFile import { ContinueServerClient } from "./continueServer/stubs/client"; import { getAuthUrlForTokenPage } from "./control-plane/auth/index"; import { getControlPlaneEnv } from "./control-plane/env"; +import { DevDataSqliteDb } from "./data/devdataSqlite"; +import { DataLogger } from "./data/log"; import { streamDiffLines } from "./edit/streamDiffLines"; import { CodebaseIndexer, PauseToken } from "./indexing/CodebaseIndexer"; import DocsService from "./indexing/docs/DocsService"; @@ -30,8 +32,6 @@ import { createNewPromptFileV2 } from "./promptFiles/v2/createNewPromptFile"; import { callTool } from "./tools/callTool"; import { ChatDescriber } from "./util/chatDescriber"; import { clipboardCache } from "./util/clipboardCache"; -import { DataLogger } from "./data/log"; -import { DevDataSqliteDb } from "./data/devdataSqlite"; import { GlobalContext } from "./util/GlobalContext"; import historyManager from "./util/history"; import { @@ -131,7 +131,8 @@ export class Core { }); // update additional submenu context providers registered via VSCode API - const additionalProviders = this.configHandler.getAdditionalSubmenuContextProviders(); + const additionalProviders = + this.configHandler.getAdditionalSubmenuContextProviders(); if (additionalProviders.length > 0) { this.messenger.send("refreshSubmenuItems", { providers: additionalProviders, @@ -651,6 +652,7 @@ export class Core { params, historyIndex, selectedCode, + completionOptions, } = msg.data; const { config } = await configHandler.loadConfig(); @@ -699,6 +701,7 @@ export class Core { config, fetch: (url, init) => fetchwithRequestOptions(url, init, config.requestOptions), + completionOptions, })) { if (abortedMessageIds.has(msg.messageId)) { abortedMessageIds.delete(msg.messageId); diff --git a/core/index.d.ts b/core/index.d.ts index ceb6e796bf..159cc022bc 100644 --- a/core/index.d.ts +++ b/core/index.d.ts @@ -736,6 +736,7 @@ export interface ContinueSDK { selectedCode: RangeInFile[]; config: ContinueConfig; fetch: FetchFunction; + completionOptions?: LLMFullCompletionOptions; } export interface SlashCommand { diff --git a/core/protocol/core.ts b/core/protocol/core.ts index 53c052894e..0a3913590a 100644 --- a/core/protocol/core.ts +++ b/core/protocol/core.ts @@ -5,6 +5,7 @@ import { ProfileDescription } from "../config/ConfigHandler"; import { OrganizationDescription } from "../config/ProfileLifecycleManager"; import { SharedConfigSchema } from "../config/sharedConfig"; +import { DevDataLogEvent } from "@continuedev/config-yaml"; import type { BrowserSerializedContinueConfig, ChatMessage, @@ -27,7 +28,6 @@ import type { SiteIndexingConfig, ToolCall, } from "../"; -import { DevDataLogEvent } from "@continuedev/config-yaml"; import { GlobalContextModelSelections } from "../util/GlobalContext"; export type OnboardingModes = "Local" | "Best" | "Custom" | "Quickstart"; @@ -107,6 +107,7 @@ export type ToCoreFromIdeOrWebviewProtocol = { params: any; historyIndex: number; selectedCode: RangeInFile[]; + completionOptions?: LLMFullCompletionOptions; }, AsyncGenerator, ]; diff --git a/gui/src/components/Layout.tsx b/gui/src/components/Layout.tsx index 07c0526753..a10fc7b6ee 100644 --- a/gui/src/components/Layout.tsx +++ b/gui/src/components/Layout.tsx @@ -19,7 +19,6 @@ import { exitEditMode } from "../redux/thunks"; import { loadLastSession, saveCurrentSession } from "../redux/thunks/session"; import { getFontSize, isMetaEquivalentKeyPressed } from "../util"; import { incrementFreeTrialCount } from "../util/freeTrial"; -import { getLocalStorage, setLocalStorage } from "../util/localStorage"; import { ROUTES } from "../util/navigation"; import TextDialog from "./dialogs"; import Footer from "./Footer"; @@ -247,18 +246,19 @@ const Layout = () => { }, [location]); const useHub = useAppSelector(selectUseHub); + // Existing users that have already seen the onboarding card // should be shown an intro card for hub.continue.dev - useEffect(() => { - if (useHub !== true) { - return; - } - const seenHubIntro = getLocalStorage("seenHubIntro"); - if (!onboardingCard.show && !seenHubIntro) { - onboardingCard.setActiveTab("ExistingUserHubIntro"); - } - setLocalStorage("seenHubIntro", true); - }, [onboardingCard.show, useHub]); + // useEffect(() => { + // if (useHub !== true) { + // return; + // } + // const seenHubIntro = getLocalStorage("seenHubIntro"); + // if (!onboardingCard.show && !seenHubIntro) { + // onboardingCard.setActiveTab("ExistingUserHubIntro"); + // } + // setLocalStorage("seenHubIntro", true); + // }, [onboardingCard.show, useHub]); return ( diff --git a/gui/src/context/Auth.tsx b/gui/src/context/Auth.tsx index 03856874ae..967db13219 100644 --- a/gui/src/context/Auth.tsx +++ b/gui/src/context/Auth.tsx @@ -165,7 +165,6 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ useEffect(() => { ideMessenger.request("config/listProfiles", undefined).then((result) => { if (result.status === "success") { - console.log("PROFILES: ", result.content); dispatch( updateProfilesThunk({ profiles: result.content, @@ -179,7 +178,6 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ useWebviewListener( "didChangeAvailableProfiles", async (data) => { - console.log("AVAILABLE: ", data.profiles, data.selectedProfileId); dispatch( updateProfilesThunk({ profiles: data.profiles, diff --git a/gui/src/hooks/useSetup.ts b/gui/src/hooks/useSetup.ts index 714f4ed75e..b86757cbfa 100644 --- a/gui/src/hooks/useSetup.ts +++ b/gui/src/hooks/useSetup.ts @@ -45,7 +45,6 @@ function useSetup() { } hasLoadedConfig.current = true; dispatch(setConfigResult(configResult)); - console.log("selecting 1", profileId); dispatch(selectProfileThunk(profileId)); // Perform any actions needed with the config @@ -95,7 +94,6 @@ function useSetup() { useWebviewListener( "configUpdate", async (update) => { - console.log("CONFIG UPDATE: ", update); if (!update) { return; } diff --git a/gui/src/pages/config/index.tsx b/gui/src/pages/config/index.tsx index f187c1067b..4bb02b7e10 100644 --- a/gui/src/pages/config/index.tsx +++ b/gui/src/pages/config/index.tsx @@ -45,7 +45,6 @@ function ConfigPage() { } = useAuth(); const changeProfileId = (id: string) => { - console.log("selecting 2", id); dispatch(selectProfileThunk(id)); }; @@ -180,43 +179,45 @@ function ConfigPage() { navigate("/")} title="Chat" />
-
-
-

Account

- {!session ? ( -
- You are not signed in. - login(false)}> - Sign in - -
- ) : ( -
- {hubEnabled ? ( - // Hub: show org selector -
- {`Organization`} - + {(session || hubEnabled || controlServerBetaEnabled) && ( +
+
+

Account

+ {!session ? ( +
+ You are not signed in. + login(false)}> + Sign in + +
+ ) : ( +
+ {hubEnabled ? ( + // Hub: show org selector +
+ {`Organization`} + +
+ ) : ( + // Continue for teams: show org text +
You are using Continue for Teams
+ )} +
+ + {session.account.label === "" + ? "Signed in" + : `Signed in as ${session.account.label}`} + + {`Sign out`}
- ) : ( - // Continue for teams: show org text -
You are using Continue for Teams
- )} -
- - {session.account.label === "" - ? "Signed in" - : `Signed in as ${session.account.label}`} - - {`Sign out`}
-
- )} + )} +
-
+ )}
diff --git a/gui/src/redux/thunks/profileAndOrg.ts b/gui/src/redux/thunks/profileAndOrg.ts index 6632b77abf..82a9602c0f 100644 --- a/gui/src/redux/thunks/profileAndOrg.ts +++ b/gui/src/redux/thunks/profileAndOrg.ts @@ -25,12 +25,6 @@ export const selectProfileThunk = createAsyncThunk< let newId = id; - console.log( - "Running Thunk: ", - initialId, - newId, - state.session.availableProfiles, - ); // If no profiles, force clear if (state.session.availableProfiles.length === 0) { newId = null; @@ -49,12 +43,6 @@ export const selectProfileThunk = createAsyncThunk< } // Only update if there's a change - console.log( - "update selected profile?", - newId, - initialId, - state.session.availableProfiles, - ); if ((newId ?? null) !== (initialId ?? null)) { dispatch( setSelectedProfile( @@ -103,7 +91,6 @@ export const updateProfilesThunk = createAsyncThunk< dispatch(setAvailableProfiles(profiles)); // This will trigger reselection if needed - console.log("selecting 3", selectedProfileId); dispatch(selectProfileThunk(selectedProfileId)); }); diff --git a/gui/src/redux/thunks/streamResponse.ts b/gui/src/redux/thunks/streamResponse.ts index 16043daeee..9c0cb4b9af 100644 --- a/gui/src/redux/thunks/streamResponse.ts +++ b/gui/src/redux/thunks/streamResponse.ts @@ -41,8 +41,8 @@ const getSlashCommandForInput = ( if (lastText.startsWith("/")) { slashCommandName = lastText.split(" ")[0].substring(1); - slashCommand = slashCommands.find( - (command) => command.name === slashCommandName, + slashCommand = slashCommands.find((command) => + lastText.startsWith(`/${command.name} `), ); } if (!slashCommand || !slashCommandName) { diff --git a/gui/src/redux/thunks/streamSlashCommand.ts b/gui/src/redux/thunks/streamSlashCommand.ts index 79336bb3d6..c18afd52cb 100644 --- a/gui/src/redux/thunks/streamSlashCommand.ts +++ b/gui/src/redux/thunks/streamSlashCommand.ts @@ -5,6 +5,7 @@ import { RangeInFile, SlashCommandDescription, } from "core"; +import { modelSupportsTools } from "core/llm/autodetect"; import { selectDefaultModel } from "../slices/configSlice"; import { abortStream, streamUpdate } from "../slices/sessionSlice"; import { ThunkApiType } from "../store"; @@ -30,11 +31,18 @@ export const streamSlashCommand = createAsyncThunk< const defaultModel = selectDefaultModel(state); const isStreaming = state.session.isStreaming; const streamAborter = state.session.streamAborter; + const toolSettings = state.ui.toolSettings; if (!defaultModel) { throw new Error("Default model not defined"); } + const useTools = state.ui.useTools; + const includeTools = + useTools && + modelSupportsTools(defaultModel) && + state.session.mode === "chat"; + const modelTitle = defaultModel.title; const checkActiveInterval = setInterval(() => { @@ -55,6 +63,14 @@ export const streamSlashCommand = createAsyncThunk< params: slashCommand.params, historyIndex, selectedCode, + completionOptions: includeTools + ? { + // Temporarily commented out until slash commands are hooked up to the tool use feedback loop + // tools: state.config.config.tools.filter( + // (tool) => toolSettings[tool.function.name] !== "disabled", + // ), + } + : {}, }, streamAborter.signal, )) {