(filePath)
| 7025 | |
| 7026 | if (error.message && error.message.includes('Authentication failed')) { |
| 7027 | errorMessage = 'Authentication Error'; |
| 7028 | errorDetail = 'Your API key is invalid or has insufficient permissions. Please check your AI configuration settings.'; |
| 7029 | } else if (error.message && error.message.includes('Network error')) { |
| 7030 | errorMessage = 'Connection Error'; |
| 7031 | errorDetail = 'Unable to connect to the AI service. Please check your internet connection and API endpoint settings.'; |
| 7032 | } else if (error.message && error.message.includes('Rate limit')) { |
| 7033 | errorMessage = 'Rate Limit Exceeded'; |
| 7034 | // Extract the detailed message if available (after "Rate limit exceeded: ") |
| 7035 | const detailedMessage = error.message.includes('Rate limit exceeded: ') |
| 7036 | ? error.message.split('Rate limit exceeded: ')[1] |
| 7037 | : 'API rate limit has been exceeded. Please try again later.'; |
| 7038 | errorDetail = detailedMessage; |
| 7039 | } else if (error.message && error.message.includes('Invalid request')) { |
| 7040 | errorMessage = 'Invalid Request'; |
| 7041 | errorDetail = error.message; |
| 7042 | } |
| 7043 | |
| 7044 | dialog.showMessageBox({ |
| 7045 | type: 'error', |
| 7046 | title: errorMessage, |
| 7047 | message: errorDetail, |
| 7048 | detail: error.stack ? `Technical details: ${error.stack.substring(0, 200)}...` : '' |
| 7049 | }); |
| 7050 | } |
| 7051 | } |
| 7052 | }); |
| 7053 | } |
| 7054 | |
| 7055 | // Check if any selected files are 3MF files |
| 7056 | const has3MFFiles = filePaths.some(fp => { |
| 7057 | const ext = path.extname(fp).toLowerCase(); |
| 7058 | // Handle zip entries - check the entry path extension |
| 7059 | if (fp.includes('::')) { |
| 7060 | const entryPath = fp.split('::')[1]; |
| 7061 | return path.extname(entryPath).toLowerCase() === '.3mf'; |
| 7062 | } |
| 7063 | return ext === '.3mf'; |
| 7064 | }); |
| 7065 | |
| 7066 | // Add "Pull Metadata" option for 3MF files |
| 7067 | if (has3MFFiles) { |
| 7068 | menuItems.push({ |
| 7069 | label: 'Pull Metadata', |
| 7070 | click: async () => { |
| 7071 | try { |
| 7072 | // Filter to only 3MF files |
| 7073 | const threeMFFiles = filePaths.filter(fp => { |
| 7074 | const ext = path.extname(fp).toLowerCase(); |
| 7075 | if (fp.includes('::')) { |
| 7076 | const entryPath = fp.split('::')[1]; |
| 7077 | return path.extname(entryPath).toLowerCase() === '.3mf'; |
| 7078 | } |
| 7079 | return ext === '.3mf'; |
| 7080 | }); |
| 7081 | |
| 7082 | if (threeMFFiles.length === 0) { |
| 7083 | return; |
| 7084 | } |
no test coverage detected