summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/main.yaml8
-rw-r--r--extension/react-app/src/components/Layout.tsx22
-rw-r--r--extension/react-app/src/components/ProgressBar.tsx77
-rw-r--r--extension/react-app/src/pages/gui.tsx43
-rw-r--r--extension/react-app/src/pages/settings.tsx9
5 files changed, 142 insertions, 17 deletions
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 6674d296..1c4fb4dc 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -256,10 +256,10 @@ jobs:
cd extension
npm ci
- # - name: Publish (Open VSX Registry)
- # run: |
- # cd extension
- # npx ovsx publish -p ${{ secrets.VSX_REGISTRY_TOKEN }} --packagePath ./build/*.vsix
+ - name: Publish (Open VSX Registry)
+ run: |
+ cd extension
+ npx ovsx publish -p ${{ secrets.VSX_REGISTRY_TOKEN }} --packagePath ./build/*.vsix
- name: Publish
run: |
diff --git a/extension/react-app/src/components/Layout.tsx b/extension/react-app/src/components/Layout.tsx
index 17100c7f..6410db8a 100644
--- a/extension/react-app/src/components/Layout.tsx
+++ b/extension/react-app/src/components/Layout.tsx
@@ -21,8 +21,9 @@ import {
Cog6ToothIcon,
} from "@heroicons/react/24/outline";
import HeaderButtonWithText from "./HeaderButtonWithText";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useLocation } from "react-router-dom";
import ModelSelect from "./ModelSelect";
+import ProgressBar from "./ProgressBar";
// #region Styled Components
const FOOTER_HEIGHT = "1.8em";
@@ -74,6 +75,7 @@ const GridDiv = styled.div`
const Layout = () => {
const navigate = useNavigate();
+ const location = useLocation();
const client = useContext(GUIClientContext);
const dispatch = useDispatch();
const dialogMessage = useSelector(
@@ -82,10 +84,11 @@ const Layout = () => {
const showDialog = useSelector(
(state: RootStore) => state.uiState.showDialog
);
- const dialogEntryOn = useSelector(
- (state: RootStore) => state.uiState.dialogEntryOn
- );
+ const defaultModel = useSelector(
+ (state: RootStore) =>
+ (state.serverState.config as any).models?.default?.class_name
+ );
// #region Selectors
const bottomMessage = useSelector(
@@ -175,6 +178,17 @@ const Layout = () => {
)}
<ModelSelect />
+ {defaultModel === "MaybeProxyOpenAI" &&
+ (location.pathname === "/settings" ||
+ parseInt(localStorage.getItem("freeTrialCounter") || "0") >=
+ 125) && (
+ <ProgressBar
+ completed={parseInt(
+ localStorage.getItem("freeTrialCounter") || "0"
+ )}
+ total={250}
+ />
+ )}
</div>
<HeaderButtonWithText
onClick={() => {
diff --git a/extension/react-app/src/components/ProgressBar.tsx b/extension/react-app/src/components/ProgressBar.tsx
new file mode 100644
index 00000000..b4a2efc9
--- /dev/null
+++ b/extension/react-app/src/components/ProgressBar.tsx
@@ -0,0 +1,77 @@
+import React from "react";
+import styled from "styled-components";
+import { StyledTooltip, lightGray, vscForeground } from ".";
+
+const ProgressBarWrapper = styled.div`
+ width: 100px;
+ height: 6px;
+ border-radius: 6px;
+ border: 0.5px solid ${lightGray};
+ margin-top: 6px;
+`;
+
+const ProgressBarFill = styled.div<{ completed: number; color?: string }>`
+ height: 100%;
+ background-color: ${(props) => props.color || vscForeground};
+ border-radius: inherit;
+ transition: width 0.2s ease-in-out;
+ width: ${(props) => props.completed}%;
+`;
+
+const GridDiv = styled.div`
+ display: grid;
+ grid-template-rows: 1fr auto;
+ align-items: center;
+ justify-items: center;
+`;
+
+const P = styled.p`
+ margin: 0;
+ margin-top: 2px;
+ font-size: 12px;
+ color: ${lightGray};
+ text-align: center;
+`;
+
+interface ProgressBarProps {
+ completed: number;
+ total: number;
+}
+
+const ProgressBar = ({ completed, total }: ProgressBarProps) => {
+ const fillPercentage = Math.min(100, Math.max(0, (completed / total) * 100));
+
+ return (
+ <>
+ <a
+ href="https://continue.dev/docs/customization"
+ className="no-underline"
+ >
+ <GridDiv data-tooltip-id="usage_progress_bar">
+ <ProgressBarWrapper>
+ <ProgressBarFill
+ completed={fillPercentage}
+ color={
+ completed / total > 0.75
+ ? completed / total > 0.95
+ ? "#f00"
+ : "#fc0"
+ : undefined
+ }
+ />
+ </ProgressBarWrapper>
+ <P>
+ Free Usage: {completed} / {total}
+ </P>
+ </GridDiv>
+ </a>
+ <StyledTooltip id="usage_progress_bar" place="bottom">
+ {
+ "Continue allows you to use our OpenAI API key for up to 250 inputs. After this, you can either use your own API key, or use a local LLM. Click the progress bar to go to the docs and learn more."
+ }
+ </StyledTooltip>
+ </>
+ );
+};
+
+export default ProgressBar;
diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx
index cb62f7ed..34e79a8f 100644
--- a/extension/react-app/src/pages/gui.tsx
+++ b/extension/react-app/src/pages/gui.tsx
@@ -66,6 +66,10 @@ function GUI(props: GUIProps) {
// #region Selectors
const history = useSelector((state: RootStore) => state.serverState.history);
+ const defaultModel = useSelector(
+ (state: RootStore) =>
+ (state.serverState.config as any).models?.default?.class_name
+ );
const user_input_queue = useSelector(
(state: RootStore) => state.serverState.user_input_queue
);
@@ -240,6 +244,43 @@ function GUI(props: GUIProps) {
return;
}
+ // Increment localstorage counter for usage of free trial
+ if (
+ defaultModel === "MaybeProxyOpenAI" &&
+ (!input.startsWith("/") || input.startsWith("/edit"))
+ ) {
+ const freeTrialCounter = localStorage.getItem("freeTrialCounter");
+ if (freeTrialCounter) {
+ const usages = parseInt(freeTrialCounter);
+ localStorage.setItem("freeTrialCounter", (usages + 1).toString());
+
+ if (usages >= 250) {
+ console.log("Free trial limit reached");
+ dispatch(setShowDialog(true));
+ dispatch(
+ setDialogMessage(
+ <div className="p-4">
+ <h3>Free Trial Limit Reached</h3>
+ You've reached the free trial limit of 250 free inputs with
+ Continue's OpenAI API key. To keep using Continue, you can
+ either use your own API key, or use a local LLM. To read more
+ about the options, see our{" "}
+ <a href="https://continue.dev/docs/customization">
+ documentation
+ </a>
+ . If you're just looking for fastest way to keep going, type
+ '/config' to open your Continue config file and paste your API
+ key into the MaybeProxyOpenAI object.
+ </div>
+ )
+ );
+ return;
+ }
+ } else {
+ localStorage.setItem("freeTrialCounter", "1");
+ }
+ }
+
setWaitingForSteps(true);
if (
@@ -266,7 +307,7 @@ function GUI(props: GUIProps) {
client.sendMainInput(input);
dispatch(temporarilyPushToUserInputQueue(input));
- // Increment localstorage counter
+ // Increment localstorage counter for popup
const counter = localStorage.getItem("mainTextEntryCounter");
if (counter) {
let currentCount = parseInt(counter);
diff --git a/extension/react-app/src/pages/settings.tsx b/extension/react-app/src/pages/settings.tsx
index 9a3d3cc2..8b3d9c5b 100644
--- a/extension/react-app/src/pages/settings.tsx
+++ b/extension/react-app/src/pages/settings.tsx
@@ -4,19 +4,12 @@ import { useSelector } from "react-redux";
import { RootStore } from "../redux/store";
import { useNavigate } from "react-router-dom";
import { ContinueConfig } from "../../../schema/ContinueConfig";
-import {
- Button,
- Select,
- TextArea,
- lightGray,
- secondaryDark,
-} from "../components";
+import { Button, TextArea, lightGray, secondaryDark } from "../components";
import styled from "styled-components";
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
import Loader from "../components/Loader";
import InfoHover from "../components/InfoHover";
import { FormProvider, useForm } from "react-hook-form";
-import ModelSettings from "../components/ModelSettings";
const Hr = styled.hr`
border: 0.5px solid ${lightGray};