vantuz 3.4.1 β†’ 3.5.0

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.
Files changed (70) hide show
  1. package/LICENSE +45 -45
  2. package/admin-keygen.js +51 -0
  3. package/cli.js +685 -585
  4. package/config.js +733 -733
  5. package/core/agent-loop.js +190 -190
  6. package/core/ai-provider.js +298 -261
  7. package/core/automation.js +523 -523
  8. package/core/brand-analyst.js +101 -0
  9. package/core/channels.js +167 -167
  10. package/core/dashboard.js +230 -230
  11. package/core/database.js +135 -36
  12. package/core/eia-monitor.js +3 -1
  13. package/core/engine.js +648 -636
  14. package/core/gateway.js +447 -447
  15. package/core/learning.js +214 -214
  16. package/core/license.js +113 -0
  17. package/core/marketplace-adapter.js +168 -168
  18. package/core/memory.js +190 -190
  19. package/core/migrations/001-initial-schema.sql +1 -1
  20. package/core/queue.js +120 -120
  21. package/core/self-healer.js +314 -314
  22. package/core/unified-product.js +214 -214
  23. package/core/vision-service.js +113 -113
  24. package/index.js +217 -174
  25. package/modules/crm/sentiment-crm.js +231 -231
  26. package/modules/healer/listing-healer.js +201 -201
  27. package/modules/oracle/predictor.js +214 -214
  28. package/modules/researcher/agent.js +169 -169
  29. package/modules/team/agents/base.js +92 -92
  30. package/modules/team/agents/dev.js +33 -33
  31. package/modules/team/agents/josh.js +40 -40
  32. package/modules/team/agents/marketing.js +33 -33
  33. package/modules/team/agents/milo.js +36 -36
  34. package/modules/team/index.js +78 -78
  35. package/modules/team/shared-memory.js +87 -87
  36. package/modules/war-room/competitor-tracker.js +250 -250
  37. package/modules/war-room/pricing-engine.js +308 -308
  38. package/nodes/warehouse.js +238 -238
  39. package/onboard.js +1 -1
  40. package/package.json +7 -6
  41. package/platforms/pttavm.js +14 -14
  42. package/plugins/vantuz/index.js +528 -528
  43. package/plugins/vantuz/memory/hippocampus.js +465 -464
  44. package/plugins/vantuz/package.json +20 -20
  45. package/plugins/vantuz/platforms/_template.js +118 -118
  46. package/plugins/vantuz/platforms/amazon.js +236 -236
  47. package/plugins/vantuz/platforms/ciceksepeti.js +166 -166
  48. package/plugins/vantuz/platforms/hepsiburada.js +180 -180
  49. package/plugins/vantuz/platforms/index.js +165 -165
  50. package/plugins/vantuz/platforms/n11.js +229 -229
  51. package/plugins/vantuz/platforms/pazarama.js +154 -154
  52. package/plugins/vantuz/platforms/pttavm.js +127 -127
  53. package/plugins/vantuz/platforms/trendyol.js +326 -326
  54. package/plugins/vantuz/services/alerts.js +253 -253
  55. package/plugins/vantuz/services/license.js +34 -34
  56. package/plugins/vantuz/services/scheduler.js +232 -232
  57. package/plugins/vantuz/tools/analytics.js +152 -152
  58. package/plugins/vantuz/tools/crossborder.js +187 -187
  59. package/plugins/vantuz/tools/nl-parser.js +211 -211
  60. package/plugins/vantuz/tools/product.js +110 -110
  61. package/plugins/vantuz/tools/quick-report.js +175 -175
  62. package/plugins/vantuz/tools/repricer.js +314 -314
  63. package/plugins/vantuz/tools/sentiment.js +115 -115
  64. package/plugins/vantuz/tools/vision.js +257 -257
  65. package/private.pem +28 -0
  66. package/public.pem +9 -0
  67. package/server/app.js +260 -260
  68. package/server/public/index.html +514 -514
  69. package/start.bat +33 -33
  70. package/vantuz.sqlite +0 -0
package/cli.js CHANGED
@@ -1,585 +1,685 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * πŸ™ VANTUZ CLI v3.2
5
- * Vantuz Gateway entegrasyonlu komut satΔ±rΔ± arayΓΌzΓΌ
6
- */
7
-
8
- import path from 'path';
9
- import os from 'os';
10
- import fs from 'fs';
11
- import readline from 'readline';
12
- import { log, getLogs, clearLogs } from './core/ai-provider.js';
13
- import { getEngine } from './core/engine.js';
14
- import { getGateway } from './core/gateway.js';
15
- import { Configurator } from './config.js'; // Import the new Configurator
16
-
17
- // ═══════════════════════════════════════════════════════════════════════════
18
- // CONFIG
19
- // ═══════════════════════════════════════════════════════════════════════════
20
-
21
- const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
22
- const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
23
- const CONFIG_JSON = path.join(VANTUZ_HOME, 'config.json');
24
-
25
- if (!fs.existsSync(VANTUZ_HOME)) {
26
- fs.mkdirSync(VANTUZ_HOME, { recursive: true });
27
- }
28
-
29
- // ═══════════════════════════════════════════════════════════════════════════
30
- // HELPERS
31
- // ═══════════════════════════════════════════════════════════════════════════
32
-
33
- const colors = {
34
- reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
35
- red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
36
- cyan: '\x1b[36m', blue: '\x1b[34m', magenta: '\x1b[35m'
37
- };
38
- const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
39
-
40
- function loadEnv() {
41
- const env = {};
42
- try {
43
- if (fs.existsSync(CONFIG_PATH)) {
44
- const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
45
- content.split('\n').forEach(line => {
46
- const match = line.match(/^([^=]+)=(.*)$/);
47
- if (match) env[match[1].trim()] = match[2].trim();
48
- });
49
- }
50
- } catch (e) { }
51
- return env;
52
- }
53
-
54
- function loadConfigJson() {
55
- try {
56
- if (fs.existsSync(CONFIG_JSON)) {
57
- return JSON.parse(fs.readFileSync(CONFIG_JSON, 'utf-8'));
58
- }
59
- } catch (e) {
60
- console.log(c('red', `Config okunamadΔ±: ${e.message}`));
61
- }
62
- return {};
63
- }
64
-
65
- function saveConfigJson(config) {
66
- try {
67
- fs.writeFileSync(CONFIG_JSON, JSON.stringify(config, null, 2));
68
- return true;
69
- } catch (e) {
70
- console.log(c('red', `Config yazΔ±lamadΔ±: ${e.message}`));
71
- return false;
72
- }
73
- }
74
-
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
-
113
- function printHeader() {
114
- const version = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf-8')).version;
115
- console.log(c('cyan', `
116
- β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
117
- β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ–ˆβ•”β•
118
- β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β•
119
- β•šβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β•
120
- β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
121
- β•šβ•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•
122
- `));
123
- console.log(c('magenta', ` Enterprise E-Commerce Management System v${version}`));
124
- console.log(c('dim', ' Powered by nca'));
125
- console.log(c('dim', ' ----------------------------------------------------------\n'));
126
- }
127
-
128
- async function showSpinner(text, duration = 1000) {
129
- const frames = ['β ‹', 'β ™', 'β Ή', 'β Έ', 'β Ό', 'β ΄', 'β ¦', 'β §', 'β ‡', '⠏'];
130
- let i = 0;
131
- const interval = setInterval(() => {
132
- process.stdout.write(`\r${c('cyan', frames[i])} ${text}...`);
133
- i = (i + 1) % frames.length;
134
- }, 80);
135
- await new Promise(r => setTimeout(r, duration));
136
- clearInterval(interval);
137
- process.stdout.write(`\r${c('green', 'βœ”')} ${text} TamamlandΔ±\n`);
138
- }
139
-
140
- // ═══════════════════════════════════════════════════════════════════════════
141
- // COMMANDS
142
- // ═══════════════════════════════════════════════════════════════════════════
143
-
144
- async function runTUI() {
145
- clearScreen();
146
- printHeader();
147
-
148
- await showSpinner('Sistem çekirdeği yükleniyor', 500);
149
- await showSpinner('Vantuz Gateway kontrol ediliyor', 400);
150
- await showSpinner('Pazaryeri bağlantıları kontrol ediliyor', 800);
151
-
152
- const engine = await getEngine();
153
- const status = engine.getStatus();
154
-
155
- // Gateway durumu
156
- if (status.gateway?.connected) {
157
- console.log(`${c('green', '●')} Vantuz Gateway ${c('green', 'BağlΔ±')} ${c('dim', `(${status.gateway.url})`)}`);
158
- } else {
159
- console.log(`${c('yellow', 'β—‹')} Vantuz Gateway ${c('yellow', 'BağlΔ± Değil')} ${c('dim', '(direkt mod)')}`);
160
- }
161
-
162
- console.log(`${c('green', '●')} Sistem Aktif ${c('dim', `(${status.connectedCount}/${status.totalPlatforms} Platform BağlΔ±)`)}`);
163
- console.log(`${c('blue', 'β„Ή')} AI SağlayΔ±cΔ±: ${c('bold', status.aiProvider || 'Gemini')}`);
164
- console.log(`${c('yellow', '⚑')} Komutlar: ${c('cyan', '/stok, /siparis, /rapor, /analiz, /durum, /temizle, /exit')}\n`);
165
-
166
- const rl = readline.createInterface({
167
- input: process.stdin,
168
- output: process.stdout,
169
- prompt: c('magenta', 'Vantuz> ')
170
- });
171
-
172
- rl.prompt();
173
-
174
- rl.on('line', async (line) => {
175
- const input = line.trim();
176
- if (input === '/exit') process.exit(0);
177
- if (input === '/temizle') {
178
- clearScreen();
179
- printHeader();
180
- rl.prompt();
181
- return;
182
- }
183
-
184
- if (input) {
185
- try {
186
- if (input.startsWith('/')) {
187
- const [cmd, ...cmdArgs] = input.split(' ');
188
- switch (cmd) {
189
- case '/help':
190
- console.log(c('yellow', '\nKullanΔ±labilir Komutlar:'));
191
- console.log(` ${c('cyan', '/stok')} - TΓΌm pazaryerlerindeki stok durumunu gΓΆsterir`);
192
- console.log(` ${c('cyan', '/siparis')} - Son siparişleri listeler`);
193
- console.log(` ${c('cyan', '/durum')} - Sistem durumunu gΓΆsterir`);
194
- console.log(` ${c('cyan', '/temizle')} - EkranΔ± temizler`);
195
- console.log(` ${c('cyan', '/exit')} - Γ‡Δ±kış\n`);
196
- 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;
233
- case '/durum':
234
- const s = engine.getStatus();
235
- console.log(c('yellow', '\n── Sistem Durumu ──'));
236
- console.log(` Engine: ${s.engine === 'active' ? c('green', '● Aktif') : c('red', 'β—‹ Pasif')}`);
237
- console.log(` Gateway: ${s.gateway?.connected ? c('green', '● BağlΔ±') : c('yellow', 'β—‹ BağlΔ± Değil')}`);
238
- console.log(` AI: ${c('cyan', s.aiProvider || 'gemini')}`);
239
- console.log(` Platformlar: ${c('bold', `${s.connectedCount}/${s.totalPlatforms}`)}`);
240
- console.log('');
241
- break;
242
- default:
243
- console.log(c('red', `[HATA] Bilinmeyen komut: ${cmd}. /help yazΔ±n.`));
244
- }
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
- }
251
- } catch (e) {
252
- console.log(c('red', `\n[HATA] ${e.message}`));
253
- }
254
- }
255
- rl.prompt();
256
- });
257
- }
258
-
259
- async function runConfig(args) {
260
- const sub = args[1]?.toLowerCase();
261
- const config = loadConfigJson(); // config.json operations
262
-
263
- if (sub === 'init') {
264
- const configurator = new Configurator();
265
- await configurator.run();
266
- return;
267
- }
268
-
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
276
- printHeader();
277
- if (args[2]) {
278
- const key = args[2];
279
- const value = config?.[key];
280
- console.log(value === undefined ? '' : String(value));
281
- return;
282
- }
283
- console.log(JSON.stringify(config, null, 2));
284
- return;
285
- }
286
-
287
- if (sub === 'set') {
288
- const key = args[2];
289
- const value = args.slice(3).join(' ');
290
- if (!key) {
291
- console.log(c('red', 'KullanΔ±m: vantuz config set <key> <value>'));
292
- process.exitCode = 2;
293
- return;
294
- }
295
- config[key] = value;
296
- const ok = saveConfigJson(config);
297
- if (ok) {
298
- console.log(c('green', '[OK] Config gΓΌncellendi'));
299
- } else {
300
- process.exitCode = 1;
301
- }
302
- return;
303
- }
304
-
305
- console.log(c('red', 'GeΓ§ersiz config komutu. KullanΔ±m: vantuz config [init | get [key] | set <key> <value>]'));
306
- process.exitCode = 2;
307
- }
308
-
309
- async function runLogs(args) {
310
- const sub = args[1]?.toLowerCase();
311
- if (sub === 'clear' || sub === 'temizle') {
312
- const ok = clearLogs();
313
- if (ok) console.log(c('green', '[OK] Loglar temizlendi'));
314
- else {
315
- console.log(c('red', '[HATA] Loglar temizlenemedi'));
316
- process.exitCode = 1;
317
- }
318
- return;
319
- }
320
-
321
- const nRaw = args[1];
322
- const n = nRaw && /^\d+$/.test(nRaw) ? Number(nRaw) : 50;
323
- printHeader();
324
- console.log(getLogs(n));
325
- }
326
-
327
- async function runGateway(args) {
328
- const sub = args[1]?.toLowerCase();
329
- const gw = await getGateway();
330
- const info = gw.getInfo();
331
-
332
- if (!sub || sub === 'status') {
333
- printHeader();
334
- console.log(c('yellow', '── Vantuz Gateway ──\n'));
335
- console.log(` URL: ${c('cyan', info.url)}`);
336
- console.log(` Durum: ${info.connected ? c('green', '● BağlΔ±') : c('red', 'β—‹ BağlΔ± Değil')}`);
337
- console.log(` Token: ${info.hasToken ? c('green', 'βœ” YapΔ±landΔ±rΔ±lmış') : c('yellow', '✘ Eksik')}`);
338
- console.log(` Config: ${info.configFound ? c('green', 'βœ” Bulundu') : c('yellow', '✘ BulunamadΔ±')}`);
339
- if (info.version) console.log(` SΓΌrΓΌm: ${c('dim', info.version)}`);
340
- console.log('');
341
-
342
- if (!info.connected) {
343
- console.log(c('dim', ' Gateway başlatmak için: vantuz gateway run'));
344
- console.log(c('dim', ' Veya: start.bat\n'));
345
- }
346
- return;
347
- }
348
-
349
- if (sub === 'health') {
350
- const result = await gw.health();
351
- if (result.success) {
352
- console.log(c('green', 'βœ” Gateway sağlΔ±klΔ±'));
353
- if (result.data) console.log(JSON.stringify(result.data, null, 2));
354
- } else {
355
- console.log(c('red', `✘ Gateway erişilemez: ${result.error}`));
356
- }
357
- return;
358
- }
359
-
360
- if (sub === 'models') {
361
- const result = await gw.getModels();
362
- if (result.success) {
363
- console.log(c('yellow', '── AI Modelleri ──\n'));
364
- const models = result.data?.data || result.data || [];
365
- if (Array.isArray(models)) {
366
- models.forEach(m => {
367
- console.log(` ${c('cyan', m.id || m.name)} ${c('dim', m.description || '')}`);
368
- });
369
- } else {
370
- console.log(JSON.stringify(models, null, 2));
371
- }
372
- } else {
373
- console.log(c('red', `Modeller alΔ±namadΔ±: ${result.error}`));
374
- }
375
- return;
376
- }
377
-
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
- }
390
-
391
- console.log(c('red', 'KullanΔ±m: vantuz gateway [status|health|models|run]'));
392
- }
393
-
394
- async function runDoctor() {
395
- printHeader();
396
- console.log(c('yellow', '── Sistem SağlΔ±k KontrolΓΌ ──\n'));
397
-
398
- await showSpinner('Kontroller yapΔ±lΔ±yor', 800);
399
-
400
- const engine = await getEngine();
401
- const report = await engine.doctor();
402
-
403
- // Engine
404
- console.log(` Engine: ${report.engine ? c('green', '● Aktif') : c('red', 'β—‹ Pasif')}`);
405
-
406
- // Gateway
407
- const gw = report.gateway;
408
- const gwIcon = gw.status === 'healthy' ? c('green', '●') :
409
- gw.status === 'not_configured' ? c('yellow', 'β—‹') : c('red', 'β—‹');
410
- console.log(` Gateway: ${gwIcon} ${gw.status === 'healthy' ? 'Sağlıklı' : gw.status === 'not_configured' ? 'Yapılandırılmamış' : 'Erişilemez'}`);
411
-
412
- // AI
413
- const ai = report.ai;
414
- console.log(` AI: ${c('cyan', ai.provider)} ${ai.keyConfigured ? c('green', 'βœ” Key OK') : c('red', '✘ Key Eksik')} ${ai.gatewayFallback ? c('dim', '(gateway fallback var)') : ''}`);
415
-
416
- // Platformlar
417
- const platformEntries = Object.entries(report.platforms).filter(([k]) => k !== 'openclaw-gateway');
418
- if (platformEntries.length > 0) {
419
- console.log(`\n ${c('bold', 'Platformlar:')}`);
420
- platformEntries.forEach(([name, connected]) => {
421
- console.log(` ${connected ? c('green', '●') : c('red', 'β—‹')} ${name}`);
422
- });
423
- } else {
424
- console.log(` Platformlar: ${c('yellow', 'Hiçbiri bağlı değil')}`);
425
- }
426
-
427
- // Kanallar
428
- const ch = report.channels;
429
- if (ch) {
430
- console.log(`\n ${c('bold', 'Kanallar:')}`);
431
- for (const [name, data] of Object.entries(ch)) {
432
- console.log(` ${data.connected ? c('green', '●') : c('yellow', 'β—‹')} ${name}: ${data.info || ''}`);
433
- }
434
- }
435
-
436
- console.log('');
437
- }
438
-
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'));
505
-
506
- const engine = await getEngine();
507
- const status = engine.getStatus();
508
- const channels = status.channels || {};
509
-
510
- for (const [name, data] of Object.entries(channels)) {
511
- const icon = data.connected ? c('green', '●') : c('yellow', 'β—‹');
512
- const mode = data.mode === 'gateway' ? c('dim', '[gateway]') : c('dim', '[local]');
513
- console.log(` ${icon} ${c('bold', name.toUpperCase())} ${mode}`);
514
- if (data.info) console.log(` ${c('dim', data.info)}`);
515
- console.log('');
516
- }
517
-
518
- if (!status.gateway?.connected) {
519
- console.log(c('dim', ' WhatsApp bağlantısı için gateway gereklidir.'));
520
- console.log(c('dim', ' Gateway başlatmak için: start.bat\n'));
521
- }
522
- }
523
-
524
- // ═══════════════════════════════════════════════════════════════════════════
525
- // MAIN
526
- // ═══════════════════════════════════════════════════════════════════════════
527
-
528
- const args = process.argv.slice(2);
529
- const command = args[0]?.toLowerCase();
530
-
531
- async function main() {
532
- switch (command) {
533
- case 'tui':
534
- case 'chat':
535
- await runTUI();
536
- break;
537
-
538
- case 'config':
539
- await runConfig(args);
540
- break;
541
-
542
- case 'logs':
543
- await runLogs(args);
544
- break;
545
-
546
- case 'gateway':
547
- case 'gw':
548
- await runGateway(args);
549
- break;
550
-
551
- case 'doctor':
552
- case 'check':
553
- await runDoctor();
554
- break;
555
-
556
- case 'channels':
557
- case 'ch':
558
- await runChannels(args);
559
- break;
560
-
561
- case 'status':
562
- printHeader();
563
- console.log(`Lisans Durumu: ${c('green', 'Aktif (Dev Mode)')}`);
564
- const gw = await getGateway();
565
- const gwInfo = gw.getInfo();
566
- console.log(`Vantuz Gateway: ${gwInfo.connected ? c('green', '● BağlΔ±') : c('yellow', 'β—‹ BağlΔ± Değil')}`);
567
- break;
568
-
569
- default:
570
- printHeader();
571
- console.log('KullanΔ±m:\n');
572
- console.log(` ${c('cyan', 'vantuz tui')} - Sohbet arayΓΌzΓΌ`);
573
- console.log(` ${c('cyan', 'vantuz status')} - Durum kontrolΓΌ`);
574
- console.log(` ${c('cyan', 'vantuz gateway')} - Gateway yΓΆnetimi`);
575
- console.log(` ${c('cyan', 'vantuz doctor')} - Sistem sağlık kontrolü`);
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`);
579
- console.log(` ${c('cyan', 'vantuz logs')} - LoglarΔ± gΓΆster`);
580
- console.log(`\nKurulum ve başlangıç ayarları için: ${c('cyan', 'vantuz config init')}`);
581
- process.exitCode = command ? 2 : 0;
582
- }
583
- }
584
-
585
- main();
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * πŸ™ VANTUZ CLI v3.2
5
+ * Vantuz Gateway entegrasyonlu komut satΔ±rΔ± arayΓΌzΓΌ
6
+ */
7
+
8
+ import path from 'path';
9
+ import os from 'os';
10
+ import fs from 'fs';
11
+ import readline from 'readline';
12
+ import { log, getLogs, clearLogs } from './core/ai-provider.js';
13
+ import { getEngine } from './core/engine.js';
14
+ import { getGateway } from './core/gateway.js';
15
+ import { licenseManager } from './core/license.js'; // Lisans yΓΆneticisi
16
+ import { Configurator } from './config.js'; // Import the new Configurator
17
+
18
+ // ═══════════════════════════════════════════════════════════════════════════
19
+ // CONFIG
20
+ // ═══════════════════════════════════════════════════════════════════════════
21
+
22
+ const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
23
+ const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
24
+ const CONFIG_JSON = path.join(VANTUZ_HOME, 'config.json');
25
+
26
+ if (!fs.existsSync(VANTUZ_HOME)) {
27
+ fs.mkdirSync(VANTUZ_HOME, { recursive: true });
28
+ }
29
+
30
+ // ═══════════════════════════════════════════════════════════════════════════
31
+ // HELPERS
32
+ // ═══════════════════════════════════════════════════════════════════════════
33
+
34
+ const colors = {
35
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
36
+ red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
37
+ cyan: '\x1b[36m', blue: '\x1b[34m', magenta: '\x1b[35m'
38
+ };
39
+ const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
40
+
41
+ function loadEnv() {
42
+ const env = {};
43
+ try {
44
+ if (fs.existsSync(CONFIG_PATH)) {
45
+ const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
46
+ content.split('\n').forEach(line => {
47
+ const match = line.match(/^([^=]+)=(.*)$/);
48
+ if (match) env[match[1].trim()] = match[2].trim();
49
+ });
50
+ }
51
+ } catch (e) { }
52
+ return env;
53
+ }
54
+
55
+ function loadConfigJson() {
56
+ try {
57
+ if (fs.existsSync(CONFIG_JSON)) {
58
+ return JSON.parse(fs.readFileSync(CONFIG_JSON, 'utf-8'));
59
+ }
60
+ } catch (e) {
61
+ console.log(c('red', `Config okunamadΔ±: ${e.message}`));
62
+ }
63
+ return {};
64
+ }
65
+
66
+ function saveConfigJson(config) {
67
+ try {
68
+ fs.writeFileSync(CONFIG_JSON, JSON.stringify(config, null, 2));
69
+ return true;
70
+ } catch (e) {
71
+ console.log(c('red', `Config yazΔ±lamadΔ±: ${e.message}`));
72
+ return false;
73
+ }
74
+ }
75
+
76
+ function clearScreen() {
77
+ process.stdout.write('\x1Bc');
78
+ }
79
+
80
+ async function promptInput(question) {
81
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
82
+ const answer = await new Promise(resolve => rl.question(question, resolve));
83
+ rl.close();
84
+ return answer.trim();
85
+ }
86
+
87
+ function normalizePhone(input) {
88
+ if (!input) return '';
89
+ const cleaned = input.replace(/[\s-]/g, '');
90
+ return cleaned.startsWith('+') ? cleaned : `+${cleaned}`;
91
+ }
92
+
93
+ function loadOpenclawConfig(configPath) {
94
+ try {
95
+ if (fs.existsSync(configPath)) {
96
+ return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
97
+ }
98
+ } catch (e) {
99
+ console.log(c('red', `Gateway config okunamadΔ±: ${e.message}`));
100
+ }
101
+ return {};
102
+ }
103
+
104
+ function saveOpenclawConfig(configPath, config) {
105
+ try {
106
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
107
+ return true;
108
+ } catch (e) {
109
+ console.log(c('red', `Gateway config yazΔ±lamadΔ±: ${e.message}`));
110
+ return false;
111
+ }
112
+ }
113
+
114
+ function printHeader() {
115
+ const version = JSON.parse(fs.readFileSync(new URL('./package.json', import.meta.url), 'utf-8')).version;
116
+ console.log(c('cyan', `
117
+ β–ˆβ–ˆβ•— β–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•— β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
118
+ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ–ˆβ•”β•
119
+ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β•
120
+ β•šβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ–ˆβ•”β•
121
+ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
122
+ β•šβ•β•β•β• β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β• β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•β•β•β•β•β•
123
+ `));
124
+ console.log(c('magenta', ` Enterprise E-Commerce Management System v${version}`));
125
+ console.log(c('dim', ' Powered by nca'));
126
+ console.log(c('dim', ' ----------------------------------------------------------\n'));
127
+ }
128
+
129
+ async function showSpinner(text, duration = 1000) {
130
+ const frames = ['β ‹', 'β ™', 'β Ή', 'β Έ', 'β Ό', 'β ΄', 'β ¦', 'β §', 'β ‡', '⠏'];
131
+ let i = 0;
132
+ const interval = setInterval(() => {
133
+ process.stdout.write(`\r${c('cyan', frames[i])} ${text}...`);
134
+ i = (i + 1) % frames.length;
135
+ }, 80);
136
+ await new Promise(r => setTimeout(r, duration));
137
+ clearInterval(interval);
138
+ process.stdout.write(`\r${c('green', 'βœ”')} ${text} TamamlandΔ±\n`);
139
+ }
140
+
141
+ // ═══════════════════════════════════════════════════════════════════════════
142
+ // COMMANDS
143
+ // ═══════════════════════════════════════════════════════════════════════════
144
+
145
+ async function runTUI() {
146
+ clearScreen();
147
+ printHeader();
148
+
149
+ // Lisans KontrolΓΌ
150
+ const license = licenseManager.check();
151
+ if (!license.valid) {
152
+ console.log(c('red', `\nπŸ›‘ ERİŞİM ENGELLENDΔ°: ${license.message}`));
153
+ console.log(c('yellow', 'LΓΌtfen geΓ§erli bir lisans anahtarΔ± girin.'));
154
+
155
+ const key = await promptInput(c('cyan', 'Lisans AnahtarΔ± (VTZ-XXXX): '));
156
+ const result = licenseManager.activate(key);
157
+
158
+ if (!result.success) {
159
+ console.log(c('red', `Hata: ${result.message}`));
160
+ process.exit(1);
161
+ }
162
+ console.log(c('green', `βœ” ${result.message}`));
163
+ await new Promise(r => setTimeout(r, 1000));
164
+ clearScreen();
165
+ printHeader();
166
+ }
167
+
168
+ await showSpinner('Sistem çekirdeği yükleniyor', 500);
169
+ await showSpinner('Vantuz Gateway kontrol ediliyor', 400);
170
+ await showSpinner('Pazaryeri bağlantıları kontrol ediliyor', 800);
171
+
172
+ const engine = await getEngine();
173
+ const status = engine.getStatus();
174
+
175
+ // Gateway durumu
176
+ if (status.gateway?.connected) {
177
+ console.log(`${c('green', '●')} Vantuz Gateway ${c('green', 'BağlΔ±')} ${c('dim', `(${status.gateway.url})`)}`);
178
+ } else {
179
+ console.log(`${c('yellow', 'β—‹')} Vantuz Gateway ${c('yellow', 'BağlΔ± Değil')} ${c('dim', '(direkt mod)')}`);
180
+ }
181
+
182
+ console.log(`${c('green', '●')} Sistem Aktif ${c('dim', `(${status.connectedCount}/${status.totalPlatforms} Platform BağlΔ±)`)}`);
183
+ console.log(`${c('blue', 'β„Ή')} AI SağlayΔ±cΔ±: ${c('bold', status.aiProvider || 'Gemini')}`);
184
+ console.log(`${c('yellow', '⚑')} Komutlar: ${c('cyan', '/stok, /siparis, /rapor, /analiz, /durum, /temizle, /exit')}\n`);
185
+
186
+ const rl = readline.createInterface({
187
+ input: process.stdin,
188
+ output: process.stdout,
189
+ prompt: c('magenta', 'Vantuz> ')
190
+ });
191
+
192
+ rl.prompt();
193
+
194
+ rl.on('line', async (line) => {
195
+ const input = line.trim();
196
+ if (input === '/exit') process.exit(0);
197
+ if (input === '/temizle') {
198
+ clearScreen();
199
+ printHeader();
200
+ rl.prompt();
201
+ return;
202
+ }
203
+
204
+ if (input) {
205
+ try {
206
+ if (input.startsWith('/')) {
207
+ const [cmd, ...cmdArgs] = input.split(' ');
208
+ switch (cmd) {
209
+ case '/help':
210
+ console.log(c('yellow', '\nKullanΔ±labilir Komutlar:'));
211
+ console.log(` ${c('cyan', '/stok')} - TΓΌm pazaryerlerindeki stok durumunu gΓΆsterir`);
212
+ console.log(` ${c('cyan', '/siparis')} - Son siparişleri listeler`);
213
+ console.log(` ${c('cyan', '/durum')} - Sistem durumunu gΓΆsterir`);
214
+ console.log(` ${c('cyan', '/temizle')} - EkranΔ± temizler`);
215
+ console.log(` ${c('cyan', '/exit')} - Γ‡Δ±kış\n`);
216
+ break;
217
+ case '/stok':
218
+ console.log(c('dim', 'Stok verileri Γ§ekiliyor...'));
219
+ const stocks = await engine.getStock();
220
+ if (stocks.length === 0) console.log(c('yellow', 'Bağlı platform bulunamadı.'));
221
+ stocks.forEach(s => {
222
+ console.log(`\n${s.icon} ${c('bold', s.platform.toUpperCase())}`);
223
+ s.products.slice(0, 5).forEach(p => {
224
+ console.log(` - ${p.title}: ${c('green', p.stock)} Adet | ${c('yellow', p.price)} TL`);
225
+ });
226
+ });
227
+ break;
228
+ case '/analiz':
229
+ process.stdout.write(c('dim', 'Analiz hazΔ±rlanΔ±yor... '));
230
+ const analysis = await engine.chat('satış ve stok analiz raporu hazırla');
231
+ process.stdout.write('\r' + ' '.repeat(30) + '\r');
232
+ console.log(`\n${analysis}\n`);
233
+ break;
234
+ case '/siparis':
235
+ console.log(c('dim', 'Siparişler çekiliyor...'));
236
+ const orders = await engine.getOrders({ size: 50, allStatuses: true });
237
+ const activeOrders = Array.isArray(orders)
238
+ ? orders.filter(o => ['Created', 'Picking', 'UnPacked'].includes(String(o.status || o.shipmentPackageStatus || o.orderStatus)))
239
+ : [];
240
+ const visible = activeOrders.slice(0, 5);
241
+ if (!Array.isArray(orders) || visible.length === 0) {
242
+ console.log(c('yellow', 'Son sipariş bulunamadı.'));
243
+ break;
244
+ }
245
+ visible.forEach(o => {
246
+ const names = Array.isArray(o.lines)
247
+ ? o.lines.map(l => l?.productName || l?.name).filter(Boolean)
248
+ : [];
249
+ const namePart = names.length > 0 ? ` | ${names.join(', ')}` : '';
250
+ 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}`);
251
+ });
252
+ break;
253
+ case '/durum':
254
+ const s = engine.getStatus();
255
+ console.log(c('yellow', '\n── Sistem Durumu ──'));
256
+ console.log(` Engine: ${s.engine === 'active' ? c('green', '● Aktif') : c('red', 'β—‹ Pasif')}`);
257
+ console.log(` Gateway: ${s.gateway?.connected ? c('green', '● BağlΔ±') : c('yellow', 'β—‹ BağlΔ± Değil')}`);
258
+ console.log(` AI: ${c('cyan', s.aiProvider || 'gemini')}`);
259
+ console.log(` Platformlar: ${c('bold', `${s.connectedCount}/${s.totalPlatforms}`)}`);
260
+ console.log('');
261
+ break;
262
+ default:
263
+ console.log(c('red', `[HATA] Bilinmeyen komut: ${cmd}. /help yazΔ±n.`));
264
+ }
265
+ } else {
266
+ process.stdout.write(c('dim', 'Düşünüyor... '));
267
+ const response = await engine.handleMessage(input, { channel: 'local', from: 'local' });
268
+ process.stdout.write('\r' + ' '.repeat(20) + '\r');
269
+ console.log(`\n${c('cyan', 'πŸ™ Vantuz:')}\n${response}\n`);
270
+ }
271
+ } catch (e) {
272
+ console.log(c('red', `\n[HATA] ${e.message}`));
273
+ }
274
+ }
275
+ rl.prompt();
276
+ });
277
+ }
278
+
279
+ async function runConfig(args) {
280
+ const sub = args[1]?.toLowerCase();
281
+ const config = loadConfigJson(); // config.json operations
282
+
283
+ if (sub === 'init') {
284
+ const configurator = new Configurator();
285
+ await configurator.run();
286
+ return;
287
+ }
288
+
289
+ if (sub === 'init' || !sub) { // If sub is 'init' OR no sub-command is provided
290
+ const configurator = new Configurator();
291
+ await configurator.run();
292
+ return; // IMPORTANT: Return after running the configurator
293
+ }
294
+
295
+ if (sub === 'get') { // Handle 'get' sub-command
296
+ printHeader();
297
+ if (args[2]) {
298
+ const key = args[2];
299
+ const value = config?.[key];
300
+ console.log(value === undefined ? '' : String(value));
301
+ return;
302
+ }
303
+ console.log(JSON.stringify(config, null, 2));
304
+ return;
305
+ }
306
+
307
+ if (sub === 'set') {
308
+ const key = args[2];
309
+ const value = args.slice(3).join(' ');
310
+ if (!key) {
311
+ console.log(c('red', 'KullanΔ±m: vantuz config set <key> <value>'));
312
+ process.exitCode = 2;
313
+ return;
314
+ }
315
+ config[key] = value;
316
+ const ok = saveConfigJson(config);
317
+ if (ok) {
318
+ console.log(c('green', '[OK] Config gΓΌncellendi'));
319
+ } else {
320
+ process.exitCode = 1;
321
+ }
322
+ return;
323
+ }
324
+
325
+ console.log(c('red', 'GeΓ§ersiz config komutu. KullanΔ±m: vantuz config [init | get [key] | set <key> <value>]'));
326
+ process.exitCode = 2;
327
+ }
328
+
329
+ async function runLogs(args) {
330
+ const sub = args[1]?.toLowerCase();
331
+ if (sub === 'clear' || sub === 'temizle') {
332
+ const ok = clearLogs();
333
+ if (ok) console.log(c('green', '[OK] Loglar temizlendi'));
334
+ else {
335
+ console.log(c('red', '[HATA] Loglar temizlenemedi'));
336
+ process.exitCode = 1;
337
+ }
338
+ return;
339
+ }
340
+
341
+ const nRaw = args[1];
342
+ const n = nRaw && /^\d+$/.test(nRaw) ? Number(nRaw) : 50;
343
+ printHeader();
344
+ console.log(getLogs(n));
345
+ }
346
+
347
+ async function runGateway(args) {
348
+ const sub = args[1]?.toLowerCase();
349
+ const gw = await getGateway();
350
+ const info = gw.getInfo();
351
+
352
+ if (!sub || sub === 'status') {
353
+ printHeader();
354
+ console.log(c('yellow', '── Vantuz Gateway ──\n'));
355
+ console.log(` URL: ${c('cyan', info.url)}`);
356
+ console.log(` Durum: ${info.connected ? c('green', '● BağlΔ±') : c('red', 'β—‹ BağlΔ± Değil')}`);
357
+ console.log(` Token: ${info.hasToken ? c('green', 'βœ” YapΔ±landΔ±rΔ±lmış') : c('yellow', '✘ Eksik')}`);
358
+ console.log(` Config: ${info.configFound ? c('green', 'βœ” Bulundu') : c('yellow', '✘ BulunamadΔ±')}`);
359
+ if (info.version) console.log(` SΓΌrΓΌm: ${c('dim', info.version)}`);
360
+ console.log('');
361
+
362
+ if (!info.connected) {
363
+ console.log(c('dim', ' Gateway başlatmak için: vantuz gateway run'));
364
+ console.log(c('dim', ' Veya: start.bat\n'));
365
+ }
366
+ return;
367
+ }
368
+
369
+ if (sub === 'health') {
370
+ const result = await gw.health();
371
+ if (result.success) {
372
+ console.log(c('green', 'βœ” Gateway sağlΔ±klΔ±'));
373
+ if (result.data) console.log(JSON.stringify(result.data, null, 2));
374
+ } else {
375
+ console.log(c('red', `✘ Gateway erişilemez: ${result.error}`));
376
+ }
377
+ return;
378
+ }
379
+
380
+ if (sub === 'models') {
381
+ const result = await gw.getModels();
382
+ if (result.success) {
383
+ console.log(c('yellow', '── AI Modelleri ──\n'));
384
+ const models = result.data?.data || result.data || [];
385
+ if (Array.isArray(models)) {
386
+ models.forEach(m => {
387
+ console.log(` ${c('cyan', m.id || m.name)} ${c('dim', m.description || '')}`);
388
+ });
389
+ } else {
390
+ console.log(JSON.stringify(models, null, 2));
391
+ }
392
+ } else {
393
+ console.log(c('red', `Modeller alΔ±namadΔ±: ${result.error}`));
394
+ }
395
+ return;
396
+ }
397
+
398
+ if (sub === 'run' || sub === 'start') {
399
+ console.log(c('cyan', 'Gateway başlatılıyor...'));
400
+ const result = await gw.start();
401
+ if (result.success) {
402
+ console.log(c('green', 'βœ” Gateway arka planda başlatΔ±ldΔ±.'));
403
+ console.log(c('dim', 'BirkaΓ§ saniye iΓ§inde hazΔ±r olacak.'));
404
+ console.log(c('dim', 'Kontrol iΓ§in: vantuz gateway status'));
405
+ } else {
406
+ console.log(c('red', result.error || 'Gateway başlatılamadı'));
407
+ }
408
+ return;
409
+ }
410
+
411
+ console.log(c('red', 'KullanΔ±m: vantuz gateway [status|health|models|run]'));
412
+ }
413
+
414
+ async function runDoctor() {
415
+ printHeader();
416
+ console.log(c('yellow', '── Sistem SağlΔ±k KontrolΓΌ ──\n'));
417
+
418
+ await showSpinner('Kontroller yapΔ±lΔ±yor', 800);
419
+
420
+ const engine = await getEngine();
421
+ const report = await engine.doctor();
422
+
423
+ // Engine
424
+ console.log(` Engine: ${report.engine ? c('green', '● Aktif') : c('red', 'β—‹ Pasif')}`);
425
+
426
+ // Gateway
427
+ const gw = report.gateway;
428
+ const gwIcon = gw.status === 'healthy' ? c('green', '●') :
429
+ gw.status === 'not_configured' ? c('yellow', 'β—‹') : c('red', 'β—‹');
430
+ console.log(` Gateway: ${gwIcon} ${gw.status === 'healthy' ? 'Sağlıklı' : gw.status === 'not_configured' ? 'Yapılandırılmamış' : 'Erişilemez'}`);
431
+
432
+ // AI
433
+ const ai = report.ai;
434
+ console.log(` AI: ${c('cyan', ai.provider)} ${ai.keyConfigured ? c('green', 'βœ” Key OK') : c('red', '✘ Key Eksik')} ${ai.gatewayFallback ? c('dim', '(gateway fallback var)') : ''}`);
435
+
436
+ // Platformlar
437
+ const platformEntries = Object.entries(report.platforms).filter(([k]) => k !== 'openclaw-gateway');
438
+ if (platformEntries.length > 0) {
439
+ console.log(`\n ${c('bold', 'Platformlar:')}`);
440
+ platformEntries.forEach(([name, connected]) => {
441
+ console.log(` ${connected ? c('green', '●') : c('red', 'β—‹')} ${name}`);
442
+ });
443
+ } else {
444
+ console.log(` Platformlar: ${c('yellow', 'Hiçbiri bağlı değil')}`);
445
+ }
446
+
447
+ // Kanallar
448
+ const ch = report.channels;
449
+ if (ch) {
450
+ console.log(`\n ${c('bold', 'Kanallar:')}`);
451
+ for (const [name, data] of Object.entries(ch)) {
452
+ console.log(` ${data.connected ? c('green', '●') : c('yellow', 'β—‹')} ${name}: ${data.info || ''}`);
453
+ }
454
+ }
455
+
456
+ console.log('');
457
+ }
458
+
459
+ async function runChannels(args) {
460
+ const sub = args[1]?.toLowerCase();
461
+ if (sub === 'login') {
462
+ printHeader();
463
+ console.log(c('yellow', '── WhatsApp Login ──\n'));
464
+
465
+ const openclawDir = path.join(os.homedir(), '.openclaw');
466
+ const configPath = path.join(openclawDir, 'openclaw.json');
467
+
468
+ if (!fs.existsSync(openclawDir)) {
469
+ fs.mkdirSync(openclawDir, { recursive: true });
470
+ }
471
+
472
+ const rawPhone = await promptInput('WhatsApp numaranΔ±z (E.164, ΓΆrn: +905551112233): ');
473
+ const phone = normalizePhone(rawPhone);
474
+ if (!phone || phone === '+') {
475
+ console.log(c('red', 'GeΓ§erli bir numara girilmedi.'));
476
+ process.exitCode = 2;
477
+ return;
478
+ }
479
+
480
+ const config = loadOpenclawConfig(configPath);
481
+ if (!config.channels) config.channels = {};
482
+ if (!config.channels.whatsapp) config.channels.whatsapp = {};
483
+
484
+ if (!config.channels.whatsapp.dmPolicy) {
485
+ config.channels.whatsapp.dmPolicy = 'allowlist';
486
+ }
487
+
488
+ const allowFrom = Array.isArray(config.channels.whatsapp.allowFrom)
489
+ ? config.channels.whatsapp.allowFrom
490
+ : [];
491
+ if (!allowFrom.includes(phone)) {
492
+ allowFrom.push(phone);
493
+ }
494
+ config.channels.whatsapp.allowFrom = allowFrom;
495
+
496
+ const saved = saveOpenclawConfig(configPath, config);
497
+ if (!saved) {
498
+ process.exitCode = 1;
499
+ return;
500
+ }
501
+
502
+ console.log(c('green', 'βœ” Gateway config gΓΌncellendi.'));
503
+ console.log(c('dim', 'Şimdi QR için login başlatılıyor...\n'));
504
+
505
+ try {
506
+ const { spawn } = await import('child_process');
507
+ const child = spawn('openclaw', ['channels', 'login'], {
508
+ stdio: 'inherit',
509
+ shell: true
510
+ });
511
+ await new Promise((resolve, reject) => {
512
+ child.on('exit', code => (code === 0 ? resolve() : reject(new Error(`gateway exit ${code}`))));
513
+ child.on('error', reject);
514
+ });
515
+ console.log(c('green', '\nβœ” QR eşleştirme tamamlandΔ±.'));
516
+ console.log(c('dim', 'Gateway başlatmak için: vantuz gateway run'));
517
+ } catch (e) {
518
+ console.log(c('red', `Login çalıştırılamadı: ${e.message}`));
519
+ }
520
+ return;
521
+ }
522
+
523
+ printHeader();
524
+ console.log(c('yellow', '── Δ°letişim KanallarΔ± ──\n'));
525
+
526
+ const engine = await getEngine();
527
+ const status = engine.getStatus();
528
+ const channels = status.channels || {};
529
+
530
+ for (const [name, data] of Object.entries(channels)) {
531
+ const icon = data.connected ? c('green', '●') : c('yellow', 'β—‹');
532
+ const mode = data.mode === 'gateway' ? c('dim', '[gateway]') : c('dim', '[local]');
533
+ console.log(` ${icon} ${c('bold', name.toUpperCase())} ${mode}`);
534
+ if (data.info) console.log(` ${c('dim', data.info)}`);
535
+ console.log('');
536
+ }
537
+
538
+ if (!status.gateway?.connected) {
539
+ console.log(c('dim', ' WhatsApp bağlantısı için gateway gereklidir.'));
540
+ console.log(c('dim', ' Gateway başlatmak için: start.bat\n'));
541
+ }
542
+ }
543
+
544
+ async function runTeam(args) {
545
+ const sub = args[1]?.toLowerCase();
546
+ const engine = await getEngine();
547
+
548
+ if (!engine.initialized) {
549
+ await showSpinner('AI TakΔ±mΔ± hazΔ±rlanΔ±yor', 500);
550
+ await engine.initialize();
551
+ }
552
+
553
+ if (!engine.team) {
554
+ console.log(c('red', 'Multi-Agent Team modülü aktif değil.'));
555
+ return;
556
+ }
557
+
558
+ if (!sub || sub === 'status') {
559
+ printHeader();
560
+ console.log(c('yellow', '── Yapay Zeka TakΔ±mΔ± ──\n'));
561
+ const agents = engine.team.agents;
562
+
563
+ if (Object.keys(agents).length === 0) {
564
+ console.log(c('dim', ' HenΓΌz ajan yΓΌklenmedi.'));
565
+ } else {
566
+ for (const [name, agent] of Object.entries(agents)) {
567
+ console.log(` ${c('green', '●')} ${c('bold', agent.displayName)}: ${c('dim', agent.role)}`);
568
+ }
569
+ }
570
+ console.log('');
571
+ console.log(c('dim', ' Komutlar:'));
572
+ console.log(c('dim', ' vantuz team chat <isim> "mesaj"'));
573
+ console.log(c('dim', ' vantuz team broadcast "duyuru"'));
574
+ console.log('');
575
+ return;
576
+ }
577
+
578
+ if (sub === 'chat') {
579
+ const agentName = args[2];
580
+ const message = args.slice(3).join(' ');
581
+ if (!agentName || !message) {
582
+ console.log(c('red', 'KullanΔ±m: vantuz team chat <agent> <mesaj>'));
583
+ return;
584
+ }
585
+ console.log(c('dim', `${agentName} düşünüyor...`));
586
+ try {
587
+ const response = await engine.team.chat(agentName, message);
588
+ console.log(`\n${c('cyan', agentName + ':')} ${response}\n`);
589
+ } catch (e) {
590
+ console.log(c('red', `Hata: ${e.message}`));
591
+ }
592
+ }
593
+
594
+ if (sub === 'broadcast') {
595
+ const message = args.slice(2).join(' ');
596
+ if (!message) {
597
+ console.log(c('red', 'KullanΔ±m: vantuz team broadcast <mesaj>'));
598
+ return;
599
+ }
600
+ console.log(c('dim', 'TΓΌm takΔ±ma iletiliyor...'));
601
+ try {
602
+ const results = await engine.team.broadcast(message);
603
+ for (const [name, resp] of Object.entries(results)) {
604
+ console.log(`\n${c('bold', name.toUpperCase())}: ${resp}`);
605
+ }
606
+ } catch (e) {
607
+ console.log(c('red', `Hata: ${e.message}`));
608
+ }
609
+ console.log('');
610
+ }
611
+ }
612
+
613
+ // ═══════════════════════════════════════════════════════════════════════════
614
+ // MAIN
615
+ // ═══════════════════════════════════════════════════════════════════════════
616
+
617
+ const args = process.argv.slice(2);
618
+ const command = args[0]?.toLowerCase();
619
+
620
+ async function main() {
621
+ switch (command) {
622
+ case 'tui':
623
+ case 'chat':
624
+ await runTUI();
625
+ break;
626
+
627
+ case 'config':
628
+ await runConfig(args);
629
+ break;
630
+
631
+ case 'logs':
632
+ await runLogs(args);
633
+ break;
634
+
635
+ case 'gateway':
636
+ case 'gw':
637
+ await runGateway(args);
638
+ break;
639
+
640
+ case 'doctor':
641
+ case 'check':
642
+ await runDoctor();
643
+ break;
644
+
645
+ case 'channels':
646
+ case 'ch':
647
+ await runChannels(args);
648
+ break;
649
+
650
+ case 'status':
651
+ printHeader();
652
+ const lic = licenseManager.getInfo();
653
+ if (lic.valid) {
654
+ console.log(`Lisans Durumu: ${c('green', 'Aktif')} (${lic.type})`);
655
+ console.log(`Kalan SΓΌre: ${c('yellow', lic.daysLeft + ' GΓΌn')}`);
656
+ } else {
657
+ console.log(`Lisans Durumu: ${c('red', 'Pasif/Süresi Dolmuş')}`);
658
+ }
659
+ const gw = await getGateway();
660
+ const gwInfo = gw.getInfo();
661
+ console.log(`Vantuz Gateway: ${gwInfo.connected ? c('green', '● BağlΔ±') : c('yellow', 'β—‹ BağlΔ± Değil')}`);
662
+ break;
663
+
664
+ case 'team':
665
+ await runTeam(args);
666
+ break;
667
+
668
+ default:
669
+ printHeader();
670
+ console.log('KullanΔ±m:\n');
671
+ console.log(` ${c('cyan', 'vantuz tui')} - Sohbet arayΓΌzΓΌ`);
672
+ console.log(` ${c('cyan', 'vantuz status')} - Durum kontrolΓΌ`);
673
+ console.log(` ${c('cyan', 'vantuz team')} - Yapay Zeka TakΔ±mΔ±`);
674
+ console.log(` ${c('cyan', 'vantuz gateway')} - Gateway yΓΆnetimi`);
675
+ console.log(` ${c('cyan', 'vantuz doctor')} - Sistem sağlık kontrolü`);
676
+ console.log(` ${c('cyan', 'vantuz channels')} - İletişim kanalları`);
677
+ console.log(` ${c('cyan', 'vantuz channels login')} - WhatsApp QR login`);
678
+ console.log(` ${c('cyan', 'vantuz config')} - AyarlarΔ± gΓΆster/gΓΌncelle`);
679
+ console.log(` ${c('cyan', 'vantuz logs')} - LoglarΔ± gΓΆster`);
680
+ console.log(`\nKurulum ve başlangıç ayarları için: ${c('cyan', 'vantuz config init')}`);
681
+ process.exitCode = command ? 2 : 0;
682
+ }
683
+ }
684
+
685
+ main();