Skip to content
Merged
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
12 changes: 7 additions & 5 deletions .cursor/rules/get-api-route.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import { NextResponse } from "next/server";
import prisma from "@/utils/prisma";
import { withAuth } from "@/utils/middleware";

// Notice how we infer the response type. We don't need to manually type it out
export type GetExampleResponse = Awaited<ReturnType<typeof getData>>;

export const GET = withAuth(async () => {
// The middleware does the error handling and authentication for us already
export const GET = withEmailAccount(async () => {
const emailAccountId = request.auth.emailAccountId;


const result = getData({ email });
return NextResponse.json(result);
});
Expand All @@ -37,8 +38,9 @@ See [data-fetching.mdc](mdc:.cursor/rules/data-fetching.mdc) as to how this woul

Key Requirements:

- Always wrap the handler with `withAuth` for consistent error handling and authentication.
- We don't need try/catch as `withAuth` handles that.
- Infer and export response type.
- Always wrap the handler with `withAuth` or `withEmailAccount` for consistent error handling and authentication.
- `withAuth` gets the user. `withEmailAccount` gets the currently active email account. A user can have multiple email accounts under it.
- We don't need try/catch as `withAuth` and `withEmailAccount` handles that.
- Infer and export response type as in the example.
- Use Prisma for database queries.
- Return responses using `NextResponse.json()`
69 changes: 0 additions & 69 deletions .cursor/rules/memory.mdc

This file was deleted.

11 changes: 1 addition & 10 deletions apps/web/app/(app)/[emailAccountId]/assistant/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,13 @@ export default async function AssistantPage({
}
}

// const hasPendingRule = prisma.rule.findFirst({
// where: { emailAccountId, automate: false },
// select: { id: true },
// });

return (
<GmailProvider>
<Suspense>
<PermissionsCheck />

<div className="flex h-[calc(100vh-theme(spacing.16))] flex-col">
<Chat
id={emailAccountId}
initialMessages={[]}
emailAccountId={emailAccountId}
/>
<Chat emailAccountId={emailAccountId} />
</div>
</Suspense>
</GmailProvider>
Expand Down
30 changes: 20 additions & 10 deletions apps/web/app/(app)/[emailAccountId]/automation/AssistantTabs.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"use client";

import useSWR from "swr";
import { History } from "@/app/(app)/[emailAccountId]/automation/History";
import { Pending } from "@/app/(app)/[emailAccountId]/automation/Pending";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
Expand All @@ -8,8 +11,14 @@ import { RulesPrompt } from "@/app/(app)/[emailAccountId]/automation/RulesPrompt
import { TabsToolbar } from "@/components/TabsToolbar";
import { TypographyP } from "@/components/Typography";
import { RuleTab } from "@/app/(app)/[emailAccountId]/automation/RuleTab";
import type { GetPendingRulesResponse } from "@/app/api/rules/pending/route";

export function AssistantTabs() {
const { data: pendingData } =
useSWR<GetPendingRulesResponse>("/api/rules/pending");

const hasPendingRule = pendingData?.hasPending ?? false;

return (
<div className="h-full overflow-y-auto">
<Tabs defaultValue="empty" className="h-full">
Expand All @@ -20,11 +29,9 @@ export function AssistantTabs() {
<TabsTrigger value="rules">Rules</TabsTrigger>
<TabsTrigger value="test">Test</TabsTrigger>
<TabsTrigger value="history">History</TabsTrigger>
{/* <Suspense>
{(await hasPendingRule) && (
<TabsTrigger value="pending">Pending</TabsTrigger>
)}
</Suspense> */}
{hasPendingRule && (
<TabsTrigger value="pending">Pending</TabsTrigger>
)}
<TabsTrigger value="knowledge">Knowledge Base</TabsTrigger>
</TabsList>
</div>
Expand Down Expand Up @@ -56,9 +63,9 @@ export function AssistantTabs() {

<TabsContent value="empty" className="mt-0 h-full">
<div className="flex h-full items-center justify-center">
<TypographyP className="max-w-sm text-center">
<TypographyP className="max-w-sm px-4 text-center">
Select a tab or chat with your AI assistant to explain how it
should handle your incoming emails
should handle incoming emails
</TypographyP>
</div>
</TabsContent>
Expand All @@ -75,12 +82,15 @@ export function AssistantTabs() {
<TabsContent value="history" className="content-container mb-10">
<History />
</TabsContent>
<TabsContent value="pending" className="content-container mb-10">
<Pending />
</TabsContent>
{hasPendingRule && (
<TabsContent value="pending" className="content-container mb-10">
<Pending />
</TabsContent>
)}
<TabsContent value="knowledge" className="content-container mb-10">
<KnowledgeBase />
</TabsContent>
{/* Set via search params. Not a visible tab. */}
<TabsContent value="rule" className="content-container mb-10">
<RuleTab />
</TabsContent>
Expand Down
2 changes: 0 additions & 2 deletions apps/web/app/(app)/[emailAccountId]/automation/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Suspense } from "react";
import Link from "next/link";
import { cookies } from "next/headers";
import { redirect } from "next/navigation";
import prisma from "@/utils/prisma";
Expand All @@ -15,7 +14,6 @@ import { PermissionsCheck } from "@/app/(app)/[emailAccountId]/PermissionsCheck"
import { TabsToolbar } from "@/components/TabsToolbar";
import { GmailProvider } from "@/providers/GmailProvider";
import { ASSISTANT_ONBOARDING_COOKIE } from "@/utils/cookies";
import { Button } from "@/components/ui/button";
import { prefixPath } from "@/utils/path";

export const maxDuration = 300; // Applies to the actions
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/api/ai/summarise/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export async function summarise({
prompt,
userEmail,
usageLabel: "Summarise",
onFinish: async (completion) => {
await saveSummary(prompt, completion);
onFinish: async (result) => {
await saveSummary(prompt, result.text);
await expire(prompt, 60 * 60 * 24);
},
});
Expand Down
Loading