Skip to content

Instantly share code, notes, and snippets.

@dminkovski
Created February 7, 2025 11:44
Show Gist options
  • Save dminkovski/16395a0bcf712eec597f288edb3e594f to your computer and use it in GitHub Desktop.
Save dminkovski/16395a0bcf712eec597f288edb3e594f to your computer and use it in GitHub Desktop.
Register llm tools and their implementation function.
import { exec } from 'child_process';
import * as vscode from 'vscode';
export function registerChatTools(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.lm.registerTool("runScript", new RunInTerminalTool()));
}
interface IRunInTerminalParameters {
command: string;
}
export class RunInTerminalTool
implements vscode.LanguageModelTool<IRunInTerminalParameters> {
async invoke(
options: vscode.LanguageModelToolInvocationOptions<IRunInTerminalParameters>,
_token: vscode.CancellationToken
) {
const params = options.input as IRunInTerminalParameters;
try{
// When starting the server, create a new terminal
if (params.command.includes("start") || params.command.includes("server.ts")) {
const terminal = vscode.window.createTerminal("Copilot Terminal");
terminal.show();
terminal.sendText(params.command);
return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart("Send command to new terminal window.")]);
}
// Run the command asynchronously
const { stdout, stderr } = await execAsyncWithTimeout(params.command, 10000);
return new vscode.LanguageModelToolResult([
new vscode.LanguageModelTextPart(stdout + " " +stderr),
]);
}
catch(err:any){
return new vscode.LanguageModelToolResult([new vscode.LanguageModelTextPart(JSON.stringify(err))]);
}
}
async prepareInvocation(
options: vscode.LanguageModelToolInvocationPrepareOptions<IRunInTerminalParameters>,
_token: vscode.CancellationToken
) {
const confirmationMessages = {
title: 'Run command in terminal',
message: new vscode.MarkdownString(
`Run this command in a terminal?` +
`\t${options.input.command}`
),
};
return {
confirmationMessages,
invocationMessage: `Running command in terminal`,
};
}
}
async function execAsyncWithTimeout(command: string, timeout: number): Promise<{ stdout: string, stderr: string }> {
return new Promise((resolve, reject) => {
const child = exec(command, (error, stdout, stderr) => {
if (error) {
reject(`${error} ${stdout}, ${stderr}`);
} else {
resolve({ stdout, stderr });
}
});
setTimeout(() => {
child.kill();
resolve({stdout:'Command timed out or successfully running over 10 seconds', stderr:''});
}, timeout);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment