Small feature changes and bug fixes
This commit is contained in:
@@ -180,15 +180,32 @@ final class EmailHandlerService {
|
||||
let response = try await provider.chat(request: request)
|
||||
|
||||
let fullResponse = response.content
|
||||
let promptTokens = response.usage?.promptTokens
|
||||
let completionTokens = response.usage?.completionTokens
|
||||
let totalTokens = response.usage.map { $0.promptTokens + $0.completionTokens }
|
||||
let totalCost: Double? = nil // Calculate if provider supports it
|
||||
|
||||
// Calculate cost if we have pricing info
|
||||
var totalCost: Double? = nil
|
||||
if let usage = response.usage,
|
||||
let models = try? await provider.listModels(),
|
||||
let modelInfo = models.first(where: { $0.id == settings.emailHandlerModel }) {
|
||||
totalCost = (Double(usage.promptTokens) * modelInfo.pricing.prompt / 1_000_000) +
|
||||
(Double(usage.completionTokens) * modelInfo.pricing.completion / 1_000_000)
|
||||
}
|
||||
|
||||
let responseTime = Date().timeIntervalSince(startTime)
|
||||
|
||||
log.info("AI response generated in \(String(format: "%.2f", responseTime))s")
|
||||
|
||||
// Generate HTML email
|
||||
let htmlBody = generateHTMLEmail(aiResponse: fullResponse, originalEmail: email)
|
||||
// Generate HTML email with stats
|
||||
let htmlBody = generateHTMLEmail(
|
||||
aiResponse: fullResponse,
|
||||
originalEmail: email,
|
||||
responseTime: responseTime,
|
||||
promptTokens: promptTokens,
|
||||
completionTokens: completionTokens,
|
||||
cost: totalCost
|
||||
)
|
||||
|
||||
// Send response email
|
||||
let replySubject = email.subject.hasPrefix("Re:") ? email.subject : "Re: \(email.subject)"
|
||||
@@ -275,10 +292,22 @@ final class EmailHandlerService {
|
||||
|
||||
// MARK: - HTML Email Generation
|
||||
|
||||
private func generateHTMLEmail(aiResponse: String, originalEmail: IncomingEmail) -> String {
|
||||
private func generateHTMLEmail(
|
||||
aiResponse: String,
|
||||
originalEmail: IncomingEmail,
|
||||
responseTime: TimeInterval,
|
||||
promptTokens: Int?,
|
||||
completionTokens: Int?,
|
||||
cost: Double?
|
||||
) -> String {
|
||||
// Convert markdown to HTML (basic implementation)
|
||||
let htmlContent = markdownToHTML(aiResponse)
|
||||
|
||||
// Format stats
|
||||
let timeFormatted = String(format: "%.2f", responseTime)
|
||||
let totalTokens = (promptTokens ?? 0) + (completionTokens ?? 0)
|
||||
let costFormatted = cost.map { String(format: "$%.4f", $0) } ?? "N/A"
|
||||
|
||||
return """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@@ -298,12 +327,34 @@ final class EmailHandlerService {
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.footer {
|
||||
.stats {
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
padding: 15px;
|
||||
background: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 8px 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.stats-label {
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
.stats-value {
|
||||
color: #666;
|
||||
}
|
||||
.footer {
|
||||
margin-top: 20px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
code {
|
||||
background: #f5f5f5;
|
||||
@@ -323,6 +374,17 @@ final class EmailHandlerService {
|
||||
<div class="content">
|
||||
\(htmlContent)
|
||||
</div>
|
||||
<div class="stats">
|
||||
<div style="font-weight: 600; margin-bottom: 6px; color: #555;">📊 Processing Stats</div>
|
||||
<div class="stats-grid">
|
||||
<span class="stats-label">Response Time:</span>
|
||||
<span class="stats-value">\(timeFormatted)s</span>
|
||||
<span class="stats-label">Tokens Used:</span>
|
||||
<span class="stats-value">\(totalTokens.formatted()) (\(promptTokens ?? 0) prompt + \(completionTokens ?? 0) completion)</span>
|
||||
<span class="stats-label">Cost:</span>
|
||||
<span class="stats-value">\(costFormatted)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>🤖 This response was generated by AI using oAI Email Handler</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user