vantuz 3.3.1 → 3.3.3

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/cli.js CHANGED
@@ -12,6 +12,7 @@ import readline from 'readline';
12
12
  import { log, getLogs, clearLogs } from './core/ai-provider.js';
13
13
  import { getEngine } from './core/engine.js';
14
14
  import { getGateway } from './core/gateway.js';
15
+ import { Configurator } from './config.js'; // Import the new Configurator
15
16
 
16
17
  // ═══════════════════════════════════════════════════════════════════════════
17
18
  // CONFIG
@@ -71,10 +72,44 @@ function saveConfigJson(config) {
71
72
  }
72
73
  }
73
74
 
74
- function clearScreen() {
75
- process.stdout.write('\x1Bc');
76
- }
77
-
75
+ function clearScreen() {
76
+ process.stdout.write('\x1Bc');
77
+ }
78
+
79
+ async function promptInput(question) {
80
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
81
+ const answer = await new Promise(resolve => rl.question(question, resolve));
82
+ rl.close();
83
+ return answer.trim();
84
+ }
85
+
86
+ function normalizePhone(input) {
87
+ if (!input) return '';
88
+ const cleaned = input.replace(/[\s-]/g, '');
89
+ return cleaned.startsWith('+') ? cleaned : `+${cleaned}`;
90
+ }
91
+
92
+ function loadOpenclawConfig(configPath) {
93
+ try {
94
+ if (fs.existsSync(configPath)) {
95
+ return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
96
+ }
97
+ } catch (e) {
98
+ console.log(c('red', `Gateway config okunamadı: ${e.message}`));
99
+ }
100
+ return {};
101
+ }
102
+
103
+ function saveOpenclawConfig(configPath, config) {
104
+ try {
105
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
106
+ return true;
107
+ } catch (e) {
108
+ console.log(c('red', `Gateway config yazılamadı: ${e.message}`));
109
+ return false;
110
+ }
111
+ }
112
+
78
113
  function printHeader() {
79
114
  const version = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url))).version;
80
115
  console.log(c('cyan', `
@@ -86,7 +121,7 @@ function printHeader() {
86
121
  ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚══════╝
87
122
  `));
88
123
  console.log(c('magenta', ` Enterprise E-Commerce Management System v${version}`));
89
- console.log(c('dim', ' Powered by Vantuz AI Gateway'));
124
+ console.log(c('dim', ' Powered by Vantuz Gateway'));
90
125
  console.log(c('dim', ' ----------------------------------------------------------\n'));
91
126
  }
92
127
 
@@ -106,7 +141,7 @@ async function showSpinner(text, duration = 1000) {
106
141
  // COMMANDS
107
142
  // ═══════════════════════════════════════════════════════════════════════════
108
143
 
109
- async function runTUI() {
144
+ async function runTUI() {
110
145
  clearScreen();
111
146
  printHeader();
112
147
 
@@ -126,7 +161,7 @@ async function runTUI() {
126
161
 
127
162
  console.log(`${c('green', '●')} Sistem Aktif ${c('dim', `(${status.connectedCount}/${status.totalPlatforms} Platform Bağlı)`)}`);
128
163
  console.log(`${c('blue', 'ℹ')} AI Sağlayıcı: ${c('bold', status.aiProvider || 'Gemini')}`);
129
- console.log(`${c('yellow', '⚡')} Komutlar: ${c('cyan', '/stok, /siparis, /rapor, /analiz, /durum, /temizle, /exit')}\n`);
164
+ console.log(`${c('yellow', '⚡')} Komutlar: ${c('cyan', '/stok, /siparis, /rapor, /analiz, /durum, /temizle, /exit')}\n`);
130
165
 
131
166
  const rl = readline.createInterface({
132
167
  input: process.stdin,
@@ -159,25 +194,42 @@ async function runTUI() {
159
194
  console.log(` ${c('cyan', '/temizle')} - Ekranı temizler`);
160
195
  console.log(` ${c('cyan', '/exit')} - Çıkış\n`);
161
196
  break;
162
- case '/stok':
163
- console.log(c('dim', 'Stok verileri çekiliyor...'));
164
- const stocks = await engine.getStock();
165
- if (stocks.length === 0) console.log(c('yellow', 'Bağlı platform bulunamadı.'));
166
- stocks.forEach(s => {
167
- console.log(`\n${s.icon} ${c('bold', s.platform.toUpperCase())}`);
168
- s.products.slice(0, 5).forEach(p => {
169
- console.log(` - ${p.title}: ${c('green', p.stock)} Adet | ${c('yellow', p.price)} TL`);
170
- });
171
- });
172
- break;
173
- case '/siparis':
174
- console.log(c('dim', 'Siparişler çekiliyor...'));
175
- const orders = await engine.getOrders({ size: 5 });
176
- if (orders.length === 0) console.log(c('yellow', 'Son sipariş bulunamadı.'));
177
- orders.forEach(o => {
178
- console.log(`${o._icon} [#${o.orderNumber || o.id}] ${c('bold', o.customerName || 'Müşteri')}: ${c('green', o.totalPrice || o.total)} TL (${o._platform})`);
179
- });
180
- break;
197
+ case '/stok':
198
+ console.log(c('dim', 'Stok verileri çekiliyor...'));
199
+ const stocks = await engine.getStock();
200
+ if (stocks.length === 0) console.log(c('yellow', 'Bağlı platform bulunamadı.'));
201
+ stocks.forEach(s => {
202
+ console.log(`\n${s.icon} ${c('bold', s.platform.toUpperCase())}`);
203
+ s.products.slice(0, 5).forEach(p => {
204
+ console.log(` - ${p.title}: ${c('green', p.stock)} Adet | ${c('yellow', p.price)} TL`);
205
+ });
206
+ });
207
+ break;
208
+ case '/analiz':
209
+ process.stdout.write(c('dim', 'Analiz hazırlanıyor... '));
210
+ const analysis = await engine.chat('satış ve stok analiz raporu hazırla');
211
+ process.stdout.write('\r' + ' '.repeat(30) + '\r');
212
+ console.log(`\n${analysis}\n`);
213
+ break;
214
+ case '/siparis':
215
+ console.log(c('dim', 'Siparişler çekiliyor...'));
216
+ const orders = await engine.getOrders({ size: 50, allStatuses: true });
217
+ const activeOrders = Array.isArray(orders)
218
+ ? orders.filter(o => ['Created', 'Picking', 'UnPacked'].includes(String(o.status || o.shipmentPackageStatus || o.orderStatus)))
219
+ : [];
220
+ const visible = activeOrders.slice(0, 5);
221
+ if (!Array.isArray(orders) || visible.length === 0) {
222
+ console.log(c('yellow', 'Son sipariş bulunamadı.'));
223
+ break;
224
+ }
225
+ visible.forEach(o => {
226
+ const names = Array.isArray(o.lines)
227
+ ? o.lines.map(l => l?.productName || l?.name).filter(Boolean)
228
+ : [];
229
+ const namePart = names.length > 0 ? ` | ${names.join(', ')}` : '';
230
+ console.log(`${o._icon} [#${o.orderNumber || o.id}] ${c('bold', o.customerName || 'Müşteri')}: ${c('green', o.totalPrice ?? o.totalAmount ?? o.total ?? '—')} TL (${o._platform})${namePart}`);
231
+ });
232
+ break;
181
233
  case '/durum':
182
234
  const s = engine.getStatus();
183
235
  console.log(c('yellow', '\n── Sistem Durumu ──'));
@@ -190,12 +242,12 @@ async function runTUI() {
190
242
  default:
191
243
  console.log(c('red', `[HATA] Bilinmeyen komut: ${cmd}. /help yazın.`));
192
244
  }
193
- } else {
194
- process.stdout.write(c('dim', 'Düşünüyor... '));
195
- const response = await engine.chat(input);
196
- process.stdout.write('\r' + ' '.repeat(20) + '\r');
197
- console.log(`\n${c('cyan', '🐙 Vantuz:')}\n${response}\n`);
198
- }
245
+ } else {
246
+ process.stdout.write(c('dim', 'Düşünüyor... '));
247
+ const response = await engine.handleMessage(input, { channel: 'local', from: 'local' });
248
+ process.stdout.write('\r' + ' '.repeat(20) + '\r');
249
+ console.log(`\n${c('cyan', '🐙 Vantuz:')}\n${response}\n`);
250
+ }
199
251
  } catch (e) {
200
252
  console.log(c('red', `\n[HATA] ${e.message}`));
201
253
  }
@@ -206,11 +258,23 @@ async function runTUI() {
206
258
 
207
259
  async function runConfig(args) {
208
260
  const sub = args[1]?.toLowerCase();
209
- const config = loadConfigJson();
261
+ const config = loadConfigJson(); // config.json operations
262
+
263
+ if (sub === 'init') {
264
+ const configurator = new Configurator();
265
+ await configurator.run();
266
+ return;
267
+ }
210
268
 
211
- if (!sub || sub === 'get') {
269
+ if (sub === 'init' || !sub) { // If sub is 'init' OR no sub-command is provided
270
+ const configurator = new Configurator();
271
+ await configurator.run();
272
+ return; // IMPORTANT: Return after running the configurator
273
+ }
274
+
275
+ if (sub === 'get') { // Handle 'get' sub-command
212
276
  printHeader();
213
- if (sub === 'get' && args[2]) {
277
+ if (args[2]) {
214
278
  const key = args[2];
215
279
  const value = config?.[key];
216
280
  console.log(value === undefined ? '' : String(value));
@@ -238,7 +302,7 @@ async function runConfig(args) {
238
302
  return;
239
303
  }
240
304
 
241
- console.log(c('red', 'Geçersiz config komutu. Kullanım: vantuz config [get [key] | set <key> <value>]'));
305
+ console.log(c('red', 'Geçersiz config komutu. Kullanım: vantuz config [init | get [key] | set <key> <value>]'));
242
306
  process.exitCode = 2;
243
307
  }
244
308
 
@@ -260,7 +324,7 @@ async function runLogs(args) {
260
324
  console.log(getLogs(n));
261
325
  }
262
326
 
263
- async function runGateway(args) {
327
+ async function runGateway(args) {
264
328
  const sub = args[1]?.toLowerCase();
265
329
  const gw = await getGateway();
266
330
  const info = gw.getInfo();
@@ -276,8 +340,8 @@ async function runGateway(args) {
276
340
  console.log('');
277
341
 
278
342
  if (!info.connected) {
279
- console.log(c('dim', ' Gateway başlatmak için: vantuz gateway run'));
280
- console.log(c('dim', ' Veya: start.bat\n'));
343
+ console.log(c('dim', ' Gateway başlatmak için: vantuz gateway run'));
344
+ console.log(c('dim', ' Veya: start.bat\n'));
281
345
  }
282
346
  return;
283
347
  }
@@ -311,31 +375,18 @@ async function runGateway(args) {
311
375
  return;
312
376
  }
313
377
 
314
- if (sub === 'run' || sub === 'start') {
315
- console.log(c('cyan', 'Gateway başlatılıyor...'));
316
- const gatewayCmd = path.join(process.cwd(), '.openclaw', 'gateway.cmd');
317
-
318
- if (fs.existsSync(gatewayCmd)) {
319
- try {
320
- const { spawn } = await import('child_process');
321
- const child = spawn(gatewayCmd, [], {
322
- detached: true,
323
- stdio: 'ignore', // Arka planda sessizce çalışsın
324
- shell: true // Windows için gerekli
325
- });
326
- child.unref(); // Parent process'ten ayır
327
-
328
- console.log(c('green', '✔ Gateway arka planda başlatıldı.'));
329
- console.log(c('dim', 'Birkaç saniye içinde hazır olacak.'));
330
- console.log(c('dim', 'Kontrol için: vantuz gateway status'));
331
- } catch (e) {
332
- console.log(c('red', `Başlatma hatası: ${e.message}`));
333
- }
334
- } else {
335
- console.log(c('red', 'Gateway başlatma dosyası bulunamadı: .openclaw/gateway.cmd'));
336
- }
337
- return;
338
- }
378
+ if (sub === 'run' || sub === 'start') {
379
+ console.log(c('cyan', 'Gateway başlatılıyor...'));
380
+ const result = await gw.start();
381
+ if (result.success) {
382
+ console.log(c('green', '✔ Gateway arka planda başlatıldı.'));
383
+ console.log(c('dim', 'Birkaç saniye içinde hazır olacak.'));
384
+ console.log(c('dim', 'Kontrol için: vantuz gateway status'));
385
+ } else {
386
+ console.log(c('red', result.error || 'Gateway başlatılamadı'));
387
+ }
388
+ return;
389
+ }
339
390
 
340
391
  console.log(c('red', 'Kullanım: vantuz gateway [status|health|models|run]'));
341
392
  }
@@ -385,9 +436,72 @@ async function runDoctor() {
385
436
  console.log('');
386
437
  }
387
438
 
388
- async function runChannels(args) {
389
- printHeader();
390
- console.log(c('yellow', '── İletişim Kanalları ──\n'));
439
+ async function runChannels(args) {
440
+ const sub = args[1]?.toLowerCase();
441
+ if (sub === 'login') {
442
+ printHeader();
443
+ console.log(c('yellow', '── WhatsApp Login ──\n'));
444
+
445
+ const openclawDir = path.join(os.homedir(), '.openclaw');
446
+ const configPath = path.join(openclawDir, 'openclaw.json');
447
+
448
+ if (!fs.existsSync(openclawDir)) {
449
+ fs.mkdirSync(openclawDir, { recursive: true });
450
+ }
451
+
452
+ const rawPhone = await promptInput('WhatsApp numaranız (E.164, örn: +905551112233): ');
453
+ const phone = normalizePhone(rawPhone);
454
+ if (!phone || phone === '+') {
455
+ console.log(c('red', 'Geçerli bir numara girilmedi.'));
456
+ process.exitCode = 2;
457
+ return;
458
+ }
459
+
460
+ const config = loadOpenclawConfig(configPath);
461
+ if (!config.channels) config.channels = {};
462
+ if (!config.channels.whatsapp) config.channels.whatsapp = {};
463
+
464
+ if (!config.channels.whatsapp.dmPolicy) {
465
+ config.channels.whatsapp.dmPolicy = 'allowlist';
466
+ }
467
+
468
+ const allowFrom = Array.isArray(config.channels.whatsapp.allowFrom)
469
+ ? config.channels.whatsapp.allowFrom
470
+ : [];
471
+ if (!allowFrom.includes(phone)) {
472
+ allowFrom.push(phone);
473
+ }
474
+ config.channels.whatsapp.allowFrom = allowFrom;
475
+
476
+ const saved = saveOpenclawConfig(configPath, config);
477
+ if (!saved) {
478
+ process.exitCode = 1;
479
+ return;
480
+ }
481
+
482
+ console.log(c('green', '✔ Gateway config güncellendi.'));
483
+ console.log(c('dim', 'Şimdi QR için login başlatılıyor...\n'));
484
+
485
+ try {
486
+ const { spawn } = await import('child_process');
487
+ const child = spawn('openclaw', ['channels', 'login'], {
488
+ stdio: 'inherit',
489
+ shell: true
490
+ });
491
+ await new Promise((resolve, reject) => {
492
+ child.on('exit', code => (code === 0 ? resolve() : reject(new Error(`gateway exit ${code}`))));
493
+ child.on('error', reject);
494
+ });
495
+ console.log(c('green', '\n✔ QR eşleştirme tamamlandı.'));
496
+ console.log(c('dim', 'Gateway başlatmak için: vantuz gateway run'));
497
+ } catch (e) {
498
+ console.log(c('red', `Login çalıştırılamadı: ${e.message}`));
499
+ }
500
+ return;
501
+ }
502
+
503
+ printHeader();
504
+ console.log(c('yellow', '── İletişim Kanalları ──\n'));
391
505
 
392
506
  const engine = await getEngine();
393
507
  const status = engine.getStatus();
@@ -459,10 +573,11 @@ async function main() {
459
573
  console.log(` ${c('cyan', 'vantuz status')} - Durum kontrolü`);
460
574
  console.log(` ${c('cyan', 'vantuz gateway')} - Gateway yönetimi`);
461
575
  console.log(` ${c('cyan', 'vantuz doctor')} - Sistem sağlık kontrolü`);
462
- console.log(` ${c('cyan', 'vantuz channels')} - İletişim kanalları`);
463
- console.log(` ${c('cyan', 'vantuz config')} - Ayarları göster/güncelle`);
576
+ console.log(` ${c('cyan', 'vantuz channels')} - İletişim kanalları`);
577
+ console.log(` ${c('cyan', 'vantuz channels login')} - WhatsApp QR login`);
578
+ console.log(` ${c('cyan', 'vantuz config')} - Ayarları göster/güncelle`);
464
579
  console.log(` ${c('cyan', 'vantuz logs')} - Logları göster`);
465
- console.log(`\nKurulum için: ${c('cyan', 'vantuz-onboard')}`);
580
+ console.log(`\nKurulum ve başlangıç ayarları için: ${c('cyan', 'vantuz config init')}`);
466
581
  process.exitCode = command ? 2 : 0;
467
582
  }
468
583
  }
package/core/agent.js ADDED
@@ -0,0 +1,82 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { exec } from 'child_process';
4
+ import https from 'https';
5
+ import http from 'http';
6
+
7
+ const DEFAULT_ALLOW_CMDS = [
8
+ 'dir', 'ls', 'rg', 'cat', 'type', 'node', 'npm', 'git', 'curl'
9
+ ];
10
+
11
+ function isAllowedCommand(command, allowList = []) {
12
+ const trimmed = String(command || '').trim();
13
+ if (!trimmed) return false;
14
+ const cmd = trimmed.split(/\s+/)[0].toLowerCase();
15
+ const allowed = allowList.length > 0 ? allowList : DEFAULT_ALLOW_CMDS;
16
+ return allowed.includes(cmd);
17
+ }
18
+
19
+ function runCommand(command, timeoutMs = 15000) {
20
+ return new Promise((resolve) => {
21
+ exec(command, { timeout: timeoutMs, windowsHide: true }, (err, stdout, stderr) => {
22
+ if (err) {
23
+ resolve({ success: false, output: stderr || err.message });
24
+ return;
25
+ }
26
+ resolve({ success: true, output: stdout || stderr || '' });
27
+ });
28
+ });
29
+ }
30
+
31
+ function readFileSafe(filePath, maxBytes = 200000) {
32
+ const resolved = path.resolve(filePath);
33
+ if (!fs.existsSync(resolved)) return { success: false, output: 'Dosya bulunamadı.' };
34
+ const stat = fs.statSync(resolved);
35
+ if (stat.size > maxBytes) return { success: false, output: 'Dosya çok büyük.' };
36
+ return { success: true, output: fs.readFileSync(resolved, 'utf-8') };
37
+ }
38
+
39
+ function listDirSafe(dirPath = '.') {
40
+ const resolved = path.resolve(dirPath);
41
+ if (!fs.existsSync(resolved)) return { success: false, output: 'Klasör bulunamadı.' };
42
+ const entries = fs.readdirSync(resolved, { withFileTypes: true })
43
+ .map(d => (d.isDirectory() ? `[D] ${d.name}` : `[F] ${d.name}`));
44
+ return { success: true, output: entries.join('\n') };
45
+ }
46
+
47
+ function httpGet(url, timeoutMs = 15000) {
48
+ return new Promise((resolve) => {
49
+ const lib = url.startsWith('https') ? https : http;
50
+ const req = lib.get(url, { timeout: timeoutMs }, (res) => {
51
+ let data = '';
52
+ res.on('data', chunk => data += chunk);
53
+ res.on('end', () => resolve({ success: true, output: data.slice(0, 200000) }));
54
+ });
55
+ req.on('error', (e) => resolve({ success: false, output: e.message }));
56
+ req.on('timeout', () => {
57
+ req.destroy();
58
+ resolve({ success: false, output: 'Timeout' });
59
+ });
60
+ });
61
+ }
62
+
63
+ export async function executeTool(tool, args = {}, config = {}) {
64
+ switch (tool) {
65
+ case 'exec': {
66
+ const command = args.command || '';
67
+ const allowList = config.agentAllowCommands || [];
68
+ if (!isAllowedCommand(command, allowList)) {
69
+ return { success: false, output: 'Komut izinli değil.' };
70
+ }
71
+ return await runCommand(command, config.agentCommandTimeoutMs || 15000);
72
+ }
73
+ case 'readFile':
74
+ return readFileSafe(args.path);
75
+ case 'listDir':
76
+ return listDirSafe(args.path);
77
+ case 'httpGet':
78
+ return await httpGet(args.url || '');
79
+ default:
80
+ return { success: false, output: 'Bilinmeyen araç.' };
81
+ }
82
+ }
@@ -10,7 +10,7 @@ import os from 'os';
10
10
 
11
11
  const LOG_FILE = path.join(os.homedir(), '.vantuz', 'vantuz.log');
12
12
 
13
- const PROVIDER_CONFIG = {
13
+ export const PROVIDER_CONFIG = {
14
14
  gemini: {
15
15
  url: (apiKey) => `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`,
16
16
  body: (systemPrompt, message) => ({
@@ -18,7 +18,11 @@ const PROVIDER_CONFIG = {
18
18
  }),
19
19
  headers: { 'Content-Type': 'application/json' },
20
20
  parseResponse: (data) => data?.candidates?.[0]?.content?.parts?.[0]?.text,
21
- errorMsg: 'Gemini yanıt vermedi'
21
+ errorMsg: 'Gemini yanıt vermedi',
22
+ config_label: 'Google Gemini',
23
+ config_description: 'Önerilen/Ücretsiz',
24
+ config_icon: '🔷',
25
+ envKey: 'GEMINI_API_KEY'
22
26
  },
23
27
  groq: {
24
28
  url: 'https://api.groq.com/openai/v1/chat/completions',
@@ -33,7 +37,11 @@ const PROVIDER_CONFIG = {
33
37
  }),
34
38
  headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
35
39
  parseResponse: (data) => data?.choices?.[0]?.message?.content,
36
- errorMsg: 'Groq yanıt vermedi'
40
+ errorMsg: 'Groq yanıt vermedi',
41
+ config_label: 'Groq',
42
+ config_description: 'Hızlı/Ücretsiz',
43
+ config_icon: '⚡',
44
+ envKey: 'GROQ_API_KEY'
37
45
  },
38
46
  openai: {
39
47
  url: 'https://api.openai.com/v1/chat/completions',
@@ -47,7 +55,11 @@ const PROVIDER_CONFIG = {
47
55
  }),
48
56
  headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
49
57
  parseResponse: (data) => data?.choices?.[0]?.message?.content,
50
- errorMsg: 'OpenAI yanıt vermedi'
58
+ errorMsg: 'OpenAI yanıt vermedi',
59
+ config_label: 'OpenAI GPT-4o',
60
+ config_description: 'Premium',
61
+ config_icon: '🟢',
62
+ envKey: 'OPENAI_API_KEY'
51
63
  },
52
64
  anthropic: {
53
65
  url: 'https://api.anthropic.com/v1/messages',
@@ -61,7 +73,11 @@ const PROVIDER_CONFIG = {
61
73
  }),
62
74
  headers: (apiKey) => ({ 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'Content-Type': 'application/json' }),
63
75
  parseResponse: (data) => data?.content?.[0]?.text,
64
- errorMsg: 'Anthropic yanıt vermedi'
76
+ errorMsg: 'Anthropic yanıt vermedi',
77
+ config_label: 'Anthropic Claude 3.5',
78
+ config_description: 'Advanced',
79
+ config_icon: '🟣',
80
+ envKey: 'ANTHROPIC_API_KEY'
65
81
  },
66
82
  deepseek: {
67
83
  url: 'https://api.deepseek.com/v1/chat/completions',
@@ -75,7 +91,11 @@ const PROVIDER_CONFIG = {
75
91
  }),
76
92
  headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
77
93
  parseResponse: (data) => data?.choices?.[0]?.message?.content,
78
- errorMsg: 'DeepSeek yanıt vermedi'
94
+ errorMsg: 'DeepSeek yanıt vermedi',
95
+ config_label: 'DeepSeek V3',
96
+ config_description: 'Fast',
97
+ config_icon: '🔵',
98
+ envKey: 'DEEPSEEK_API_KEY'
79
99
  }
80
100
  };
81
101