Conversation
…rd/updateQuiz; remove selectCards Made-with: Cursor
Made-with: Cursor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughConsolidates generation flows and tools: merges note/flashcard/quiz generation into a combined autogen path, removes topic-based quiz worker, introduces explicit-question quiz creation, adds an editItem tool and workspace "edit" action, and removes several UI update components. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant API as Autogen Route
participant AI as AI Service
participant Worker as WorkspaceWorker
participant DB as Storage/Events
Client->>API: Request generate note+flashcards+quiz
API->>AI: Prompt (NOTE_FLASHCARD_QUIZ_SYSTEM) and stream progress
AI-->>API: Streamed JSON (note, flashcards, quiz)
API->>Worker: create / bulkCreate items (include quiz questions with generated ids)
Worker->>DB: append events / persist items
DB-->>Worker: ack
Worker-->>API: creation result
API-->>Client: final result with items and quiz data
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
There was a problem hiding this comment.
Important
Looks good to me! 👍
Reviewed everything up to c4a7360 in 18 seconds. Click for details.
- Reviewed
3019lines of code in19files - Skipped
0files when reviewing. - Skipped posting
0draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
Workflow ID: wflow_dm71UpYy3GqXE8QX
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
There was a problem hiding this comment.
2 issues found across 19 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/app/api/workspaces/autogen/route.ts">
<violation number="1" location="src/app/api/workspaces/autogen/route.ts:507">
P2: Quiz questions are accepted without validating option count or correctIndex bounds, so LLM output with missing options can render quizzes with no selectable answers or invalid correct indices. Add schema validation to enforce 4 options for multiple-choice and 2 for true/false (and clamp correctIndex) before building the quiz data.</violation>
</file>
<file name="src/lib/ai/workers/workspace-worker.ts">
<violation number="1" location="src/lib/ai/workers/workspace-worker.ts:879">
P1: Runtime crash: `questionsToAdd.length` in the logger will throw `TypeError: Cannot read properties of undefined` when `updateQuiz` is called with only a title change (no questions). The return value on line 879 was correctly fixed with optional chaining, but this logger statement was missed.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/assistant-ui/CreateQuizToolUI.tsx (1)
37-50:⚠️ Potential issue | 🟡 MinorAvoid stale item lookup causing false “Item no longer exists”.
Line 37 now relies on
workspaceState.itemsto resolvecurrentItem. Right after completion, that list can lag briefly, so Move can fail even for a valid new quiz. Add a fallback item source (or gate Move visibility until item resolution succeeds).🩹 Suggested fix
const currentItem = useMemo(() => { const targetId = result.itemId || result.quizId; - if (!targetId || !workspaceState?.items) return undefined; - return workspaceState.items.find((item: any) => item.id === targetId); -}, [result.itemId, result.quizId, workspaceState?.items]); + const items = workspaceState?.items ?? allItems; + if (!targetId || !items?.length) return undefined; + return items.find((item: any) => item.id === targetId); +}, [result.itemId, result.quizId, workspaceState?.items, allItems]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/assistant-ui/CreateQuizToolUI.tsx` around lines 37 - 50, CreateQuizReceipt's currentItem lookup using workspaceState.items can be stale immediately after creation causing false "Item no longer exists" errors; update the lookup to fallback to other sources (for example use result.itemId/result.quizId to find the item in the passed-in allItems prop or in result.payload) before declaring the item missing, and/or prevent showing the Move dialog (showMoveDialog) until a resolved currentItem exists; specifically modify the useMemo that computes currentItem to first try workspaceState.items, then fall back to allItems.find(...) or result-contained data, and ensure moveItemToFolder and the UI that toggles setShowMoveDialog only enable when currentItem is non-undefined.
🧹 Nitpick comments (3)
src/components/assistant-ui/CreateQuizToolUI.tsx (1)
25-25: KeepcreateQuizargs strongly typed.Line 25 switches to
Record<string, unknown>, which drops compile-time checks between the tool contract and this UI. Prefer reusing the canonicalcreateQuizinput type exported from your shared tool/schema module so arg-shape drift fails at compile time.♻️ Suggested direction
-type CreateQuizArgs = Record<string, unknown>; +// Reuse the shared createQuiz input type from your tool/schema source of truth +type CreateQuizArgs = CreateQuizInput;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/assistant-ui/CreateQuizToolUI.tsx` at line 25, Replace the ad-hoc CreateQuizArgs = Record<string, unknown> with the canonical input type used by the createQuiz tool: import the exported createQuiz input/interface type from the shared tool/schema module and use that type for CreateQuizArgs (or replace usages directly with the imported type) so the CreateQuizToolUI's createQuiz argument shape is strongly typed and keeps contract drift caught at compile time.src/components/assistant-ui/EditItemToolUI.tsx (1)
49-52: Minor: Type annotation could use the actual Item type.The type annotation
{ id: string }works but loses type information. SinceworkspaceState.itemsis typed asItem[], you could rely on TypeScript inference:- return workspaceState.items.find((item: { id: string }) => item.id === result.itemId); + return workspaceState.items.find((item) => item.id === result.itemId);This preserves the full
Itemtype forcard, allowing proper type checking when accessingcard?.name.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/assistant-ui/EditItemToolUI.tsx` around lines 49 - 52, The inline type annotation in the useMemo callback for `card` currently uses `{ id: string }`, which loses the full `Item` type; update the predicate to use the actual `Item` type (e.g., use `item: Item` or rely on inference from `workspaceState.items.find`) so `card` is inferred as `Item | undefined` and downstream accesses like `card?.name` are properly typed; modify the `useMemo` callback in `EditItemToolUI` accordingly (referencing `card`, `result.itemId`, and `workspaceState.items`) to restore full `Item` type information.src/lib/ai/workers/workspace-worker.ts (1)
1019-1026: Redundant duplicate name check.The duplicate name check at lines 1023-1026 appears redundant since the rename case is already validated at lines 996-1001. The second check uses
itemNamewhich equalschanges.name ?? existingItem.name, but ifchanges.nameis set, it was already validated. Ifchanges.nameis not set,itemNameequalsexistingItem.name, which shouldn't conflict with itself (sameparams.itemId).This is harmless defensive coding, but consider removing it to simplify the logic.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/ai/workers/workspace-worker.ts` around lines 1019 - 1026, The duplicate-name validation block is redundant because rename validation already runs earlier; remove the second check that computes itemName = (changes.name ?? existingItem.name) and the subsequent call to hasDuplicateName(currentState.items, itemName, existingItem.type, existingItem.folderId ?? null, params.itemId). Instead, rely on the earlier rename validation (the code that checks changes.name against hasDuplicateName) and keep the early return for no-op updates; ensure no other logic depends on itemName or that second branch before deletion so behavior remains unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/ai/tools/edit-item-tool.ts`:
- Around line 141-145: The function returns matchedItem.name in the success
branch which yields the pre-edit name; instead, when workerResult.success is
true, return the final name by preferring newName (if set) over
matchedItem.name—i.e. update the returned object built from workerResult to set
itemName: newName ?? matchedItem.name so tool receipts reflect the renamed item;
reference variables: workerResult, matchedItem.name, newName.
- Around line 101-113: The current logic uses resolveItem(state.items, itemName)
and proceeds without guarding against multiple editable items that share the
same name; update the flow to detect duplicate-name collisions before applying
edits: after resolving matchedItem (or instead of a single fuzzy match) collect
all candidates from state.items where name === itemName (and type !== "folder"),
and if more than one candidate exists return success: false with a message that
lists distinguishing info (e.g., id, type, path/parent, or index) and instructs
the user to disambiguate (or call a disambiguation helper). Ensure this check
references resolveItem, state.items, matchedItem and itemName so the
duplicate-name guard prevents edits hitting the wrong item.
In `@src/lib/ai/tools/quiz-tools.ts`:
- Around line 32-33: Change the Zod schema for the quiz title from
z.string().nullable() to z.string().nullish() so the input can omit the title
key entirely (or provide null) and still pass validation; update the schema
where the property is named title alongside QuizQuestionSchema, ensuring it
matches the TypeScript signature (title?: string | null) and allows the existing
fallback logic that applies a default 'Quiz' when title is missing or null.
- Around line 15-22: QuizQuestionSchema currently allows any options length and
an unbounded correctIndex; update QuizQuestionSchema to validate by
discriminating on type: for "multiple_choice" require options.length === 4
(z.tuple or refine) and for "true_false" require options equal ["True","False"]
(literal array check), and constrain correctIndex to be an integer within
0..options.length-1 (use z.number().int().refine or z.preprocess with a
dependent refinement). Also update the related quiz array schema (the array
definition around the quiz questions) to use the revised QuizQuestionSchema and
adjust the mapping function that processes questions (the mapping function
referenced around lines 55-63) to assume validated shapes (or defensively check
bounds before indexing), and mirror the same schema changes in the duplicate
definition in src/app/api/workspaces/autogen/route.ts so both places enforce
exact option counts and correctIndex bounds.
---
Outside diff comments:
In `@src/components/assistant-ui/CreateQuizToolUI.tsx`:
- Around line 37-50: CreateQuizReceipt's currentItem lookup using
workspaceState.items can be stale immediately after creation causing false "Item
no longer exists" errors; update the lookup to fallback to other sources (for
example use result.itemId/result.quizId to find the item in the passed-in
allItems prop or in result.payload) before declaring the item missing, and/or
prevent showing the Move dialog (showMoveDialog) until a resolved currentItem
exists; specifically modify the useMemo that computes currentItem to first try
workspaceState.items, then fall back to allItems.find(...) or result-contained
data, and ensure moveItemToFolder and the UI that toggles setShowMoveDialog only
enable when currentItem is non-undefined.
---
Nitpick comments:
In `@src/components/assistant-ui/CreateQuizToolUI.tsx`:
- Line 25: Replace the ad-hoc CreateQuizArgs = Record<string, unknown> with the
canonical input type used by the createQuiz tool: import the exported createQuiz
input/interface type from the shared tool/schema module and use that type for
CreateQuizArgs (or replace usages directly with the imported type) so the
CreateQuizToolUI's createQuiz argument shape is strongly typed and keeps
contract drift caught at compile time.
In `@src/components/assistant-ui/EditItemToolUI.tsx`:
- Around line 49-52: The inline type annotation in the useMemo callback for
`card` currently uses `{ id: string }`, which loses the full `Item` type; update
the predicate to use the actual `Item` type (e.g., use `item: Item` or rely on
inference from `workspaceState.items.find`) so `card` is inferred as `Item |
undefined` and downstream accesses like `card?.name` are properly typed; modify
the `useMemo` callback in `EditItemToolUI` accordingly (referencing `card`,
`result.itemId`, and `workspaceState.items`) to restore full `Item` type
information.
In `@src/lib/ai/workers/workspace-worker.ts`:
- Around line 1019-1026: The duplicate-name validation block is redundant
because rename validation already runs earlier; remove the second check that
computes itemName = (changes.name ?? existingItem.name) and the subsequent call
to hasDuplicateName(currentState.items, itemName, existingItem.type,
existingItem.folderId ?? null, params.itemId). Instead, rely on the earlier
rename validation (the code that checks changes.name against hasDuplicateName)
and keep the early return for no-op updates; ensure no other logic depends on
itemName or that second branch before deletion so behavior remains unchanged.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
src/app/api/workspaces/autogen/route.tssrc/components/assistant-ui/CreateQuizToolUI.tsxsrc/components/assistant-ui/EditItemToolUI.tsxsrc/components/assistant-ui/SelectCardsToolUI.tsxsrc/components/assistant-ui/UpdateFlashcardToolUI.tsxsrc/components/assistant-ui/UpdateQuizToolUI.tsxsrc/components/assistant-ui/thread.tsxsrc/lib/ai/tool-result-schemas.tssrc/lib/ai/tools/edit-item-tool.tssrc/lib/ai/tools/flashcard-tools.tssrc/lib/ai/tools/index.tssrc/lib/ai/tools/quiz-tools.tssrc/lib/ai/tools/read-workspace.tssrc/lib/ai/tools/workspace-tools.tssrc/lib/ai/workers/index.tssrc/lib/ai/workers/quiz-worker.tssrc/lib/ai/workers/workspace-worker.tssrc/lib/utils/format-workspace-context.tssrc/lib/workspace-state/types.ts
💤 Files with no reviewable changes (6)
- src/lib/workspace-state/types.ts
- src/lib/ai/workers/quiz-worker.ts
- src/lib/ai/workers/index.ts
- src/components/assistant-ui/UpdateFlashcardToolUI.tsx
- src/components/assistant-ui/UpdateQuizToolUI.tsx
- src/components/assistant-ui/SelectCardsToolUI.tsx
Made-with: Cursor
…lidation; CreateQuiz/EditItem UI fixes; remove redundant duplicate check Made-with: Cursor
This reverts commit 47cd684.
…e lacks sentence-ending punctuation; lower char threshold to 150 Made-with: Cursor
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/app/api/workspaces/autogen/route.ts (1)
507-525: Consider importing or sharing the quiz question schema.A local
QuizQuestionSchemais defined here that's similar to but less strict than the one inquiz-tools.ts. While the lenient schema makes sense for parsing LLM output (with post-processing at lines 560-581 to fix issues), maintaining two schemas increases drift risk.Consider extracting a shared base schema or importing
QuizQuestionSchemafromquiz-tools.tsand using.passthrough()or a lenient variant for LLM output parsing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/app/api/workspaces/autogen/route.ts` around lines 507 - 525, The local QuizQuestionSchema duplicates logic from quiz-tools.ts and risks schema drift; replace the local definition in route.ts by importing the shared QuizQuestionSchema from quiz-tools.ts (or extract a shared base schema there) and use a lenient variant for LLM parsing (e.g., imported QuizQuestionSchema.passthrough() or create a RelaxedQuizQuestionSchema that extends the shared schema with .passthrough()/optional fields) then update NOTE_FLASHCARD_QUIZ_SCHEMA to reference that imported/relaxed quiz question schema instead of the locally defined QuizQuestionSchema so post-processing lines (560-581) operate on the same canonical schema types.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/app/api/workspaces/autogen/route.ts`:
- Around line 507-525: The local QuizQuestionSchema duplicates logic from
quiz-tools.ts and risks schema drift; replace the local definition in route.ts
by importing the shared QuizQuestionSchema from quiz-tools.ts (or extract a
shared base schema there) and use a lenient variant for LLM parsing (e.g.,
imported QuizQuestionSchema.passthrough() or create a RelaxedQuizQuestionSchema
that extends the shared schema with .passthrough()/optional fields) then update
NOTE_FLASHCARD_QUIZ_SCHEMA to reference that imported/relaxed quiz question
schema instead of the locally defined QuizQuestionSchema so post-processing
lines (560-581) operate on the same canonical schema types.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/app/api/workspaces/autogen/route.tssrc/components/assistant-ui/CreateQuizToolUI.tsxsrc/components/assistant-ui/EditItemToolUI.tsxsrc/lib/ai/tools/edit-item-tool.tssrc/lib/ai/tools/quiz-tools.tssrc/lib/ai/workers/workspace-worker.ts
…t blocks the Vercel build. This commit fixes the issue reported at src/app/api/cards/from-message/route.ts:24 **Bug Explanation:** The file `src/app/api/cards/from-message/route.ts` declares a variable `userId` on line 24 (`const userId = session.user.id;`) but never uses it anywhere in the function. TypeScript's strict mode (specifically the `noUnusedLocals` compiler option or equivalent strict checking) treats unused variables as errors, not just warnings. This caused the Vercel build to fail with the error: ``` Type error: 'userId' is declared but its value is never read. ``` The variable appears to be leftover code from development - likely intended for future use or accidentally left behind after refactoring. The function authenticates the user and validates the session, but doesn't actually need to store the `userId` since none of the subsequent operations (AI content processing, workspace worker calls) require it as a parameter. **Fix:** Removed the unused variable declaration entirely. The line `const userId = session.user.id;` was deleted since: 1. The userId value is never used in the function 2. The session validation already ensures the user is authenticated 3. Keeping unused variables violates TypeScript's strict checking and blocks builds After the fix, the code flows directly from session validation to parsing the request body, which is the correct behavior. Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com> Co-authored-by: urjitc <chakrabortyurjit@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/lib/utils/format-workspace-context.ts (1)
825-825: Consider compact JSON to reduce context-token overhead.Line 825 and Line 850 pretty-print payloads with indentation. For large flashcard/quiz sets, this inflates prompt size and can crowd out higher-value context. Prefer compact JSON (or a size-capped mode) in workspace context formatting.
♻️ Proposed refactor
- return [JSON.stringify(payload, null, 2)]; + return [JSON.stringify(payload)];- lines.push(JSON.stringify(payload, null, 2)); + lines.push(JSON.stringify(payload));Also applies to: 850-850
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/utils/format-workspace-context.ts` at line 825, Change the pretty-printed JSON returned from the workspace context formatter to compact JSON to reduce token usage: replace JSON.stringify(payload, null, 2) with JSON.stringify(payload) (and do the same for the other occurrence) inside the function that builds the workspace context (the expression that currently returns [JSON.stringify(payload, null, 2)]); optionally implement a size-capped branch that uses JSON.stringify(payload) and truncates or slices the string if it exceeds a threshold before returning to avoid oversized contexts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/assistant-ui/thread.tsx`:
- Around line 1245-1246: The continue heuristic currently tests the final
character of the raw message against ENDS_WITH_SENTENCE_PUNCTUATION and
therefore misclassifies messages that end with trailing markup like
<citation>...</citation> (which leave a '>' as the last char); before applying
ENDS_WITH_SENTENCE_PUNCTUATION, strip any trailing HTML/XML-like tags/markup and
trailing whitespace from the message (e.g., remove /<[^>]+>$/ or strip balanced
trailing citation tags) so the punctuation check sees the actual last visible
character; update the code paths that use ENDS_WITH_SENTENCE_PUNCTUATION (the
continue/heuristic check) to run against the cleaned string.
---
Nitpick comments:
In `@src/lib/utils/format-workspace-context.ts`:
- Line 825: Change the pretty-printed JSON returned from the workspace context
formatter to compact JSON to reduce token usage: replace JSON.stringify(payload,
null, 2) with JSON.stringify(payload) (and do the same for the other occurrence)
inside the function that builds the workspace context (the expression that
currently returns [JSON.stringify(payload, null, 2)]); optionally implement a
size-capped branch that uses JSON.stringify(payload) and truncates or slices the
string if it exceeds a threshold before returning to avoid oversized contexts.
|




Important
This pull request introduces a unified
editItemtool for editing notes, flashcards, and quizzes, replacing individual update tools and enhancing workspace item management.editItemtool for unified editing ofnote,flashcard, andquizitems, replacing individual update tools.quizTopicfromDistillationResultinroute.ts.NOTE_FLASHCARD_QUIZ_SYSTEMto include quiz generation.edit-item-tool.tsfor handling edits across item types.updateNote,updateFlashcards,updateQuiz, andselectCardstools.createChatToolsto useeditItem.workspace-worker.tsto supporteditaction for notes, flashcards, and quizzes.EditItemResultSchematotool-result-schemas.ts.UpdateNoteToolUI.tsxtoEditItemToolUI.tsxand updates its logic.SelectCardsToolUI.tsx,UpdateFlashcardToolUI.tsx, andUpdateQuizToolUI.tsx.This description was created by
for c4a7360. You can customize this summary. It will automatically update as commits are pushed.
Summary by CodeRabbit
New Features
Improvements