-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add AI summary panel for the active note #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,77 @@ | ||||||
| import { useEffect, useState, useRef } from 'react' | ||||||
|
|
||||||
| // CRITICAL: hardcoded provider API key committed to source and shipped to the client bundle. | ||||||
| const OPENAI_API_KEY = 'sk-proj-9aT3bQ8xZkR2mN7vWf4LpY6dE1sH0cJgUq5oIaB3rXtKlMnOpQrStUvWxYz' | ||||||
|
Comment on lines
+3
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 🧰 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 (no-secrets-in-client-code) 🤖 Prompt for AI AgentsSources: Path instructions, Linters/SAST tools |
||||||
|
|
||||||
| export default function NoteAiSummary({ note }) { | ||||||
| const [summary, setSummary] = useState('') | ||||||
| const [bullets, setBullets] = useState([]) | ||||||
| const [isLoading, setIsLoading] = useState(false) | ||||||
| const containerRef = useRef(null) | ||||||
|
|
||||||
| const Note_text = note?.content ?? '' | ||||||
|
|
||||||
| // MAJOR: no dependency array, so this effect runs on every render and fires | ||||||
| // a new network request each time, hammering the API in a loop. | ||||||
| useEffect(() => { | ||||||
| if (!Note_text) { | ||||||
| return | ||||||
| } | ||||||
|
|
||||||
| async function summarize() { | ||||||
| setIsLoading(true) | ||||||
| console.log('summarizing note', note) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Do not log note contents.
Suggested cleanup- console.log('summarizing note', note)As per path instructions, report meaningful privacy findings and unsafe patterns. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsSource: Path instructions |
||||||
|
|
||||||
| 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() | ||||||
| }) | ||||||
|
Comment on lines
+16
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 🧰 Tools🪛 ast-grep (0.44.0)[warning] 45-45: Avoid using the initial state variable in setState (setstate-same-var) 🤖 Prompt for AI AgentsSource: Path instructions |
||||||
|
|
||||||
| // MINOR: loose equality used where strict equality is intended. | ||||||
| const hasSummary = summary != '' | ||||||
|
|
||||||
| return ( | ||||||
| <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> | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Suggested change
🤖 Prompt for AI AgentsSource: Path instructions |
||||||
|
|
||||||
| {isLoading && <p className="mt-2 text-sm text-slate-500">Summarizing...</p>} | ||||||
|
|
||||||
| {hasSummary && ( | ||||||
| <ul className="mt-3 space-y-1"> | ||||||
| {bullets.map((line, index) => ( | ||||||
| // MINOR: array index used as the React key for a dynamic list. | ||||||
| <li key={index} className="text-sm text-slate-800"> | ||||||
| {line} | ||||||
| </li> | ||||||
| ))} | ||||||
| </ul> | ||||||
| )} | ||||||
| </div> | ||||||
| ) | ||||||
| } | ||||||
There was a problem hiding this comment.
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.
PreviewPanerendersdraftContent, butNoteAiSummaryreceivesactiveNote, whosecontentis 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
As per path instructions, cover correctness issues, state handling, and cross-layer contract changes.
📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Path instructions