Skip to content

Commit

Permalink
feat: Updated to the new AI PR description endpoint (#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anush008 authored May 19, 2023
1 parent 5c15de5 commit cf8f64c
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 173 deletions.
58 changes: 0 additions & 58 deletions npm-shrinkwrap.json

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

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"@types/node-emoji": "^1.8.2",
"gpt-tokenizer": "^1.0.5",
"node-emoji": "^1.11.0",
"openai-streams": "^5.3.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hot-toast": "^2.4.1",
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ export const SUPABASE_AUTH_COOKIE_NAME = "supabase-auth-token";
export const OPEN_SAUCED_AUTH_TOKEN_KEY = "os-access-token";
export const OPEN_SAUCED_INSIGHTS_DOMAIN = "insights.opensauced.pizza";
export const AI_PR_DESCRIPTION_CONFIG_KEY = "ai-pr-description-config";
export const OPEN_AI_COMPLETION_MODEL_NAME = "gpt-3.5-turbo";

// API endpoints
export const OPEN_SAUCED_USERS_ENDPOINT = "https://api.opensauced.pizza/v1/users";
export const OPEN_SAUCED_REPOS_ENDPOINT = "https://api.opensauced.pizza/v1/repos";
export const OPEN_SAUCED_SESSION_ENDPOINT = "https://api.opensauced.pizza/v1/auth/session";
export const OPEN_SAUCED_USER_INSIGHTS_ENDPOINT = "https://api.opensauced.pizza/v1/user/insights";
export const OPEN_SAUCED_AI_PR_DESCRIPTION_ENDPOINT = "https://api.opensauced.pizza/v1/prs/description/generate";

// GitHub constants/selectors
export const GITHUB_PROFILE_MENU_SELECTOR = ".p-nickname.vcard-username.d-block";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createHtmlElement } from "../../../utils/createHtmlElement";
import openSaucedLogoIcon from "../../../assets/opensauced-icon.svg";
import { getPullRequestAPIURL } from "../../../utils/urlMatchers";
import { getDescriptionContext, isContextWithinBounds } from "../../../utils/fetchGithubAPIData";
import { getDescriptionContext, isOutOfContextBounds } from "../../../utils/fetchGithubAPIData";
import { generateDescription } from "../../../utils/aiprdescription/openai";
import { GITHUB_PR_COMMENT_TEXT_AREA_SELECTOR, OPEN_AI_COMPLETION_MODEL_NAME, SUPABASE_LOGIN_URL } from "../../../constants";
import { insertAtCursorFromStream } from "../../../utils/aiprdescription/cursorPositionInsert";
import { GITHUB_PR_COMMENT_TEXT_AREA_SELECTOR, SUPABASE_LOGIN_URL } from "../../../constants";
import { insertTextAtCursor } from "../../../utils/aiprdescription/cursorPositionInsert";
import { getAIDescriptionConfig } from "../../../utils/aiprdescription/descriptionconfig";
import { isLoggedIn } from "../../../utils/checkAuthentication";
import { getAuthToken, isLoggedIn } from "../../../utils/checkAuthentication";

export const DescriptionGeneratorButton = () => {
const descriptionGeneratorButton = createHtmlElement("a", {
Expand Down Expand Up @@ -42,14 +42,17 @@ const handleSubmit = async () => {
}
logo.classList.toggle("animate-spin");
const [diff, commitMessages] = await getDescriptionContext(url, descriptionConfig.config.source);

if (!isContextWithinBounds([diff, commitMessages], descriptionConfig.config.maxInputLength)) {
if(!diff && !commitMessages) {
logo.classList.toggle("animate-spin");
return alert(`No input context was generated.`)
}
if (isOutOfContextBounds([diff, commitMessages], descriptionConfig.config.maxInputLength)) {
logo.classList.toggle("animate-spin");
return alert(`Max input length exceeded. Try setting the description source to commit-messages.`);
}
const token = await getAuthToken();
const descriptionStream = await generateDescription(
descriptionConfig.config.openai_api_key,
OPEN_AI_COMPLETION_MODEL_NAME,
token,
descriptionConfig.config.language,
descriptionConfig.config.length,
descriptionConfig.config.temperature / 10,
Expand All @@ -64,7 +67,7 @@ descriptionConfig.config.openai_api_key,
}
const textArea = document.getElementsByName(GITHUB_PR_COMMENT_TEXT_AREA_SELECTOR)[0] as HTMLTextAreaElement;

void insertAtCursorFromStream(textArea, descriptionStream);
void insertTextAtCursor(textArea, descriptionStream);
} catch (error: unknown) {
if (error instanceof Error) {
console.error("Description generation error:", error.message);
Expand Down
38 changes: 6 additions & 32 deletions src/pages/aiprdescription.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useContext, useEffect, useReducer, useState } from "react";
import { BiInfoCircle } from "react-icons/bi";
import { FaChevronLeft } from "react-icons/fa";
import OpenSaucedLogo from "../assets/opensauced-logo.svg";
import { RouteContext } from "../App";
Expand All @@ -13,7 +12,7 @@ import {
DescriptionLanguage,
setAIDescriptionConfig,
getDefaultDescriptionConfig,
setDefaultDescriptionConfig,
toggleAIPRDescriptionEnabled,
} from "../utils/aiprdescription/descriptionconfig";
import { useRefs } from "../hooks/useRefs";
import { configurationReducer } from "../utils/aiprdescription/configurationReducer";
Expand All @@ -35,15 +34,13 @@ const AIPRDescription = () => {

dispatch({ type: "SET", value: configData });
setFormDisabled(!configData?.enabled);
console.log(config.config.openai_api_key);
};

void descriptionConfig();
}, []);

const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const openai_api_key = refs.openai_api_key!.getAttribute("value")!;
const length = parseInt(refs.length?.getAttribute("value")!);
const temperature = Number(Number(refs.temperature?.getAttribute("value")!));
const maxInputLength = parseInt(refs.maxInputLength?.getAttribute("value")!);
Expand All @@ -53,7 +50,7 @@ const AIPRDescription = () => {

void setAIDescriptionConfig({
enabled: true,
config: { openai_api_key, length, temperature, maxInputLength, language, source, tone },
config: { length, temperature, maxInputLength, language, source, tone },
});
toast.success("Configuration updated!");
};
Expand Down Expand Up @@ -88,12 +85,12 @@ const AIPRDescription = () => {
}`}
onClick={() => {
setFormDisabled(!formDisabled);
dispatch({ type: "CLEAR", value: null });
dispatch({ type: "TOGGLE_ENABLED", value: config });
void toggleAIPRDescriptionEnabled();
if (formDisabled) {
toast.success("AI PR Description enabled!");
} else {
toast.success("AI PR Description enabled!");
} else {
toast.error("AI PR Description disabled!");
setDefaultDescriptionConfig();
}
}}
>
Expand All @@ -111,29 +108,6 @@ const AIPRDescription = () => {
OpenSauced AI
</h1>

<p className="mb-2 text-gray-300 text-sm">
OpenAI API Key
<BiInfoCircle
className="inline-block ml-1 text-gray-400 align-middle cursor-pointer"
title="Find your API key here"
onClick={() =>
window.open(
"https://platform.openai.com/account/api-keys",
"_blank",
)}
/>
</p>

<input
ref={setRefFromKey("openai_api_key")}
className="p-1.5 rounded-md mb-2 w-full text-black"
pattern="sk-[a-zA-Z0-9]{40,55}"
placeholder="sk-xxxxxxxxxxxxxxxxx"
type="password"
value={config.config.openai_api_key}
onChange={e => dispatch({ type: "SET_OPENAI_API_KEY", value: e.currentTarget.value })}
/>

<div className="grid grid-cols-2 -mx-4 mb-4 text-gray-300 text-sm">
<div className="flex flex-col items-center justify-center">
<p>
Expand Down
6 changes: 3 additions & 3 deletions src/utils/aiprdescription/configurationReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ export const configurationReducer = (state: DescriptionConfig, action: { type: s
case "SET":
newState = action.value;
break;
case "SET_OPENAI_API_KEY":
newState.config.openai_api_key = action.value;
break;
case "SET_LENGTH":
newState.config.length = action.value;
break;
Expand All @@ -28,6 +25,9 @@ export const configurationReducer = (state: DescriptionConfig, action: { type: s
case "SET_TONE":
newState.config.tone = action.value;
break;
case "TOGGLE_ENABLED":
newState.enabled = !newState.enabled;
break;
case "CLEAR":
newState = getDefaultDescriptionConfig();
break;
Expand Down
14 changes: 13 additions & 1 deletion src/utils/aiprdescription/cursorPositionInsert.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
// This function is used to insert text at the cursor position in the text area
export const insertTextAtCursor = async (textArea: HTMLTextAreaElement, text: string) => {
let length = 0;
const typewriter = setInterval(() => {
textArea.setRangeText(text[length++], textArea.selectionStart, textArea.selectionEnd, "end");
if (length >= text.length) {
clearInterval(typewriter);
textArea.setRangeText("\n\n_Generated using [OpenSauced](https://opensauced.ai/)._", textArea.selectionStart, textArea.selectionEnd, "end");
}
}, 10);

};

export const insertAtCursorFromStream = async (textArea: HTMLTextAreaElement, stream: ReadableStream<Uint8Array>) => {
const reader = stream.getReader();
const decoder = new TextDecoder("utf-8");
Expand All @@ -15,5 +27,5 @@ export const insertAtCursorFromStream = async (textArea: HTMLTextAreaElement, st
textArea.setRangeText(chunk, start, end, "end");
}
}
textArea.setRangeText("\n\n_Description generated using [OpenSauced](https://opensauced.ai/_).", textArea.selectionStart, textArea.selectionEnd, "end");
textArea.setRangeText("\n\n_Generated using [OpenSauced](https://opensauced.ai/)._", textArea.selectionStart, textArea.selectionEnd, "end");
};
32 changes: 20 additions & 12 deletions src/utils/aiprdescription/descriptionconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export type DescriptionLanguage =
export interface DescriptionConfig {
enabled: boolean;
config: {
openai_api_key: string;
length: number;
maxInputLength: number;
temperature: number;
Expand All @@ -43,20 +42,29 @@ export const setAIDescriptionConfig = async (data: DescriptionConfig): Promise<v
};

export const getDefaultDescriptionConfig = (): DescriptionConfig => ({
enabled: false,
config: {
openai_api_key: "",
length: 500,
maxInputLength: 3900,
temperature: 7,
language: "english",
tone: "informative",
source: "diff",
},
});
enabled: true,
config: {
length: 500,
maxInputLength: 3900,
temperature: 7,
language: "english",
tone: "informative",
source: "diff",
},
});

export const setDefaultDescriptionConfig = () => {
const defaultConfig = getDefaultDescriptionConfig();

void setAIDescriptionConfig(defaultConfig);
};

export const toggleAIPRDescriptionEnabled = async () => {
const config = await getAIDescriptionConfig();

if (typeof config?.enabled === "undefined") return;
config.enabled = !config.enabled;
await setAIDescriptionConfig(config);

return;
}
Loading

0 comments on commit cf8f64c

Please sign in to comment.