Skip to content

Commit

Permalink
Merge branch 'mckaywrigley:main' into org
Browse files Browse the repository at this point in the history
  • Loading branch information
jollytoad authored Apr 9, 2024
2 parents 7d628cb + b865b05 commit ebd27af
Show file tree
Hide file tree
Showing 48 changed files with 698 additions and 249 deletions.
3 changes: 3 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ AZURE_EMBEDDINGS_NAME=
# General Configuration (Optional)
EMAIL_DOMAIN_WHITELIST=
EMAIL_WHITELIST=

# File size limit for uploads in bytes
NEXT_PUBLIC_USER_FILE_SIZE_LIMIT=10485760
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ custom-prompts
sw.js
sw.js.map
workbox-*.js
workbox-*.js.map
workbox-*.js.map
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you find Chatbot UI useful, please consider [sponsoring](https://github.com/s

We restrict "Issues" to actual issues related to the codebase.

We're getting escessive amounts of issues that amount to things like feature requests, cloud provider issues, etc.
We're getting excessive amounts of issues that amount to things like feature requests, cloud provider issues, etc.

If you are having issues with things like setup, please refer to the "Help" section in the "Discussions" tab above.

Expand Down
5 changes: 5 additions & 0 deletions __tests__/playwright-test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
91 changes: 91 additions & 0 deletions __tests__/playwright-test/package-lock.json

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

18 changes: 18 additions & 0 deletions __tests__/playwright-test/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "playwright-test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"integration": "playwright test",
"integration:open": "playwright test --ui",
"integration:codegen": "playwright codegen"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.41.2",
"@types/node": "^20.11.20"
}
}
77 changes: 77 additions & 0 deletions __tests__/playwright-test/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { defineConfig, devices } from '@playwright/test';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});
46 changes: 46 additions & 0 deletions __tests__/playwright-test/tests/login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { test, expect } from '@playwright/test';

test('start chatting is displayed', async ({ page }) => {
await page.goto('http://localhost:3000/');

//expect the start chatting link to be visible
await expect (page.getByRole('link', { name: 'Start Chatting' })).toBeVisible();
});

test('No password error message', async ({ page }) => {
await page.goto('http://localhost:3000/login');
//fill in dummy email
await page.getByPlaceholder('you@example.com').fill('dummyemail@gmail.com');
await page.getByRole('button', { name: 'Login' }).click();
//wait for netwrok to be idle
await page.waitForLoadState('networkidle');
//validate that correct message is shown to the user
await expect(page.getByText('Invalid login credentials')).toBeVisible();

});
test('No password for signup', async ({ page }) => {
await page.goto('http://localhost:3000/login');

await page.getByPlaceholder('you@example.com').fill('dummyEmail@Gmail.com');
await page.getByRole('button', { name: 'Sign Up' }).click();
//validate appropriate error is thrown for missing password when signing up
await expect(page.getByText('Signup requires a valid')).toBeVisible();
});
test('invalid username for signup', async ({ page }) => {
await page.goto('http://localhost:3000/login');

await page.getByPlaceholder('you@example.com').fill('dummyEmail');
await page.getByPlaceholder('••••••••').fill('dummypassword');
await page.getByRole('button', { name: 'Sign Up' }).click();
//validate appropriate error is thrown for invalid username when signing up
await expect(page.getByText('Unable to validate email')).toBeVisible();
});
test('password reset message', async ({ page }) => {
await page.goto('http://localhost:3000/login');
await page.getByPlaceholder('you@example.com').fill('demo@gmail.com');
await page.getByRole('button', { name: 'Reset' }).click();
//validate appropriate message is shown
await expect(page.getByText('Check email to reset password')).toBeVisible();
});

//more tests can be added here
2 changes: 1 addition & 1 deletion app/[locale]/[workspaceid]/chat/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function ChatPage() {

<div className="flex grow flex-col items-center justify-center" />

<div className="w-[300px] pb-8 sm:w-[400px] md:w-[500px] lg:w-[660px] xl:w-[800px]">
<div className="w-full min-w-[300px] items-end px-2 pb-3 pt-0 sm:w-[600px] sm:pb-8 sm:pt-5 md:w-[700px] lg:w-[700px] xl:w-[800px]">
<ChatInput />
</div>

Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default async function RootLayout({
resources={resources}
>
<Toaster richColors position="top-center" duration={3000} />
<div className="bg-background text-foreground flex h-screen flex-col items-center">
<div className="bg-background text-foreground flex h-dvh flex-col items-center overflow-x-auto">
{session ? <GlobalState>{children}</GlobalState> : children}
</div>
</TranslationsProvider>
Expand Down
85 changes: 70 additions & 15 deletions app/api/chat/anthropic/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { CHAT_SETTING_LIMITS } from "@/lib/chat-setting-limits"
import { checkApiKey, getServerProfile } from "@/lib/server/server-chat-helpers"
import { getBase64FromDataURL, getMediaTypeFromDataURL } from "@/lib/utils"
import { ChatSettings } from "@/types"
import Anthropic from "@anthropic-ai/sdk"
import { AnthropicStream, StreamingTextResponse } from "ai"
import { NextRequest, NextResponse } from "next/server"

// export const runtime = "edge"
export const runtime = "edge"

export async function POST(request: Request) {
export async function POST(request: NextRequest) {
const json = await request.json()
const { chatSettings, messages } = json as {
chatSettings: ChatSettings
Expand All @@ -20,23 +22,76 @@ export async function POST(request: Request) {

let ANTHROPIC_FORMATTED_MESSAGES: any = messages.slice(1)

ANTHROPIC_FORMATTED_MESSAGES = ANTHROPIC_FORMATTED_MESSAGES?.map(
(message: any) => {
const messageContent =
typeof message?.content === "string"
? [message.content]
: message?.content

return {
...message,
content: messageContent.map((content: any) => {
if (typeof content === "string") {
// Handle the case where content is a string
return { type: "text", text: content }
} else if (
content?.type === "image_url" &&
content?.image_url?.length
) {
return {
type: "image",
source: {
type: "base64",
media_type: getMediaTypeFromDataURL(content.image_url),
data: getBase64FromDataURL(content.image_url)
}
}
} else {
return content
}
})
}
}
)

const anthropic = new Anthropic({
apiKey: profile.anthropic_api_key || ""
})

const response = await anthropic.messages.create({
model: chatSettings.model,
messages: ANTHROPIC_FORMATTED_MESSAGES,
temperature: chatSettings.temperature,
system: messages[0].content,
max_tokens:
CHAT_SETTING_LIMITS[chatSettings.model].MAX_TOKEN_OUTPUT_LENGTH,
stream: true
})
try {
const response = await anthropic.messages.create({
model: chatSettings.model,
messages: ANTHROPIC_FORMATTED_MESSAGES,
temperature: chatSettings.temperature,
system: messages[0].content,
max_tokens:
CHAT_SETTING_LIMITS[chatSettings.model].MAX_TOKEN_OUTPUT_LENGTH,
stream: true
})

const stream = AnthropicStream(response)

return new StreamingTextResponse(stream)
try {
const stream = AnthropicStream(response)
return new StreamingTextResponse(stream)
} catch (error: any) {
console.error("Error parsing Anthropic API response:", error)
return new NextResponse(
JSON.stringify({
message:
"An error occurred while parsing the Anthropic API response"
}),
{ status: 500 }
)
}
} catch (error: any) {
console.error("Error calling Anthropic API:", error)
return new NextResponse(
JSON.stringify({
message: "An error occurred while calling the Anthropic API"
}),
{ status: 500 }
)
}
} catch (error: any) {
let errorMessage = error.message || "An unexpected error occurred"
const errorCode = error.status || 500
Expand All @@ -49,7 +104,7 @@ export async function POST(request: Request) {
"Anthropic API Key is incorrect. Please fix it in your profile settings."
}

return new Response(JSON.stringify({ message: errorMessage }), {
return new NextResponse(JSON.stringify({ message: errorMessage }), {
status: errorCode
})
}
Expand Down
Loading

0 comments on commit ebd27af

Please sign in to comment.