Skip to content

feat: conversation starters #4758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ Icon?
notes.md

manual-testing-sandbox/.idea/**
manual-testing-sandbox/.continue/**
extensions/intellij/.idea/**

**/.idea/workspace.xml
Expand Down
2 changes: 1 addition & 1 deletion binary/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions core/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function slashFromCustomCommand(
return {
name: customCommand.name,
description: customCommand.description ?? "",
prompt: customCommand.prompt,
run: async function* ({ input, llm, history, ide, completionOptions }) {
// Remove slash command prefix from input
let userInput = input;
Expand Down
3 changes: 2 additions & 1 deletion core/commands/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { v4 as uuidv4 } from "uuid";

import { ContextItemWithId, RangeInFileWithContents } from "../";
import { findUriInDirs, getUriPathBasename } from "../util/uri";
import { v4 as uuidv4 } from "uuid";

export function rifWithContentsToContextItem(
rif: RangeInFileWithContents,
Expand Down
11 changes: 3 additions & 8 deletions core/config/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import ContinueProxyContextProvider from "../context/providers/ContinueProxyCont
import CustomContextProviderClass from "../context/providers/CustomContextProvider";
import FileContextProvider from "../context/providers/FileContextProvider";
import { contextProviderClassFromName } from "../context/providers/index";
import PromptFilesContextProvider from "../context/providers/PromptFilesContextProvider";
import { useHub } from "../control-plane/env";
import { allEmbeddingsProviders } from "../indexing/allEmbeddingsProviders";
import { BaseLLM } from "../llm";
Expand Down Expand Up @@ -401,8 +400,6 @@ async function intermediateToFinalConfig(
...(!config.disableIndexing
? [new CodebaseContextProvider(codebaseContextParams)]
: []),
// Add prompt files provider if enabled
...(loadPromptFiles ? [new PromptFilesContextProvider({})] : []),
];

const DEFAULT_CONTEXT_PROVIDERS_TITLES = DEFAULT_CONTEXT_PROVIDERS.map(
Expand Down Expand Up @@ -667,11 +664,9 @@ async function finalToBrowserConfig(
models: final.models.map(llmToSerializedModelDescription),
systemMessage: final.systemMessage,
completionOptions: final.completionOptions,
slashCommands: final.slashCommands?.map((s) => ({
name: s.name,
description: s.description,
params: s.params, // TODO: is this why params aren't referenced properly by slash commands?
})),
slashCommands: final.slashCommands?.map(
({ run, ...slashCommandDescription }) => slashCommandDescription,
),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stylistically prefer old way, not important

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Submitted this to the @tomasz-stefaniak oracle (e.g. Clean Code assistant)

Prompt

    slashCommands: final.slashCommands?.map(
      ({ run, ...slashCommandDescription }) => slashCommandDescription,
    ),
slashCommands: final.slashCommands?.map((s) => ({
name: s.name,
description: s.description,
params: s.params, // TODO: is this why params aren't referenced properly by slash commands?
}))

which version is cleaner?


Response
The first version using destructuring is cleaner and more maintainable for several reasons:

slashCommands: final.slashCommands?.map(
  ({ run, ...slashCommandDescription }) => slashCommandDescription,
),

Advantages of the first version:

  1. It uses object destructuring with rest parameters (...) to explicitly show we're removing the run property while keeping everything else
  2. It's more maintainable - if new properties are added to slash commands in the future, they'll automatically be included without modifying this code
  3. It follows the Open/Closed Principle better - the code is open for extension (new properties) but closed for modification
  4. It's more concise and has less repetition

The second version:

slashCommands: final.slashCommands?.map((s) => ({
  name: s.name,
  description: s.description,
  params: s.params,
}))

Has these drawbacks:

  1. It explicitly lists every property that needs to be copied
  2. It's more brittle - if new properties are added, this code needs to be updated
  3. More verbose and repetitive
  4. Higher chance of human error when maintaining the property list

The first version is the better choice as it's more maintainable, flexible, and follows SOLID principles better. It also makes it very clear that we're intentionally excluding the run property while preserving everything else.


I made the update mostly stylistically but I think I agree with the points made by the model.

Copy link
Collaborator

@RomneyDa RomneyDa Mar 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good!

contextProviders: final.contextProviders?.map((c) => c.description),
disableIndexing: final.disableIndexing,
disableSessionTitles: final.disableSessionTitles,
Expand Down
2 changes: 1 addition & 1 deletion core/config/profile/ControlPlaneProfileLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ConfigJson } from "@continuedev/config-types";
import { ConfigResult } from "@continuedev/config-yaml";

import { ControlPlaneClient } from "../../control-plane/client.js";
import { PRODUCTION_ENV } from "../../control-plane/env.js";
import {
ContinueConfig,
IDE,
Expand All @@ -10,7 +11,6 @@ import {
} from "../../index.js";
import { ProfileDescription } from "../ProfileLifecycleManager.js";

import { PRODUCTION_ENV } from "../../control-plane/env.js";
import doLoadConfig from "./doLoadConfig.js";
import { IProfileLoader } from "./IProfileLoader.js";

Expand Down
3 changes: 1 addition & 2 deletions core/config/profile/PlatformProfileLoader.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { AssistantUnrolled, ConfigResult } from "@continuedev/config-yaml";

import { ControlPlaneClient } from "../../control-plane/client.js";
import { getControlPlaneEnv } from "../../control-plane/env.js";
import { ContinueConfig, IDE, IdeSettings } from "../../index.js";

import { ProfileDescription } from "../ProfileLifecycleManager.js";

import { getControlPlaneEnv } from "../../control-plane/env.js";
import doLoadConfig from "./doLoadConfig.js";
import { IProfileLoader } from "./IProfileLoader.js";

Expand Down
2 changes: 2 additions & 0 deletions core/config/profile/doLoadConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ConfigValidationError,
ModelRole,
} from "@continuedev/config-yaml";

import {
ContinueConfig,
ContinueRcJson,
Expand All @@ -26,6 +27,7 @@ import { loadContinueConfigFromJson } from "../load";
import { migrateJsonSharedConfig } from "../migrateSharedConfig";
import { rectifySelectedModelsFromGlobalContext } from "../selectedModels";
import { loadContinueConfigFromYaml } from "../yaml/loadYaml";

import { PlatformConfigMetadata } from "./PlatformProfileLoader";

export default async function doLoadConfig(
Expand Down
1 change: 1 addition & 0 deletions core/config/validation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ConfigValidationError } from "@continuedev/config-yaml";

import { ModelDescription, SerializedContinueConfig } from "../";
import { Telemetry } from "../util/posthog";

Expand Down
2 changes: 0 additions & 2 deletions core/config/yaml/loadYaml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import CodebaseContextProvider from "../../context/providers/CodebaseContextProv
import DocsContextProvider from "../../context/providers/DocsContextProvider";
import FileContextProvider from "../../context/providers/FileContextProvider";
import { contextProviderClassFromName } from "../../context/providers/index";
import PromptFilesContextProvider from "../../context/providers/PromptFilesContextProvider";
import { ControlPlaneClient } from "../../control-plane/client";
import { allEmbeddingsProviders } from "../../indexing/allEmbeddingsProviders";
import FreeTrial from "../../llm/llms/FreeTrial";
Expand Down Expand Up @@ -334,7 +333,6 @@ async function configYamlToContinueConfig(
const DEFAULT_CONTEXT_PROVIDERS = [
new FileContextProvider({}),
new CodebaseContextProvider(codebaseContextParams),
new PromptFilesContextProvider({}),
];

const DEFAULT_CONTEXT_PROVIDERS_TITLES = DEFAULT_CONTEXT_PROVIDERS.map(
Expand Down
57 changes: 0 additions & 57 deletions core/context/providers/PromptFilesContextProvider.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯🤯🤯🤯🤯

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is valid since all prompt files are now rendered as slash commands.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was just excitement hahaha

This file was deleted.

58 changes: 30 additions & 28 deletions core/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ export interface IndexingProgressUpdate {
desc: string;
shouldClearIndexes?: boolean;
status:
| "loading"
| "indexing"
| "done"
| "failed"
| "paused"
| "disabled"
| "cancelled";
| "loading"
| "indexing"
| "done"
| "failed"
| "paused"
| "disabled"
| "cancelled";
debugInfo?: string;
}

Expand Down Expand Up @@ -316,7 +316,12 @@ export interface CompletionOptions extends BaseCompletionOptions {
model: string;
}

export type ChatMessageRole = "user" | "assistant" | "thinking" | "system" | "tool";
export type ChatMessageRole =
| "user"
| "assistant"
| "thinking"
| "system"
| "tool";

export type TextMessagePart = {
type: "text";
Expand Down Expand Up @@ -692,10 +697,10 @@ export interface IDE {
getCurrentFile(): Promise<
| undefined
| {
isUntitled: boolean;
path: string;
contents: string;
}
isUntitled: boolean;
path: string;
contents: string;
}
>;

getLastFileSaveTimestamp?(): number;
Expand Down Expand Up @@ -761,6 +766,7 @@ export interface ContinueSDK {
export interface SlashCommand {
name: string;
description: string;
prompt?: string;
params?: { [key: string]: any };
run: (sdk: ContinueSDK) => AsyncGenerator<string | undefined>;
}
Expand Down Expand Up @@ -864,11 +870,7 @@ export interface ContextProviderWithParams {
params: { [key: string]: any };
}

export interface SlashCommandDescription {
name: string;
description: string;
params?: { [key: string]: any };
}
export type SlashCommandDescription = Omit<SlashCommand, "run">;

export interface CustomCommand {
name: string;
Expand All @@ -879,11 +881,11 @@ export interface CustomCommand {
export interface Prediction {
type: "content";
content:
| string
| {
type: "text";
text: string;
}[];
| string
| {
type: "text";
text: string;
}[];
}

export interface ToolExtras {
Expand Down Expand Up @@ -1223,9 +1225,9 @@ export interface Config {
embeddingsProvider?: EmbeddingsProviderDescription | ILLM;
/** The model that Continue will use for tab autocompletions. */
tabAutocompleteModel?:
| CustomLLM
| ModelDescription
| (CustomLLM | ModelDescription)[];
| CustomLLM
| ModelDescription
| (CustomLLM | ModelDescription)[];
/** Options for tab autocomplete */
tabAutocompleteOptions?: Partial<TabAutocompleteOptions>;
/** UI styles customization */
Expand Down Expand Up @@ -1319,9 +1321,9 @@ export type PackageDetailsSuccess = PackageDetails & {
export type PackageDocsResult = {
packageInfo: ParsedPackageInfo;
} & (
| { error: string; details?: never }
| { details: PackageDetailsSuccess; error?: never }
);
| { error: string; details?: never }
| { details: PackageDetailsSuccess; error?: never }
);

export interface TerminalOptions {
reuseTerminal?: boolean;
Expand Down
11 changes: 5 additions & 6 deletions core/promptFiles/v1/slashCommandFromPromptFile.ts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider renaming/moving file/function to reflect v2 support

Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,15 @@ export function slashCommandFromPromptFileV1(
path: string,
content: string,
): SlashCommand | null {
const { name, description, systemMessage, prompt, version } =
parsePromptFileV1V2(path, content);

if (version !== 1) {
return null;
}
const { name, description, systemMessage, prompt } = parsePromptFileV1V2(
path,
content,
);

return {
name,
description,
prompt,
run: async function* (context) {
const originalSystemMessage = context.llm.systemMessage;
context.llm.systemMessage = systemMessage;
Expand Down
1 change: 1 addition & 0 deletions core/promptFiles/v2/parse.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as YAML from "yaml";

import { getLastNPathParts } from "../../util/uri";

export function extractName(preamble: { name?: string }, path: string): string {
Expand Down
1 change: 1 addition & 0 deletions core/promptFiles/v2/parsePromptFileV1V2.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as YAML from "yaml";

import { getLastNPathParts } from "../../util/uri";

export function parsePromptFileV1V2(path: string, content: string) {
Expand Down
1 change: 1 addition & 0 deletions core/promptFiles/v2/renderPromptFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { contextProviderClassFromName } from "../../context/providers";
import URLContextProvider from "../../context/providers/URLContextProvider";
import { resolveRelativePathInDir } from "../../util/ideUtils";
import { getUriPathBasename } from "../../util/uri";

import { getPreambleAndBody } from "./parse";

async function resolveAttachment(
Expand Down
9 changes: 6 additions & 3 deletions core/protocol/core.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { ConfigResult, ModelRole } from "@continuedev/config-yaml";
import {
ConfigResult,
DevDataLogEvent,
ModelRole,
} from "@continuedev/config-yaml";

import { AutocompleteInput } from "../autocomplete/util/types";
import { ProfileDescription } from "../config/ConfigHandler";
import { OrganizationDescription } from "../config/ProfileLifecycleManager";
import { SharedConfigSchema } from "../config/sharedConfig";
import { GlobalContextModelSelections } from "../util/GlobalContext";

import { DevDataLogEvent } from "@continuedev/config-yaml";
import type {
BrowserSerializedContinueConfig,
ChatMessage,
Expand All @@ -29,7 +33,6 @@ import type {
SlashCommandDescription,
ToolCall,
} from "../";
import { GlobalContextModelSelections } from "../util/GlobalContext";

export type OnboardingModes = "Local" | "Best" | "Custom" | "Quickstart";

Expand Down
2 changes: 1 addition & 1 deletion core/util/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import * as fs from "fs";
import * as os from "os";
import * as path from "path";

import { DevEventName } from "@continuedev/config-yaml";
import * as JSONC from "comment-json";
import dotenv from "dotenv";

import { DevEventName } from "@continuedev/config-yaml";
import { IdeType, SerializedContinueConfig } from "../";
import { defaultConfig, defaultConfigJetBrains } from "../config/default";
import Types from "../config/types";
Expand Down
Loading
Loading