-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
147 lines (120 loc) · 4.72 KB
/
background.js
File metadata and controls
147 lines (120 loc) · 4.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// =======================================================================
// FILE: background.js
// =======================================================================
// This service worker handles all communication with the AI model
// and manages background tasks.
// Import the API key from the config file, and rename it for clarity
import { apiKey as defaultApiKey } from './config.js';
// Listen for messages from the content script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "generateReplies") {
// Call the AI suggestion function
getAiSuggestions(request.payload)
.then(suggestions => {
sendResponse({ status: "success", suggestions: suggestions });
})
.catch(error => {
console.error("AI API Error:", error);
sendResponse({ status: "error", message: error.message });
});
// Return true to indicate that we will respond asynchronously
return true;
}
});
async function getAiSuggestions(payload) {
// Destructure payload, including the optional user-provided API key and model
const { chatHistory, customStrategy, userDraft, apiKey, model } = payload;
console.log("Received payload for AI suggestions:", payload);
// Use the user's API key if provided, otherwise fall back to the default
const keyToUse = apiKey || defaultApiKey;
if (!keyToUse) {
throw new Error("API key is missing. Please add it to config.js or in the extension settings.");
}
// Use the user's selected model, or fall back to a default
const modelToUse = model || 'gemini-2.5-flash-lite-preview-06-17';
// --- THIS IS THE REAL GEMINI API CALL ---
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${modelToUse}:generateContent?key=${keyToUse}`;
console.log("Calling Gemini API with payload:", payload);
// Build a detailed prompt based on the provided payload
let taskDescription = '';
if (userDraft) {
taskDescription = `
**User's Draft Reply:**
"${userDraft}"
**Task:**
Based on the strategy and history, refine the user's draft reply. Provide 3 improved versions.
`;
} else {
taskDescription = `
**Task:**
Based on the strategy and history, suggest 3 potential replies to the last message.
`;
}
const prompt = `You are a communication assistant. Your goal is to help the user reply to messages based on a specific strategy.
**Custom Reply Strategy:**
${customStrategy || "Reply in a friendly and supportive tone."}
**Recent Chat History:**
${chatHistory || "(No history available)"}
${taskDescription}
`;
console.log("--- GENERATED PROMPT ---");
console.log(prompt);
console.log("----------------------");
const apiPayload = {
contents: [{
role: "user",
parts: [{ text: prompt }]
}],
generationConfig: {
response_mime_type: "application/json",
response_schema: {
type: "object",
properties: {
"suggestions": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["suggestions"]
}
}
};
console.log("--- API PAYLOAD ---");
console.log(JSON.stringify(apiPayload, null, 2));
console.log("----------------------");
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(apiPayload),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`API request failed with status ${response.status}: ${errorBody}`);
}
const result = await response.json();
if (result.candidates && result.candidates.length > 0 &&
result.candidates[0].content && result.candidates[0].content.parts &&
result.candidates[0].content.parts.length > 0) {
const rawText = result.candidates[0].content.parts[0].text;
// The model is now instructed to return a JSON string conforming to the schema.
const parsedJson = JSON.parse(rawText);
if (!parsedJson.suggestions || !Array.isArray(parsedJson.suggestions)) {
throw new Error("Invalid JSON structure in API response. 'suggestions' array not found.");
}
const suggestions = parsedJson.suggestions.map(s => s.trim()).filter(s => s);
console.log("Received suggestions from AI:", suggestions);
return suggestions;
} else {
console.error("Unexpected API response structure:", result);
throw new Error("Could not parse suggestions from API response.");
}
} catch (error) {
console.error("Error fetching AI suggestions:", error);
throw error; // Re-throw the error to be caught by the caller
}
}