Fix AI tagging issues and improve error messages
Build and Push Docker Image / build (push) Successful in 9m33s Details

- Fall back to ai_enabled setting if ai_tagging_enabled not set
- Check both tags array and projectTags relationship for untagged projects
- Add detailed logging for debugging
- Show errors in toast instead of just counts
- Handle "no projects to tag" case with appropriate message
- Add early checks for OpenAI config and available tags

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Matt 2026-02-05 09:24:44 +01:00
parent 6f6d5ef501
commit 7f95f681d6
2 changed files with 77 additions and 23 deletions

View File

@ -252,9 +252,16 @@ export default function ProjectsPage() {
// AI batch tagging mutation
const batchTagProjects = trpc.tag.batchTagProjects.useMutation({
onSuccess: (result) => {
toast.success(
`AI Tagging complete: ${result.processed} tagged, ${result.skipped} skipped, ${result.failed} failed`
)
if (result.errors && result.errors.length > 0) {
// Show first error if there are any
toast.error(`AI Tagging issue: ${result.errors[0]}`)
} else if (result.processed === 0 && result.skipped === 0 && result.failed === 0) {
toast.info('No projects to tag - all projects in this round already have tags')
} else {
toast.success(
`AI Tagging complete: ${result.processed} tagged, ${result.skipped} skipped, ${result.failed} failed`
)
}
setAiTagDialogOpen(false)
setSelectedRoundForTagging('')
utils.project.list.invalidate()

View File

@ -101,15 +101,23 @@ async function getTaggingSettings(): Promise<{
const settings = await prisma.systemSettings.findMany({
where: {
key: {
in: ['ai_tagging_enabled', 'ai_tagging_max_tags'],
in: ['ai_tagging_enabled', 'ai_tagging_max_tags', 'ai_enabled'],
},
},
})
const settingsMap = new Map(settings.map((s) => [s.key, s.value]))
// AI tagging is enabled if:
// 1. ai_tagging_enabled is explicitly 'true', OR
// 2. ai_tagging_enabled is not set but ai_enabled is 'true' (fall back to general AI setting)
const taggingEnabled = settingsMap.get('ai_tagging_enabled')
const aiEnabled = settingsMap.get('ai_enabled')
const enabled = taggingEnabled === 'true' || (taggingEnabled === undefined && aiEnabled === 'true')
return {
enabled: settingsMap.get('ai_tagging_enabled') === 'true',
enabled,
maxTags: parseInt(settingsMap.get('ai_tagging_max_tags') || String(DEFAULT_MAX_TAGS)),
}
}
@ -409,34 +417,73 @@ export async function batchTagProjects(
onProgress?: (processed: number, total: number) => void
): Promise<BatchTaggingResult> {
const settings = await getTaggingSettings()
console.log('[AI Tagging] Settings:', settings)
if (!settings.enabled) {
console.log('[AI Tagging] AI tagging is disabled in settings')
return {
processed: 0,
failed: 0,
skipped: 0,
errors: ['AI tagging is disabled'],
errors: ['AI tagging is disabled. Enable it in Settings > AI or set ai_enabled to true.'],
results: [],
}
}
// Get untagged projects in round
const projects = await prisma.project.findMany({
where: {
roundId,
projectTags: { none: {} }, // Only projects with no tags
},
include: {
files: { select: { fileType: true } },
_count: { select: { teamMembers: true, files: true } },
},
})
if (projects.length === 0) {
// Check if OpenAI is configured
const openai = await getOpenAI()
if (!openai) {
console.log('[AI Tagging] OpenAI is not configured')
return {
processed: 0,
failed: 0,
skipped: 0,
errors: [],
errors: ['OpenAI API is not configured. Add your API key in Settings > AI.'],
results: [],
}
}
// Check if there are any available tags
const availableTags = await getAvailableTags()
console.log(`[AI Tagging] Found ${availableTags.length} available expertise tags`)
if (availableTags.length === 0) {
return {
processed: 0,
failed: 0,
skipped: 0,
errors: ['No expertise tags defined. Create tags in Settings > Tags first.'],
results: [],
}
}
// Get ALL projects in round to check their tag status
const allProjects = await prisma.project.findMany({
where: { roundId },
include: {
files: { select: { fileType: true } },
_count: { select: { teamMembers: true, files: true } },
projectTags: { select: { tagId: true } },
},
})
console.log(`[AI Tagging] Found ${allProjects.length} total projects in round`)
// Filter to only projects that truly have no tags (empty tags array AND no projectTags)
const untaggedProjects = allProjects.filter(p =>
(p.tags.length === 0) && (p.projectTags.length === 0)
)
const alreadyTaggedCount = allProjects.length - untaggedProjects.length
console.log(`[AI Tagging] ${untaggedProjects.length} untagged projects, ${alreadyTaggedCount} already have tags`)
if (untaggedProjects.length === 0) {
return {
processed: 0,
failed: 0,
skipped: alreadyTaggedCount,
errors: alreadyTaggedCount > 0
? []
: ['No projects found in this round'],
results: [],
}
}
@ -446,8 +493,8 @@ export async function batchTagProjects(
let failed = 0
const errors: string[] = []
for (let i = 0; i < projects.length; i++) {
const project = projects[i]
for (let i = 0; i < untaggedProjects.length; i++) {
const project = untaggedProjects[i]
try {
const result = await tagProject(project.id, userId)
results.push(result)
@ -459,7 +506,7 @@ export async function batchTagProjects(
// Report progress
if (onProgress) {
onProgress(i + 1, projects.length)
onProgress(i + 1, untaggedProjects.length)
}
}