fix(agents): empêcher le déplacement des cartes lors du toggle
Le tri par `updatedAt` provoquait un saut de position quand on toggait un agent car Prisma mettait à jour `updatedAt` automatiquement. - Tri stable par `createdAt` au lieu de `updatedAt` - Mise à jour optimiste locale via `onToggle` au lieu d'un re-fetch complet - Rollback automatique en cas d'erreur serveur - Désactivation du bouton toggle pendant l'opération (anti double-clic) - Suppression du `revalidatePath` superflu dans `toggleAgent` Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
209
keep-notes/app/actions/agent-actions.ts
Normal file
209
keep-notes/app/actions/agent-actions.ts
Normal file
@@ -0,0 +1,209 @@
|
||||
'use server'
|
||||
|
||||
/**
|
||||
* Agent Server Actions
|
||||
* CRUD operations for agents and execution triggers.
|
||||
*/
|
||||
|
||||
import { auth } from '@/auth'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { executeAgent } from '@/lib/ai/services/agent-executor.service'
|
||||
|
||||
// --- CRUD ---
|
||||
|
||||
export async function createAgent(data: {
|
||||
name: string
|
||||
description?: string
|
||||
type: string
|
||||
role: string
|
||||
sourceUrls?: string[]
|
||||
sourceNotebookId?: string
|
||||
targetNotebookId?: string
|
||||
frequency?: string
|
||||
}) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const agent = await prisma.agent.create({
|
||||
data: {
|
||||
name: data.name,
|
||||
description: data.description,
|
||||
type: data.type,
|
||||
role: data.role,
|
||||
sourceUrls: data.sourceUrls ? JSON.stringify(data.sourceUrls) : null,
|
||||
sourceNotebookId: data.sourceNotebookId || null,
|
||||
targetNotebookId: data.targetNotebookId || null,
|
||||
frequency: data.frequency || 'manual',
|
||||
userId: session.user.id,
|
||||
}
|
||||
})
|
||||
|
||||
revalidatePath('/agents')
|
||||
return { success: true, agent }
|
||||
} catch (error) {
|
||||
console.error('Error creating agent:', error)
|
||||
throw new Error('Impossible de creer l\'agent')
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateAgent(id: string, data: {
|
||||
name?: string
|
||||
description?: string
|
||||
type?: string
|
||||
role?: string
|
||||
sourceUrls?: string[]
|
||||
sourceNotebookId?: string | null
|
||||
targetNotebookId?: string | null
|
||||
frequency?: string
|
||||
isEnabled?: boolean
|
||||
}) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const existing = await prisma.agent.findUnique({ where: { id } })
|
||||
if (!existing || existing.userId !== session.user.id) {
|
||||
throw new Error('Agent non trouve')
|
||||
}
|
||||
|
||||
const updateData: Record<string, unknown> = {}
|
||||
if (data.name !== undefined) updateData.name = data.name
|
||||
if (data.description !== undefined) updateData.description = data.description
|
||||
if (data.type !== undefined) updateData.type = data.type
|
||||
if (data.role !== undefined) updateData.role = data.role
|
||||
if (data.sourceUrls !== undefined) updateData.sourceUrls = JSON.stringify(data.sourceUrls)
|
||||
if (data.sourceNotebookId !== undefined) updateData.sourceNotebookId = data.sourceNotebookId
|
||||
if (data.targetNotebookId !== undefined) updateData.targetNotebookId = data.targetNotebookId
|
||||
if (data.frequency !== undefined) updateData.frequency = data.frequency
|
||||
if (data.isEnabled !== undefined) updateData.isEnabled = data.isEnabled
|
||||
|
||||
const agent = await prisma.agent.update({
|
||||
where: { id },
|
||||
data: updateData
|
||||
})
|
||||
|
||||
revalidatePath('/agents')
|
||||
return { success: true, agent }
|
||||
} catch (error) {
|
||||
console.error('Error updating agent:', error)
|
||||
throw new Error('Impossible de mettre a jour l\'agent')
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteAgent(id: string) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const existing = await prisma.agent.findUnique({ where: { id } })
|
||||
if (!existing || existing.userId !== session.user.id) {
|
||||
throw new Error('Agent non trouve')
|
||||
}
|
||||
|
||||
await prisma.agent.delete({ where: { id } })
|
||||
revalidatePath('/agents')
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
console.error('Error deleting agent:', error)
|
||||
throw new Error('Impossible de supprimer l\'agent')
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAgents() {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const agents = await prisma.agent.findMany({
|
||||
where: { userId: session.user.id },
|
||||
include: {
|
||||
_count: { select: { actions: true } },
|
||||
actions: {
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 1,
|
||||
},
|
||||
notebook: {
|
||||
select: { id: true, name: true, icon: true }
|
||||
}
|
||||
},
|
||||
orderBy: { createdAt: 'desc' }
|
||||
})
|
||||
|
||||
return agents
|
||||
} catch (error) {
|
||||
console.error('Error fetching agents:', error)
|
||||
throw new Error('Impossible de charger les agents')
|
||||
}
|
||||
}
|
||||
|
||||
// --- Execution ---
|
||||
|
||||
export async function runAgent(id: string) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await executeAgent(id, session.user.id)
|
||||
revalidatePath('/agents')
|
||||
revalidatePath('/')
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error('Error running agent:', error)
|
||||
return {
|
||||
success: false,
|
||||
actionId: '',
|
||||
error: error instanceof Error ? error.message : 'Erreur inconnue'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- History ---
|
||||
|
||||
export async function getAgentActions(agentId: string) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const actions = await prisma.agentAction.findMany({
|
||||
where: { agentId },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 20,
|
||||
})
|
||||
return actions
|
||||
} catch (error) {
|
||||
console.error('Error fetching agent actions:', error)
|
||||
throw new Error('Impossible de charger l\'historique')
|
||||
}
|
||||
}
|
||||
|
||||
export async function toggleAgent(id: string, isEnabled: boolean) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Non autorise')
|
||||
}
|
||||
|
||||
try {
|
||||
const agent = await prisma.agent.update({
|
||||
where: { id },
|
||||
data: { isEnabled }
|
||||
})
|
||||
return { success: true, agent }
|
||||
} catch (error) {
|
||||
console.error('Error toggling agent:', error)
|
||||
throw new Error('Impossible de modifier l\'agent')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user