Skip to content

SCRUM-228-챗봇 연동#37

Merged
gs0428 merged 8 commits into
devfrom
SCRUM-228
Jun 23, 2025
Merged

SCRUM-228-챗봇 연동#37
gs0428 merged 8 commits into
devfrom
SCRUM-228

Conversation

@gs0428

@gs0428 gs0428 commented Jun 23, 2025

Copy link
Copy Markdown
Member

🛠️ 구현한 부분

  • 챗봇 세션 목록 전체 조회
  • 챗봇 세션 생성
  • 챗봇과 채팅

🖼️ 실행 화면(선택)

챗봇 열기 전

스크린샷 2025-06-24 오전 12 44 44

첫 대화 시작

스크린샷 2025-06-24 오전 12 45 04

세션(채팅 내역) 조회

스크린샷 2025-06-24 오전 12 45 56

🔥 어려웠던 부분(선택)

🔍 참고(선택)

Summary by CodeRabbit

  • New Features

    • Introduced a chat bot feature with a chat interface, session management, and real-time message streaming.
    • Added a floating chat bot panel accessible from the bottom right of the screen.
    • Implemented chat session history, allowing users to view and switch between previous chat sessions.
  • Improvements

    • Enhanced user profile handling with improved user info management.
    • Updated icon set with new chat bot and send icons.
    • Improved conditional rendering of graph visualization based on available data.
  • Bug Fixes

    • Adjusted styling for color input and improved responsive UI behavior.
  • Chores

    • Added new dependencies for markdown rendering and enhanced typography support.
    • Updated Tailwind CSS configuration for broader file matching and better typography.

@gs0428 gs0428 self-assigned this Jun 23, 2025
@gs0428 gs0428 added the ✨ feat 기능 구현을 진행합니다. label Jun 23, 2025
@coderabbitai

coderabbitai Bot commented Jun 23, 2025

Copy link
Copy Markdown

Walkthrough

This update introduces a chat bot feature to the application, including a new chat UI with session management, streaming assistant responses, and Markdown rendering. Supporting changes include new API routes, service modules, React Query hooks, Zustand state for user info, new icons, TypeScript models, and Tailwind CSS enhancements. Several dependencies are added or updated.

Changes

File(s) / Group Change Summary
apps/extension/src/pages/create-bookmark.tsx Made rendering of <Graph2D> conditional on the presence of the id query parameter.
apps/www/package.json Added dependencies: @tailwindcss/typography, @types/dompurify, dompurify, and marked.
apps/www/src/app/api/chat/route.ts Added a POST API route handler for chat, forwarding requests to an external AI API and streaming the response to the client.
apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx New chat interface component with session management, streaming assistant responses, Markdown rendering, and responsive UI.
apps/www/src/components/bookmarks/graph/chat-bot/index.tsx New ChatBot component for toggling chat UI, displaying session list, and managing active session state.
apps/www/src/components/bookmarks/graph/graph-detail.tsx Rendered new ChatBot component fixed at the bottom right; wrapped sidebar in a fragment. Minor whitespace change.
apps/www/src/components/bookmarks/sidebar/index.tsx Switched from useGetUserInfo to custom useUserInfo hook; updated user info access and input styling.
apps/www/src/components/common/icon.tsx Added chatBot and send SVG icon components to the icon set.
apps/www/src/constants/chat.ts Introduced CHAT enum with values for chat session and message actions.
apps/www/src/hooks/use-user-info.ts Added new useUserInfo hook integrating Zustand store and async fetching for user info.
apps/www/src/lib/tanstack/mutation/chat.ts Added useCreateChatSession mutation hook with cache invalidation on success.
apps/www/src/lib/tanstack/query/chat.ts Added useGetChatMessages and useGetAllChatSessions hooks for chat data fetching.
apps/www/src/lib/zustand/user.ts Introduced Zustand store for user info state management.
apps/www/src/models/chat.ts Added TypeScript interfaces for chat sessions and messages: ChatSessionDTO, ChatSessionListDTO, ChatMessageDTO.
apps/www/src/models/user.ts Changed UserInfoDTO.id type from string to number.
apps/www/src/service/chat.ts New chat service module with functions for creating sessions, fetching messages, and listing sessions.
apps/www/tailwind.config.mts Expanded UI content file patterns, added typography extension, and enabled Tailwind Typography plugin.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ChatBotUI
    participant API_Route
    participant ExternalAI

    User->>ChatBotUI: Opens chat, submits message or starts session
    ChatBotUI->>API_Route: POST /api/chat with userId, message, session_id
    API_Route->>ExternalAI: Forwards request to external AI API
    ExternalAI-->>API_Route: Streams assistant response
    API_Route-->>ChatBotUI: Streams response to UI
    ChatBotUI-->>User: Displays streaming assistant message in chat
Loading

Poem

In the meadow of code, a chat bot appears,
With sessions and streams, it now lends its ears.
Markdown it renders, with icons anew,
User info in Zustand, and queries in queue.
Tailwind grows smarter, the bot hops with glee—
More features for all, from this code rabbit spree!

(_/)
( •_•)
/ >🍃

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@gs0428 gs0428 merged commit 0944b01 into dev Jun 23, 2025
2 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (8)
apps/www/src/lib/tanstack/mutation/chat.ts (1)

7-17: Consider enhancing error handling for better user experience.

The mutation hook follows React Query best practices with proper cache invalidation. However, consider providing user-facing error feedback instead of just console logging.

    onError: (error) => {
-     console.error("onError", error);
+     console.error("Failed to create chat session:", error);
+     // Consider adding toast notification or error state management
+     // toast.error("Failed to create chat session. Please try again.");
    },
apps/www/src/components/bookmarks/sidebar/index.tsx (1)

212-212: Minor CSS change noted.

The removal of the w-full class reduces the width of the color input. Ensure this aligns with the intended design.

apps/www/src/app/api/chat/route.ts (1)

5-66: Consider adding rate limiting and request size limits.

The API endpoint should have rate limiting and request size limits to prevent abuse.

Consider implementing:

  • Rate limiting per user/IP
  • Request body size limits
  • Timeout handling for the external API call
  • Logging for monitoring and debugging
apps/www/src/components/bookmarks/graph/graph-detail.tsx (1)

215-391: Consider accessibility and mobile responsiveness.

While the implementation is functionally correct, consider these enhancements:

  • Add ARIA labels for screen readers
  • Test mobile responsiveness as fixed positioning might cause issues on smaller screens
  • Consider z-index conflicts with other fixed/absolute elements
-      <div className="fixed bottom-5 text-white" style={{ right: open ? "23.75rem" : "1.25rem" }}>
+      <div 
+        className="fixed bottom-5 text-white z-50" 
+        style={{ right: open ? "23.75rem" : "1.25rem" }}
+        role="complementary"
+        aria-label="Chatbot"
+      >
         <ChatBot />
       </div>
apps/www/src/lib/tanstack/query/chat.ts (1)

13-18: Consider making pagination configurable.

The useGetAllChatSessions hook hardcodes pagination parameters (limit: 20, offset: 0). For better reusability, consider making these configurable:

-export const useGetAllChatSessions = () => {
+export const useGetAllChatSessions = (params = { limit: 20, offset: 0 }) => {
   return useQuery({
     queryKey: [CHAT.GET_ALL_CHAT_SESSIONS],
-    queryFn: () => getAllChatSessions({ limit: 20, offset: 0 }),
+    queryFn: () => getAllChatSessions(params),
   });
 };

This would enable future pagination features while maintaining backward compatibility.

apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (1)

25-37: Consider keyboard navigation support.

The session list lacks keyboard navigation support. For better accessibility, consider adding keyboard event handlers.

 <button
   className={cn(
     "w-full max-w-52 truncate rounded-md p-1 text-start",
     currentSession === session.sessionId && "bg-[#e8e8e8]"
   )}
   onClick={() => setCurrentSession(session.sessionId)}
+  onKeyDown={(e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      setCurrentSession(session.sessionId);
+    }
+  }}
 >
   {session.title}
 </button>
apps/www/src/service/chat.ts (1)

1-24: Consider adding request/response logging for debugging.

For a new chat feature, consider adding logging to help with debugging and monitoring API interactions.

You could add a simple logging wrapper or use the existing API instance's interceptors to log chat-related requests. This would be valuable during the initial rollout phase.

apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (1)

66-100: Consider more specific error handling for streaming.

The streaming implementation looks good. Consider adding more context to error messages to help with debugging.

          } catch (error) {
-            console.error("JSON parsing error:", error, "line:", line);
+            console.error("[Chat Stream] JSON parsing error:", {
+              error,
+              line,
+              sessionId,
+              chunk: line.substring(0, 100) // Log first 100 chars for debugging
+            });
          }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3143cef and 2da828b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • apps/extension/src/pages/create-bookmark.tsx (1 hunks)
  • apps/www/package.json (1 hunks)
  • apps/www/src/app/api/chat/route.ts (1 hunks)
  • apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (1 hunks)
  • apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (1 hunks)
  • apps/www/src/components/bookmarks/graph/graph-detail.tsx (2 hunks)
  • apps/www/src/components/bookmarks/sidebar/index.tsx (4 hunks)
  • apps/www/src/components/common/icon.tsx (1 hunks)
  • apps/www/src/constants/chat.ts (1 hunks)
  • apps/www/src/hooks/use-user-info.ts (1 hunks)
  • apps/www/src/lib/tanstack/mutation/chat.ts (1 hunks)
  • apps/www/src/lib/tanstack/query/chat.ts (1 hunks)
  • apps/www/src/lib/zustand/user.ts (1 hunks)
  • apps/www/src/models/chat.ts (1 hunks)
  • apps/www/src/models/user.ts (1 hunks)
  • apps/www/src/service/chat.ts (1 hunks)
  • apps/www/tailwind.config.mts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
apps/www/src/components/bookmarks/sidebar/index.tsx (1)
apps/www/src/hooks/use-user-info.ts (1)
  • useUserInfo (6-20)
apps/www/src/lib/tanstack/query/chat.ts (1)
apps/www/src/service/chat.ts (2)
  • getChatMessages (12-16)
  • getAllChatSessions (18-23)
apps/www/src/lib/zustand/user.ts (1)
apps/www/src/models/user.ts (1)
  • UserInfoDTO (1-5)
apps/www/src/lib/tanstack/mutation/chat.ts (1)
apps/www/src/service/chat.ts (1)
  • createChatSession (6-10)
apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (4)
apps/www/src/hooks/use-user-info.ts (1)
  • useUserInfo (6-20)
apps/www/src/lib/tanstack/query/chat.ts (1)
  • useGetChatMessages (5-11)
apps/www/src/service/chat.ts (1)
  • createChatSession (6-10)
apps/www/src/lib/tanstack/mutation/chat.ts (1)
  • useCreateChatSession (7-17)
apps/www/src/service/chat.ts (1)
apps/www/src/models/chat.ts (3)
  • ChatSessionDTO (1-3)
  • ChatMessageDTO (14-27)
  • ChatSessionListDTO (5-12)
apps/www/src/hooks/use-user-info.ts (1)
apps/www/src/lib/tanstack/query/user.ts (1)
  • useGetUserInfo (5-10)
🪛 Biome (1.9.4)
apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx

[error] 29-29: Avoid passing content using the dangerouslySetInnerHTML prop.

Setting content using code can expose users to cross-site scripting (XSS) attacks

(lint/security/noDangerouslySetInnerHtml)

🔇 Additional comments (19)
apps/www/package.json (1)

13-17: Verify dependency versions and security.

The added dependencies support the chat feature's Markdown rendering capabilities. Please ensure these versions are the latest stable releases and free from known vulnerabilities.

#!/bin/bash
# Check for latest versions and security advisories for the new dependencies
echo "Checking @tailwindcss/typography..."
npm view @tailwindcss/typography versions --json | jq -r '.[-1]'

echo "Checking dompurify..."
npm view dompurify versions --json | jq -r '.[-1]'

echo "Checking marked..."
npm view marked versions --json | jq -r '.[-1]'

# Check for security advisories
echo "Checking for security advisories..."
npm audit --json | jq '.vulnerabilities | length'
apps/www/src/constants/chat.ts (1)

1-4: LGTM! Clean implementation of query key constants.

The enum provides type safety and centralizes chat-related query keys, following good naming conventions and maintainability practices.

apps/www/src/models/user.ts (1)

2-2: I’ll inspect all userInfo.id usages and pull in the surrounding code to confirm they handle the new number type correctly.

#!/bin/bash
echo "Inspecting all userInfo.id occurrences with context:"
rg -n "userInfo\.id" -g "*.ts" -g "*.tsx" -A 2 -B 2

echo -e "\nExtracting chat.tsx around line 119 and 150:"
sed -n '115,130p' apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx
sed -n '145,160p' apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx

echo -e "\nExtracting route.ts around userId handling:"
sed -n '1,30p' apps/www/src/app/api/chat/route.ts
apps/extension/src/pages/create-bookmark.tsx (1)

201-205: Good defensive programming practice.

The conditional rendering prevents the graph from displaying when there's no relevant data (id), which improves the user experience by avoiding empty or invalid graph states.

apps/www/src/components/bookmarks/sidebar/index.tsx (1)

12-12: LGTM! Proper integration with new user state management.

The changes correctly integrate with the new centralized user state management using the useUserInfo hook, maintaining consistency across the application.

Also applies to: 31-31, 144-144

apps/www/src/lib/zustand/user.ts (1)

1-13: LGTM! Clean Zustand store implementation.

The store follows Zustand best practices with a clear interface and focused responsibility for user state management.

apps/www/src/components/common/icon.tsx (1)

100-131: LGTM! Consistent icon implementations.

The new chatBot and send icons follow the established pattern and interface of existing icons in the component.

apps/www/src/components/bookmarks/graph/graph-detail.tsx (2)

17-17: Import statement looks correct.

The ChatBot component import follows the expected relative path pattern and is properly typed.


215-219: ChatBot positioning logic is well implemented.

The dynamic positioning based on the sidebar's open state is elegant:

  • When sidebar is open: positioned at right: 23.75rem (accounting for sidebar width)
  • When sidebar is closed: positioned at right: 1.25rem (standard margin from edge)

The fixed positioning ensures the chatbot remains accessible regardless of scroll position.

apps/www/tailwind.config.mts (3)

9-9: Content pattern expansion is appropriate.

Expanding from just .tsx to include .js, .ts, .jsx, and .tsx files ensures Tailwind processes all relevant UI package files. This is necessary for proper style generation across the component library.


38-46: Typography configuration is well-structured.

The custom typography configuration properly:

  • Uses theme function to access colors consistently
  • Sets prose bullets and counters to gray.500 for visual consistency
  • Follows Tailwind's typography plugin conventions

This supports the Markdown rendering in the chat components.


48-48: Plugin addition is correct.

Adding the @tailwindcss/typography plugin enables enhanced typography utilities needed for the chat Markdown rendering.

apps/www/src/lib/tanstack/query/chat.ts (1)

5-11: Chat messages hook implementation is solid.

The useGetChatMessages hook correctly:

  • Uses sessionId in query key for proper caching per session
  • Enables query only when sessionId exists (prevents unnecessary requests)
  • Follows React Query best practices
apps/www/src/components/bookmarks/graph/chat-bot/index.tsx (1)

11-16: State management is appropriate.

The component correctly manages:

  • isOpen for toggle functionality
  • currentSession for active session tracking
  • Uses React Query hook for data fetching
apps/www/src/service/chat.ts (1)

6-10: Chat session creation function is well-typed.

The createChatSession function correctly:

  • Accepts a typed body parameter
  • Returns properly typed promise
  • Uses consistent API pattern
apps/www/src/models/chat.ts (1)

1-27: Well-structured type definitions!

The interfaces are properly typed and follow TypeScript best practices. The use of Partial<> for optional metadata fields is appropriate.

apps/www/src/components/bookmarks/graph/chat-bot/chat.tsx (3)

24-36: Proper security implementation for HTML rendering.

Good use of DOMPurify to sanitize the HTML output from marked. This properly mitigates XSS risks when using dangerouslySetInnerHTML.


165-275: Excellent UI implementation with good UX considerations.

The component handles all states gracefully with proper loading indicators, auto-resizing textarea, and keyboard shortcuts. The conditional rendering logic is clean and easy to follow.


52-56: Add safety check for array access.

The code assumes chatHistory.result has at least one element when accessing chatHistory.result[0]. This could throw an error if the array is empty.

Apply this fix:

-    if (chatHistory?.result && chatHistory.result.length > 0 && messages.length === 0) {
+    if (chatHistory?.result && chatHistory.result.length > 0 && messages.length === 0) {
+      const firstSession = chatHistory.result[0];
+      if (firstSession && firstSession.messages) {
-      setMessages(chatHistory.result[0].messages);
+        setMessages(firstSession.messages);
+      }
    }

Likely an incorrect or invalid review comment.

Comment on lines +10 to +14
useEffect(() => {
if (data?.result && !isLoading && !userInfo) {
setUserInfo(data.result);
}
}, [data, isLoading]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix missing dependencies in useEffect.

The useEffect hook is missing userInfo and setUserInfo in its dependency array, which could lead to stale closures or unexpected behavior.

  useEffect(() => {
    if (data?.result && !isLoading && !userInfo) {
      setUserInfo(data.result);
    }
-  }, [data, isLoading]);
+  }, [data, isLoading, userInfo, setUserInfo]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (data?.result && !isLoading && !userInfo) {
setUserInfo(data.result);
}
}, [data, isLoading]);
useEffect(() => {
if (data?.result && !isLoading && !userInfo) {
setUserInfo(data.result);
}
}, [data, isLoading, userInfo, setUserInfo]);
🤖 Prompt for AI Agents
In apps/www/src/hooks/use-user-info.ts around lines 10 to 14, the useEffect
hook's dependency array is missing userInfo and setUserInfo, which can cause
stale closures or unexpected behavior. Add userInfo and setUserInfo to the
dependency array to ensure the effect runs correctly when these values change.

Comment on lines +15 to +19
body: JSON.stringify({
userId,
message,
session_id,
}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Sanitize user input before forwarding.

User input should be sanitized before forwarding to external APIs to prevent injection attacks.

Consider adding input sanitization:

      body: JSON.stringify({
-        userId,
-        message,
+        userId: String(userId).trim(),
+        message: String(message).trim().slice(0, 1000), // Limit message length
        session_id,
      }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
body: JSON.stringify({
userId,
message,
session_id,
}),
body: JSON.stringify({
userId: String(userId).trim(),
message: String(message).trim().slice(0, 1000), // Limit message length
session_id,
}),
🤖 Prompt for AI Agents
In apps/www/src/app/api/chat/route.ts around lines 15 to 19, the user input
fields userId, message, and session_id are directly included in the JSON payload
without sanitization. To fix this, sanitize these inputs by removing or escaping
any potentially harmful characters or scripts before including them in the
JSON.stringify call. Use a suitable sanitization method or library to clean the
inputs and ensure no injection attacks can occur when forwarding data to
external APIs.

Comment on lines +56 to +64
} catch (error: unknown) {
return NextResponse.json(
{
code: "BAD_REQUEST",
message: `Error: ${(error as Error).message}`,
data: null,
},
{ status: 400 }
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid exposing internal error details.

The error response may expose internal implementation details that could be used maliciously.

  } catch (error: unknown) {
    return NextResponse.json(
      {
        code: "BAD_REQUEST",
-        message: `Error: ${(error as Error).message}`,
+        message: "Failed to process chat request",
        data: null,
      },
      { status: 400 }
    );
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error: unknown) {
return NextResponse.json(
{
code: "BAD_REQUEST",
message: `Error: ${(error as Error).message}`,
data: null,
},
{ status: 400 }
);
} catch (error: unknown) {
return NextResponse.json(
{
code: "BAD_REQUEST",
message: "Failed to process chat request",
data: null,
},
{ status: 400 }
);
}
🤖 Prompt for AI Agents
In apps/www/src/app/api/chat/route.ts around lines 56 to 64, the error response
currently includes the internal error message, which may expose sensitive
implementation details. Modify the catch block to return a generic error message
instead of the actual error message, such as "An unexpected error occurred,"
while keeping the status code 400. This prevents leaking internal details while
still informing the client of the failure.

Comment on lines +7 to +8
const body = await req.json();
const { userId, message, session_id } = body;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add input validation and authentication.

The API endpoint lacks input validation and authentication checks, which are critical for security.

export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    const { userId, message, session_id } = body;
+
+    // Validate required fields
+    if (!userId || !message) {
+      return NextResponse.json(
+        { code: "BAD_REQUEST", message: "Missing required fields: userId, message", data: null },
+        { status: 400 }
+      );
+    }
+
+    // TODO: Add authentication check
+    // Verify that the requesting user has permission to use this userId
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const body = await req.json();
const { userId, message, session_id } = body;
export async function POST(req: NextRequest) {
try {
const body = await req.json();
const { userId, message, session_id } = body;
// Validate required fields
if (!userId || !message) {
return NextResponse.json(
{ code: "BAD_REQUEST", message: "Missing required fields: userId, message", data: null },
{ status: 400 }
);
}
// TODO: Add authentication check
// Verify that the requesting user has permission to use this userId
// ...rest of your handler logic...
} catch (error) {
// existing error handling
}
}
🤖 Prompt for AI Agents
In apps/www/src/app/api/chat/route.ts around lines 7 to 8, the code extracts
userId, message, and session_id from the request body without validating the
input or checking authentication. Add input validation to ensure these fields
are present and of the expected type, and implement authentication checks to
verify the user's identity before processing the request. Return appropriate
error responses if validation or authentication fails.

@@ -0,0 +1,66 @@
import { NextRequest, NextResponse } from "next/server";

const baseUrl = process.env.AI_API_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate environment variable on startup.

The AI_API_URL environment variable should be validated to ensure it's properly configured.

const baseUrl = process.env.AI_API_URL;
+
+if (!baseUrl) {
+  throw new Error('AI_API_URL environment variable is required');
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const baseUrl = process.env.AI_API_URL;
const baseUrl = process.env.AI_API_URL;
if (!baseUrl) {
throw new Error('AI_API_URL environment variable is required');
}
🤖 Prompt for AI Agents
In apps/www/src/app/api/chat/route.ts at line 3, the environment variable
AI_API_URL is used without validation. Add a check during application startup to
verify that AI_API_URL is defined and not empty. If the variable is missing or
invalid, throw an error or log a critical message to prevent the app from
running with a misconfiguration.

Comment on lines +38 to +44
<button
type="submit"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

"새로운 대화 시작하기" button has incorrect type.

The button has type="submit" but it's not inside a form. This should be type="button" to prevent any unintended form submission behavior.

 <button
-  type="submit"
+  type="button"
   className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
   onClick={() => setCurrentSession("")}
 >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
type="submit"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>
<button
type="button"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/graph/chat-bot/index.tsx around lines 38 to
44, the button currently has type="submit" but is not inside a form, which can
cause unintended form submissions. Change the button's type attribute from
"submit" to "button" to prevent this behavior.

Comment on lines +22 to +48
{isOpen && (
<div className="absolute bottom-0 right-full mr-2 flex h-96 gap-5 rounded-lg bg-white p-2 text-black">
<ul className="relative flex flex-col gap-2 overflow-y-auto">
{chatSessions?.result.map((session) => (
<li key={session.sessionId}>
<button
className={cn(
"w-full max-w-52 truncate rounded-md p-1 text-start",
currentSession === session.sessionId && "bg-[#e8e8e8]"
)}
onClick={() => setCurrentSession(session.sessionId)}
>
{session.title}
</button>
</li>
))}
<button
type="submit"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>
</ul>
<Chat sessionId={currentSession} onSessionCreated={setCurrentSession} />
</div>
)}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and loading states.

The component doesn't handle loading or error states from the useGetAllChatSessions hook. This could lead to poor UX when the API is slow or fails.

-  const { data: chatSessions } = useGetAllChatSessions();
+  const { data: chatSessions, isLoading, error } = useGetAllChatSessions();

   return (
     <div className="relative text-sm">
       <button className="rounded-lg bg-white p-2" onClick={() => setIsOpen(!isOpen)}>
         <Icon.chatBot />
       </button>
       {isOpen && (
         <div className="absolute bottom-0 right-full mr-2 flex h-96 gap-5 rounded-lg bg-white p-2 text-black">
           <ul className="relative flex flex-col gap-2 overflow-y-auto">
+            {isLoading && <li className="p-2 text-gray-500">Loading sessions...</li>}
+            {error && <li className="p-2 text-red-500">Failed to load sessions</li>}
             {chatSessions?.result.map((session) => (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{isOpen && (
<div className="absolute bottom-0 right-full mr-2 flex h-96 gap-5 rounded-lg bg-white p-2 text-black">
<ul className="relative flex flex-col gap-2 overflow-y-auto">
{chatSessions?.result.map((session) => (
<li key={session.sessionId}>
<button
className={cn(
"w-full max-w-52 truncate rounded-md p-1 text-start",
currentSession === session.sessionId && "bg-[#e8e8e8]"
)}
onClick={() => setCurrentSession(session.sessionId)}
>
{session.title}
</button>
</li>
))}
<button
type="submit"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>
</ul>
<Chat sessionId={currentSession} onSessionCreated={setCurrentSession} />
</div>
)}
// before
- const { data: chatSessions } = useGetAllChatSessions();
// after
const { data: chatSessions, isLoading, error } = useGetAllChatSessions();
return (
<div className="relative text-sm">
<button
className="rounded-lg bg-white p-2"
onClick={() => setIsOpen(!isOpen)}
>
<Icon.chatBot />
</button>
{isOpen && (
<div className="absolute bottom-0 right-full mr-2 flex h-96 gap-5 rounded-lg bg-white p-2 text-black">
<ul className="relative flex flex-col gap-2 overflow-y-auto">
{isLoading && (
<li className="p-2 text-gray-500">Loading sessions...</li>
)}
{error && (
<li className="p-2 text-red-500">Failed to load sessions</li>
)}
{chatSessions?.result.map((session) => (
<li key={session.sessionId}>
<button
className={cn(
"w-full max-w-52 truncate rounded-md p-1 text-start",
currentSession === session.sessionId && "bg-[#e8e8e8]"
)}
onClick={() => setCurrentSession(session.sessionId)}
>
{session.title}
</button>
</li>
))}
<button
type="submit"
className="sticky bottom-0 flex w-full items-center justify-center rounded-md bg-black py-2 text-white"
onClick={() => setCurrentSession("")}
>
새로운 대화 시작하기
</button>
</ul>
<Chat
sessionId={currentSession}
onSessionCreated={setCurrentSession}
/>
</div>
)}
</div>
);
🤖 Prompt for AI Agents
In apps/www/src/components/bookmarks/graph/chat-bot/index.tsx around lines 22 to
48, the component currently does not handle loading or error states from the
useGetAllChatSessions hook. To fix this, add conditional rendering to display a
loading indicator while data is being fetched and an error message if the API
call fails. This involves checking the loading and error states returned by the
hook and rendering appropriate UI elements before attempting to map over
chatSessions.result.

Comment on lines +12 to +16
export const getChatMessages = async (
sessionId: string
): Promise<BaseResponseDTO<ChatMessageDTO[]>> => {
return api.get(`/chat/sessions/${sessionId}/messages`);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for sessionId.

The getChatMessages function should validate the sessionId parameter to prevent API calls with invalid or empty values.

 export const getChatMessages = async (
   sessionId: string
 ): Promise<BaseResponseDTO<ChatMessageDTO[]>> => {
+  if (!sessionId || sessionId.trim() === '') {
+    throw new Error('Session ID is required');
+  }
   return api.get(`/chat/sessions/${sessionId}/messages`);
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getChatMessages = async (
sessionId: string
): Promise<BaseResponseDTO<ChatMessageDTO[]>> => {
return api.get(`/chat/sessions/${sessionId}/messages`);
};
export const getChatMessages = async (
sessionId: string
): Promise<BaseResponseDTO<ChatMessageDTO[]>> => {
if (!sessionId || sessionId.trim() === '') {
throw new Error('Session ID is required');
}
return api.get(`/chat/sessions/${sessionId}/messages`);
};
🤖 Prompt for AI Agents
In apps/www/src/service/chat.ts around lines 12 to 16, the getChatMessages
function lacks validation for the sessionId parameter. Add a check at the start
of the function to ensure sessionId is not empty or invalid (e.g., null,
undefined, or an empty string). If the validation fails, throw an error or
return a rejected promise to prevent making an API call with an invalid
sessionId.

Comment on lines +18 to +23
export const getAllChatSessions = async (params: {
limit: number;
offset: number;
}): Promise<BaseResponseDTO<ChatSessionListDTO[]>> => {
return api.get(`/chat/sessions?limit=${params.limit}&offset=${params.offset}`);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add parameter validation for pagination.

The getAllChatSessions function should validate pagination parameters to prevent invalid API requests.

 export const getAllChatSessions = async (params: {
   limit: number;
   offset: number;
 }): Promise<BaseResponseDTO<ChatSessionListDTO[]>> => {
+  if (params.limit <= 0 || params.offset < 0) {
+    throw new Error('Invalid pagination parameters');
+  }
   return api.get(`/chat/sessions?limit=${params.limit}&offset=${params.offset}`);
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const getAllChatSessions = async (params: {
limit: number;
offset: number;
}): Promise<BaseResponseDTO<ChatSessionListDTO[]>> => {
return api.get(`/chat/sessions?limit=${params.limit}&offset=${params.offset}`);
};
export const getAllChatSessions = async (params: {
limit: number;
offset: number;
}): Promise<BaseResponseDTO<ChatSessionListDTO[]>> => {
if (params.limit <= 0 || params.offset < 0) {
throw new Error('Invalid pagination parameters');
}
return api.get(`/chat/sessions?limit=${params.limit}&offset=${params.offset}`);
};
🤖 Prompt for AI Agents
In apps/www/src/service/chat.ts around lines 18 to 23, the getAllChatSessions
function lacks validation for the pagination parameters limit and offset. Add
checks to ensure limit and offset are valid numbers and within acceptable ranges
before making the API call. If the parameters are invalid, throw an error or
handle it appropriately to prevent sending invalid requests to the API.

@gs0428 gs0428 deleted the SCRUM-228 branch July 7, 2025 11:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 기능 구현을 진행합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant