-
Notifications
You must be signed in to change notification settings - Fork 536
feat: add Memory tab with custom vocabulary to AI settings #3816
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: main
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for hyprnote ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for hyprnote-storybook canceled.
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
b1133c9 to
389c98a
Compare
389c98a to
b96e938
Compare
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.
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.
apps/desktop/src/components/settings/memory/custom-vocabulary.tsx
Outdated
Show resolved
Hide resolved
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
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.
apps/desktop/src/components/settings/memory/custom-vocabulary.tsx
Outdated
Show resolved
Hide resolved
….devin.ai/proxy/github.com/fastrepl/hyprnote into devin/1770712735-add-memory-tab
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.
| } else if (e.key === "Escape") { | ||
| e.preventDefault(); | ||
| onCancelEdit(); |
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.
🟡 Edit form state not reset on cancel, showing stale value on re-edit
When a user edits a vocabulary item, modifies the text, then cancels (via Escape key or X button), and then re-opens the edit mode, the form input shows the previously typed (unsaved) value instead of the current item.text.
Root Cause
The VocabularyItem component creates a useForm instance with defaultValues: { text: item.text } at line 167-170. TanStack Form's defaultValues are only used for initial form state — they do not automatically reset when the user cancels editing.
Both cancel paths fail to call form.reset() before exiting edit mode:
- Escape key handler at line 234-236: calls
onCancelEdit()without resetting. - X button at line 267: calls
onCancelEdit()without resetting.
Since VocabularyItem uses key={item.rowId} (apps/desktop/src/components/settings/memory/custom-vocabulary.tsx:122), the component does NOT unmount/remount between edit sessions — the form instance and its stale state persist across cancel → re-edit cycles.
Scenario:
- User clicks edit on item "hello"
- User types "world" into the input
- User presses Escape or clicks X →
onCancelEdit()setseditingIdto null, span shows "hello" - User clicks edit again on the same item → input shows "world" (stale) instead of "hello"
Impact: Confusing UX — users see a value they previously discarded, and if they immediately press Enter to confirm, the item gets updated to the stale value they intended to cancel.
Prompt for agents
In apps/desktop/src/components/settings/memory/custom-vocabulary.tsx, the VocabularyItem component needs to reset its form state when cancelling an edit. There are two cancel paths that need fixing:
1. The Escape key handler around line 234-236: add form.reset() before onCancelEdit()
2. The X button onClick handler at line 267: change from onClick={onCancelEdit} to an inline handler that calls form.reset() then onCancelEdit()
Specifically:
- Line 235-236: change to:
form.reset();
onCancelEdit();
- Line 267: change onClick={onCancelEdit} to onClick={() => { form.reset(); onCancelEdit(); }}
Was this helpful? React with 👍 or 👎 to provide feedback.
feat: add Memory tab with custom vocabulary to AI settings
Summary
Restores custom vocabulary management as a Memory tab within AI settings. Users can add, edit, search, and delete industry/company-specific terms intended to improve transcription accuracy.
Changes across layers:
memorySchema(Zod) andmemoriestable (TinyBase) withuser_id,type,text,created_atfieldsmemoriestable (memories.json), registered alongside existing persistersvisibleVocabsquery filtering memories bytype === "vocab"CustomVocabularyViewcomponent with search/add/edit/delete, inline editing with duplicate detectionMemoryvariant added toAiTabenum (Rust + generated TS bindings), wired intoai.tsxUpdates since last revision
onSubmithandler now checks for existing terms before callingmutations.create().onCancelEdit()is now called unconditionally on submit so the user always exits edit mode.user_idguard inuseVocabMutations.create()to prevent persisting rows with emptyuser_idbefore the store is fully initialized (matches the guard pattern used elsewhere in the codebase, e.g.ai.tsx).onSubmithandler caused by a bad merge — a duplicated code block madeCustomVocabularyViewunparseable. The handler is now correctly structured with duplicate detection.main.Review & Testing Checklist for Human
ONBOARDING=0 pnpm -F desktop tauri dev) and verify the Memory tab appears in AI settings with the Brain icon, vocabulary can be added/edited/deleted, and items persist after restartvisibleVocabsquery does not filter byuser_id— unlikevisibleTemplatesand other queries that usewhere("user_id", param("user_id")), the new query only filters onwhere("type", "vocab"). If multi-user data isolation matters for this table, auser_idfilter needs to be added to the query definition inmain.ts.useSetPartialRowCallbacktype cast —updateRowinuseVocabMutationsusesas (args: { rowId: string; text: string }) => voidwhich could mask type mismatches at runtimebindings.gen.tsstays in sync — it was manually edited to add"memory"alongside the Rust enum change; verify regeneration produces the same resultcustom_vocabularyfield during transcription (seeplugins/local-stt/src/ext.rs). If end-to-end integration is expected, that's a follow-upRecommended test plan: Open AI settings → click Memory tab → add a few terms → search → try adding a duplicate (Enter + button) → edit one → delete one → restart app → confirm terms persist.
Notes