fix(quotas): unifier le décompte IA (BYOK, rollback) et combler les fuites
Centralise la réserve via ai-quota, corrige admin unavailable (-1), brancher les routes sans quota et le host-pays brainstorm, avec usage-meter élargi, noms de clusters, MCP et ajustements dashboard/insights. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -17,6 +17,8 @@ import { extractAndDownloadImages, extractImageUrlsFromHtml, downloadImage } fro
|
||||
import { calculateNextRun } from '@/lib/agents/schedule'
|
||||
import { markdownToHtml } from '@/lib/markdown-to-html'
|
||||
import { createNotification } from '@/app/actions/notifications'
|
||||
import { withAiQuota } from '@/lib/ai-quota'
|
||||
import type { FeatureName } from '@/lib/quota-utils'
|
||||
|
||||
// Import tools for side-effect registration
|
||||
import '../tools'
|
||||
@@ -25,6 +27,12 @@ import '../tools'
|
||||
|
||||
export type AgentType = 'scraper' | 'researcher' | 'monitor' | 'custom' | 'slide-generator' | 'excalidraw-generator' | 'task-extractor'
|
||||
|
||||
function quotaFeatureForAgentType(type: string): FeatureName {
|
||||
if (type === 'slide-generator') return 'slide_generate'
|
||||
if (type === 'excalidraw-generator') return 'excalidraw_generate'
|
||||
return 'reformulate'
|
||||
}
|
||||
|
||||
export interface AgentExecutionResult {
|
||||
success: boolean
|
||||
actionId: string
|
||||
@@ -1759,36 +1767,45 @@ export async function executeAgent(agentId: string, userId: string, promptOverri
|
||||
|
||||
// Detect user language
|
||||
const lang = await getUserLanguage(userId)
|
||||
const quotaFeature = quotaFeatureForAgentType(agent.type || 'scraper')
|
||||
|
||||
try {
|
||||
let result: AgentExecutionResult
|
||||
const result = await withAiQuota(
|
||||
userId,
|
||||
quotaFeature,
|
||||
async () => {
|
||||
let inner: AgentExecutionResult
|
||||
|
||||
const hasTools = agent.tools && agent.tools !== '[]' && agent.tools !== 'null'
|
||||
|
||||
if (hasTools) {
|
||||
result = await executeToolUseAgent(agent, action.id, lang, promptOverride)
|
||||
inner = await executeToolUseAgent(agent, action.id, lang, promptOverride)
|
||||
} else {
|
||||
switch ((agent.type || 'scraper') as AgentType) {
|
||||
case 'scraper':
|
||||
result = await executeScraperAgent(agent, action.id, lang)
|
||||
inner = await executeScraperAgent(agent, action.id, lang)
|
||||
break
|
||||
case 'researcher':
|
||||
result = await executeResearcherAgent(agent, action.id, lang)
|
||||
inner = await executeResearcherAgent(agent, action.id, lang)
|
||||
break
|
||||
case 'monitor':
|
||||
result = await executeMonitorAgent(agent, action.id, lang)
|
||||
inner = await executeMonitorAgent(agent, action.id, lang)
|
||||
break
|
||||
case 'custom':
|
||||
result = await executeCustomAgent(agent, action.id, lang)
|
||||
inner = await executeCustomAgent(agent, action.id, lang)
|
||||
break
|
||||
case 'slide-generator':
|
||||
case 'excalidraw-generator':
|
||||
result = await executeToolUseAgent(agent, action.id, lang, promptOverride)
|
||||
inner = await executeToolUseAgent(agent, action.id, lang, promptOverride)
|
||||
break
|
||||
default:
|
||||
result = await executeScraperAgent(agent, action.id, lang)
|
||||
inner = await executeScraperAgent(agent, action.id, lang)
|
||||
}
|
||||
}
|
||||
return inner
|
||||
},
|
||||
{ lane: 'chat' },
|
||||
)
|
||||
|
||||
const nextRunUpdate: Record<string, Date | null> = {}
|
||||
if (agent.frequency !== 'manual') {
|
||||
|
||||
Reference in New Issue
Block a user