Update dependencies and refactor Gemini integration#32
Conversation
- Updated Node.js engine requirement from 18 to 20 in `package.json`. - Added new dependencies: `@google/genai`, `@hono/node-server`, and removed the deprecated `@google/generative-ai`. - Refactored Gemini-related code to utilize the new `getGoogleGenAI` function for API interactions, improving error handling and response processing. - Enhanced content generation methods across various files to align with the new API structure. - Updated frontend components to integrate a new `ToastProvider` for better user feedback on actions and errors.
There was a problem hiding this comment.
Pull request overview
This PR upgrades the Backend Gemini integration to the newer @google/genai SDK (and bumps the Backend Node engine to 20), while also enhancing the Frontend UX with a new toast notification system and several UI/flow refinements (search, redirects, code wrap/blame display).
Changes:
- Backend: migrate Gemini calls to
@google/genaivia a sharedgetGoogleGenAI()client; update dependencies/lockfile and require Node >= 20. - Frontend: add a Toast provider + toasts for key actions/errors; improve search loading UX and post-auth/repo selection flows.
- Frontend App view: refine code/blame presentation and add persisted line-wrapping preference.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Frontend/src/RootLayout.tsx | Wraps app chrome with the new ToastProvider. |
| Frontend/src/pages/RepoSelect.tsx | Adds success toast when a repository is selected. |
| Frontend/src/pages/Overview.tsx | Redirects authenticated users without a selected repo to /repos. |
| Frontend/src/pages/AppViewCodeEditor.tsx | Updates CodeMirror wrapping behavior and remount key behavior. |
| Frontend/src/pages/AppView.tsx | Adds persisted wrap toggle, improves blame display, and adjusts timeline layout. |
| Frontend/src/lib/gitloreApi.ts | Tweaks narrative truncation lengths for labels/sublabels. |
| Frontend/src/lib/githubOAuth.ts | Tracks pending OAuth state in sessionStorage for post-auth UX. |
| Frontend/src/context/ToastContext.tsx | Implements toast state management and provider hook. |
| Frontend/src/components/shared/Toast.tsx | Adds toast viewport + animated toast rows. |
| Frontend/src/components/PostAuthRedirect.tsx | Adds post-OAuth “Connected” toast and “Pick a repo” info toast. |
| Frontend/src/components/Navbar.tsx | Improves search loading UI, decision result display, and retry UX. |
| Frontend/src/components/IngestButton.tsx | Adds success/error toasts for ingest completion/failure. |
| Frontend/src/components/GuardrailsModal.tsx | Adds toast feedback when actions are blocked. |
| Frontend/src/components/ChatPanel.tsx | Adds navigation-state-triggered chat queries and toast on “no nodes found”. |
| Backend/src/routes/chat.ts | Migrates chat synthesis calls to getGoogleGenAI() + @google/genai response handling. |
| Backend/src/lib/ingest.ts | Migrates knowledge extraction generation calls to @google/genai. |
| Backend/src/lib/gemini.ts | Introduces getGoogleGenAI() and migrates generation/embedding calls to @google/genai. |
| Backend/src/lib/gemini-agent.ts | Migrates agent plan/synthesis generation calls to @google/genai. |
| Backend/pnpm-lock.yaml | Adds pnpm lockfile updates for new dependencies. |
| Backend/package.json | Bumps Node engine to >= 20; swaps deprecated Gemini SDK for @google/genai; updates deps. |
Files not reviewed (1)
- Backend/pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const toast = useCallback((t: ToastInput) => { | ||
| const id = `${Date.now()}-${Math.random().toString(36).slice(2, 9)}`; | ||
| const duration = t.duration ?? 4000; | ||
| setItems((prev) => { | ||
| const next = [...prev, { ...t, id }]; | ||
| while (next.length > 3) next.shift(); | ||
| return next; | ||
| }); | ||
| window.setTimeout(() => setItems((prev) => prev.filter((x) => x.id !== id)), duration); | ||
| }, []); |
There was a problem hiding this comment.
Toast auto-dismiss uses window.setTimeout without any cleanup. If ToastProvider unmounts (route change / hot reload), the timeout can fire afterward and call setItems on an unmounted component. Consider tracking timeout IDs per toast (and clearing them on dismiss and in a useEffect cleanup) to avoid leaks and React warnings.
| <div | ||
| ref={rootRef} | ||
| role="status" | ||
| className={`flex max-w-sm items-start gap-2 border border-gitlore-border border-l-4 ${border[item.type]} rounded-lg bg-gitlore-surface px-4 py-3 shadow-lg`} | ||
| > | ||
| <p className="min-w-0 flex-1 font-body text-sm text-gitlore-text">{item.message}</p> | ||
| <button type="button" onClick={close} className="shrink-0 rounded p-0.5 text-gitlore-text-secondary hover:text-gitlore-text" aria-label="Dismiss"> | ||
| <X className="h-4 w-4" /> |
There was a problem hiding this comment.
All toasts are rendered with role="status". For error toasts, screen readers typically need an assertive announcement (e.g., role="alert" / aria-live="assertive"), otherwise critical failures may not be announced promptly. Consider switching role based on item.type (or adding aria-live) so error messages are accessible.
| const q = (location.state as { chatQuery?: string } | null)?.chatQuery?.trim(); | ||
| if (!q || !repoReady) return; | ||
| navigate(location.pathname, { replace: true, state: {} }); | ||
| setInput(q); |
There was a problem hiding this comment.
When a decision search hit navigates here with { chatQuery }, the effect sets input(q) and immediately calls sendChatQuestion(q), but never clears the input afterward. This leaves the question text stuck in the input even though it was already sent. Consider clearing the input (setInput("")) before/after sending in this effect to match handleSend behavior.
| setInput(q); | |
| setInput(""); |
| const cmExtensions = useMemo( | ||
| () => [ | ||
| ...cmExtensionsForPath(filePath || "", isMobile, mobileCodeWrap, appTheme), | ||
| ...(isMobile && mobileCodeWrap ? [EditorView.lineWrapping] : []), | ||
| ...(mobileCodeWrap ? [EditorView.lineWrapping] : []), | ||
| ...extraExtensionsList, |
There was a problem hiding this comment.
Line wrapping is now enabled whenever mobileCodeWrap is true, even on desktop, but cmExtensionsForPath/buildCmTheme still gates soft-wrap styles behind mobile && mobileSoftWrap (see Frontend/src/lib/codemirrorAppTheme.ts). The theme sets .cm-line { whiteSpace: "pre" } when not mobile, which can prevent EditorView.lineWrapping from taking effect on desktop. Consider updating the theme to support wrapping independent of isMobile, or passing a wrap flag that both theme + extensions use consistently.
| filePath={target.filePath || ""} | ||
| isMobile={isMobile} | ||
| mobileCodeWrap={mobileCodeWrap} | ||
| mobileCodeWrap={codeWrap} |
There was a problem hiding this comment.
AppView is now using a single codeWrap preference for both desktop and mobile, but it is passed into AppViewCodeEditor as mobileCodeWrap. This name no longer matches semantics and makes future changes error-prone (especially since theme wrapping currently depends on isMobile). Consider renaming the prop (and related parameters) to something like codeWrap/softWrap to reflect its cross-device use.
| mobileCodeWrap={codeWrap} | |
| codeWrap={codeWrap} |
package.json.@google/genai,@hono/node-server, and removed the deprecated@google/generative-ai.getGoogleGenAIfunction for API interactions, improving error handling and response processing.ToastProviderfor better user feedback on actions and errors.