Skip to content

Commit

Permalink
Open ai (#23)
Browse files Browse the repository at this point in the history
* feed error msg to openai

* ai helper work

---------

Co-authored-by: Hariharan Subramanian <hsubramanian@microsoft.com>
  • Loading branch information
Tatsinnit and hsubramanianaks committed Sep 13, 2023
1 parent b73bbce commit afc7dec
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/commands/aksKubectlCommands/aksKubectlCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { failed } from '../utils/errorable';
import * as tmpfile from '../utils/tempfile';
import { KubectlDataProvider, KubectlPanel } from '../../panels/KubectlPanel';
import { getKubectlCustomCommands } from '../utils/config';
import { openaiHelper } from '../utils/helper/openaiHelper';
// import { openaiHelper } from '../utils/helper/openaiHelper';

export async function aksRunKubectlCommands(_context: IActionContext, target: any) {
const kubectl = await k8s.extension.kubectl.v1;
Expand Down Expand Up @@ -43,7 +43,7 @@ export async function aksRunKubectlCommands(_context: IActionContext, target: an

const customCommands = getKubectlCustomCommands();
// test sake only.
await openaiHelper();
// await openaiHelper('How can use kubectl?');
const kubeConfigFile = await tmpfile.createTempFile(clusterInfo.result.kubeconfigYaml, "yaml");
const dataProvider = new KubectlDataProvider(kubectl, kubeConfigFile.filePath, clusterInfo.result.name, customCommands);
const panel = new KubectlPanel(extension.result.extensionUri);
Expand Down
21 changes: 12 additions & 9 deletions src/commands/utils/helper/openaiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ const openai = new OpenAI({
apiKey: process.env["OPENAI_API_KEY"]
});

export async function openaiHelper() {
// Question: How can use kubectl? is placeholder for the user input.
const teststream = await openai.chat.completions.create({ messages: [{ role: 'user', content: 'How can use kubectl?' }], model: 'gpt-3.5-turbo', stream: true }, {
timeout: 5 * 1000,
});

for await (const part of teststream) {
process.stdout.write(part.choices[0]?.delta?.content || '');
export async function openaiHelper(error: any): Promise<string | null | undefined> {
if (!error) {
return;
}
let content = error;

console.log(teststream);
if (error?.error) {
content = error?.error;
}
const response = await openai.chat.completions.create({ messages: [{ role: 'user', content: content }], model: 'gpt-3.5-turbo' }, {
timeout: 30000,
});
console.log(response);
return response.choices[0]?.message?.content || '';
}
15 changes: 13 additions & 2 deletions src/panels/KubectlPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { BasePanel, PanelDataProvider } from "./BasePanel";
import { invokeKubectlCommand } from "../commands/utils/kubectl";
import { InitialState, PresetCommand, ToVsCodeMsgDef, ToWebViewMsgDef } from "../webview-contract/webviewDefinitions/kubectl";
import { addKubectlCustomCommand, deleteKubectlCustomCommand } from "../commands/utils/config";
import { openaiHelper } from "../commands/utils/helper/openaiHelper";

export class KubectlPanel extends BasePanel<"kubectl"> {
constructor(extensionUri: Uri) {
Expand Down Expand Up @@ -44,15 +45,25 @@ export class KubectlDataProvider implements PanelDataProvider<"kubectl"> {
const kubectlresult = await invokeKubectlCommand(this.kubectl, this.kubeConfigFilePath, command);

if (failed(kubectlresult)) {
// TODO: Run some kind of AI processing over the command and error to generate an explanation.
const explanation = undefined;
const aiMsg = await openaiHelper(kubectlresult);
const explanation = aiMsg ? `OpenAI GPT-3 Suggestion: ${aiMsg}` : undefined;
webview.postMessage({
command: "runCommandResponse", parameters: {
errorMessage: kubectlresult.error,
explanation
}
});
return;
}

if (kubectlresult.result.stderr !== "" || kubectlresult.result.stdout === "") {
const explanation = undefined;
webview.postMessage({
command: "runCommandResponse", parameters: {
errorMessage: kubectlresult.result.stderr,
explanation
}
});
return;
}

Expand Down
2 changes: 1 addition & 1 deletion webview-ui/src/Kubectl/CommandOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export function CommandOutput(props: CommandOutputProps) {
{props.isCommandRunning && <VSCodeProgressRing />}
{hasOutput && <pre>{props.output}</pre>}
{hasError && <pre className={styles.error}>{props.errorMessage}</pre>}
{hasExplanation && <pre>{props.explanation}</pre>}
{hasExplanation && <pre className={styles.warning}>{props.explanation}</pre>}
</>
);
}
4 changes: 4 additions & 0 deletions webview-ui/src/Kubectl/Kubectl.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,7 @@ ul.commandList .commandDelete:hover {
pre.error {
color: var(--vscode-testing-iconFailed);
}

pre.explanation {
color: var(--vscode-editor-foreground);
}
4 changes: 2 additions & 2 deletions webview-ui/src/Kubectl/Kubectl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function Kubectl(props: InitialState) {
}

function handleRunCommand(command: string) {
setState({...state, isCommandRunning: true, output: undefined, errorMessage: undefined});
setState({...state, isCommandRunning: true, output: undefined, errorMessage: undefined, explanation: undefined});
vscode.postMessage({ command: "runCommandRequest", parameters: {command: command.trim()} });
}

Expand Down Expand Up @@ -93,7 +93,7 @@ export function Kubectl(props: InitialState) {
<div className={styles.mainContent}>
<CommandInput command={state.selectedCommand || ''} matchesExisting={matchesExisting} onCommandUpdate={handleCommandUpdate} onRunCommand={handleRunCommand} onSaveRequest={handleSaveRequest} />
<VSCodeDivider />
<CommandOutput isCommandRunning={state.isCommandRunning} output={state.output} errorMessage={state.errorMessage} />
<CommandOutput isCommandRunning={state.isCommandRunning} output={state.output} errorMessage={state.errorMessage} explanation={state.explanation}/>
</div>

<SaveCommandDialog isShown={state.isSaveDialogShown} existingNames={allCommandNames} onCancel={handleSaveDialogCancel} onAccept={handleSaveDialogAccept} />
Expand Down

0 comments on commit afc7dec

Please sign in to comment.