Skip to content
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

Added Copilot UI elements - I23 #26

Merged
merged 1 commit into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
131 changes: 11 additions & 120 deletions client/package-lock.json

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

34 changes: 34 additions & 0 deletions client/src/browserClientMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ import {
loadModels,
} from './commands/loadModels';

import { inlineSuggestionProvider } from './copilot/inlineSuggestionProvider';
import { promptProvider } from './copilot/promptProvider';
import { createSettingsWebview } from './copilot/configSetting';
import { createStatusBarItem } from './copilot/statusBarItemProvider';
import { GENERAL, STATUS_BAR } from './constants';

/**
* Called when VS Code extension is activated. The conditions for
* activation are specified in package.json (e.g. opening a .cto file)
Expand Down Expand Up @@ -73,6 +79,34 @@ export async function activate(context: vscode.ExtensionContext) {

context.subscriptions.push(vscode.commands
.registerCommand('cicero-vscode-extension.loadModels', (file) => loadModels(client,file)));

// Register the inline suggestion provider
context.subscriptions.push(vscode.languages.registerInlineCompletionItemProvider(
{ pattern: '**/*' }, // Apply to all file types
inlineSuggestionProvider
));

// Register the prompt provider command, startPromptProviderUI
context.subscriptions.push(vscode.commands
.registerCommand('cicero-vscode-extension.startPromptProviderUI', () => promptProvider.showPromptInputBox(client)));

// Register the settings webview command, configureSettings
context.subscriptions.push(vscode.commands
.registerCommand('cicero-vscode-extension.configureSettings', () => createSettingsWebview(context)));

// Register the quick pick command
context.subscriptions.push(vscode.commands.registerCommand('cicero-vscode-extension.showQuickPick', async () => {
const options = [GENERAL.QUICK_PICK_OPTION_SETTINGS, GENERAL.QUICK_PICK_OPTION_SUGGESTIONS];
const selection = await vscode.window.showQuickPick(options, { placeHolder: GENERAL.QUICK_PICK_PLACEHOLDER });
if (selection === GENERAL.QUICK_PICK_OPTION_SETTINGS) {
vscode.commands.executeCommand('cicero-vscode-extension.configureSettings');
} else if (selection === GENERAL.QUICK_PICK_OPTION_SUGGESTIONS) {
vscode.commands.executeCommand('cicero-vscode-extension.startPromptProviderUI');
}
}));

// Create and show the status bar item, statusBarItem
createStatusBarItem(context);
}

function createWorkerLanguageClient(context: vscode.ExtensionContext, clientOptions: LanguageClientOptions) {
Expand Down
61 changes: 61 additions & 0 deletions client/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Constants for VS Code prompts and error messages
export const ERROR_MESSAGES = {
NO_ACTIVE_EDITOR: "No active editor found.",
NO_API_KEY: "API key is required.",
NO_API_URL: "API URL is required.",
NO_MODEL_NAME: "Model name is required.",
NO_MAX_TOKENS: "Max tokens is required.",
NO_TEMPERATURE: "Temperature is required.",
NO_ADDITIONAL_PARAMS: "Additional parameters are required."
};

// General constants
export const GENERAL = {
ACTIVATION_MESSAGE: 'Accord Project Extension activated',
CLIENT_READY_MESSAGE: 'Accord Project client is ready',
QUICK_PICK_PLACEHOLDER: 'Choose an action',
QUICK_PICK_OPTION_SETTINGS: '$(gear) Open Copilot Settings',
QUICK_PICK_OPTION_SUGGESTIONS: '$(copilot) Get Inline Suggestions',
PATTERN_ALL_FILES: '**/*'
};

// Constants for prompts
export const PROMPTS = {
INPUT_BOX: "Enter your prompt for AI-driven suggestion",
ENTER_API_KEY: "Enter your API key",
ENTER_API_URL: "Enter the API URL",
ENTER_MODEL_NAME: "Enter the model name",
ENTER_MAX_TOKENS: "Enter the maximum number of tokens",
ENTER_TEMPERATURE: "Enter the temperature value",
ENTER_ADDITIONAL_PARAMS: "Enter additional parameters as a JSON string"
};

// Constants for status bar
export const STATUS_BAR = {
TEXT: '$(copilot) Accord Copilot',
TOOLTIP: 'Click to access Accord Copilot settings or suggestions',
COMMAND: 'cicero-vscode-extension.showQuickPick',
PRIORITY: 100
};

// Constants for line range calculations
export const LINE_RANGE = {
START_OFFSET: 10,
END_OFFSET: 10
};

// Default configuration values
export const CONFIG_DEFAULTS = {
apiKey: '',
apiUrl: '',
modelName: 'gpt-4',
maxTokens: 100,
temperature: 0.7,
additionalParams: {}
};






43 changes: 43 additions & 0 deletions client/src/copilot/configSetting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as vscode from 'vscode';
import { CONFIG_DEFAULTS } from '../constants';
import { htmlTemplate } from './templates/settingsView';
import { cssTemplate } from './templates/settingsStyle';
import { scriptTemplate } from './templates/settingScript';

export function createSettingsWebview(context: vscode.ExtensionContext) {
const panel = vscode.window.createWebviewPanel(
'copilotSettings',
'Copilot Settings',
vscode.ViewColumn.One,
{
enableScripts: true
}
);

const config = vscode.workspace.getConfiguration('cicero-vscode-extension');
const configValues = {
apiKey: config.get('apiKey', CONFIG_DEFAULTS.apiKey),
apiUrl: config.get('apiUrl', CONFIG_DEFAULTS.apiUrl),
modelName: config.get('modelName', CONFIG_DEFAULTS.modelName),
maxTokens: config.get('maxTokens', CONFIG_DEFAULTS.maxTokens).toString(),
temperature: config.get('temperature', CONFIG_DEFAULTS.temperature).toString(),
additionalParams: JSON.stringify(config.get('additionalParams', CONFIG_DEFAULTS.additionalParams), null, 2)
};

panel.webview.html = htmlTemplate(cssTemplate, scriptTemplate, configValues);

panel.webview.onDidReceiveMessage(async message => {
switch (message.command) {
case 'saveSettings':
await config.update('apiKey', message.apiKey, vscode.ConfigurationTarget.Global);
await config.update('apiUrl', message.apiUrl, vscode.ConfigurationTarget.Global);
await config.update('modelName', message.modelName, vscode.ConfigurationTarget.Global);
await config.update('maxTokens', message.maxTokens, vscode.ConfigurationTarget.Global);
await config.update('temperature', message.temperature, vscode.ConfigurationTarget.Global);
await config.update('additionalParams', JSON.parse(message.additionalParams), vscode.ConfigurationTarget.Global);
vscode.window.showInformationMessage('Configuration updated successfully!');
break;
}
});
}

35 changes: 35 additions & 0 deletions client/src/copilot/inlineSuggestionProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as vscode from 'vscode';
import { getDummySuggestion } from './promptParser';
import { getSurroundingLines } from '../utils';

const debounceDelay = 2000; // 2 seconds
let debouncePromise: Promise<vscode.InlineCompletionItem[] | null> | null = null;

export const inlineSuggestionProvider: vscode.InlineCompletionItemProvider = {
provideInlineCompletionItems: async (document, position, context, token) => {
// Cancel any existing debounce promise
if (debouncePromise) {
debouncePromise = null;
}

// Set a new debounce promise
debouncePromise = new Promise<vscode.InlineCompletionItem[] | null>((resolve) => {
setTimeout(async () => {
const lineText = document.lineAt(position.line).text;
const surroundingLines = await getSurroundingLines(document, position);
const prompt = `${surroundingLines}\n${lineText}`;
const suggestion = await getDummySuggestion(prompt);
const items: vscode.InlineCompletionItem[] = [
new vscode.InlineCompletionItem(
suggestion,
new vscode.Range(position, position.translate(0, 10))
)
];
resolve(items);
}, debounceDelay);
});

// Wait for the debounce promise to resolve
return debouncePromise || null;
}
};
37 changes: 37 additions & 0 deletions client/src/copilot/promptParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as vscode from 'vscode';

export function getDummySuggestion(prompt: string): string {

const config = vscode.workspace.getConfiguration('cicero-vscode-extension');
const apiKey = config.get<string>('apiKey');
const apiUrl = config.get<string>('apiUrl');
const modelName = config.get<string>('modelName');
const maxTokens = config.get<number>('maxTokens');
const temperature = config.get<number>('temperature');
const topP = config.get<number>('topP');
const additionalParams = config.get<any>('additionalParams');

// // Construct the API call using the user-provided configuration
// const response = await fetch(apiUrl, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// 'Authorization': `Bearer ${apiKey}`
// },
// body: JSON.stringify({
// model: modelName,
// prompt: prompt,
// max_tokens: maxTokens,
// temperature: temperature,
// top_p: topP,
// ...additionalParams
// })
// });

// const data = await response.json();
// return data.choices[0].text.trim();

// For now, return a dummy suggestion
// In the future, this function will call the corresponding LLM's API
return 'This is a dummy suggestion';
}
Loading