Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/src/app/chat/dropbox-chat/DropboxChat.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import clsx from "clsx";
import { Field, useForm } from "react-final-form";
import { useEffect } from "react";
import { useRouter } from "next/router";

import { Card } from "ui/card/Card";
import { Button } from "ui/button/Button";
Expand All @@ -19,6 +20,8 @@ export const DropboxChat: React.FC<DropboxChatProps> = ({ className, onSubmit })

const formContext = useFormContext();

const router = useRouter();

const { messages, actions, clearMessages, saveMessageThread } = useMessageContext();

useEffect(() => {
Expand All @@ -27,6 +30,19 @@ export const DropboxChat: React.FC<DropboxChatProps> = ({ className, onSubmit })
formContext.setForm(form);
}, [form]);

useEffect(() => {
if (!formContext.form) return;

const fileName = router.query?.fileName;

if (fileName) {
formContext.setFieldValue(
FormFieldNames.message,
`Extra el contenido de "${fileName}" y responde: ¿cuántos artículos tiene la Constitución Política de Guatemala?`,
);
}
}, [formContext.form]);

useEffect(() => {
const element = document.querySelector(`#messages`);

Expand Down
1 change: 1 addition & 0 deletions app/src/context/form/FormContext.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type FormContextControllerProps = {
};

export type FormContextType = {
form?: FormState;
setForm: Dispatch<SetStateAction<FormState | undefined>>;
setCurrentMessageMetadata: Dispatch<SetStateAction<Record<string, any>>>;
setFieldValue: (field: string, text: string) => void;
Expand Down
11 changes: 11 additions & 0 deletions app/src/context/form/FormContextController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { sample } from "lodash";
import { APIChatHeaderKeyNames, CurrentMessageMetadata, FileAgentRequest, FileAgentResponse } from "api/chat/types";
import { OAuthTokenStoreKey } from "api/oauth/oauth.types";
import axios from "axios";
import { useRouter } from "next/router";

import { useMessageContext } from "context/message/useMessageContext";
import { ChatFormValues, FormFieldNames } from "app/chat/dropbox-chat/DropboxChat.types";
import { ChatContextMessage, TextChatCompletionMessage } from "context/message/MessageContext.types";
import { useRoutes } from "hooks/useRoutes/useRoutes";
import { useAuthorizationContext } from "context/authorization/useAuthorizationContext";
import { useFileContext } from "context/file/useFileContext";
import { X_PUBLIC_BUCKET_NAME } from "providers/chat/constants";

import { FormContextControllerProps, FormContextType, FormState } from "./FormContext.types";
import { FormContext } from "./FormContext";
Expand Down Expand Up @@ -56,6 +58,8 @@ export const FormContextController = ({ children }: FormContextControllerProps)

const fileContext = useFileContext();

const router = useRouter();

useEffect(() => {
setCurrentMessageMetadata({ bucketName: fileContext.getStorageBucketName() });
}, []);
Expand Down Expand Up @@ -115,6 +119,12 @@ export const FormContextController = ({ children }: FormContextControllerProps)
headers[APIChatHeaderKeyNames.x_square_access_token] = authContext.accessTokens[OAuthTokenStoreKey.square_api]!;
}

const fileName = router.query?.fileName;

if (fileName) {
headers[APIChatHeaderKeyNames.x_public_bucket_name] = X_PUBLIC_BUCKET_NAME;
}

const options = {
method: "POST",
body: JSON.stringify({
Expand Down Expand Up @@ -166,6 +176,7 @@ export const FormContextController = ({ children }: FormContextControllerProps)
updateTextareaHeight,
resetTextareaHeight,
submit,
form,
};

return <FormContext.Provider value={props}>{children}</FormContext.Provider>;
Expand Down
28 changes: 28 additions & 0 deletions app/src/context/message/MessageContextController.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { useRouter } from "next/router";

import { useLocalStorage } from "hooks/useLocalStorage/useLocalStorage";
import { MessageFileType } from "ui/dropzone/message-file-type/MessageFileType";
Expand All @@ -24,6 +25,8 @@ export const MessageContextController = ({ children }: MessageContextControllerP
isProcessingRequest: false,
});

const router = useRouter();

const ls = useLocalStorage();

const chatSidebarContext = useChatSidebarContext();
Expand Down Expand Up @@ -202,6 +205,31 @@ export const MessageContextController = ({ children }: MessageContextControllerP
};

const displayInitialMessage = () => {
const fileName = router.query?.fileName;

if (fileName) {
switch (fileName) {
case "Constitucion_politica_de_la_republica_de_guatemala.pdf":
appendMessage({
content: `¡Hola! **Pregúntale a la Constitución Política de Guatemala**.

Extrajimos el contenido de este archivo PDF: <a href="https://dosykuehmswkuuurtgyx.supabase.co/storage/v1/object/sign/guest-a62e/Constitucion_politica_de_la_republica_de_guatemala.pdf?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1cmwiOiJndWVzdC1hNjJlL0NvbnN0aXR1Y2lvbl9wb2xpdGljYV9kZV9sYV9yZXB1YmxpY2FfZGVfZ3VhdGVtYWxhLnBkZiIsImlhdCI6MTY5Nzc0MDg3MywiZXhwIjoyMDEzMTAwODczfQ.7_rdImgNN1JVq4yDKaF9oAS05qBEFD7XDKhcb9m_WY4&t=2023-10-19T18%3A41%3A13.490Z" target="_blank">Constitucion_politica_de_la_republica_de_guatemala.pdf</a> para que le preguntes lo que querrás!

En vez de leerla... 🥱`,
role: "assistant",
readOnly: true,
hasInnerHtml: true,
type: "text",
});
break;

default:
break;
}

return;
}

const lsMessages = ls.get<ChatContextMessage[]>(LocalStorageKeys.messages);

if (lsMessages && lsMessages?.length > 0) {
Expand Down
40 changes: 38 additions & 2 deletions app/src/pages/api/chat/openai/completions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";

import logger from "providers/logger";
import chat from "providers/chat";
Expand All @@ -13,8 +14,25 @@ export default async function Fn(request: NextApiRequest, response: NextApiRespo
try {
logger.info(`getting chat completion from model ${openai.model}`);

const data: FileAgentRequest =
typeof request.body.body === "string" ? JSON.parse(request.body.body, json.reviver) : request.body.body;
const data: FileAgentRequest = (() => {
if (request.body?.currentMessageMetadata?.source === "messagebird") {
return {
...request.body,
messages: [
{
role: "user",
content: "",
},
],
};
}

if (typeof request.body.body === "string") {
return JSON.parse(request.body.body, json.reviver);
}

return request.body.body;
})();

const chatCompletion = await openai.client.chat.completions.create({
messages: [
Expand All @@ -38,6 +56,24 @@ export default async function Fn(request: NextApiRequest, response: NextApiRespo
return;
}

if (data.currentMessageMetadata?.source === "messagebird") {
await axios({
method: "PATCH",
url: "https://api.bird.com/workspaces/305b8974-7995-4878-a7b9-9c426cec8e17/flows/f543bea1-11d9-4893-9ac3-e97ec9e2baca/runs",
headers: {
Authorization: `AccessKey tz8si6wlFuTjOWUPiqDMgr9NV0bKpOrHFaXu`,
"Content-Type": "application/json",
},
data: {
action: "resume",
resumeKey: "f3561227-7aa8-4d3f-baf8-3759fd2db462",
resumeExtraInput: {
choices,
},
},
});
}

response.status(200).json({ choices });
} catch (error) {
logger.error(error);
Expand Down
4 changes: 4 additions & 0 deletions app/src/pages/api/chat/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import { ChatCompletionChoice } from "providers/chat/chat.types";
export enum APIChatHeaderKeyNames {
x_dropbox_access_token = "x-dropbox-access-token",
x_square_access_token = "x-square-access-token",

// [fileName].tsx path
x_public_bucket_name = "x_public_bucket_name",
}

export type CurrentMessageMetadata = {
bucketName?: string;
source?: "messagebird" | "app";
};

export type FileAgentRequest = {
Expand Down
38 changes: 38 additions & 0 deletions app/src/pages/chat/public/[fileName].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { GetServerSidePropsContext, NextPage } from "next";
import { i18n, useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import Head from "next/head";

import { AccountId } from "providers/near/contracts/market/market.types";
import { ChatLayout } from "layouts/chat-layout/ChatLayout";
import { DropboxChatContainer } from "app/chat/dropbox-chat/DropboxChatContainer";

const Index: NextPage<{ marketId: AccountId }> = () => {
const { t } = useTranslation("head");

return (
<ChatLayout>
<Head>
<title>{t("head.og.title")}</title>
<meta name="description" content={t("head.og.description")} />
<meta property="og:title" content={t("head.og.title")} />
<meta property="og:description" content={t("head.og.description")} />
<meta property="og:url" content="https://fileagent.ai/" />
</Head>

<DropboxChatContainer />
</ChatLayout>
);
};

export const getServerSideProps = async ({ locale }: GetServerSidePropsContext) => {
await i18n?.reloadResources();

return {
props: {
...(await serverSideTranslations(locale!, ["common", "head", "chat"])),
},
};
};

export default Index;
1 change: 1 addition & 0 deletions app/src/providers/chat/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const X_PUBLIC_BUCKET_NAME = "guest-a62e";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileAgentRequest } from "api/chat/types";
import { APIChatHeaderKeyNames, FileAgentRequest } from "api/chat/types";
import { CreateChatCompletionRequestMessage } from "openai/resources/chat";
import { NextApiRequest } from "next";

Expand All @@ -19,7 +19,9 @@ const extract_content_from_pdf_file = async (
try {
const body = JSON.parse(request.body.body);

const bucketName = body.currentMessageMetadata?.bucketName;
const bucketName = request.body.headers[APIChatHeaderKeyNames.x_public_bucket_name]
? (request.body.headers[APIChatHeaderKeyNames.x_public_bucket_name] as string)
: body.currentMessageMetadata?.bucketName;

const fileName = args.file_name;

Expand Down
7 changes: 7 additions & 0 deletions app/src/ui/dropzone/_mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,13 @@
color: var(--color-primary);
}
}

ul,
ol {
li {
@include text();
}
}
}
}
@mixin options {
Expand Down
8 changes: 4 additions & 4 deletions app/src/ui/typography/Typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ const Headline4: React.FC<TypographyProps> = ({ children, className, inline, ...
</h4>
);

const Headline5: React.FC<TypographyProps> = ({ children, className, ...props }) => (
<h5 className={clsx(styles.typography__headline5, className)} {...props}>
const Headline5: React.FC<TypographyProps> = ({ children, className, flat, ...props }) => (
<h5 className={clsx(styles.typography__headline5, className, { [styles.typography__flat]: flat })} {...props}>
{children}
</h5>
);

const Headline6: React.FC<TypographyProps> = ({ children, className, ...props }) => (
<h6 className={clsx(styles.typography__headline6, className)} {...props}>
const Headline6: React.FC<TypographyProps> = ({ children, className, flat, ...props }) => (
<h6 className={clsx(styles.typography__headline6, className, { [styles.typography__flat]: flat })} {...props}>
{children}
</h6>
);
Expand Down
89 changes: 89 additions & 0 deletions database/migrations/20231017160215-create-table-square_orders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const DataTypes = require("sequelize").DataTypes;
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("orders", {
id: {
type: DataTypes.STRING,
primaryKey: true,
allowNull: false,
},
location_id: {
type: DataTypes.STRING,
allowNull: false,
},
line_items: {
type: DataTypes.JSONB,
allowNull: false,
},
created_at: {
type: DataTypes.DATE,
},
updated_at: {
type: DataTypes.DATE,
},
state: {
type: DataTypes.STRING,
allowNull: false,
},
total_tax_money: {
type: DataTypes.JSONB,
allowNull: false,
},
total_discount_money: {
type: DataTypes.JSONB,
allowNull: false,
},
total_tip_money: {
type: DataTypes.JSONB,
allowNull: false,
},
total_money: {
type: DataTypes.JSONB,
allowNull: false,
},
closed_at: {
type: DataTypes.DATE,
allowNull: false,
},
tenders: {
type: DataTypes.JSONB,
allowNull: false,
},
total_service_charge_money: {
type: DataTypes.JSONB,
allowNull: false,
},
return_amounts: {
type: DataTypes.JSONB,
allowNull: false,
},
net_amounts: {
type: DataTypes.JSONB,
allowNull: false,
},
source: {
type: DataTypes.JSONB,
allowNull: false,
},
customer_id: {
type: DataTypes.STRING,
allowNull: false,
},
net_amount_due_money: {
type: DataTypes.JSONB,
allowNull: false,
},
createdAt: {
type: DataTypes.DATE,
field: "created_at",
},
updatedAt: {
type: DataTypes.DATE,
field: "updated_at",
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("orders");
},
};
Loading