vantuz 4.0.0 → 4.0.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 +9 -9
- package/config.js +6 -6
- package/core/agent-loop.js +6 -6
- package/core/agent.js +6 -6
- package/core/ai-copilot.js +461 -0
- package/core/ai-provider.js +60 -10
- package/core/automation.js +8 -8
- package/core/cache-manager.js +232 -0
- package/core/channels.js +8 -8
- package/core/dashboard.js +5 -5
- package/core/database-manager.js +331 -0
- package/core/database.js +124 -83
- package/core/eia-brain.js +2 -2
- package/core/eia-monitor.js +7 -7
- package/core/engine.js +24 -24
- package/core/error-handler.js +203 -0
- package/core/gateway.js +9 -9
- package/core/learning.js +7 -7
- package/core/license-manager.js +1 -1
- package/core/license.js +6 -6
- package/core/logger.js +228 -0
- package/core/marketplace-adapter.js +5 -5
- package/core/memory.js +6 -6
- package/core/multi-agent.js +180 -0
- package/core/openclaw-bridge.js +6 -6
- package/core/queue.js +3 -3
- package/core/scheduler.js +6 -6
- package/core/scrapers/Scraper.js +1 -1
- package/core/scrapers/TrendyolScraper.js +1 -1
- package/core/self-healer.js +8 -6
- package/core/unified-product.js +8 -8
- package/core/vector-db.js +5 -5
- package/core/vision-service.js +5 -5
- package/desktop/index.html +2804 -0
- package/desktop/main.js +97 -0
- package/desktop/preload.js +30 -0
- package/dev.sh +5 -0
- package/index.js +483 -115
- package/modules/crm/sentiment-crm.js +4 -4
- package/modules/healer/listing-healer.js +2 -2
- package/modules/oracle/predictor.js +5 -5
- package/modules/researcher/agent.js +4 -4
- package/modules/war-room/competitor-tracker.js +5 -5
- package/modules/war-room/pricing-engine.js +5 -5
- package/nodes/warehouse.js +5 -5
- package/onboard.js +1 -1
- package/package.json +11 -3
- package/pkg.json +26 -0
- package/plugins/vantuz/index.js +16 -17
- package/plugins/vantuz/memory/hippocampus.js +3 -3
- package/plugins/vantuz/platforms/_request.js +1 -1
- package/plugins/vantuz/platforms/_template.js +2 -2
- package/plugins/vantuz/platforms/amazon.js +3 -3
- package/plugins/vantuz/platforms/ciceksepeti.js +2 -2
- package/plugins/vantuz/platforms/hepsiburada.js +2 -2
- package/plugins/vantuz/platforms/index.js +9 -24
- package/plugins/vantuz/platforms/n11.js +3 -3
- package/plugins/vantuz/platforms/pazarama.js +2 -2
- package/plugins/vantuz/platforms/pttavm.js +2 -2
- package/plugins/vantuz/platforms/trendyol.js +3 -3
- package/plugins/vantuz/services/alerts.js +1 -1
- package/plugins/vantuz/services/scheduler.js +1 -1
- package/plugins/vantuz/tools/nl-parser.js +1 -1
- package/plugins/vantuz/tools/quick-report.js +2 -2
- package/plugins/vantuz/tools/repricer.js +1 -1
- package/plugins/vantuz/tools/vision.js +3 -3
- package/server/app.js +8 -8
- package/DOCS_TR.md +0 -80
- package/modules/team/agents/base.js +0 -92
- package/modules/team/agents/dev.js +0 -33
- package/modules/team/agents/josh.js +0 -40
- package/modules/team/agents/marketing.js +0 -33
- package/modules/team/agents/milo.js +0 -36
- package/modules/team/index.js +0 -78
- package/modules/team/shared-memory.js +0 -87
- package/n11docs.md +0 -1680
- package/openclawdocs.md +0 -3
- package/vantuz.sqlite +0 -0
- package/workspace/AGENTS.md +0 -73
- package/workspace/BRAND.md +0 -29
- package/workspace/SOUL.md +0 -72
- package/workspace/team/DECISIONS.md +0 -3
- package/workspace/team/GOALS.md +0 -3
- package/workspace/team/PROJECT_STATUS.md +0 -3
- package/workspace/team/agents/dev/SOUL.md +0 -12
- package/workspace/team/agents/josh/SOUL.md +0 -12
- package/workspace/team/agents/marketing/SOUL.md +0 -12
- package/workspace/team/agents/milo/SOUL.md +0 -12
package/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* 🐙 VANTUZ v4.0 - E-Ticaret Yönetim Platformu
|
|
5
|
+
* Stabilite ve Genel İyileştirmeler ile Güncellenmiş Versiyon
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// --- YENİ İMPORTLAR (Stabilite İyileştirmeleri) ---
|
|
3
9
|
const fs = require('fs');
|
|
4
10
|
const { execSync } = require('child_process');
|
|
5
11
|
const clear = require('console-clear');
|
|
@@ -9,10 +15,59 @@ const inquirer = require('inquirer');
|
|
|
9
15
|
const boxen = require('boxen');
|
|
10
16
|
const ora = require('ora');
|
|
11
17
|
const Conf = require('conf');
|
|
18
|
+
const http = require('http');
|
|
19
|
+
const { URL } = require('url');
|
|
20
|
+
|
|
21
|
+
// --- YENİ STABİLİTE MODÜLLERİ ---
|
|
22
|
+
const logger = require('./core/logger');
|
|
23
|
+
const { setupGracefulShutdown, withErrorHandler, withTimeout, APITimeoutHandler } = require('./core/error-handler');
|
|
24
|
+
const { globalCache, debounce, createLazyLoader } = require('./core/cache-manager');
|
|
25
|
+
const { DatabaseManager, scheduleDailyBackup } = require('./core/database-manager');
|
|
26
|
+
|
|
27
|
+
// --- MEVCUT MODÜLLER ---
|
|
12
28
|
const db = require('./core/database');
|
|
13
29
|
const licenseManager = require('./core/license-manager');
|
|
30
|
+
const productManager = require('./core/product-manager');
|
|
31
|
+
const brandAnalyst = require('./core/brand-analyst');
|
|
32
|
+
const { getCopilot, getCopilotFunctions } = require('./core/ai-copilot');
|
|
14
33
|
const pkg = require('./package.json');
|
|
15
34
|
|
|
35
|
+
// Session tracking
|
|
36
|
+
process.env.SESSION_START = Date.now();
|
|
37
|
+
process.env.SESSION_ID = `session-${Date.now()}`;
|
|
38
|
+
logger.startSession(process.env.SESSION_ID);
|
|
39
|
+
|
|
40
|
+
const config = new Conf({ projectName: 'vantuz' });
|
|
41
|
+
const DEFAULT_API_PORT = process.env.VANTUZ_API_PORT || 3131;
|
|
42
|
+
const apiTimeout = new APITimeoutHandler(30000); // 30s default timeout
|
|
43
|
+
|
|
44
|
+
// --- DATABASE MANAGER BAŞLATICI ---
|
|
45
|
+
let dbManager = null;
|
|
46
|
+
async function initDatabaseManager() {
|
|
47
|
+
try {
|
|
48
|
+
await db.initDB();
|
|
49
|
+
dbManager = new DatabaseManager(db, require('./core/database').dbPath || require('path').join(process.cwd(), 'vantuz.sqlite'));
|
|
50
|
+
|
|
51
|
+
// Auto-migration
|
|
52
|
+
await dbManager.runMigrations();
|
|
53
|
+
|
|
54
|
+
// Bütünlük kontrolü
|
|
55
|
+
const integrity = await dbManager.checkIntegrity();
|
|
56
|
+
if (!integrity.valid) {
|
|
57
|
+
logger.warn('Veri bütünlüğü sorunları tespit edildi', { issues: integrity.issues });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Günlük backup planla
|
|
61
|
+
scheduleDailyBackup(dbManager, 3, 0); // Her gece 03:00
|
|
62
|
+
|
|
63
|
+
logger.info('Database Manager başlatıldı');
|
|
64
|
+
return dbManager;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error('Database Manager başlatma hatası', { error: error.message });
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
16
71
|
// --- BASİT KOMUT SATIRI ARGÜMANLARI ---
|
|
17
72
|
const args = process.argv.slice(2);
|
|
18
73
|
|
|
@@ -27,19 +82,13 @@ if (args.includes('--upgrade') || args.includes('-U')) {
|
|
|
27
82
|
console.log(chalk.yellow(' 🚀 Güncelleme Kontrol Ediliyor...\n'));
|
|
28
83
|
|
|
29
84
|
try {
|
|
30
|
-
// Check current version
|
|
31
85
|
const currentVersion = pkg.version;
|
|
32
|
-
|
|
33
|
-
// Run upgrade
|
|
34
86
|
console.log(chalk.cyan(' 📦 En güncel paketler indiriliyor...'));
|
|
35
87
|
execSync('npm install -g vantuz@latest', { stdio: 'pipe' });
|
|
36
|
-
|
|
37
|
-
// Show success
|
|
38
88
|
console.log(chalk.green(' ✅ Tüm paketler güncellendi!'));
|
|
39
89
|
console.log(chalk.white('\n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
40
90
|
console.log(chalk.green(' 🎉 Vantuz ' + currentVersion + ' → ' + pkg.version + ' başarıyla yükseltildi!'));
|
|
41
91
|
console.log(chalk.white(' ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
|
|
42
|
-
|
|
43
92
|
} catch(e) {
|
|
44
93
|
console.log(chalk.red(' ❌ Güncelleme sırasında hata oluştu:'));
|
|
45
94
|
console.log(chalk.gray(' ' + e.message));
|
|
@@ -47,43 +96,350 @@ if (args.includes('--upgrade') || args.includes('-U')) {
|
|
|
47
96
|
process.exit(0);
|
|
48
97
|
}
|
|
49
98
|
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
99
|
+
// --- YARDIM KOMUTU ---
|
|
100
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
101
|
+
clear();
|
|
102
|
+
console.log(chalk.cyan(figlet.textSync('VANTUZ', { horizontalLayout: 'full' })));
|
|
103
|
+
console.log(chalk.white(`
|
|
104
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
105
|
+
🐙 E-Ticaretin Yapay Zeka Beyni
|
|
106
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
107
|
+
|
|
108
|
+
Kullanım: vantuz [komut] [seçenekler]
|
|
109
|
+
|
|
110
|
+
Komutlar:
|
|
111
|
+
(boş) Interaktif mod başlat
|
|
112
|
+
--api API server modu başlat
|
|
113
|
+
--version Versiyon göster
|
|
114
|
+
--upgrade Paketi güncelle
|
|
115
|
+
--help Bu yardımı göster
|
|
116
|
+
|
|
117
|
+
Seçenekler:
|
|
118
|
+
--port <p> API port (varsayılan: 3131)
|
|
119
|
+
--debug Debug modu
|
|
120
|
+
|
|
121
|
+
Interaktif Mod Komutları:
|
|
122
|
+
/orders Sipariş yönetimi
|
|
123
|
+
/products Ürün & Stok (Vision AI)
|
|
124
|
+
/analytics Pazar analizi
|
|
125
|
+
/chat AI Takımı ile sohbet
|
|
126
|
+
/stores Mağazalarım
|
|
127
|
+
/settings Ayarlar
|
|
128
|
+
/exit Çıkış
|
|
129
|
+
|
|
130
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
131
|
+
`));
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
56
134
|
|
|
57
|
-
|
|
135
|
+
// --- YENİ: CACHE İSTATİSTİKLERİ ---
|
|
136
|
+
if (args.includes('--cache-stats')) {
|
|
137
|
+
const stats = globalCache.getStats();
|
|
138
|
+
console.log(chalk.cyan('📊 Cache İstatistikleri:'));
|
|
139
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
140
|
+
process.exit(0);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// --- YENİ: BACKUP OLUŞTUR ---
|
|
144
|
+
if (args.includes('--backup')) {
|
|
145
|
+
clear();
|
|
146
|
+
console.log(chalk.cyan('💾 Backup Oluşturuluyor...'));
|
|
147
|
+
initDatabaseManager().then(async (mgr) => {
|
|
148
|
+
if (mgr) {
|
|
149
|
+
const result = await mgr.createBackup('manual');
|
|
150
|
+
if (result.success) {
|
|
151
|
+
console.log(chalk.green(`✅ Backup oluşturuldu: ${result.file}`));
|
|
152
|
+
} else {
|
|
153
|
+
console.log(chalk.red(`❌ Backup hatası: ${result.error}`));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
process.exit(0);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// --- YENİ: SİSTEM KONTROLÜ ---
|
|
161
|
+
if (args.includes('--doctor') || args.includes('--check')) {
|
|
162
|
+
clear();
|
|
163
|
+
console.log(chalk.cyan(figlet.textSync('VANTUZ', { horizontalLayout: 'full' })));
|
|
164
|
+
console.log(chalk.yellow(' 🔍 Sistem Sağlık Kontrolü\n'));
|
|
165
|
+
|
|
166
|
+
const checks = [
|
|
167
|
+
{ name: 'Veritabanı', check: async () => {
|
|
168
|
+
try {
|
|
169
|
+
await db.initDB();
|
|
170
|
+
return { status: 'ok', info: 'Bağlantı başarılı' };
|
|
171
|
+
} catch (e) {
|
|
172
|
+
return { status: 'error', info: e.message };
|
|
173
|
+
}
|
|
174
|
+
}},
|
|
175
|
+
{ name: 'Cache', check: async () => {
|
|
176
|
+
const stats = globalCache.getStats();
|
|
177
|
+
return { status: 'ok', info: `Hit Rate: ${stats.hitRate}` };
|
|
178
|
+
}},
|
|
179
|
+
{ name: 'Logs', check: async () => {
|
|
180
|
+
const logs = logger.getLogs(5);
|
|
181
|
+
return { status: 'ok', info: `${logs.length} son log` };
|
|
182
|
+
}}
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
(async () => {
|
|
186
|
+
for (const check of checks) {
|
|
187
|
+
const spinner = ora(`${check.name} kontrol ediliyor...`).start();
|
|
188
|
+
try {
|
|
189
|
+
const result = await check.check();
|
|
190
|
+
spinner.succeed(`${check.name}: ${result.status === 'ok' ? '✅' : '❌'} ${result.info}`);
|
|
191
|
+
} catch (e) {
|
|
192
|
+
spinner.fail(`${check.name}: ❌ ${e.message}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
console.log(chalk.gray('\n Tam rapor için vantuz doctor'));
|
|
196
|
+
process.exit(0);
|
|
197
|
+
})();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// --- API HELPERS (Timeout ile) ---
|
|
201
|
+
function sendJson(res, status, payload) {
|
|
202
|
+
res.statusCode = status;
|
|
203
|
+
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
204
|
+
res.end(JSON.stringify(payload));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function parseBody(req) {
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
let body = '';
|
|
210
|
+
req.on('data', chunk => { body += chunk; });
|
|
211
|
+
req.on('end', () => {
|
|
212
|
+
if (!body) return resolve({});
|
|
213
|
+
try {
|
|
214
|
+
resolve(JSON.parse(body));
|
|
215
|
+
} catch (e) {
|
|
216
|
+
reject(new Error('Geçersiz JSON'));
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// --- LAZY LOADERS ---
|
|
223
|
+
const statsLoader = createLazyLoader(async () => {
|
|
224
|
+
logger.debug('Stats yükleniyor (lazy)');
|
|
225
|
+
const orders = await db.Order.findAll();
|
|
226
|
+
const revenue = orders.reduce((sum, order) => sum + (Number(order.totalAmount) || 0), 0);
|
|
227
|
+
const products = await db.Product.count();
|
|
228
|
+
const stores = await db.Store.count();
|
|
229
|
+
return { orders: orders.length, revenue, products, stores };
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const ordersLoader = createLazyLoader(async () => {
|
|
233
|
+
logger.debug('Siparişler yükleniyor (lazy)');
|
|
234
|
+
return await db.Order.findAll();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const productsLoader = createLazyLoader(async () => {
|
|
238
|
+
logger.debug('Ürünler yükleniyor (lazy)');
|
|
239
|
+
return await db.Product.findAll();
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// --- DEBOUNCED API CALLS ---
|
|
243
|
+
const debouncedStatsRefresh = debounce(async () => {
|
|
244
|
+
logger.info('Debounced stats refresh tetiklendi');
|
|
245
|
+
statsLoader.refresh();
|
|
246
|
+
}, 500);
|
|
247
|
+
|
|
248
|
+
// --- API SERVER ---
|
|
249
|
+
async function startApiServer(options = {}) {
|
|
250
|
+
const port = options.port || DEFAULT_API_PORT;
|
|
251
|
+
|
|
252
|
+
await initDatabaseManager();
|
|
253
|
+
await db.initDB();
|
|
254
|
+
|
|
255
|
+
const server = http.createServer(async (req, res) => {
|
|
256
|
+
const requestUrl = new URL(req.url, `http://${req.headers.host}`);
|
|
257
|
+
const { pathname } = requestUrl;
|
|
258
|
+
|
|
259
|
+
if (!pathname.startsWith('/api')) {
|
|
260
|
+
res.statusCode = 404;
|
|
261
|
+
return res.end('Not Found');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// CORS headers
|
|
265
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
266
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
267
|
+
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
268
|
+
|
|
269
|
+
if (req.method === 'OPTIONS') {
|
|
270
|
+
res.statusCode = 204;
|
|
271
|
+
return res.end();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
try {
|
|
275
|
+
// --- /api/stats (Cache ile) ---
|
|
276
|
+
if (req.method === 'GET' && pathname === '/api/stats') {
|
|
277
|
+
const stats = await statsLoader.get();
|
|
278
|
+
return sendJson(res, 200, stats);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// --- /api/stats/refresh ---
|
|
282
|
+
if (req.method === 'POST' && pathname === '/api/stats/refresh') {
|
|
283
|
+
debouncedStatsRefresh();
|
|
284
|
+
return sendJson(res, 200, { message: 'Refresh tetiklendi' });
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// --- /api/orders (Lazy load) ---
|
|
288
|
+
if (req.method === 'GET' && pathname === '/api/orders') {
|
|
289
|
+
const orders = await ordersLoader.get();
|
|
290
|
+
return sendJson(res, 200, orders);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// --- /api/products (Lazy load) ---
|
|
294
|
+
if (req.method === 'GET' && pathname === '/api/products') {
|
|
295
|
+
const products = await productsLoader.get();
|
|
296
|
+
return sendJson(res, 200, products);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// --- /api/stores ---
|
|
300
|
+
if (req.method === 'GET' && pathname === '/api/stores') {
|
|
301
|
+
const stores = await withTimeout(
|
|
302
|
+
db.Store.findAll(),
|
|
303
|
+
10000,
|
|
304
|
+
'Store Query'
|
|
305
|
+
);
|
|
306
|
+
return sendJson(res, 200, stores);
|
|
307
|
+
}
|
|
58
308
|
|
|
59
|
-
// ---
|
|
60
|
-
|
|
309
|
+
// --- /api/cache/stats ---
|
|
310
|
+
if (req.method === 'GET' && pathname === '/api/cache/stats') {
|
|
311
|
+
return sendJson(res, 200, globalCache.getStats());
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// --- /api/cache/clear ---
|
|
315
|
+
if (req.method === 'POST' && pathname === '/api/cache/clear') {
|
|
316
|
+
globalCache.clear();
|
|
317
|
+
statsLoader.refresh();
|
|
318
|
+
ordersLoader.refresh();
|
|
319
|
+
productsLoader.refresh();
|
|
320
|
+
return sendJson(res, 200, { message: 'Cache temizlendi' });
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// --- /api/chat (Timeout ile) ---
|
|
324
|
+
if (req.method === 'POST' && pathname === '/api/chat') {
|
|
325
|
+
const body = await parseBody(req);
|
|
326
|
+
const message = (body.message || '').toString().trim();
|
|
327
|
+
if (!message) return sendJson(res, 400, { error: 'Mesaj gerekli' });
|
|
328
|
+
|
|
329
|
+
const response = await apiTimeout.request(async () => {
|
|
330
|
+
const lower = message.toLowerCase();
|
|
331
|
+
const [orderCount, productCount, storeCount] = await Promise.all([
|
|
332
|
+
db.Order.count(),
|
|
333
|
+
db.Product.count(),
|
|
334
|
+
db.Store.count()
|
|
335
|
+
]);
|
|
336
|
+
|
|
337
|
+
if (lower.includes('sipariş')) {
|
|
338
|
+
return `📦 Toplam sipariş: ${orderCount}`;
|
|
339
|
+
} else if (lower.includes('ürün') || lower.includes('stok')) {
|
|
340
|
+
return `🛍️ Toplam ürün: ${productCount}`;
|
|
341
|
+
} else if (lower.includes('mağaza') || lower.includes('store')) {
|
|
342
|
+
return `🏪 Aktif mağaza: ${storeCount}`;
|
|
343
|
+
} else {
|
|
344
|
+
return '💬 Mesajınızı aldım. Size yardımcı olmak için verileri hazırlıyorum.';
|
|
345
|
+
}
|
|
346
|
+
}, 15000);
|
|
347
|
+
|
|
348
|
+
return sendJson(res, 200, { response });
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// --- /api/settings ---
|
|
352
|
+
if (req.method === 'GET' && pathname === '/api/settings') {
|
|
353
|
+
const licenseKey = config.get('licenseKey');
|
|
354
|
+
const licenseStatus = licenseKey ? licenseManager.verifyLicense(licenseKey) : { valid: false };
|
|
355
|
+
const userName = licenseStatus.valid ? licenseStatus.data.customer : 'Misafir';
|
|
356
|
+
const plan = licenseStatus.valid ? 'Pro Plan' : 'Free Plan';
|
|
357
|
+
const avatar = userName ? userName[0].toUpperCase() : 'V';
|
|
358
|
+
|
|
359
|
+
return sendJson(res, 200, {
|
|
360
|
+
user: { name: userName, plan, avatar },
|
|
361
|
+
companyInfo: config.get('companyInfo') || null,
|
|
362
|
+
ai: { provider: config.get('ai.provider') || 'OpenAI' },
|
|
363
|
+
cache: globalCache.getStats()
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// --- Health check ---
|
|
368
|
+
if (req.method === 'GET' && pathname === '/api/health') {
|
|
369
|
+
return sendJson(res, 200, {
|
|
370
|
+
status: 'ok',
|
|
371
|
+
timestamp: new Date().toISOString(),
|
|
372
|
+
uptime: process.uptime(),
|
|
373
|
+
memory: process.memoryUsage(),
|
|
374
|
+
cache: globalCache.getStats()
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return sendJson(res, 404, { error: 'Not Found' });
|
|
61
379
|
|
|
380
|
+
} catch (e) {
|
|
381
|
+
logger.error('API Error', {
|
|
382
|
+
path: pathname,
|
|
383
|
+
error: e.message,
|
|
384
|
+
stack: e.stack
|
|
385
|
+
});
|
|
386
|
+
return sendJson(res, 500, { error: e.message || 'Sunucu hatası' });
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// Graceful shutdown kur
|
|
391
|
+
setupGracefulShutdown(server, db);
|
|
392
|
+
|
|
393
|
+
return new Promise(resolve => {
|
|
394
|
+
server.listen(port, () => {
|
|
395
|
+
logger.info(`API Server başladı`, { port });
|
|
396
|
+
resolve(server);
|
|
397
|
+
});
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// --- HELPERS ---
|
|
62
402
|
const printHeader = () => {
|
|
63
403
|
clear();
|
|
64
404
|
console.log(chalk.cyan(figlet.textSync('VANTUZ', { horizontalLayout: 'full' })));
|
|
65
405
|
console.log(chalk.grey(` 🐙 E-Ticaretin Yapay Zeka Beyni | v${pkg.version}\n`));
|
|
66
406
|
};
|
|
67
407
|
|
|
68
|
-
|
|
69
|
-
|
|
408
|
+
const printHeaderCompact = () => {
|
|
409
|
+
clear();
|
|
410
|
+
console.log(chalk.cyan(figlet.textSync('VANTUZ', { horizontalLayout: 'full' })));
|
|
411
|
+
};
|
|
70
412
|
|
|
71
|
-
|
|
72
|
-
|
|
413
|
+
// --- MAIN ---
|
|
414
|
+
async function main() {
|
|
415
|
+
printHeaderCompact();
|
|
73
416
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
417
|
+
// Database Manager init
|
|
418
|
+
await initDatabaseManager();
|
|
77
419
|
|
|
78
|
-
//
|
|
420
|
+
// 1. Lisans Kontrolü
|
|
79
421
|
let licenseKey = config.get('licenseKey');
|
|
80
422
|
let licenseStatus = licenseKey ? licenseManager.verifyLicense(licenseKey) : { valid: false };
|
|
81
423
|
|
|
82
424
|
if (!licenseStatus.valid) {
|
|
83
425
|
if (licenseKey) console.log(chalk.red(`⚠️ Lisans Hatası: ${licenseStatus.reason}`));
|
|
84
426
|
|
|
85
|
-
console.log(boxen(chalk.white('🔒 VANTUZ
|
|
86
|
-
|
|
427
|
+
console.log(boxen(chalk.white('🔒 VANTUZ Lisens Aktivasyonu\nDevam etmek için satıcınızdan aldığınız anahtarı girin.'), { padding: 1, borderColor: 'cyan', borderStyle: 'classic' }));
|
|
428
|
+
|
|
429
|
+
const { key } = await inquirer.prompt([{ type: 'password', name: 'key', message: 'Lisans Anahtarı:', mask: '*' }]);
|
|
430
|
+
const spinner = ora('Anahtar doğrulanıyor...').start();
|
|
431
|
+
await new Promise(r => setTimeout(r, 1500));
|
|
432
|
+
|
|
433
|
+
const status = licenseManager.verifyLicense(key);
|
|
434
|
+
if (status.valid) {
|
|
435
|
+
spinner.succeed(`Lisans Aktif: ${status.data.customer}`);
|
|
436
|
+
config.set('licenseKey', key);
|
|
437
|
+
licenseStatus = status;
|
|
438
|
+
} else {
|
|
439
|
+
spinner.fail(`Hata: ${status.reason}`);
|
|
440
|
+
console.log(chalk.yellow('Lütfen geçerli bir anahtar girin.'));
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
87
443
|
} else {
|
|
88
444
|
const expiryDate = licenseStatus.data.expires || licenseStatus.data.expiry || new Date(Date.now() + 365*24*60*60*1000).toISOString();
|
|
89
445
|
const daysLeft = Math.floor((new Date(expiryDate) - new Date()) / (1000 * 60 * 60 * 24));
|
|
@@ -91,21 +447,26 @@ async function main() {
|
|
|
91
447
|
await new Promise(r => setTimeout(r, 1000));
|
|
92
448
|
}
|
|
93
449
|
|
|
94
|
-
//
|
|
450
|
+
// 2. Veritabanı Bağlantısı
|
|
95
451
|
const spinner = ora('Sistem nöronları başlatılıyor...').start();
|
|
96
|
-
|
|
97
|
-
|
|
452
|
+
try {
|
|
453
|
+
await withTimeout(db.initDB(), 10000, 'Database Init');
|
|
454
|
+
spinner.succeed('Çekirdek Aktif');
|
|
455
|
+
} catch (error) {
|
|
456
|
+
spinner.fail(`Veritabanı hatası: ${error.message}`);
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
98
459
|
|
|
99
|
-
//
|
|
460
|
+
// 3. Mağaza Kontrolü
|
|
100
461
|
const storeCount = await db.Store.count();
|
|
101
462
|
if (storeCount === 0) {
|
|
102
463
|
console.log(chalk.yellow('\n⚠️ Hiçbir mağaza bağlı değil.'));
|
|
103
464
|
await setupWizard();
|
|
104
465
|
}
|
|
105
466
|
|
|
106
|
-
//
|
|
467
|
+
// 4. Ana Döngü
|
|
107
468
|
while (true) {
|
|
108
|
-
|
|
469
|
+
printHeaderCompact();
|
|
109
470
|
await showDashboard(licenseStatus.data || { customer: 'Misafir', expires: '2099-01-01' });
|
|
110
471
|
|
|
111
472
|
const { action } = await inquirer.prompt([
|
|
@@ -125,56 +486,16 @@ async function main() {
|
|
|
125
486
|
}
|
|
126
487
|
]);
|
|
127
488
|
|
|
128
|
-
if (action === 'exit')
|
|
489
|
+
if (action === 'exit') {
|
|
490
|
+
console.log(chalk.green('\n👋 Güle güle!'));
|
|
491
|
+
process.exit(0);
|
|
492
|
+
}
|
|
493
|
+
|
|
129
494
|
await handleAction(action);
|
|
130
495
|
}
|
|
131
496
|
}
|
|
132
497
|
|
|
133
|
-
|
|
134
|
-
clear();
|
|
135
|
-
console.log(chalk.cyan(figlet.textSync('Merhaba!', { horizontalLayout: 'full' })));
|
|
136
|
-
console.log(boxen(chalk.white(`
|
|
137
|
-
VANTUZ'a Hoşgeldiniz.
|
|
138
|
-
|
|
139
|
-
Bu yazılım, e-ticaret operasyonlarınızı yapay zeka ile yönetmenizi sağlar.
|
|
140
|
-
Kuruluma başlamadan önce lütfen şunları hazırlayın:
|
|
141
|
-
|
|
142
|
-
1. Lisans Anahtarınız
|
|
143
|
-
2. Pazaryeri API Bilgileriniz (Trendyol, Hepsiburada vb.)
|
|
144
|
-
3. (Opsiyonel) OpenAI API Anahtarı - Vision özelliği için
|
|
145
|
-
|
|
146
|
-
Başlamaya hazır mısınız?
|
|
147
|
-
`), { padding: 1, borderStyle: 'double', borderColor: 'green' }));
|
|
148
|
-
|
|
149
|
-
const { ready } = await inquirer.prompt([{ type: 'confirm', name: 'ready', message: 'Kuruluma Başla', default: true }]);
|
|
150
|
-
if (!ready) {
|
|
151
|
-
console.log(chalk.yellow('Kurulum iptal edildi. Çıkılıyor...'));
|
|
152
|
-
process.exit(0);
|
|
153
|
-
}
|
|
154
|
-
config.set('installed', true);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
async function activateLicense() {
|
|
158
|
-
const { key } = await inquirer.prompt([{ type: 'password', name: 'key', message: 'Lisans Anahtarı:', mask: '*' }]);
|
|
159
|
-
const spinner = ora('Anahtar doğrulanıyor...').start();
|
|
160
|
-
await new Promise(r => setTimeout(r, 1500)); // Dramatik bekleme
|
|
161
|
-
|
|
162
|
-
const status = licenseManager.verifyLicense(key);
|
|
163
|
-
|
|
164
|
-
if (status.valid) {
|
|
165
|
-
spinner.succeed(`Lisans Aktif: ${status.data.customer}`);
|
|
166
|
-
config.set('licenseKey', key);
|
|
167
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
168
|
-
} else {
|
|
169
|
-
spinner.fail(`Hata: ${status.reason}`);
|
|
170
|
-
console.log(chalk.yellow('Lütfen geçerli bir anahtar girin veya satıcınızla görüşün.'));
|
|
171
|
-
process.exit(1);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ... (setupWizard, showDashboard, handleAction fonksiyonları aynı kalacak, sadece ufak revizyonlar) ...
|
|
176
|
-
|
|
177
|
-
// setupWizard fonksiyonunu güncelleme (Mağaza kurulumu)
|
|
498
|
+
// --- WIZARD ---
|
|
178
499
|
async function setupWizard() {
|
|
179
500
|
console.log(chalk.bold('\n🛒 Mağaza Bağlantı Sihirbazı\n'));
|
|
180
501
|
const { storeName } = await inquirer.prompt([{ type: 'input', name: 'storeName', message: 'Mağaza Adı:' }]);
|
|
@@ -194,64 +515,71 @@ async function setupWizard() {
|
|
|
194
515
|
]);
|
|
195
516
|
|
|
196
517
|
let creds = {};
|
|
197
|
-
|
|
198
518
|
if (platform === 'trendyol') {
|
|
199
|
-
console.log(chalk.cyan('\n👉 Trendyol Entegrasyonu:'));
|
|
200
519
|
creds = await inquirer.prompt([
|
|
201
520
|
{ type: 'password', name: 'supplierId', message: 'Supplier ID:', mask: '*' },
|
|
202
521
|
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' },
|
|
203
522
|
{ type: 'password', name: 'apiSecret', message: 'API Secret:', mask: '*' }
|
|
204
523
|
]);
|
|
205
524
|
} else if (platform === 'hepsiburada') {
|
|
206
|
-
console.log(chalk.cyan('\n👉 Hepsiburada Entegrasyonu:'));
|
|
207
525
|
creds = await inquirer.prompt([
|
|
208
526
|
{ type: 'input', name: 'merchantId', message: 'Merchant ID:' },
|
|
209
527
|
{ type: 'password', name: 'username', message: 'Username (MP):', mask: '*' },
|
|
210
528
|
{ type: 'password', name: 'password', message: 'Password:', mask: '*' }
|
|
211
529
|
]);
|
|
212
530
|
} else if (platform === 'n11') {
|
|
213
|
-
console.log(chalk.cyan('\n👉 N11 Entegrasyonu:'));
|
|
214
531
|
creds = await inquirer.prompt([
|
|
215
532
|
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' },
|
|
216
533
|
{ type: 'password', name: 'apiSecret', message: 'API Secret:', mask: '*' }
|
|
217
534
|
]);
|
|
218
535
|
} else if (platform === 'amazon') {
|
|
219
|
-
console.log(chalk.cyan('\n👉 Amazon SP-API Entegrasyonu:'));
|
|
220
536
|
creds = await inquirer.prompt([
|
|
221
537
|
{ type: 'input', name: 'sellerId', message: 'Seller ID:' },
|
|
222
538
|
{ type: 'password', name: 'clientId', message: 'Client ID:', mask: '*' },
|
|
223
539
|
{ type: 'password', name: 'clientSecret', message: 'Client Secret:', mask: '*' },
|
|
224
|
-
{ type: 'password', name: 'refreshToken', message: 'Refresh Token:', mask: '*' }
|
|
225
|
-
{ type: 'list', name: 'region', message: 'Bölge:', choices: ['eu', 'na', 'tr'], default: 'tr' }
|
|
540
|
+
{ type: 'password', name: 'refreshToken', message: 'Refresh Token:', mask: '*' }
|
|
226
541
|
]);
|
|
227
542
|
}
|
|
228
543
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
544
|
+
try {
|
|
545
|
+
await db.Store.create({ name: storeName, platform, credentials: creds });
|
|
546
|
+
console.log(chalk.green(`\n✅ ${storeName} (${platform}) Başarıyla Bağlandı!`));
|
|
547
|
+
await brandAnalyst.analyzeAndSave(storeName, config);
|
|
548
|
+
} catch (error) {
|
|
549
|
+
logger.error('Mağaza oluşturma hatası', { error: error.message });
|
|
550
|
+
console.log(chalk.red(`\n❌ Hata: ${error.message}`));
|
|
551
|
+
}
|
|
235
552
|
await new Promise(r => setTimeout(r, 1500));
|
|
236
553
|
}
|
|
237
554
|
|
|
555
|
+
// --- DASHBOARD ---
|
|
238
556
|
async function showDashboard(licenseData) {
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
557
|
+
const spinner = ora('Veriler yükleniyor...').start();
|
|
558
|
+
try {
|
|
559
|
+
const [stores, orders] = await Promise.all([
|
|
560
|
+
db.Store.findAll(),
|
|
561
|
+
db.Order.count()
|
|
562
|
+
]);
|
|
563
|
+
spinner.stop();
|
|
564
|
+
|
|
565
|
+
console.log(chalk.bold(`🏢 Lisans Sahibi: ${chalk.cyan(licenseData.customer)}`));
|
|
566
|
+
console.log(`📦 Aktif Mağazalar: ${stores.length} | Toplam Sipariş: ${orders}`);
|
|
567
|
+
console.log(chalk.grey('----------------------------------------'));
|
|
568
|
+
|
|
569
|
+
// Cache stats
|
|
570
|
+
const cacheStats = globalCache.getStats();
|
|
571
|
+
console.log(chalk.dim(` Cache Hit Rate: ${cacheStats.hitRate}`));
|
|
572
|
+
|
|
573
|
+
} catch (error) {
|
|
574
|
+
spinner.fail(`Dashboard yükleme hatası: ${error.message}`);
|
|
575
|
+
}
|
|
245
576
|
}
|
|
246
577
|
|
|
578
|
+
// --- ACTION HANDLER ---
|
|
247
579
|
async function handleAction(action) {
|
|
248
|
-
const inquirer = require('inquirer');
|
|
249
|
-
const chalk = require('chalk');
|
|
250
|
-
|
|
251
580
|
if (action === 'products') {
|
|
252
581
|
await productManager.manageProducts();
|
|
253
582
|
} else if (action === 'ai_chat') {
|
|
254
|
-
// AI Chat
|
|
255
583
|
let companyInfo = config.get('companyInfo');
|
|
256
584
|
if (!companyInfo || !companyInfo.market) {
|
|
257
585
|
console.log(chalk.cyan('\n🏢 FİRMA KAYDI'));
|
|
@@ -279,19 +607,18 @@ async function handleAction(action) {
|
|
|
279
607
|
let response = '';
|
|
280
608
|
|
|
281
609
|
if (lower.includes('pazar') || lower.includes('araştır')) {
|
|
282
|
-
response = `📊 ${companyInfo.market} pazarında araştırma yapıyorum
|
|
610
|
+
response = `📊 ${companyInfo.market} pazarında araştırma yapıyorum...`;
|
|
283
611
|
} else if (lower.includes('stok') || lower.includes('ürün')) {
|
|
284
|
-
response = `📦 Stok
|
|
612
|
+
response = `📦 Stok: ${await db.Product.count()} ürün, ${await db.Store.count()} mağaza`;
|
|
285
613
|
} else if (lower.includes('sipariş')) {
|
|
286
|
-
response = `📦
|
|
614
|
+
response = `📦 Sipariş: ${await db.Order.count()} toplam sipariş`;
|
|
287
615
|
} else {
|
|
288
|
-
response =
|
|
616
|
+
response = `"${message}" anladım. Komutlar: "pazar araştır", "stok durumu", "siparişler"`;
|
|
289
617
|
}
|
|
290
618
|
|
|
291
619
|
console.log(chalk.white('\n' + response + '\n'));
|
|
292
620
|
}
|
|
293
621
|
} else if (action === 'stores') {
|
|
294
|
-
// Mağazalarım
|
|
295
622
|
console.log(chalk.cyan('\n🏪 MAĞAZALARIM'));
|
|
296
623
|
console.log(chalk.grey('─'.repeat(40)));
|
|
297
624
|
const stores = await db.Store.findAll();
|
|
@@ -302,10 +629,8 @@ async function handleAction(action) {
|
|
|
302
629
|
console.log(chalk.white(` ${i+1}. ${s.name} (${s.platform})`));
|
|
303
630
|
});
|
|
304
631
|
}
|
|
305
|
-
|
|
306
|
-
await inquirer.prompt([{ type: 'input', name: 'ok', message: '' }]);
|
|
632
|
+
await inquirer.prompt([{ type: 'input', name: 'ok', message: '\n Devam için Enter...' }]);
|
|
307
633
|
} else if (action === 'settings') {
|
|
308
|
-
// Settings
|
|
309
634
|
console.log(chalk.cyan('\n⚙️ AYARLAR'));
|
|
310
635
|
console.log(chalk.grey('─'.repeat(40)));
|
|
311
636
|
|
|
@@ -317,6 +642,8 @@ async function handleAction(action) {
|
|
|
317
642
|
choices: [
|
|
318
643
|
'🔑 Lisans Değiştir',
|
|
319
644
|
'🤖 AI Model Ayarları',
|
|
645
|
+
'💾 Backup Oluştur',
|
|
646
|
+
'📊 Cache Durumu',
|
|
320
647
|
'🔙 Geri'
|
|
321
648
|
]
|
|
322
649
|
}
|
|
@@ -324,7 +651,7 @@ async function handleAction(action) {
|
|
|
324
651
|
|
|
325
652
|
if (setting === '🔑 Lisans Değiştir') {
|
|
326
653
|
const { newKey } = await inquirer.prompt([
|
|
327
|
-
{ type: '
|
|
654
|
+
{ type: 'password', name: 'newKey', message: 'Yeni lisans anahtarı:', mask: '*' }
|
|
328
655
|
]);
|
|
329
656
|
const result = licenseManager.verifyLicense(newKey);
|
|
330
657
|
if (result.valid) {
|
|
@@ -335,7 +662,6 @@ async function handleAction(action) {
|
|
|
335
662
|
}
|
|
336
663
|
} else if (setting === '🤖 AI Model Ayarları') {
|
|
337
664
|
console.log(chalk.yellow('\n 📝 AI Model Ayarları:'));
|
|
338
|
-
|
|
339
665
|
const { provider } = await inquirer.prompt([
|
|
340
666
|
{
|
|
341
667
|
type: 'list',
|
|
@@ -356,12 +682,54 @@ async function handleAction(action) {
|
|
|
356
682
|
console.log(chalk.green(' ✅ Kaydedildi!'));
|
|
357
683
|
}
|
|
358
684
|
}
|
|
685
|
+
} else if (setting === '💾 Backup Oluştur') {
|
|
686
|
+
console.log(chalk.cyan('\n💾 Backup oluşturuluyor...'));
|
|
687
|
+
if (dbManager) {
|
|
688
|
+
const result = await dbManager.createBackup('manual');
|
|
689
|
+
if (result.success) {
|
|
690
|
+
console.log(chalk.green(` ✅ ${result.file}`));
|
|
691
|
+
} else {
|
|
692
|
+
console.log(chalk.red(` ❌ ${result.error}`));
|
|
693
|
+
}
|
|
694
|
+
} else {
|
|
695
|
+
console.log(chalk.yellow(' ⚠️ Database Manager hazır değil'));
|
|
696
|
+
}
|
|
697
|
+
} else if (setting === '📊 Cache Durumu') {
|
|
698
|
+
const stats = globalCache.getStats();
|
|
699
|
+
console.log(chalk.cyan('\n📊 Cache İstatistikleri:'));
|
|
700
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
359
701
|
}
|
|
360
|
-
|
|
702
|
+
|
|
703
|
+
await inquirer.prompt([{ type: 'input', name: 'ok', message: '\n Devam için Enter...' }]);
|
|
361
704
|
}
|
|
362
705
|
}
|
|
363
706
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
process.
|
|
367
|
-
|
|
707
|
+
// --- ENTRY POINT ---
|
|
708
|
+
if (require.main === module) {
|
|
709
|
+
const isApiMode = process.argv.includes('--api') || process.env.VANTUZ_DESKTOP_API === '1';
|
|
710
|
+
|
|
711
|
+
(async () => {
|
|
712
|
+
try {
|
|
713
|
+
if (isApiMode) {
|
|
714
|
+
await startApiServer();
|
|
715
|
+
} else {
|
|
716
|
+
await main();
|
|
717
|
+
}
|
|
718
|
+
} catch (error) {
|
|
719
|
+
logger.fatal('Fatal error', {
|
|
720
|
+
message: error.message,
|
|
721
|
+
stack: error.stack
|
|
722
|
+
});
|
|
723
|
+
console.error(chalk.red(`\n💀 Fatal Error: ${error.message}`));
|
|
724
|
+
process.exit(1);
|
|
725
|
+
}
|
|
726
|
+
})();
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
module.exports = {
|
|
730
|
+
startApiServer,
|
|
731
|
+
initDatabaseManager,
|
|
732
|
+
globalCache,
|
|
733
|
+
getCopilot,
|
|
734
|
+
getCopilotFunctions
|
|
735
|
+
};
|