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 CHANGED
@@ -97,7 +97,53 @@ function extractClassName(selector) {
97
97
  return null;
98
98
  }
99
99
 
100
- // ── Call Gemini API ───────────────────────────────────────────────────────────
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 callGemini(cfg.apiKey, prompt);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "draply-dev",
3
- "version": "1.3.2",
3
+ "version": "1.3.4",
4
4
  "description": "Visual overlay for any frontend project — move, resize, restyle live in the browser, save to CSS",
5
5
  "author": "Arman",
6
6
  "type": "commonjs",
@@ -257,13 +257,18 @@
257
257
 
258
258
  <!-- SETTINGS -->
259
259
  <div class="ps-settings" id="__ps_settings__">
260
- <div class="ps-settings-label">Gemini API Key</div>
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="AIza...">
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
- Get free key at <a href="https://aistudio.google.com/apikey" target="_blank" style="color:#a855f7">aistudio.google.com</a>
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: 'gemini' })
360
+ body: JSON.stringify({ apiKey: key, provider: selectedProvider })
337
361
  }).then(r => r.json()).then(d => {
338
362
  if (d.ok) {
339
- keyStatus.textContent = '✅ API key saved!';
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
  };