-
Notifications
You must be signed in to change notification settings - Fork 388
Merge conflicts resolved - Pr 987 ready for review #1237
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
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: Rishabh Choudhary <rishabh998186@gmail.com>
…, remove unused getApiUrl function Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: Rishabh Choudhary <rishabh998186@gmail.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: Rishabh Choudhary <rishabh998186@gmail.com>
…tions Signed-off-by: rishabh998186 <rishabh998186@gmail.com.com>
Signed-off-by: rishabh998186 <rishabh998186@gmail.com.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.
Pull request overview
This pull request resolves merge conflicts from 20+ commits in main and introduces auto-refresh functionality using SWR (Stale-While-Revalidate) for agent data management.
Changes:
- Adds SWR-based data fetching with configurable auto-refresh settings stored in localStorage
- Introduces a settings panel allowing users to toggle auto-refresh and configure refresh intervals
- Migrates AgentsProvider from manual state management to SWR hooks for improved data synchronization
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/src/lib/fetcher.ts | New utility file providing SWR fetcher functions with BaseResponse unwrapping and URL building helpers |
| ui/src/contexts/SettingsContext.tsx | New context for managing auto-refresh settings with localStorage persistence |
| ui/src/components/ui/switch.tsx | New UI component for toggle switches (shadcn/ui component) |
| ui/src/components/SettingsPanel.tsx | New settings panel component for configuring auto-refresh behavior |
| ui/src/components/RefreshIndicator.tsx | New visual indicator showing when data is being refreshed |
| ui/src/components/ClientOnly.tsx | New utility component to prevent SSR/client hydration mismatches |
| ui/src/components/AgentsProvider.tsx | Refactored to use SWR hooks instead of manual state management, but contains critical bugs |
| ui/src/components/AgentList.tsx | Updated to include RefreshIndicator and SettingsPanel components |
| ui/src/app/layout.tsx | Updated to include SettingsProvider in the provider hierarchy and add suppressHydrationWarning |
| ui/package.json | Adds swr and @radix-ui/react-switch dependencies |
| ui/package-lock.json | Lock file updates for new dependencies |
Files not reviewed (1)
- ui/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| refreshInterval: autoRefreshEnabled ? autoRefreshInterval : 0, | ||
| revalidateOnFocus: true, | ||
| revalidateOnReconnect: true, | ||
| dedupingInterval: 0, // Disable deduping to ensure every request goes through |
Copilot
AI
Jan 23, 2026
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.
Setting dedupingInterval to 0 means SWR will not deduplicate requests, potentially causing multiple identical requests to be sent simultaneously if multiple components mount at the same time. The default value of 2000ms (2 seconds) is usually appropriate for most use cases. Consider removing this configuration or using a small non-zero value to prevent unnecessary duplicate requests while still allowing frequent updates.
| dedupingInterval: 0, // Disable deduping to ensure every request goes through |
| if (!hasMounted) { | ||
| return fallback as React.ReactElement; | ||
| } | ||
|
|
||
| return children as React.ReactElement; |
Copilot
AI
Jan 23, 2026
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.
The type assertions as React.ReactElement are unsafe because both fallback and children can be null, a fragment, or an array of elements, which are all valid React.ReactNode types but not React.ReactElement types. This will cause TypeScript errors in strict mode. The return type should be React.ReactElement | null or the function should return the values directly without type assertion.
| /** | ||
| * Fetcher function for SWR | ||
| * Handles API requests with proper error handling and BaseResponse unwrapping | ||
| */ | ||
| export const fetcher = async (url: string): Promise<unknown> => { | ||
| const response = await fetch(url); | ||
|
|
||
| if (!response.ok) { | ||
| const error = new Error(`HTTP ${response.status}: ${response.statusText}`) as Error & { | ||
| info?: unknown; | ||
| status?: number; | ||
| }; | ||
| // Attach extra info to the error object | ||
| error.info = await response.json().catch(() => ({})); | ||
| error.status = response.status; | ||
| throw error; | ||
| } | ||
|
|
||
| const jsonData = await response.json(); | ||
|
|
||
| // If the response follows the BaseResponse format, return the data property | ||
| // Otherwise, return the raw response | ||
| if (jsonData && typeof jsonData === 'object' && 'data' in jsonData) { | ||
| return jsonData.data; | ||
| } | ||
|
|
||
| return jsonData; | ||
| }; | ||
|
|
||
| import { getBackendUrl } from '@/lib/utils'; | ||
|
|
||
| /** | ||
| * Build full API URL for a given endpoint using existing backend URL utility | ||
| */ | ||
| export const buildApiUrl = (endpoint: string): string => { | ||
| const baseUrl = getBackendUrl(); | ||
| return `${baseUrl}${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`; | ||
| }; | ||
|
|
||
| /** | ||
| * Type-safe fetcher for specific data types | ||
| */ | ||
| export const createTypedFetcher = <T>() => { | ||
| return async (url: string): Promise<T> => { | ||
| const result = await fetcher(url); | ||
| return result as T; | ||
| }; | ||
| }; |
Copilot
AI
Jan 23, 2026
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.
The new fetcher.ts file in ui/src/lib/ lacks test coverage. Other files in the lib directory have corresponding test files in tests (e.g., utils.test.ts, providers.test.ts, toolUtils.test.ts). Following the established pattern, this file should have a fetcher.test.ts file covering the fetcher, buildApiUrl, and createTypedFetcher functions.
| import React, { createContext, useContext, ReactNode, useCallback, useMemo } from "react"; | ||
| import { getAgent as getAgentAction, createAgent, getAgents } from "@/app/actions/agents"; | ||
| import { getTools } from "@/app/actions/tools"; | ||
| import { getModels } from "@/app/actions/models"; |
Copilot
AI
Jan 23, 2026
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.
The import of getModels from '@/app/actions/models' is incorrect for this use case. The function getModels returns ProviderModelsResponse (a dictionary of available model names per provider), while the AgentsProvider needs ModelConfig[] (configured model instances). This import should be changed to getModelConfigs from '@/app/actions/modelConfigs' to match the expected data type.
| import { getModels } from "@/app/actions/models"; | |
| import { getModelConfigs } from "@/app/actions/modelConfigs"; |
| return jsonData; | ||
| }; | ||
|
|
||
| import { getBackendUrl } from '@/lib/utils'; |
Copilot
AI
Jan 23, 2026
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.
Import statement should be placed at the top of the file with other imports, not in the middle of the file after exports. This violates standard JavaScript/TypeScript conventions where all imports should be at the beginning of the file.
| const value = { | ||
| agents, | ||
| models, | ||
| loading, | ||
| error, | ||
| tools, | ||
| refreshAgents: fetchAgents, | ||
| refreshModels: fetchModels, | ||
| refreshAgents, | ||
| createNewAgent, | ||
| updateAgent, | ||
| getAgent, | ||
| validateAgentData, | ||
| isRefreshing, | ||
| }; |
Copilot
AI
Jan 23, 2026
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.
The interface AgentsContextType declares refreshModels as a required method, but it is not included in the value object that is passed to the context provider on lines 261-273. This will cause a TypeScript error and runtime issues when ui/src/app/models/new/page.tsx tries to call refreshModels via useAgents(). Either add a refreshModels implementation to the value object or remove it from the interface.
| const modelsFetcher = useCallback(async () => { | ||
| // Note: models in AgentsProvider appears unused - model selection uses getModelConfigs() directly | ||
| // Return empty array to satisfy type | ||
| return []; | ||
| }, []); |
Copilot
AI
Jan 23, 2026
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.
The modelsFetcher returns an empty array which means the models field will always be empty. However, this field is used in ui/src/app/agents/new/page.tsx (line 442) where it's passed to ModelSelectionSection. This will prevent users from selecting models when creating or editing agents. The fetcher should call getModelConfigs() instead to properly populate the models data.
| import React, { createContext, useContext, ReactNode, useCallback, useMemo } from "react"; | ||
| import { getAgent as getAgentAction, createAgent, getAgents } from "@/app/actions/agents"; | ||
| import { getTools } from "@/app/actions/tools"; | ||
| import { getModels } from "@/app/actions/models"; |
Copilot
AI
Jan 23, 2026
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.
Unused import getModels.
| import { getModels } from "@/app/actions/models"; |
Signed-off-by: Bhavishya Mohan Aggarwal <130919943+BHAVISHYA2005@users.noreply.github.com>
I've resolved the merge conflicts that arose from 20+ commits in main.