diff --git a/src/main/apiServer/routes/agents/handlers/agents.ts b/src/main/apiServer/routes/agents/handlers/agents.ts index 1e772932e2..d6f31a555d 100644 --- a/src/main/apiServer/routes/agents/handlers/agents.ts +++ b/src/main/apiServer/routes/agents/handlers/agents.ts @@ -132,6 +132,20 @@ export const createAgent = async (req: Request, res: Response): Promise try { const limit = req.query.limit ? parseInt(req.query.limit as string) : 20 const offset = req.query.offset ? parseInt(req.query.offset as string) : 0 + const sortBy = (req.query.sortBy as 'created_at' | 'updated_at' | 'name') || 'created_at' + const orderBy = (req.query.orderBy as 'asc' | 'desc') || 'desc' - logger.debug('Listing agents', { limit, offset }) + logger.debug('Listing agents', { limit, offset, sortBy, orderBy }) - const result = await agentService.listAgents({ limit, offset }) + const result = await agentService.listAgents({ limit, offset, sortBy, orderBy }) logger.info('Agents listed', { returned: result.agents.length, diff --git a/src/main/services/agents/services/AgentService.ts b/src/main/services/agents/services/AgentService.ts index 78e7acadb8..53af37f670 100644 --- a/src/main/services/agents/services/AgentService.ts +++ b/src/main/services/agents/services/AgentService.ts @@ -11,7 +11,7 @@ import { UpdateAgentRequest, UpdateAgentResponse } from '@types' -import { count, eq } from 'drizzle-orm' +import { asc, count, desc, eq } from 'drizzle-orm' import { BaseService } from '../BaseService' import { type AgentRow, agentsTable, type InsertAgentRow } from '../database/schema' @@ -100,7 +100,13 @@ export class AgentService extends BaseService { const totalResult = await this.database.select({ count: count() }).from(agentsTable) - const baseQuery = this.database.select().from(agentsTable).orderBy(agentsTable.created_at) + const sortBy = options.sortBy || 'created_at' + const orderBy = options.orderBy || 'desc' + + const sortField = agentsTable[sortBy] + const orderFn = orderBy === 'asc' ? asc : desc + + const baseQuery = this.database.select().from(agentsTable).orderBy(orderFn(sortField)) const result = options.limit !== undefined diff --git a/src/renderer/src/api/agent.ts b/src/renderer/src/api/agent.ts index a16e4eb600..ecc772464d 100644 --- a/src/renderer/src/api/agent.ts +++ b/src/renderer/src/api/agent.ts @@ -21,6 +21,7 @@ import { ListAgentSessionsResponseSchema, type ListAgentsResponse, ListAgentsResponseSchema, + ListOptions, objectEntries, objectKeys, UpdateAgentForm, @@ -95,10 +96,19 @@ export class AgentApiClient { } } - public async listAgents(): Promise { + public async listAgents(options?: ListOptions): Promise { const url = this.agentPaths.base try { - const response = await this.axios.get(url) + const params = new URLSearchParams() + if (options?.limit !== undefined) params.append('limit', String(options.limit)) + if (options?.offset !== undefined) params.append('offset', String(options.offset)) + if (options?.sortBy) params.append('sortBy', options.sortBy) + if (options?.orderBy) params.append('orderBy', options.orderBy) + + const queryString = params.toString() + const fullUrl = queryString ? `${url}?${queryString}` : url + + const response = await this.axios.get(fullUrl) const result = ListAgentsResponseSchema.safeParse(response.data) if (!result.success) { throw new Error('Not a valid Agents array.') diff --git a/src/renderer/src/hooks/agents/useAgents.ts b/src/renderer/src/hooks/agents/useAgents.ts index bf23c2c9c8..f14b893519 100644 --- a/src/renderer/src/hooks/agents/useAgents.ts +++ b/src/renderer/src/hooks/agents/useAgents.ts @@ -33,7 +33,7 @@ export const useAgents = () => { if (!apiServerRunning) { throw new Error(t('agent.server.error.not_running')) } - const result = await client.listAgents() + const result = await client.listAgents({ sortBy: 'created_at', orderBy: 'desc' }) // NOTE: We only use the array for now. useUpdateAgent depends on this behavior. return result.data }, [apiServerConfig.enabled, apiServerRunning, client, t]) diff --git a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx index 952d0a2c07..b0c9018513 100644 --- a/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx +++ b/src/renderer/src/pages/home/Tabs/AssistantsTab.tsx @@ -126,6 +126,8 @@ const AssistantsTab: FC = (props) => { /> )} + + {assistantsTabSortType === 'tags' ? ( = (props) => { /> )} - - {!dragging &&
} ) diff --git a/src/renderer/src/pages/home/Tabs/hooks/useUnifiedItems.ts b/src/renderer/src/pages/home/Tabs/hooks/useUnifiedItems.ts index 09c5cc7bb8..d9190b430d 100644 --- a/src/renderer/src/pages/home/Tabs/hooks/useUnifiedItems.ts +++ b/src/renderer/src/pages/home/Tabs/hooks/useUnifiedItems.ts @@ -43,9 +43,11 @@ export const useUnifiedItems = (options: UseUnifiedItemsOptions) => { } }) - // Add new items (not in saved order) to the end - availableAgents.forEach((agent) => items.push({ type: 'agent', data: agent })) - availableAssistants.forEach((assistant) => items.push({ type: 'assistant', data: assistant })) + // Add new items (not in saved order) to the beginning + const newItems: UnifiedItem[] = [] + availableAgents.forEach((agent) => newItems.push({ type: 'agent', data: agent })) + availableAssistants.forEach((assistant) => newItems.push({ type: 'assistant', data: assistant })) + items.unshift(...newItems) return items }, [agents, assistants, apiServerEnabled, agentsLoading, agentsError, unifiedListOrder]) diff --git a/src/renderer/src/store/assistants.ts b/src/renderer/src/store/assistants.ts index 162a8edd48..575e448597 100644 --- a/src/renderer/src/store/assistants.ts +++ b/src/renderer/src/store/assistants.ts @@ -37,7 +37,7 @@ const assistantsSlice = createSlice({ state.assistants = action.payload }, addAssistant: (state, action: PayloadAction) => { - state.assistants.push(action.payload) + state.assistants.unshift(action.payload) }, insertAssistant: (state, action: PayloadAction<{ index: number; assistant: Assistant }>) => { const { index, assistant } = action.payload diff --git a/src/renderer/src/types/agent.ts b/src/renderer/src/types/agent.ts index ca1e88cbd1..e0dd7cd3e6 100644 --- a/src/renderer/src/types/agent.ts +++ b/src/renderer/src/types/agent.ts @@ -121,6 +121,8 @@ export const isAgentEntity = (value: unknown): value is AgentEntity => { export interface ListOptions { limit?: number offset?: number + sortBy?: 'created_at' | 'updated_at' | 'name' + orderBy?: 'asc' | 'desc' } // AgentSession entity representing a conversation session with one or more agents