Implement Gemini API with OpenAI-compatible endpoint.#116
Conversation
- Added support for Gemini AI provider in AIContext with corresponding default settings and model retrieval - Introduced new tests for AIContext to validate initialization and provider switching - Updated jest setup to include jest-fetch-mock for API testing - Refactored imports in various components for consistency - Improved test coverage for App component with routing context Performance optimizations: - Fixed React context re-rendering issues by wrapping AIContextValue in useMemo - Memoized getAvailableModels and checkApiKeyValidity functions with useCallback - Prevented unnecessary re-renders of components consuming AIContext Bug fixes: - Fixed CSS class string concatenation bug in Editor highlightTerms function - Corrected malformed HTML output in search highlighting functionality - Validated dangerouslySetInnerHTML usage as necessary for rich text content Testing improvements: - Enhanced AIContext test suite with comprehensive memoization and edge case coverage - Added focused tests for highlightTerms function and regex escaping - Improved test reliability with better mocking and async handling - Fixed ESLint violations in test files
9fd0a52 to
30b0ca6
Compare
- Change default Gemini model to gemini-2.0-flash throughout app - Update available Gemini models list and placeholders - Add reasoning_effort: none for Gemini API requests to disable "thinking" - Improve error handling for AI requests and streaming, with clearer messages - Fix Settings modal max-width for better layout - Add API key field to Gemini tab
30b0ca6 to
6de2be0
Compare
|
Hey @UdaraJay, can I get an review for this? |
|
Hey! Thanks for the PR! I'll test these out soon. At a glance feedback for now--
|
- Remove GeminiIcon and related import/exports - Merge OpenAI and Gemini tabs into a single "Remote AI" tab - Add provider selector for OpenAI/Gemini with dynamic fields and placeholders - Remember model and base URL per provider - Update styles for improved tab appearance and select input - Ignore package-lock.json and pnpm-lock.yaml in .gitignore - Reduce settings modal max width back to 500px
- Replace single-pass regex with iterative approach to handle malformed HTML and strip nested < characters - Addresses CodeQL alert for incomplete multi-character sanitization
- Switch Gemini model input to dropdown selector - Improve AI settings layout and input widths - Remove unused error listener cleanup code
There was a problem hiding this comment.
Pull Request Overview
This PR integrates full Gemini provider support alongside OpenAI in the AI context, refactors the settings UI for dynamic provider selection and debounced inputs, and implements streaming AI completions via Electron IPC while updating several components and tests for consistency.
- Added Gemini support in
AIContextwith proper defaults, provider switching, HTML-to-text conversion, and streaming via main-process IPC. - Refactored
AISettingsTabsto unify remote provider settings (OpenAI/Gemini), add debounced inputs, and remember per-provider models. - Updated
Editor,LinkPreview, and embedding utilities to support the new providers, added PropTypes, and improved accessibility and testing setup.
Reviewed Changes
Copilot reviewed 23 out of 24 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/renderer/pages/Pile/Settings/AISettingsTabs/index.jsx | Unified tabs into a “remote” provider, added debounced state and per-provider model memory |
| src/renderer/pages/Pile/Settings/AISettingsTabs/AISettingTabs.module.scss | Adjusted select styling, spacing, and min-width for responsive layout |
| src/renderer/pages/Pile/Editor/index.jsx | Integrated AI streaming responses, updated paste/drop handlers, added PropTypes |
| src/renderer/pages/Pile/Editor/LinkPreviews/LinkPreview/index.jsx | Refactored to fetch previews via context hook, added accessibility roles and PropTypes |
| src/renderer/pages/Pile/Chat/Message/index.js | Removed unused Markdown import |
| src/renderer/pages/License/index.tsx | Removed unused TrashIcon import |
| src/renderer/pages/CreatePile/index.tsx | Fixed relative imports, replaced invalid placeholder on <button> |
| src/renderer/icons/img/CardIcon.js | Converted SVG attributes to React props (fillRule, strokeLinecap), adjusted export form |
| src/renderer/icons/img/BoxOpenIcon.js | Same SVG attribute fixes and export form |
| src/renderer/context/AIContext.js | Added Gemini defaults, provider-switch logic, HTML-to-text helper, streaming IPC |
| src/main/utils/pileEmbeddings.js | Extended embedding logic to support Ollama, Gemini, and OpenAI clients |
| src/main/preload.ts | Broadened IPC channel typing |
| src/main/ipc.ts | Registered new AI handlers |
| src/main/handlers/ai.ts | Implemented ai-generate-completion and streaming with Gemini reasoning disabled |
| src/tests/jest.setup.js | Configured jest-fetch-mock, HTML-to-text mocking, global React mocks |
| src/tests/Editor.test.js | Added comprehensive tests for highlight logic |
| src/tests/App.test.tsx | Expanded route and context mocking |
| src/tests/AIContext.test.js | Covered provider switching, key validity, and streaming setup |
| package.json | Switched build scripts to pnpm, updated Jest and Testing-Library config |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (7)
src/renderer/pages/Pile/Editor/LinkPreviews/LinkPreview/index.jsx:4
- You call
getLinkinside the effect but never destructure it from the context. Addconst { getLink } = useLinksContext();before using it.
import { useLinksContext } from 'renderer/context/LinksContext';
src/main/utils/pileEmbeddings.js:146
axiosis not imported in this file. You needconst axios = require('axios');or switch to the OpenAI client you imported.
const response = await axios.post(url, data);
src/renderer/icons/img/CardIcon.js:9
- Inline
//comments are not valid inside JSX props. Move this ESLint-disable above the JSX element or use a{/* ... */}comment block.
// eslint-disable-next-line react/jsx-props-no-spreading
src/renderer/icons/img/BoxOpenIcon.js:9
- JSX does not support
//comments within tag attributes. Either lift this comment above the<svg>or convert to{/* eslint-disable-next-line ... */}.
// eslint-disable-next-line react/jsx-props-no-spreading
src/renderer/pages/Pile/Editor/index.jsx:116
- Tiptap's
handlePastesignature is(view, event, slice). Changing it tohandlePaste(event)will break paste handling. Restore the correct parameter list.
handlePaste(event) {
src/renderer/pages/Pile/Editor/index.jsx:131
- Tiptap's
handleDropsignature is(view, event, slice, moved). Removingviewandsliceparameters will break drop handling; restore the original signature.
handleDrop(event, moved) {
src/renderer/pages/Pile/Editor/index.jsx:329
- The
// eslint-disable-next-line react/no-dangercomment is placed within JSX attributes, which is invalid syntax. Move it above the element or use a JSX comment block.
// eslint-disable-next-line react/no-danger
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Ojasw Upadhyay <46334571+oupadhyay@users.noreply.github.com>


This PR fixes #58.
Core AI provider enhancements:
Model persistence and provider switching:
Testing improvements:
Performance optimizations:
Bug fixes: