-
+
{props.title}
{props.description && (
@@ -60,11 +59,11 @@ const Toast = (props: Props) => {
setOpen(false);
}}
>
- {t('copy')}
+ Copy
)}
- {t('close')}
+ Close
diff --git a/src/components/types/index.ts b/src/components/types/index.ts
new file mode 100644
index 00000000..0da11ae0
--- /dev/null
+++ b/src/components/types/index.ts
@@ -0,0 +1 @@
+export * from "./propTypes";
diff --git a/src/components/types/propTypes.ts b/src/components/types/propTypes.ts
new file mode 100644
index 00000000..ada874d4
--- /dev/null
+++ b/src/components/types/propTypes.ts
@@ -0,0 +1,15 @@
+export type toolTipProperties = {
+ message?: string;
+ disabled?: boolean;
+};
+
+export type reactModelStates = {
+ customApiKey: string;
+ setCustomApiKey: (key: string) => void;
+ customModelName: string;
+ setCustomModelName: (key: string) => void;
+ customTemperature: number;
+ setCustomTemperature: (temperature: number) => void;
+ customMaxLoops: number;
+ setCustomMaxLoops: (numberOfLoops: number) => void;
+};
diff --git a/src/env/schema.mjs b/src/env/schema.mjs
index f35db1a9..50044b5f 100644
--- a/src/env/schema.mjs
+++ b/src/env/schema.mjs
@@ -1,9 +1,21 @@
// @ts-check
import { z } from "zod";
-const requiredForProduction = () => process.env.NODE_ENV === "production"
+const requiredForProduction = () =>
+ process.env.NODE_ENV === "production"
? z.string().min(1).trim()
- : z.string().min(1).trim().optional()
+ : z.string().min(1).trim().optional();
+
+const requiredAuthEnabledForProduction = () => {
+ return process.env.NODE_ENV === "production" &&
+ process.env.NEXT_PUBLIC_FF_AUTH_ENABLED === "true"
+ ? z.string().min(1).trim()
+ : z.string().min(1).trim().optional();
+};
+
+function stringToBoolean() {
+ return z.preprocess((str) => str === "true", z.boolean());
+}
/**
* Specify your server-side environment variables schema here.
@@ -18,16 +30,20 @@ export const serverSchema = z.object({
// Since NextAuth.js automatically uses the VERCEL_URL if present.
(str) => process.env.VERCEL_URL ?? str,
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
- process.env.VERCEL ? z.string() : z.string().url(),
+ process.env.VERCEL ? z.string() : z.string().url()
),
OPENAI_API_KEY: z.string(),
-// GOOGLE_CLIENT_ID: requiredForProduction(),
-// GOOGLE_CLIENT_SECRET: requiredForProduction(),
-// GITHUB_CLIENT_ID: requiredForProduction(),
-// GITHUB_CLIENT_SECRET: requiredForProduction(),
-// DISCORD_CLIENT_ID: requiredForProduction(),
-// DISCORD_CLIENT_SECRET: requiredForProduction(),
+ GOOGLE_CLIENT_ID: requiredAuthEnabledForProduction(),
+ GOOGLE_CLIENT_SECRET: requiredAuthEnabledForProduction(),
+ GITHUB_CLIENT_ID: requiredAuthEnabledForProduction(),
+ GITHUB_CLIENT_SECRET: requiredAuthEnabledForProduction(),
+ DISCORD_CLIENT_ID: requiredAuthEnabledForProduction(),
+ DISCORD_CLIENT_SECRET: requiredAuthEnabledForProduction(),
+
+ STRIPE_SECRET_KEY: z.string().optional(),
+ STRIPE_WEBHOOK_SECRET: z.string().optional(),
+ STRIPE_SUBSCRIPTION_PRICE_ID: z.string().optional(),
});
/**
@@ -41,12 +57,16 @@ export const serverEnv = {
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
-// GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
-// GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
-// GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
-// GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
-// DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
-// DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET
+ GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,
+ GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
+ GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
+ GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
+ DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
+ DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET,
+
+ STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
+ STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
+ STRIPE_SUBSCRIPTION_PRICE_ID: process.env.STRIPE_SUBSCRIPTION_PRICE_ID,
};
/**
@@ -55,10 +75,17 @@ export const serverEnv = {
* To expose them to the client, prefix them with `NEXT_PUBLIC_`.
*/
export const clientSchema = z.object({
- // NEXT_PUBLIC_CLIENTVAR: z.string(),
- NEXT_PUBLIC_VERCEL_ENV: z.enum(["production", "preview", "development"]),
- NEXT_PUBLIC_STRIPE_DONATION_ENABLED: z.string().transform(str => str ==='true').optional(),
- NEXT_PUBLIC_FF_AUTH_ENABLED: z.string().transform(str => str ==='true').optional()
+ // NEXT_PUBLIC_CLIENTVAR: z.string(),
+ NEXT_PUBLIC_VERCEL_ENV: z.enum(["production", "preview", "development"]),
+ NEXT_PUBLIC_STRIPE_DONATION_ENABLED: z
+ .string()
+ .transform((str) => str === "true")
+ .optional(),
+ NEXT_PUBLIC_FF_AUTH_ENABLED: stringToBoolean(),
+ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().optional(),
+ NEXT_PUBLIC_FF_SUB_ENABLED: stringToBoolean(),
+ NEXT_PUBLIC_FF_MOCK_MODE_ENABLED: stringToBoolean(),
+ NEXT_PUBLIC_VERCEL_URL: z.string().optional(),
});
/**
@@ -69,6 +96,14 @@ export const clientSchema = z.object({
*/
export const clientEnv = {
NEXT_PUBLIC_VERCEL_ENV: process.env.NEXT_PUBLIC_VERCEL_ENV ?? "development",
- NEXT_PUBLIC_STRIPE_DONATION_ENABLED: process.env.NEXT_PUBLIC_STRIPE_DONATION_ENABLED,
- NEXT_PUBLIC_FF_AUTH_ENABLED: process.env.NEXT_PUBLIC_FF_AUTH_ENABLED
+ NEXT_PUBLIC_STRIPE_DONATION_ENABLED:
+ process.env.NEXT_PUBLIC_STRIPE_DONATION_ENABLED,
+ NEXT_PUBLIC_FF_AUTH_ENABLED: process.env.NEXT_PUBLIC_FF_AUTH_ENABLED,
+ NEXT_PUBLIC_VERCEL_URL:
+ process.env.NEXT_PUBLIC_VERCEL_URL ?? "http://localhost:3000",
+ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY:
+ process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
+ NEXT_PUBLIC_FF_SUB_ENABLED: process.env.NEXT_PUBLIC_FF_SUB_ENABLED,
+ NEXT_PUBLIC_FF_MOCK_MODE_ENABLED:
+ process.env.NEXT_PUBLIC_FF_MOCK_MODE_ENABLED,
};
diff --git a/src/hooks/useAgent.ts b/src/hooks/useAgent.ts
new file mode 100644
index 00000000..3654d2e3
--- /dev/null
+++ b/src/hooks/useAgent.ts
@@ -0,0 +1,32 @@
+import { api } from "../utils/api";
+import type { Message } from "../types/agentTypes";
+import { useAuth } from "./useAuth";
+
+export interface SaveProps {
+ name: string;
+ goal: string;
+ tasks: Message[];
+}
+
+export function useAgent() {
+ const { status } = useAuth();
+ const utils = api.useContext();
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ const voidFunc = () => {};
+ const saveMutation = api.agent.create.useMutation({
+ onSuccess: (data) => {
+ utils.agent.getAll.setData(voidFunc(), (oldData) => [
+ data,
+ ...(oldData ?? []),
+ ]);
+ },
+ });
+
+ const saveAgent = (data: SaveProps) => {
+ if (status === "authenticated") saveMutation.mutate(data);
+ };
+
+ return {
+ saveAgent,
+ };
+}
diff --git a/src/layout/default.tsx b/src/layout/default.tsx
index e5d5e5e5..621588a1 100644
--- a/src/layout/default.tsx
+++ b/src/layout/default.tsx
@@ -2,11 +2,11 @@ import { type ReactNode } from "react";
import Head from "next/head";
import DottedGridBackground from "../components/DottedGridBackground";
import clsx from "clsx";
-import Script from "next/script";
interface LayoutProps {
children: ReactNode;
className?: string;
+ centered?: boolean;
}
const DefaultLayout = (props: LayoutProps) => {
@@ -34,13 +34,10 @@ const DefaultLayout = (props: LayoutProps) => {
content="sG4QDkC8g2oxKSopgJdIe2hQ_SaJDaEaBjwCXZNkNWA"
/>
-
-
+
{props.children}
diff --git a/src/pages/agent/index.tsx b/src/pages/agent/index.tsx
new file mode 100644
index 00000000..86fefa06
--- /dev/null
+++ b/src/pages/agent/index.tsx
@@ -0,0 +1,96 @@
+import { type NextPage, type GetStaticProps } from "next";
+import DefaultLayout from "../../layout/default";
+import Button from "../../components/Button";
+
+import React, { useState } from "react";
+import { useRouter } from "next/router";
+import { api } from "../../utils/api";
+import ChatWindow from "../../components/ChatWindow";
+import type { Message } from "../../types/agentTypes";
+import Toast from "../../components/toast";
+import { FaTrash, FaShare, FaBackspace } from "react-icons/fa";
+import { env } from "../../env/client.mjs";
+import { useTranslation } from "next-i18next";
+import { serverSideTranslations } from "next-i18next/serverSideTranslations";
+
+const AgentPage: NextPage = () => {
+ const [showCopied, setShowCopied] = useState(false);
+ const router = useRouter();
+ const { t } = useTranslation();
+
+ const agentId = typeof router.query.id === "string" ? router.query.id : "";
+
+ const getAgent = api.agent.findById.useQuery(agentId, {
+ enabled: router.isReady,
+ });
+
+ const deleteAgent = api.agent.deleteById.useMutation({
+ onSuccess: () => {
+ void router.push("/");
+ },
+ });
+
+ const messages = getAgent.data ? (getAgent.data.tasks as Message[]) : [];
+
+ const shareLink = () => {
+ return encodeURI(`${env.NEXT_PUBLIC_VERCEL_URL as string}${router.asPath}`);
+ };
+
+ return (
+