From 59c294b29998a861a870629d513f6da74b3d76ac Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:53:53 +0000 Subject: [PATCH] feat: deep-research on user profile and tiptap integration (#672) deep-research on user profile add novel integration tiptap 3.x integration --- .github/workflows/claude-code-review.yml | 66 ++-- apps/web/.env.example | 4 +- apps/web/app/(auth)/login/new/page.tsx | 14 +- .../extract-content}/route.ts | 0 apps/web/app/api/onboarding/research/route.ts | 81 +++++ apps/web/app/new/onboarding/page.tsx | 22 +- apps/web/app/new/settings/page.tsx | 8 +- .../new/add-document/connections.tsx | 2 +- apps/web/components/new/add-document/file.tsx | 21 +- .../web/components/new/add-document/index.tsx | 2 +- apps/web/components/new/add-document/link.tsx | 2 +- apps/web/components/new/add-document/note.tsx | 21 +- apps/web/components/new/chat/index.tsx | 13 +- .../new/chat/input/chain-of-thought.tsx | 2 +- apps/web/components/new/chat/input/index.tsx | 2 +- .../new/chat/message/related-memories.tsx | 2 +- .../components/new/chat/model-selector.tsx | 2 +- .../new/document-cards/file-preview.tsx | 2 +- .../document-cards/google-docs-preview.tsx | 2 +- .../new/document-cards/mcp-preview.tsx | 13 +- .../new/document-cards/note-preview.tsx | 53 ++- .../new/document-cards/tweet-preview.tsx | 2 +- .../new/document-cards/website-preview.tsx | 2 +- .../new/document-cards/youtube-preview.tsx | 2 +- .../new/document-modal/document-icon.tsx | 4 +- .../components/new/document-modal/index.tsx | 122 ++++++- .../components/new/document-modal/title.tsx | 2 +- apps/web/components/new/header.tsx | 12 +- apps/web/components/new/mcp-modal/index.tsx | 2 +- .../new/mcp-modal/mcp-detail-view.tsx | 11 +- apps/web/components/new/memories-grid.tsx | 11 +- .../new/onboarding/setup/chat-sidebar.tsx | 240 +++++++++----- .../new/onboarding/setup/header.tsx | 0 .../onboarding/setup/integrations-step.tsx | 8 +- .../onboarding/setup/relatable-question.tsx | 2 +- .../new/onboarding/welcome/continue-step.tsx | 2 +- .../new/onboarding/welcome/features-step.tsx | 2 +- .../new/onboarding/welcome/greeting-step.tsx | 0 .../new/onboarding/welcome/input-step.tsx | 0 .../new/onboarding/welcome/profile-step.tsx} | 150 ++++----- .../new/onboarding/welcome/welcome-step.tsx | 0 .../onboarding}/x-bookmarks-detail-view.tsx | 6 +- apps/web/components/new/settings/account.tsx | 2 +- .../new/settings/connections-mcp.tsx | 2 +- .../components/new/settings/integrations.tsx | 2 +- apps/web/components/new/settings/support.tsx | 2 +- .../components/new/text-editor/extensions.tsx | 92 ++++++ apps/web/components/new/text-editor/index.tsx | 174 ++++++++++ .../new/text-editor/slash-command.tsx | 308 ++++++++++++++++++ .../new/text-editor/suggestions.tsx | 103 ++++++ apps/web/globals.css | 32 ++ apps/web/hooks/use-document-mutations.ts | 47 ++- apps/web/{utils => lib}/fonts.ts | 0 apps/web/lib/url-helpers.ts | 190 +++++++++++ apps/web/next.config.ts | 13 + apps/web/package.json | 20 +- apps/web/utils/url-helpers.ts | 59 ---- bun.lock | 208 +++++++++++- packages/ui/components/button.tsx | 2 +- 59 files changed, 1805 insertions(+), 365 deletions(-) rename apps/web/app/api/{exa/fetch-content => onboarding/extract-content}/route.ts (100%) create mode 100644 apps/web/app/api/onboarding/research/route.ts rename apps/web/{app => components}/new/onboarding/setup/chat-sidebar.tsx (74%) rename apps/web/{app => components}/new/onboarding/setup/header.tsx (100%) rename apps/web/{app => components}/new/onboarding/setup/integrations-step.tsx (95%) rename apps/web/{app => components}/new/onboarding/setup/relatable-question.tsx (98%) rename apps/web/{app => components}/new/onboarding/welcome/continue-step.tsx (95%) rename apps/web/{app => components}/new/onboarding/welcome/features-step.tsx (98%) rename apps/web/{app => components}/new/onboarding/welcome/greeting-step.tsx (100%) rename apps/web/{app => components}/new/onboarding/welcome/input-step.tsx (100%) rename apps/web/{app/new/onboarding/welcome/memories-step.tsx => components/new/onboarding/welcome/profile-step.tsx} (67%) rename apps/web/{app => components}/new/onboarding/welcome/welcome-step.tsx (100%) rename apps/web/components/{ => new/onboarding}/x-bookmarks-detail-view.tsx (95%) create mode 100644 apps/web/components/new/text-editor/extensions.tsx create mode 100644 apps/web/components/new/text-editor/index.tsx create mode 100644 apps/web/components/new/text-editor/slash-command.tsx create mode 100644 apps/web/components/new/text-editor/suggestions.tsx rename apps/web/{utils => lib}/fonts.ts (100%) create mode 100644 apps/web/lib/url-helpers.ts delete mode 100644 apps/web/utils/url-helpers.ts diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 44f4ab85..8564713b 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -3,21 +3,9 @@ name: Claude Code Review on: pull_request: types: [opened, synchronize] - # Optional: Only run on specific file changes - # paths: - # - "src/**/*.ts" - # - "src/**/*.tsx" - # - "src/**/*.js" - # - "src/**/*.jsx" jobs: claude-review: - # Optional: Filter by PR author - # if: | - # github.event.pull_request.user.login == 'external-contributor' || - # github.event.pull_request.user.login == 'new-developer' || - # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' - runs-on: ubuntu-latest permissions: contents: read @@ -38,17 +26,53 @@ jobs: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} use_sticky_comment: true prompt: | - Please review this pull request and provide feedback on: - - Code quality and best practices - - Potential bugs or issues - - Performance considerations - - Security concerns - - Test coverage + You are reviewing a PR for supermemory - a Turbo monorepo with multiple apps and packages. - Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback. + ## Repository Structure Context + + **Apps (apps/):** + - `web` - Next.js web application (no tests) + - `mcp` - Model Context Protocol server on Cloudflare Workers (no tests) + - `browser-extension` - WXT-based browser extension (no tests) + - `raycast-extension` - Raycast app extension (no tests) + - `docs` - Mintlify documentation site + + **Published Packages (packages/) - with tests:** + - `tools` - AI SDK memory tools (Vitest) + - `ai-sdk` - supermemory AI SDK wrapper (Vitest) + - `openai-sdk-python` - Python OpenAI integration (pytest) + - `pipecat-sdk-python` - Python Pipecat integration (pytest) + + **Internal Packages (packages/) - no tests:** + - `ui` - Shared React/Radix UI components + - `lib` - Shared utilities + - `hooks` - Custom React hooks + - `memory-graph` - D3-based graph visualization + - `validation` - Zod schemas + + ## Review Instructions + + 1. First, run `gh pr diff` to see what files changed + + 2. Based on the changes, review for: + - **Code quality**: Follow Biome linting rules (double quotes, tabs, no default exports) + - **Type safety**: Ensure proper TypeScript usage + - **Security**: Check for injection vulnerabilities, credential exposure, unsafe patterns + - **Performance**: Look for unnecessary re-renders (React), N+1 queries, memory leaks + + 3. **Test coverage** - ONLY review if changes touch these packages: + - `packages/tools/**` or `packages/ai-sdk/**` → Check for Vitest tests + - `packages/openai-sdk-python/**` or `packages/pipecat-sdk-python/**` → Check for pytest tests + - Skip test coverage review for apps and other packages (they have no test setup) + + 4. **Package-specific concerns:** + - Published packages (tools, ai-sdk, memory-graph, *-python): Check for breaking API changes + - UI package: Check accessibility (a11y) and component API consistency + - Web app: Check for proper data fetching patterns (TanStack Query), Zustand state management + - MCP server: Check Hono routing and Cloudflare Workers compatibility + + 5. Be concise and actionable. Focus on issues that matter, not style nitpicks (Biome handles that). Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR. - # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md - # or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' diff --git a/apps/web/.env.example b/apps/web/.env.example index 969d7377..aaf5fab4 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -1,2 +1,4 @@ NEXT_PUBLIC_BACKEND_URL=https://api.supermemory.ai -NEXT_PUBLIC_POSTHOG_KEY= \ No newline at end of file +NEXT_PUBLIC_POSTHOG_KEY= +EXA_API_KEY= +XAI_API_KEY= \ No newline at end of file diff --git a/apps/web/app/(auth)/login/new/page.tsx b/apps/web/app/(auth)/login/new/page.tsx index ddea896e..4fc7536b 100644 --- a/apps/web/app/(auth)/login/new/page.tsx +++ b/apps/web/app/(auth)/login/new/page.tsx @@ -14,7 +14,7 @@ import { InitialHeader } from "@/components/initial-header" import { useRouter, useSearchParams } from "next/navigation" import { useState, useEffect } from "react" import { motion } from "motion/react" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" import { Logo } from "@ui/assets/Logo" @@ -30,7 +30,11 @@ function AnimatedGradientBackground() { }} transition={{ y: { duration: 0.75, ease: "easeOut" }, - opacity: { duration: 8, repeat: Number.POSITIVE_INFINITY, ease: "easeInOut" }, + opacity: { + duration: 8, + repeat: Number.POSITIVE_INFINITY, + ease: "easeInOut", + }, }} /> 0 + ? `\n\nAdditional context about the user:\n${contextParts.join("\n")}` + : "" + + const { text } = await generateText({ + model: xai("grok-4-1-fast-reasoning"), + prompt: finalPrompt(xUrl, userContext), + providerOptions: { + xai: { + searchParameters: { + mode: "on", + sources: [ + { + type: "web", + safeSearch: true, + }, + { + type: "x", + includedXHandles: [lowerUrl.replace("https://x.com/", "").replace("https://twitter.com/", "")], + postFavoriteCount: 10, + }, + ], + }, + }, + }, + }) + + return Response.json({ text }) + } catch (error) { + console.error("Research API error:", error) + return Response.json({ error: "Internal server error" }, { status: 500 }) + } +} diff --git a/apps/web/app/new/onboarding/page.tsx b/apps/web/app/new/onboarding/page.tsx index 57b5b4fb..1b4962e4 100644 --- a/apps/web/app/new/onboarding/page.tsx +++ b/apps/web/app/new/onboarding/page.tsx @@ -6,18 +6,18 @@ import { useState, useEffect } from "react" import { useAuth } from "@lib/auth-context" import { cn } from "@lib/utils" -import { InputStep } from "./welcome/input-step" -import { GreetingStep } from "./welcome/greeting-step" -import { WelcomeStep } from "./welcome/welcome-step" -import { ContinueStep } from "./welcome/continue-step" -import { FeaturesStep } from "./welcome/features-step" -import { MemoriesStep } from "./welcome/memories-step" -import { RelatableQuestion } from "./setup/relatable-question" -import { IntegrationsStep } from "./setup/integrations-step" +import { InputStep } from "../../../components/new/onboarding/welcome/input-step" +import { GreetingStep } from "../../../components/new/onboarding/welcome/greeting-step" +import { WelcomeStep } from "../../../components/new/onboarding/welcome/welcome-step" +import { ContinueStep } from "../../../components/new/onboarding/welcome/continue-step" +import { FeaturesStep } from "../../../components/new/onboarding/welcome/features-step" +import { ProfileStep } from "../../../components/new/onboarding/welcome/profile-step" +import { RelatableQuestion } from "../../../components/new/onboarding/setup/relatable-question" +import { IntegrationsStep } from "../../../components/new/onboarding/setup/integrations-step" import { InitialHeader } from "@/components/initial-header" -import { SetupHeader } from "./setup/header" -import { ChatSidebar } from "./setup/chat-sidebar" +import { SetupHeader } from "../../../components/new/onboarding/setup/header" +import { ChatSidebar } from "../../../components/new/onboarding/setup/chat-sidebar" import { Logo } from "@ui/assets/Logo" import NovaOrb from "@/components/nova/nova-orb" import { AnimatedGradientBackground } from "@/components/new/animated-gradient-background" @@ -152,7 +152,7 @@ export default function OnboardingPage() { case "features": return case "memories": - return + return default: return null } diff --git a/apps/web/app/new/settings/page.tsx b/apps/web/app/new/settings/page.tsx index fbb0bc08..2b5df3ca 100644 --- a/apps/web/app/new/settings/page.tsx +++ b/apps/web/app/new/settings/page.tsx @@ -6,7 +6,7 @@ import { motion } from "motion/react" import NovaOrb from "@/components/nova/nova-orb" import { useState, useEffect, useRef } from "react" import { cn } from "@lib/utils" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import Account from "@/components/new/settings/account" import Integrations from "@/components/new/settings/integrations" import ConnectionsMCP from "@/components/new/settings/connections-mcp" @@ -175,7 +175,11 @@ export default function SettingsPage() { return (
-
diff --git a/apps/web/components/new/add-document/connections.tsx b/apps/web/components/new/add-document/connections.tsx index 5a89cf70..b146fb4c 100644 --- a/apps/web/components/new/add-document/connections.tsx +++ b/apps/web/components/new/add-document/connections.tsx @@ -10,7 +10,7 @@ import { Check, Loader, Trash2, Zap } from "lucide-react" import { useEffect, useState } from "react" import { toast } from "sonner" import type { z } from "zod" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import { cn } from "@lib/utils" import { Button } from "@ui/components/button" diff --git a/apps/web/components/new/add-document/file.tsx b/apps/web/components/new/add-document/file.tsx index 8e7dc4c4..bb605f03 100644 --- a/apps/web/components/new/add-document/file.tsx +++ b/apps/web/components/new/add-document/file.tsx @@ -2,7 +2,7 @@ import { useState, useEffect } from "react" import { cn } from "@lib/utils" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import { FileIcon } from "lucide-react" import { useHotkeys } from "react-hotkeys-hook" @@ -19,7 +19,12 @@ interface FileContentProps { isOpen?: boolean } -export function FileContent({ onSubmit, onDataChange, isSubmitting, isOpen }: FileContentProps) { +export function FileContent({ + onSubmit, + onDataChange, + isSubmitting, + isOpen, +}: FileContentProps) { const [isDragging, setIsDragging] = useState(false) const [selectedFile, setSelectedFile] = useState(null) const [title, setTitle] = useState("") @@ -33,8 +38,16 @@ export function FileContent({ onSubmit, onDataChange, isSubmitting, isOpen }: Fi } } - const updateData = (newFile: File | null, newTitle: string, newDescription: string) => { - onDataChange?.({ file: newFile, title: newTitle, description: newDescription }) + const updateData = ( + newFile: File | null, + newTitle: string, + newDescription: string, + ) => { + onDataChange?.({ + file: newFile, + title: newTitle, + description: newDescription, + }) } const handleFileChange = (file: File | null) => { diff --git a/apps/web/components/new/add-document/index.tsx b/apps/web/components/new/add-document/index.tsx index 9e117912..a99505bd 100644 --- a/apps/web/components/new/add-document/index.tsx +++ b/apps/web/components/new/add-document/index.tsx @@ -3,7 +3,7 @@ import { useState, useEffect, useMemo, useCallback } from "react" import { Dialog, DialogContent, DialogTitle } from "@repo/ui/components/dialog" import { cn } from "@lib/utils" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import { FileTextIcon, GlobeIcon, diff --git a/apps/web/components/new/add-document/link.tsx b/apps/web/components/new/add-document/link.tsx index 544af86d..2efb67dc 100644 --- a/apps/web/components/new/add-document/link.tsx +++ b/apps/web/components/new/add-document/link.tsx @@ -3,7 +3,7 @@ import { useState, useEffect } from "react" import { cn } from "@lib/utils" import { Button } from "@ui/components/button" -import { dmSansClassName } from "@/utils/fonts" +import { dmSansClassName } from "@/lib/fonts" import { useHotkeys } from "react-hotkeys-hook" import { Image as ImageIcon, Loader2 } from "lucide-react" import { toast } from "sonner" diff --git a/apps/web/components/new/add-document/note.tsx b/apps/web/components/new/add-document/note.tsx index 465e295a..4f833ca2 100644 --- a/apps/web/components/new/add-document/note.tsx +++ b/apps/web/components/new/add-document/note.tsx @@ -1,7 +1,7 @@ "use client" import { useState, useEffect } from "react" -import { useHotkeys } from "react-hotkeys-hook" +import { TextEditor } from "../text-editor" interface NoteContentProps { onSubmit?: (content: string) => void @@ -31,11 +31,6 @@ export function NoteContent({ onContentChange?.(newContent) } - useHotkeys("mod+enter", handleSubmit, { - enabled: isOpen && canSubmit, - enableOnFormTags: ["TEXTAREA"], - }) - // Reset content when modal closes useEffect(() => { if (!isOpen) { @@ -45,12 +40,12 @@ export function NoteContent({ }, [isOpen, onContentChange]) return ( -