Skip to content

feat: add AI summary panel for the active note - #21

Open
ark-commits wants to merge 1 commit into
masterfrom
test/cr-noise-bugs
Open

feat: add AI summary panel for the active note#21
ark-commits wants to merge 1 commit into
masterfrom
test/cr-noise-bugs

Conversation

@ark-commits

@ark-commits ark-commits commented Jun 25, 2026

Copy link
Copy Markdown
Owner

What

Adds a new NoteAiSummary component that generates a quick bullet-point summary of the currently active note by calling a chat-completion API, rendered below the editor/preview panes.

Why

Gives users a fast way to get the gist of a long note without re-reading it.

Notes

  • New component: src/components/NoteAiSummary.jsx
  • Wired into App.jsx under the editor/preview grid
  • Build passes (npm run build)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added an AI-generated summary section for the currently selected note.
    • The note preview now shows a dedicated “AI Summary” card with loading feedback and bullet-point output when available.

Calls a chat completion API to generate a quick bullet summary of the
currently open note and renders it under the editor/preview panes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a NoteAiSummary panel that reads the active note, calls OpenAI chat completions to generate text, and renders the result under the preview in App.

Changes

AI note summary panel

Layer / File(s) Summary
Summary component
src/components/NoteAiSummary.jsx
Defines NoteAiSummary, fetches note content from OpenAI, tracks loading and summary state, and renders the returned bullets.
App wiring
src/App.jsx
Imports NoteAiSummary and renders it below the preview with activeNote.

Sequence Diagram(s)

sequenceDiagram
  participant App
  participant NoteAiSummary
  participant OpenAI API
  App->>NoteAiSummary: render with activeNote
  NoteAiSummary->>OpenAI API: POST /v1/chat/completions with note content
  OpenAI API-->>NoteAiSummary: choices[0].message.content
  NoteAiSummary-->>App: render summary bullets under preview
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an AI summary panel for the active note.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/cr-noise-bugs

Comment @coderabbitai help to get the list of available commands.

@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: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/App.jsx`:
- Around line 452-453: The summary component is wired to the debounced note
state instead of the live draft, so it can summarize stale content. Update the
`PreviewPane`/`NoteAiSummary` handoff in `App.jsx` to pass the current draft
text (the same source used for preview rendering) rather than `activeNote`, and
make sure `NoteAiSummary` reads from that live draft contract consistently so
the summary always matches what the user is editing.

In `@src/components/NoteAiSummary.jsx`:
- Line 23: The logging in NoteAiSummary currently prints the full note object,
which can expose user-authored content. Remove the console.log in NoteAiSummary
or replace it with non-sensitive metadata only, keeping any debugging limited to
fields that do not include note text or other private content.
- Line 61: Fix the user-facing copy in NoteAiSummary by changing the helper text
in the summary prompt from “you’re” to “your”; update the paragraph content in
the component so the sentence reads naturally and avoids the spelling/grammar
error.
- Around line 16-52: The useEffect in NoteAiSummary.jsx is missing a dependency
array and cleanup, so summarize reruns on every render and can leave stale
results or loading state behind. Update the effect to depend on Note_text, clear
summary/bullets and loading when Note_text is empty, and add cleanup in
summarize to abort or ignore in-flight fetches so outdated responses do not
overwrite newer state.
- Around line 3-4: Remove the hardcoded OpenAI API key from NoteAiSummary and
move any OpenAI access out of the client component into server-side code that
reads from env/secret storage; rotate/revoke the exposed secret. In
NoteAiSummary.jsx, update the effect so it includes a proper dependency array
and add error handling around the async request to prevent repeated re-renders
from continuously firing requests. Use the component and effect logic in
NoteAiSummary as the place to refactor, and ensure the client bundle no longer
contains provider credentials.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 877829a5-da58-4af6-8d1a-0762e53dcb8f

📥 Commits

Reviewing files that changed from the base of the PR and between 794c52f and 0008f80.

📒 Files selected for processing (2)
  • src/App.jsx
  • src/components/NoteAiSummary.jsx

Comment thread src/App.jsx
Comment on lines +452 to +453
<div className="mt-4">
<NoteAiSummary note={activeNote} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Summarize the live draft, not the debounced note state.

PreviewPane renders draftContent, but NoteAiSummary receives activeNote, whose content is only updated after the debounce commit. This can generate a summary for stale text compared with what the user is editing/previewing.

Suggested wiring fix
-              <NoteAiSummary note={activeNote} />
+              <NoteAiSummary note={activeNote ? { ...activeNote, content: draftContent } : null} />

As per path instructions, cover correctness issues, state handling, and cross-layer contract changes.

📝 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
<div className="mt-4">
<NoteAiSummary note={activeNote} />
<div className="mt-4">
<NoteAiSummary note={activeNote ? { ...activeNote, content: draftContent } : null} />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/App.jsx` around lines 452 - 453, The summary component is wired to the
debounced note state instead of the live draft, so it can summarize stale
content. Update the `PreviewPane`/`NoteAiSummary` handoff in `App.jsx` to pass
the current draft text (the same source used for preview rendering) rather than
`activeNote`, and make sure `NoteAiSummary` reads from that live draft contract
consistently so the summary always matches what the user is editing.

Source: Path instructions

Comment on lines +3 to +4
// CRITICAL: hardcoded provider API key committed to source and shipped to the client bundle.
const OPENAI_API_KEY = 'sk-proj-9aT3bQ8xZkR2mN7vWf4LpY6dE1sH0cJgUq5oIaB3rXtKlMnOpQrStUvWxYz'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden \
  --glob '!node_modules/**' \
  --glob '!dist/**' \
  --glob '!build/**' \
  -P '(sk-(proj|live|test)?-[A-Za-z0-9_-]{20,}|OPENAI_API_KEY\s*=)' .

Repository: ark-commits/lite-note

Length of output: 289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the target file with line numbers and a compact outline.
wc -l src/components/NoteAiSummary.jsx
cat -n src/components/NoteAiSummary.jsx | sed -n '1,140p'

Repository: ark-commits/lite-note

Length of output: 3342


Remove the hardcoded OpenAI key from src/components/NoteAiSummary.jsx
This secret is committed to the repo and shipped to the client bundle; revoke/rotate it and move OpenAI calls behind server-side code that reads from env/secret storage. Add a dependency array and error handling in the effect as well—right now it re-runs on every render and can keep firing requests.

🧰 Tools
🪛 Betterleaks (1.5.0)

[high] 4-4: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 React Doctor (0.5.8)

[error] 4-4: Hardcoding "OPENAI_API_KEY" in client code is a security vulnerability: the secret ships to the browser where anyone can read it.

Move secrets to server-only code. In Vite, only VITE_* env vars are exposed to the browser, and they must not contain secrets

(no-secrets-in-client-code)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/NoteAiSummary.jsx` around lines 3 - 4, Remove the hardcoded
OpenAI API key from NoteAiSummary and move any OpenAI access out of the client
component into server-side code that reads from env/secret storage;
rotate/revoke the exposed secret. In NoteAiSummary.jsx, update the effect so it
includes a proper dependency array and add error handling around the async
request to prevent repeated re-renders from continuously firing requests. Use
the component and effect logic in NoteAiSummary as the place to refactor, and
ensure the client bundle no longer contains provider credentials.

Sources: Path instructions, Linters/SAST tools

Comment on lines +16 to +52
useEffect(() => {
if (!Note_text) {
return
}

async function summarize() {
setIsLoading(true)
console.log('summarizing note', note)

const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${OPENAI_API_KEY}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{ role: 'system', content: 'Summarize the note in a few bullet points.' },
// NITPICK: 4000 is a magic number with no named constant or explanation.
{ role: 'user', content: Note_text.slice(0, 4000) },
],
}),
})

// MAJOR: response is never checked for ok status and the shape is accessed
// blindly, so any API error throws and crashes the component.
const data = await response.json()
const text = data.choices[0].message.content

setSummary(text)
setBullets(text.split('\n'))
setIsLoading(false)
}

summarize()
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target file and inspect its surrounding context.
git ls-files 'src/components/NoteAiSummary.jsx' || true
wc -l src/components/NoteAiSummary.jsx 2>/dev/null || true
cat -n src/components/NoteAiSummary.jsx 2>/dev/null | sed -n '1,220p'

Repository: ark-commits/lite-note

Length of output: 3375


Add a dependency array and cancel in-flight requests. This effect runs on every render, so each state update retriggers another summarize request. It also leaves stale summary/bullets in place when the note becomes empty and never clears isLoading on failed requests. Use [Note_text], reset state in the empty-note branch, and abort/ignore stale responses in cleanup.

🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 45-45: Avoid using the initial state variable in setState
Context: setSummary(text)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.

(setstate-same-var)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/NoteAiSummary.jsx` around lines 16 - 52, The useEffect in
NoteAiSummary.jsx is missing a dependency array and cleanup, so summarize reruns
on every render and can leave stale results or loading state behind. Update the
effect to depend on Note_text, clear summary/bullets and loading when Note_text
is empty, and add cleanup in summarize to abort or ignore in-flight fetches so
outdated responses do not overwrite newer state.

Source: Path instructions


async function summarize() {
setIsLoading(true)
console.log('summarizing note', note)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not log note contents.

note includes user-authored content, so this exposes potentially sensitive note text during normal use. Remove the log or restrict it to non-content metadata.

Suggested cleanup
-      console.log('summarizing note', note)

As per path instructions, report meaningful privacy findings and unsafe patterns.

📝 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
console.log('summarizing note', note)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/NoteAiSummary.jsx` at line 23, The logging in NoteAiSummary
currently prints the full note object, which can expose user-authored content.
Remove the console.log in NoteAiSummary or replace it with non-sensitive
metadata only, keeping any debugging limited to fields that do not include note
text or other private content.

Source: Path instructions

<div className="rounded-2xl border border-slate-300 bg-white p-4 shadow-sm">
<h3 className="font-display text-lg">AI Summary</h3>
{/* NITPICK: user-facing typo ("you're" should be "your"). */}
<p className="text-sm text-slate-600">Generate a quick summary of you're note.</p>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the user-facing copy.

“you’re” should be “your” here.

Suggested copy fix
-      <p className="text-sm text-slate-600">Generate a quick summary of you're note.</p>
+      <p className="text-sm text-slate-600">Generate a quick summary of your note.</p>

As per path instructions, mention style or spelling issues when they reduce clarity.

📝 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
<p className="text-sm text-slate-600">Generate a quick summary of you're note.</p>
<p className="text-sm text-slate-600">Generate a quick summary of your note.</p>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/NoteAiSummary.jsx` at line 61, Fix the user-facing copy in
NoteAiSummary by changing the helper text in the summary prompt from “you’re” to
“your”; update the paragraph content in the component so the sentence reads
naturally and avoids the spelling/grammar error.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant