draply-dev 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +48 -2
- package/package.json +1 -1
- package/src/draply-features.js +31 -7
package/bin/cli.js
CHANGED
|
@@ -97,7 +97,53 @@ function extractClassName(selector) {
|
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
// ── Call
|
|
100
|
+
// ── Call AI API (Gemini or Groq) ──────────────────────────────────────────────
|
|
101
|
+
function callAI(apiKey, prompt, provider) {
|
|
102
|
+
if (provider === 'groq') return callGroq(apiKey, prompt);
|
|
103
|
+
return callGemini(apiKey, prompt);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function callGroq(apiKey, prompt) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
const body = JSON.stringify({
|
|
109
|
+
model: 'llama-3.3-70b-versatile',
|
|
110
|
+
messages: [{ role: 'user', content: prompt }],
|
|
111
|
+
temperature: 0.1,
|
|
112
|
+
max_tokens: 8192
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const options = {
|
|
116
|
+
hostname: 'api.groq.com',
|
|
117
|
+
path: '/openai/v1/chat/completions',
|
|
118
|
+
method: 'POST',
|
|
119
|
+
headers: {
|
|
120
|
+
'Content-Type': 'application/json',
|
|
121
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
122
|
+
'Content-Length': Buffer.byteLength(body)
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const req = https.request(options, res => {
|
|
127
|
+
const chunks = [];
|
|
128
|
+
res.on('data', c => chunks.push(c));
|
|
129
|
+
res.on('end', () => {
|
|
130
|
+
try {
|
|
131
|
+
const data = JSON.parse(Buffer.concat(chunks).toString());
|
|
132
|
+
if (data.error) {
|
|
133
|
+
reject(new Error(data.error.message || 'Groq API error'));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const text = data.choices?.[0]?.message?.content || '';
|
|
137
|
+
resolve(text);
|
|
138
|
+
} catch (e) { reject(e); }
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
req.on('error', reject);
|
|
142
|
+
req.write(body);
|
|
143
|
+
req.end();
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
|
|
101
147
|
function callGemini(apiKey, prompt) {
|
|
102
148
|
return new Promise((resolve, reject) => {
|
|
103
149
|
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=${apiKey}`;
|
|
@@ -245,7 +291,7 @@ RULES:
|
|
|
245
291
|
Return ONLY the complete modified file. No markdown fences, no explanations.`;
|
|
246
292
|
|
|
247
293
|
try {
|
|
248
|
-
const result = await
|
|
294
|
+
const result = await callAI(cfg.apiKey, prompt, cfg.provider || 'groq');
|
|
249
295
|
let code = result.trim();
|
|
250
296
|
if (code.startsWith('```')) {
|
|
251
297
|
code = code.replace(/^```[a-z]*\n?/, '').replace(/\n?```$/, '');
|
package/package.json
CHANGED
package/src/draply-features.js
CHANGED
|
@@ -257,13 +257,18 @@
|
|
|
257
257
|
|
|
258
258
|
<!-- SETTINGS -->
|
|
259
259
|
<div class="ps-settings" id="__ps_settings__">
|
|
260
|
-
<div class="ps-settings-label">
|
|
260
|
+
<div class="ps-settings-label">AI Provider</div>
|
|
261
|
+
<div class="ps-settings-row" style="margin-bottom:6px">
|
|
262
|
+
<button class="ps-eb active" id="__ps_prov_groq__" data-prov="groq" style="flex:1;text-align:center">Groq (free)</button>
|
|
263
|
+
<button class="ps-eb" id="__ps_prov_gemini__" data-prov="gemini" style="flex:1;text-align:center">Gemini</button>
|
|
264
|
+
</div>
|
|
265
|
+
<div class="ps-settings-label">API Key</div>
|
|
261
266
|
<div class="ps-settings-row">
|
|
262
|
-
<input class="ps-settings-input" id="__ps_apikey__" type="password" placeholder="
|
|
267
|
+
<input class="ps-settings-input" id="__ps_apikey__" type="password" placeholder="gsk_...">
|
|
263
268
|
<button class="ps-settings-save" id="__ps_keysave__">Save</button>
|
|
264
269
|
</div>
|
|
265
270
|
<div class="ps-settings-status" id="__ps_keystatus__">
|
|
266
|
-
|
|
271
|
+
Free key → <a href="https://console.groq.com/keys" target="_blank" style="color:#a855f7">console.groq.com</a>
|
|
267
272
|
</div>
|
|
268
273
|
</div>
|
|
269
274
|
|
|
@@ -313,11 +318,30 @@
|
|
|
313
318
|
const keySaveBtn = document.getElementById('__ps_keysave__');
|
|
314
319
|
const keyStatus = document.getElementById('__ps_keystatus__');
|
|
315
320
|
const aiBtn = document.getElementById('__ps_ai__');
|
|
321
|
+
const provGroq = document.getElementById('__ps_prov_groq__');
|
|
322
|
+
const provGemini = document.getElementById('__ps_prov_gemini__');
|
|
323
|
+
let selectedProvider = 'groq';
|
|
324
|
+
|
|
325
|
+
// Provider toggle
|
|
326
|
+
provGroq.onclick = () => {
|
|
327
|
+
selectedProvider = 'groq';
|
|
328
|
+
provGroq.classList.add('active');
|
|
329
|
+
provGemini.classList.remove('active');
|
|
330
|
+
apiKeyInput.placeholder = 'gsk_...';
|
|
331
|
+
keyStatus.innerHTML = 'Free key → <a href="https://console.groq.com/keys" target="_blank" style="color:#a855f7">console.groq.com</a>';
|
|
332
|
+
};
|
|
333
|
+
provGemini.onclick = () => {
|
|
334
|
+
selectedProvider = 'gemini';
|
|
335
|
+
provGemini.classList.add('active');
|
|
336
|
+
provGroq.classList.remove('active');
|
|
337
|
+
apiKeyInput.placeholder = 'AIza...';
|
|
338
|
+
keyStatus.innerHTML = 'Free key → <a href="https://aistudio.google.com/apikey" target="_blank" style="color:#a855f7">aistudio.google.com</a>';
|
|
339
|
+
};
|
|
316
340
|
|
|
317
341
|
function checkApiKey() {
|
|
318
342
|
fetch('/draply-config').then(r => r.json()).then(d => {
|
|
319
343
|
if (d.hasKey) {
|
|
320
|
-
keyStatus.textContent = '✅ API key configured';
|
|
344
|
+
keyStatus.textContent = '✅ API key configured (' + (d.provider || 'groq') + ')';
|
|
321
345
|
keyStatus.className = 'ps-settings-status ok';
|
|
322
346
|
aiBtn.disabled = false;
|
|
323
347
|
} else {
|
|
@@ -333,14 +357,14 @@
|
|
|
333
357
|
fetch('/draply-config', {
|
|
334
358
|
method: 'POST',
|
|
335
359
|
headers: { 'Content-Type': 'application/json' },
|
|
336
|
-
body: JSON.stringify({ apiKey: key, provider:
|
|
360
|
+
body: JSON.stringify({ apiKey: key, provider: selectedProvider })
|
|
337
361
|
}).then(r => r.json()).then(d => {
|
|
338
362
|
if (d.ok) {
|
|
339
|
-
keyStatus.textContent = '✅
|
|
363
|
+
keyStatus.textContent = '✅ Saved! (' + selectedProvider + ')';
|
|
340
364
|
keyStatus.className = 'ps-settings-status ok';
|
|
341
365
|
apiKeyInput.value = '';
|
|
342
366
|
aiBtn.disabled = false;
|
|
343
|
-
showToast('🔑 API key saved');
|
|
367
|
+
showToast('🔑 API key saved (' + selectedProvider + ')');
|
|
344
368
|
}
|
|
345
369
|
});
|
|
346
370
|
};
|