vantuz 3.3.5 → 3.3.6
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/config.js +31 -8
- package/core/engine.js +296 -339
- package/core/gateway.js +139 -68
- package/package.json +1 -1
- package/platforms/amazon.js +4 -1
- package/platforms/ciceksepeti.js +2 -1
- package/platforms/n11.js +2 -2
- package/platforms/pazarama.js +2 -1
- package/platforms/pttavm.js +14 -0
package/config.js
CHANGED
|
@@ -384,7 +384,8 @@ class Configurator {
|
|
|
384
384
|
choice: String(index + 1),
|
|
385
385
|
label: `${icon} ${label}`,
|
|
386
386
|
description: description,
|
|
387
|
-
envKey: providerInfo.envKey // Store the actual env key
|
|
387
|
+
envKey: providerInfo.envKey, // Store the actual env key
|
|
388
|
+
key: key // Store the provider key (e.g., 'gemini', 'groq')
|
|
388
389
|
};
|
|
389
390
|
});
|
|
390
391
|
|
|
@@ -432,13 +433,15 @@ class Configurator {
|
|
|
432
433
|
|
|
433
434
|
if (key && key.trim()) {
|
|
434
435
|
this.envVars[selectedOption.envKey] = key.trim();
|
|
436
|
+
this.envVars.AI_PROVIDER = selectedOption.key; // Save the provider key (e.g., 'groq')
|
|
437
|
+
|
|
435
438
|
// Clear other AI keys if one is selected
|
|
436
439
|
providerOptions.forEach(option => {
|
|
437
440
|
if (option.envKey !== selectedOption.envKey && this.envVars[option.envKey]) {
|
|
438
441
|
delete this.envVars[option.envKey];
|
|
439
442
|
}
|
|
440
443
|
});
|
|
441
|
-
console.log(this.successMessage('API anahtarı kaydedildi'));
|
|
444
|
+
console.log(this.successMessage('API anahtarı ve sağlayıcı seçimi kaydedildi'));
|
|
442
445
|
} else {
|
|
443
446
|
if (this.envVars[selectedOption.envKey]) {
|
|
444
447
|
delete this.envVars[selectedOption.envKey];
|
|
@@ -595,13 +598,33 @@ class Configurator {
|
|
|
595
598
|
console.log('');
|
|
596
599
|
|
|
597
600
|
if (!info.configFound || !info.hasToken || !info.connected) {
|
|
598
|
-
console.log(this.warningMessage('Gateway tam olarak yapılandırılmamış veya çalışmıyor
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
601
|
+
console.log(this.warningMessage('Gateway tam olarak yapılandırılmamış veya çalışmıyor.'));
|
|
602
|
+
|
|
603
|
+
const startChoice = await this.prompt('Sistemi otomatik başlatmak ister misiniz? (E/h)', 'E');
|
|
604
|
+
if (startChoice.toLowerCase() !== 'h') {
|
|
605
|
+
console.log(c('dim', 'Sistem başlatılıyor (Gateway + Server)...'));
|
|
606
|
+
const result = await gateway.startFullStack();
|
|
607
|
+
|
|
608
|
+
if (result.success) {
|
|
609
|
+
console.log(this.successMessage('Başlatma komutları gönderildi.'));
|
|
610
|
+
console.log(c('dim', 'Servislerin açılması 10-15 saniye sürebilir.'));
|
|
611
|
+
await sleep(5000); // Wait a bit before re-checking
|
|
612
|
+
|
|
613
|
+
// Re-check status
|
|
614
|
+
const newInfo = (await gateway.health()).success;
|
|
615
|
+
if (newInfo) console.log(this.successMessage('Gateway bağlantısı sağlandı!'));
|
|
616
|
+
else console.log(c('yellow', 'Gateway henüz hazır değil, arka planda açılıyor...'));
|
|
617
|
+
} else {
|
|
618
|
+
console.log(this.errorMessage('Başlatma sırasında hata oluştu.'));
|
|
619
|
+
if (result.gateway?.error) console.log(c('red', `Gateway Hatası: ${result.gateway.error}`));
|
|
620
|
+
if (result.server?.error) console.log(c('red', `Server Hatası: ${result.server.error}`));
|
|
621
|
+
}
|
|
622
|
+
} else {
|
|
623
|
+
console.log(c('dim', 'Manuel başlatmak için `start.bat` kullanabilirsiniz.'));
|
|
624
|
+
}
|
|
602
625
|
} else {
|
|
603
|
-
console.log(this.successMessage('Gateway başarılı bir şekilde yapılandırılmış ve çalışıyor
|
|
604
|
-
console.log(c('
|
|
626
|
+
console.log(this.successMessage('Gateway başarılı bir şekilde yapılandırılmış ve çalışıyor.'));
|
|
627
|
+
console.log(c('dim', 'Durumu kontrol etmek için: vantuz gateway status'));
|
|
605
628
|
}
|
|
606
629
|
await this.prompt(c('dim', '▶ Devam etmek için Enter\'a basın...'));
|
|
607
630
|
}
|
package/core/engine.js
CHANGED
|
@@ -16,11 +16,11 @@ import platformHub from '../plugins/vantuz/platforms/index.js';
|
|
|
16
16
|
// AI Provider & Gateway
|
|
17
17
|
import { getChannelManager } from './channels.js';
|
|
18
18
|
import { chat as aiChat, log } from './ai-provider.js';
|
|
19
|
-
import { getGateway } from './gateway.js';
|
|
20
|
-
import { getEIAMonitor } from './eia-monitor.js'; // New import
|
|
21
|
-
import AutomationManager from './automation.js';
|
|
22
|
-
import OpenClawBridge from './openclaw-bridge.js';
|
|
23
|
-
import { executeTool } from './agent.js';
|
|
19
|
+
import { getGateway } from './gateway.js';
|
|
20
|
+
import { getEIAMonitor } from './eia-monitor.js'; // New import
|
|
21
|
+
import AutomationManager from './automation.js';
|
|
22
|
+
import OpenClawBridge from './openclaw-bridge.js';
|
|
23
|
+
import { executeTool } from './agent.js';
|
|
24
24
|
|
|
25
25
|
// Tools
|
|
26
26
|
import { repricerTool } from '../plugins/vantuz/tools/repricer.js';
|
|
@@ -40,32 +40,25 @@ const PLATFORM_CONFIG_MAP = {
|
|
|
40
40
|
envPrefix: 'HEPSIBURADA',
|
|
41
41
|
keys: ['merchantId', 'username', 'password']
|
|
42
42
|
},
|
|
43
|
-
n11: {
|
|
44
|
-
envPrefix: 'N11',
|
|
45
|
-
keys: ['apiKey', 'apiSecret']
|
|
46
|
-
},
|
|
43
|
+
n11: {
|
|
44
|
+
envPrefix: 'N11',
|
|
45
|
+
keys: ['apiKey', 'apiSecret']
|
|
46
|
+
},
|
|
47
47
|
amazon: {
|
|
48
48
|
envPrefix: 'AMAZON',
|
|
49
|
-
|
|
50
|
-
eu: {
|
|
51
|
-
keys: ['sellerId', 'clientId', 'refreshToken']
|
|
52
|
-
},
|
|
53
|
-
us: {
|
|
54
|
-
keys: ['sellerId', 'clientId', 'refreshToken']
|
|
55
|
-
}
|
|
56
|
-
}
|
|
49
|
+
keys: ['sellerId', 'clientId', 'clientSecret', 'refreshToken', 'region']
|
|
57
50
|
},
|
|
58
51
|
ciceksepeti: {
|
|
59
52
|
envPrefix: 'CICEKSEPETI',
|
|
60
|
-
keys: ['apiKey', '
|
|
53
|
+
keys: ['apiKey', 'supplierId']
|
|
61
54
|
},
|
|
62
55
|
pttavm: {
|
|
63
56
|
envPrefix: 'PTTAVM',
|
|
64
|
-
keys: ['apiKey', '
|
|
57
|
+
keys: ['apiKey', 'token', 'shopId']
|
|
65
58
|
},
|
|
66
59
|
pazarama: {
|
|
67
60
|
envPrefix: 'PAZARAMA',
|
|
68
|
-
keys: ['
|
|
61
|
+
keys: ['clientId', 'clientSecret']
|
|
69
62
|
}
|
|
70
63
|
};
|
|
71
64
|
|
|
@@ -82,7 +75,7 @@ const CONFIG_JSON = path.join(VANTUZ_HOME, 'config.json');
|
|
|
82
75
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
83
76
|
|
|
84
77
|
export class VantuzEngine {
|
|
85
|
-
constructor() {
|
|
78
|
+
constructor() {
|
|
86
79
|
this.initialized = false;
|
|
87
80
|
this.config = {};
|
|
88
81
|
this.env = {};
|
|
@@ -93,9 +86,9 @@ export class VantuzEngine {
|
|
|
93
86
|
products: [],
|
|
94
87
|
connectedPlatforms: []
|
|
95
88
|
};
|
|
96
|
-
this.eiaMonitor = null; // New property
|
|
97
|
-
this.automation = null;
|
|
98
|
-
this.bridge = null;
|
|
89
|
+
this.eiaMonitor = null; // New property
|
|
90
|
+
this.automation = null;
|
|
91
|
+
this.bridge = null;
|
|
99
92
|
|
|
100
93
|
// Tool Registry
|
|
101
94
|
this.tools = {
|
|
@@ -112,29 +105,29 @@ export class VantuzEngine {
|
|
|
112
105
|
/**
|
|
113
106
|
* Engine'i başlat
|
|
114
107
|
*/
|
|
115
|
-
async initialize() {
|
|
116
|
-
log('INFO', 'Vantuz Engine v3.2 başlatılıyor...');
|
|
117
|
-
|
|
118
|
-
// Config ve env yükle
|
|
119
|
-
this._loadConfig();
|
|
120
|
-
this._loadEnv();
|
|
121
|
-
|
|
122
|
-
// Vantuz Gateway bağlantısı
|
|
123
|
-
try {
|
|
124
|
-
this.gateway = await getGateway();
|
|
125
|
-
if (this.gateway.isConnected()) {
|
|
126
|
-
log('INFO', 'Vantuz Gateway bağlı', this.gateway.getInfo());
|
|
127
|
-
} else if (this._shouldAutoStartGateway()) {
|
|
128
|
-
const started = await this.gateway.ensureRunning();
|
|
129
|
-
if (started.success) {
|
|
130
|
-
log('INFO', 'Vantuz Gateway otomatik başlatıldı', this.gateway.getInfo());
|
|
131
|
-
} else {
|
|
132
|
-
log('WARN', 'Gateway otomatik başlatılamadı', { error: started.error });
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
} catch (e) {
|
|
136
|
-
log('WARN', 'Gateway bağlantısı başarısız, direkt mod', { error: e.message });
|
|
137
|
-
}
|
|
108
|
+
async initialize() {
|
|
109
|
+
log('INFO', 'Vantuz Engine v3.2 başlatılıyor...');
|
|
110
|
+
|
|
111
|
+
// Config ve env yükle
|
|
112
|
+
this._loadConfig();
|
|
113
|
+
this._loadEnv();
|
|
114
|
+
|
|
115
|
+
// Vantuz Gateway bağlantısı
|
|
116
|
+
try {
|
|
117
|
+
this.gateway = await getGateway();
|
|
118
|
+
if (this.gateway.isConnected()) {
|
|
119
|
+
log('INFO', 'Vantuz Gateway bağlı', this.gateway.getInfo());
|
|
120
|
+
} else if (this._shouldAutoStartGateway()) {
|
|
121
|
+
const started = await this.gateway.ensureRunning();
|
|
122
|
+
if (started.success) {
|
|
123
|
+
log('INFO', 'Vantuz Gateway otomatik başlatıldı', this.gateway.getInfo());
|
|
124
|
+
} else {
|
|
125
|
+
log('WARN', 'Gateway otomatik başlatılamadı', { error: started.error });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch (e) {
|
|
129
|
+
log('WARN', 'Gateway bağlantısı başarısız, direkt mod', { error: e.message });
|
|
130
|
+
}
|
|
138
131
|
|
|
139
132
|
// Channel Manager'ı başlat
|
|
140
133
|
this.channels = await getChannelManager();
|
|
@@ -146,70 +139,70 @@ export class VantuzEngine {
|
|
|
146
139
|
await this._buildContext();
|
|
147
140
|
|
|
148
141
|
// Initialize and start EIA Monitor
|
|
149
|
-
this.eiaMonitor = getEIAMonitor(this.config, this.env);
|
|
150
|
-
await this.eiaMonitor.initMonitoringTasks(); // New line
|
|
151
|
-
|
|
152
|
-
// Automation manager
|
|
153
|
-
this.automation = new AutomationManager(this);
|
|
154
|
-
this.automation.init();
|
|
155
|
-
|
|
156
|
-
// Gateway WS bridge (inbound)
|
|
157
|
-
if (this._shouldStartBridge()) {
|
|
158
|
-
try {
|
|
159
|
-
this.bridge = new OpenClawBridge(this, this.gateway);
|
|
160
|
-
this.bridge.start();
|
|
161
|
-
} catch (e) {
|
|
162
|
-
log('WARN', 'Gateway bridge başlatılamadı', { error: e.message });
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
this.initialized = true;
|
|
142
|
+
this.eiaMonitor = getEIAMonitor(this.config, this.env);
|
|
143
|
+
await this.eiaMonitor.initMonitoringTasks(); // New line
|
|
144
|
+
|
|
145
|
+
// Automation manager
|
|
146
|
+
this.automation = new AutomationManager(this);
|
|
147
|
+
this.automation.init();
|
|
148
|
+
|
|
149
|
+
// Gateway WS bridge (inbound)
|
|
150
|
+
if (this._shouldStartBridge()) {
|
|
151
|
+
try {
|
|
152
|
+
this.bridge = new OpenClawBridge(this, this.gateway);
|
|
153
|
+
this.bridge.start();
|
|
154
|
+
} catch (e) {
|
|
155
|
+
log('WARN', 'Gateway bridge başlatılamadı', { error: e.message });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.initialized = true;
|
|
167
160
|
log('INFO', 'Vantuz Engine hazır', {
|
|
168
161
|
platforms: this.context.connectedPlatforms.length,
|
|
169
162
|
gateway: this.gateway?.isConnected() || false
|
|
170
163
|
});
|
|
171
164
|
|
|
172
|
-
return this;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Gelişmiş mesaj işleme (otomasyon + onay)
|
|
177
|
-
*/
|
|
178
|
-
async handleMessage(message, meta = { channel: 'local', from: 'local' }) {
|
|
179
|
-
if (!this.initialized) await this.initialize();
|
|
180
|
-
if (this.automation) {
|
|
181
|
-
const result = await this.automation.handleMessage(message, meta);
|
|
182
|
-
if (result?.handled) {
|
|
183
|
-
return result.response;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return await this.chat(message);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Gateway otomatik başlatılsın mı?
|
|
191
|
-
*/
|
|
192
|
-
_shouldAutoStartGateway() {
|
|
193
|
-
const envValue = this.env.VANTUZ_GATEWAY_AUTOSTART;
|
|
194
|
-
if (envValue !== undefined) {
|
|
195
|
-
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
196
|
-
}
|
|
197
|
-
if (this.config && this.config.gatewayAutoStart !== undefined) {
|
|
198
|
-
return this.config.gatewayAutoStart !== false;
|
|
199
|
-
}
|
|
200
|
-
return true;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
_shouldStartBridge() {
|
|
204
|
-
const envValue = this.env.VANTUZ_OPENCLAW_BRIDGE;
|
|
205
|
-
if (envValue !== undefined) {
|
|
206
|
-
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
207
|
-
}
|
|
208
|
-
if (this.config && this.config.openclawBridge !== undefined) {
|
|
209
|
-
return this.config.openclawBridge !== false;
|
|
210
|
-
}
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Gelişmiş mesaj işleme (otomasyon + onay)
|
|
170
|
+
*/
|
|
171
|
+
async handleMessage(message, meta = { channel: 'local', from: 'local' }) {
|
|
172
|
+
if (!this.initialized) await this.initialize();
|
|
173
|
+
if (this.automation) {
|
|
174
|
+
const result = await this.automation.handleMessage(message, meta);
|
|
175
|
+
if (result?.handled) {
|
|
176
|
+
return result.response;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return await this.chat(message);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Gateway otomatik başlatılsın mı?
|
|
184
|
+
*/
|
|
185
|
+
_shouldAutoStartGateway() {
|
|
186
|
+
const envValue = this.env.VANTUZ_GATEWAY_AUTOSTART;
|
|
187
|
+
if (envValue !== undefined) {
|
|
188
|
+
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
189
|
+
}
|
|
190
|
+
if (this.config && this.config.gatewayAutoStart !== undefined) {
|
|
191
|
+
return this.config.gatewayAutoStart !== false;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
_shouldStartBridge() {
|
|
197
|
+
const envValue = this.env.VANTUZ_OPENCLAW_BRIDGE;
|
|
198
|
+
if (envValue !== undefined) {
|
|
199
|
+
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
200
|
+
}
|
|
201
|
+
if (this.config && this.config.openclawBridge !== undefined) {
|
|
202
|
+
return this.config.openclawBridge !== false;
|
|
203
|
+
}
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
213
206
|
|
|
214
207
|
/**
|
|
215
208
|
* Config dosyasını yükle
|
|
@@ -252,60 +245,23 @@ export class VantuzEngine {
|
|
|
252
245
|
for (const platformName in PLATFORM_CONFIG_MAP) {
|
|
253
246
|
const platformMap = PLATFORM_CONFIG_MAP[platformName];
|
|
254
247
|
|
|
255
|
-
if (
|
|
256
|
-
const
|
|
257
|
-
let
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
248
|
+
if (platformMap.envPrefix && platformMap.keys) { // Handle all platforms with direct keys
|
|
249
|
+
const config = {};
|
|
250
|
+
let hasRequiredEnv = false;
|
|
251
|
+
for (const key of platformMap.keys) {
|
|
252
|
+
const upper = key.toUpperCase();
|
|
253
|
+
const snake = key.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
254
|
+
const envKey = `${platformMap.envPrefix}_${upper}`;
|
|
255
|
+
const altEnvKey = `${platformMap.envPrefix}_${snake}`;
|
|
256
|
+
const value = this.env[envKey] || this.env[altEnvKey];
|
|
257
|
+
if (value) {
|
|
258
|
+
config[key] = value;
|
|
259
|
+
hasRequiredEnv = true;
|
|
267
260
|
}
|
|
268
261
|
}
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
hasAmazonEnv = true;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Handle US configuration (add similar logic here if needed)
|
|
275
|
-
const usConfig = {};
|
|
276
|
-
let hasUsEnv = false;
|
|
277
|
-
for (const key of PLATFORM_CONFIG_MAP.amazon.nested.us.keys) {
|
|
278
|
-
const envKey = `AMAZON_US_${key.toUpperCase()}`; // Assuming US specific env keys
|
|
279
|
-
if (this.env[envKey]) {
|
|
280
|
-
usConfig[key] = this.env[envKey];
|
|
281
|
-
hasUsEnv = true;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
if (hasUsEnv) {
|
|
285
|
-
amazonConfig.us = usConfig;
|
|
286
|
-
hasAmazonEnv = true;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (hasAmazonEnv) {
|
|
290
|
-
platformConfig[platformName] = amazonConfig;
|
|
262
|
+
if (hasRequiredEnv) {
|
|
263
|
+
platformConfig[platformName] = config;
|
|
291
264
|
}
|
|
292
|
-
} else if (platformMap.envPrefix && platformMap.keys) { // Handle other platforms with direct keys
|
|
293
|
-
const config = {};
|
|
294
|
-
let hasRequiredEnv = false;
|
|
295
|
-
for (const key of platformMap.keys) {
|
|
296
|
-
const upper = key.toUpperCase();
|
|
297
|
-
const snake = key.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
298
|
-
const envKey = `${platformMap.envPrefix}_${upper}`;
|
|
299
|
-
const altEnvKey = `${platformMap.envPrefix}_${snake}`;
|
|
300
|
-
const value = this.env[envKey] || this.env[altEnvKey];
|
|
301
|
-
if (value) {
|
|
302
|
-
config[key] = value;
|
|
303
|
-
hasRequiredEnv = true;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (hasRequiredEnv) {
|
|
307
|
-
platformConfig[platformName] = config;
|
|
308
|
-
}
|
|
309
265
|
}
|
|
310
266
|
}
|
|
311
267
|
|
|
@@ -324,50 +280,50 @@ export class VantuzEngine {
|
|
|
324
280
|
async _buildContext() {
|
|
325
281
|
this.context.connectedPlatforms = platformHub.getConnected();
|
|
326
282
|
|
|
327
|
-
for (const platform of this.context.connectedPlatforms) {
|
|
328
|
-
try {
|
|
329
|
-
const api = platformHub.resolve(platform);
|
|
330
|
-
if (api && typeof api.getProducts === 'function') {
|
|
331
|
-
const result = await api.getProducts({ page: 0, size: 10 });
|
|
332
|
-
if (result?.success) {
|
|
333
|
-
const data = result.data;
|
|
334
|
-
let products = [];
|
|
335
|
-
if (Array.isArray(data?.content)) products = data.content;
|
|
336
|
-
else if (Array.isArray(data)) products = data;
|
|
337
|
-
else if (Array.isArray(data?.productList?.product)) products = data.productList.product;
|
|
338
|
-
if (products.length > 0) {
|
|
339
|
-
this.context.products.push(...products.map(p => ({
|
|
340
|
-
...p,
|
|
341
|
-
_platform: platform
|
|
342
|
-
})));
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
} catch (e) {
|
|
347
|
-
log('ERROR', `${platform} veri çekme hatası`, { error: e.message });
|
|
348
|
-
}
|
|
349
|
-
}
|
|
283
|
+
for (const platform of this.context.connectedPlatforms) {
|
|
284
|
+
try {
|
|
285
|
+
const api = platformHub.resolve(platform);
|
|
286
|
+
if (api && typeof api.getProducts === 'function') {
|
|
287
|
+
const result = await api.getProducts({ page: 0, size: 10 });
|
|
288
|
+
if (result?.success) {
|
|
289
|
+
const data = result.data;
|
|
290
|
+
let products = [];
|
|
291
|
+
if (Array.isArray(data?.content)) products = data.content;
|
|
292
|
+
else if (Array.isArray(data)) products = data;
|
|
293
|
+
else if (Array.isArray(data?.productList?.product)) products = data.productList.product;
|
|
294
|
+
if (products.length > 0) {
|
|
295
|
+
this.context.products.push(...products.map(p => ({
|
|
296
|
+
...p,
|
|
297
|
+
_platform: platform
|
|
298
|
+
})));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
} catch (e) {
|
|
303
|
+
log('ERROR', `${platform} veri çekme hatası`, { error: e.message });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
350
306
|
}
|
|
351
307
|
|
|
352
308
|
/**
|
|
353
309
|
* AI ile sohbet - Tool destekli
|
|
354
310
|
*/
|
|
355
|
-
async chat(message) {
|
|
356
|
-
if (!this.initialized) await this.initialize();
|
|
357
|
-
|
|
358
|
-
// 1. Basit komut kontrolü (Tool çağırma)
|
|
359
|
-
const toolResult = await this._tryExecuteToolFromMessage(message);
|
|
360
|
-
if (toolResult) return toolResult;
|
|
361
|
-
|
|
362
|
-
// 1.5 Gelişmiş ajan (araç çağrıları)
|
|
363
|
-
const agentResult = await this._tryAgent(message);
|
|
364
|
-
if (agentResult) return agentResult;
|
|
365
|
-
|
|
366
|
-
// 2. Gateway üzerinden AI (Eğer varsa)
|
|
367
|
-
if (this.gateway?.isConnected()) {
|
|
368
|
-
try {
|
|
369
|
-
const gatewayResult = await this.gateway.chat(message, {
|
|
370
|
-
systemPrompt: this._buildContextInfo()
|
|
311
|
+
async chat(message) {
|
|
312
|
+
if (!this.initialized) await this.initialize();
|
|
313
|
+
|
|
314
|
+
// 1. Basit komut kontrolü (Tool çağırma)
|
|
315
|
+
const toolResult = await this._tryExecuteToolFromMessage(message);
|
|
316
|
+
if (toolResult) return toolResult;
|
|
317
|
+
|
|
318
|
+
// 1.5 Gelişmiş ajan (araç çağrıları)
|
|
319
|
+
const agentResult = await this._tryAgent(message);
|
|
320
|
+
if (agentResult) return agentResult;
|
|
321
|
+
|
|
322
|
+
// 2. Gateway üzerinden AI (Eğer varsa)
|
|
323
|
+
if (this.gateway?.isConnected()) {
|
|
324
|
+
try {
|
|
325
|
+
const gatewayResult = await this.gateway.chat(message, {
|
|
326
|
+
systemPrompt: this._buildContextInfo()
|
|
371
327
|
});
|
|
372
328
|
if (gatewayResult.success) return gatewayResult.response;
|
|
373
329
|
} catch (e) { }
|
|
@@ -376,98 +332,99 @@ export class VantuzEngine {
|
|
|
376
332
|
// 3. Direkt API (Fallback)
|
|
377
333
|
const enrichedConfig = {
|
|
378
334
|
...this.config,
|
|
335
|
+
aiProvider: this.env.AI_PROVIDER || this.config.aiProvider || 'gemini',
|
|
379
336
|
systemContext: this._buildContextInfo()
|
|
380
337
|
};
|
|
381
338
|
|
|
382
|
-
return await aiChat(message, enrichedConfig, this.env);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
async _tryAgent(message) {
|
|
386
|
-
const mode = this.config?.agentMode || this.env.VANTUZ_AGENT_MODE;
|
|
387
|
-
if (!mode || mode === 'off') return null;
|
|
388
|
-
|
|
389
|
-
const systemPrompt = [
|
|
390
|
-
'Sen Vantuz gelişmiş ajanısın.',
|
|
391
|
-
'Gerekirse aşağıdaki araçlardan birini çağır:',
|
|
392
|
-
'exec, readFile, listDir, httpGet, apiQuery',
|
|
393
|
-
'Sadece JSON döndür.',
|
|
394
|
-
'Şema: { "tool": "exec|readFile|listDir|httpGet|apiQuery", "args": { ... } }',
|
|
395
|
-
'apiQuery args: { "platform": "n11|trendyol|hepsiburada|amazon|ciceksepeti|pazarama|pttavm", "action": "orders|products|stock|categories", "params": { ... } }',
|
|
396
|
-
'Eğer araç gerekmezse: { "final": "cevap" }',
|
|
397
|
-
'Dosya yollarını ve komutları kısa tut.'
|
|
398
|
-
].join('\n');
|
|
399
|
-
|
|
400
|
-
const plan = await aiChat(message, {
|
|
401
|
-
aiProvider: this.config.aiProvider || 'gemini',
|
|
402
|
-
systemContext: systemPrompt
|
|
403
|
-
}, this.env);
|
|
404
|
-
|
|
405
|
-
const jsonMatch = plan.match(/\{[\s\S]*\}/);
|
|
406
|
-
if (!jsonMatch) return null;
|
|
407
|
-
let obj;
|
|
408
|
-
try { obj = JSON.parse(jsonMatch[0]); } catch { return null; }
|
|
409
|
-
if (obj.final) return obj.final;
|
|
410
|
-
if (!obj.tool) return null;
|
|
411
|
-
|
|
412
|
-
let toolResult;
|
|
413
|
-
if (obj.tool === 'apiQuery') {
|
|
414
|
-
toolResult = await this._runApiQuery(obj.args || {});
|
|
415
|
-
} else {
|
|
416
|
-
toolResult = await executeTool(obj.tool, obj.args || {}, this.config);
|
|
417
|
-
}
|
|
418
|
-
const followup = await aiChat(
|
|
419
|
-
`Kullanıcı mesajı: ${message}\nAraç çıktısı:\n${toolResult.output}\nCevap ver.`,
|
|
420
|
-
{ aiProvider: this.config.aiProvider || 'gemini' },
|
|
421
|
-
this.env
|
|
422
|
-
);
|
|
423
|
-
return followup;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
async _runApiQuery(args = {}) {
|
|
427
|
-
const platform = (args.platform || '').toLowerCase();
|
|
428
|
-
const action = (args.action || '').toLowerCase();
|
|
429
|
-
const params = args.params || {};
|
|
430
|
-
const api = platformHub.resolve(platform);
|
|
431
|
-
if (!api) return { success: false, output: 'Platform bulunamadı.' };
|
|
432
|
-
|
|
433
|
-
try {
|
|
434
|
-
if (action === 'orders' && api.getOrders) {
|
|
435
|
-
const result = await api.getOrders(params);
|
|
436
|
-
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
437
|
-
}
|
|
438
|
-
if (action === 'products' && api.getProducts) {
|
|
439
|
-
const result = await api.getProducts(params);
|
|
440
|
-
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
441
|
-
}
|
|
442
|
-
if (action === 'stock' && api.getProducts) {
|
|
443
|
-
const result = await api.getProducts(params);
|
|
444
|
-
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
445
|
-
}
|
|
446
|
-
if (action === 'categories' && api.getTopCategories) {
|
|
447
|
-
const result = await api.getTopCategories(params);
|
|
448
|
-
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
449
|
-
}
|
|
450
|
-
return { success: false, output: 'Bu platform için istenen action desteklenmiyor.' };
|
|
451
|
-
} catch (e) {
|
|
452
|
-
return { success: false, output: e.message };
|
|
453
|
-
}
|
|
454
|
-
}
|
|
339
|
+
return await aiChat(message, enrichedConfig, this.env);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async _tryAgent(message) {
|
|
343
|
+
const mode = this.config?.agentMode || this.env.VANTUZ_AGENT_MODE;
|
|
344
|
+
if (!mode || mode === 'off') return null;
|
|
345
|
+
|
|
346
|
+
const systemPrompt = [
|
|
347
|
+
'Sen Vantuz gelişmiş ajanısın.',
|
|
348
|
+
'Gerekirse aşağıdaki araçlardan birini çağır:',
|
|
349
|
+
'exec, readFile, listDir, httpGet, apiQuery',
|
|
350
|
+
'Sadece JSON döndür.',
|
|
351
|
+
'Şema: { "tool": "exec|readFile|listDir|httpGet|apiQuery", "args": { ... } }',
|
|
352
|
+
'apiQuery args: { "platform": "n11|trendyol|hepsiburada|amazon|ciceksepeti|pazarama|pttavm", "action": "orders|products|stock|categories", "params": { ... } }',
|
|
353
|
+
'Eğer araç gerekmezse: { "final": "cevap" }',
|
|
354
|
+
'Dosya yollarını ve komutları kısa tut.'
|
|
355
|
+
].join('\n');
|
|
356
|
+
|
|
357
|
+
const plan = await aiChat(message, {
|
|
358
|
+
aiProvider: this.config.aiProvider || 'gemini',
|
|
359
|
+
systemContext: systemPrompt
|
|
360
|
+
}, this.env);
|
|
361
|
+
|
|
362
|
+
const jsonMatch = plan.match(/\{[\s\S]*\}/);
|
|
363
|
+
if (!jsonMatch) return null;
|
|
364
|
+
let obj;
|
|
365
|
+
try { obj = JSON.parse(jsonMatch[0]); } catch { return null; }
|
|
366
|
+
if (obj.final) return obj.final;
|
|
367
|
+
if (!obj.tool) return null;
|
|
368
|
+
|
|
369
|
+
let toolResult;
|
|
370
|
+
if (obj.tool === 'apiQuery') {
|
|
371
|
+
toolResult = await this._runApiQuery(obj.args || {});
|
|
372
|
+
} else {
|
|
373
|
+
toolResult = await executeTool(obj.tool, obj.args || {}, this.config);
|
|
374
|
+
}
|
|
375
|
+
const followup = await aiChat(
|
|
376
|
+
`Kullanıcı mesajı: ${message}\nAraç çıktısı:\n${toolResult.output}\nCevap ver.`,
|
|
377
|
+
{ aiProvider: this.config.aiProvider || 'gemini' },
|
|
378
|
+
this.env
|
|
379
|
+
);
|
|
380
|
+
return followup;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async _runApiQuery(args = {}) {
|
|
384
|
+
const platform = (args.platform || '').toLowerCase();
|
|
385
|
+
const action = (args.action || '').toLowerCase();
|
|
386
|
+
const params = args.params || {};
|
|
387
|
+
const api = platformHub.resolve(platform);
|
|
388
|
+
if (!api) return { success: false, output: 'Platform bulunamadı.' };
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
if (action === 'orders' && api.getOrders) {
|
|
392
|
+
const result = await api.getOrders(params);
|
|
393
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
394
|
+
}
|
|
395
|
+
if (action === 'products' && api.getProducts) {
|
|
396
|
+
const result = await api.getProducts(params);
|
|
397
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
398
|
+
}
|
|
399
|
+
if (action === 'stock' && api.getProducts) {
|
|
400
|
+
const result = await api.getProducts(params);
|
|
401
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
402
|
+
}
|
|
403
|
+
if (action === 'categories' && api.getTopCategories) {
|
|
404
|
+
const result = await api.getTopCategories(params);
|
|
405
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
406
|
+
}
|
|
407
|
+
return { success: false, output: 'Bu platform için istenen action desteklenmiyor.' };
|
|
408
|
+
} catch (e) {
|
|
409
|
+
return { success: false, output: e.message };
|
|
410
|
+
}
|
|
411
|
+
}
|
|
455
412
|
|
|
456
413
|
/**
|
|
457
414
|
* Mesajdan Tool tespiti (Basit NLP)
|
|
458
415
|
*/
|
|
459
|
-
async _tryExecuteToolFromMessage(message) {
|
|
460
|
-
const lower = message.toLowerCase().trim();
|
|
461
|
-
const normalized = lower
|
|
462
|
-
.replace(/[çÇ]/g, 'c')
|
|
463
|
-
.replace(/[ğĞ]/g, 'g')
|
|
464
|
-
.replace(/[ıİ]/g, 'i')
|
|
465
|
-
.replace(/[öÖ]/g, 'o')
|
|
466
|
-
.replace(/[şŞ]/g, 's')
|
|
467
|
-
.replace(/[üÜ]/g, 'u');
|
|
468
|
-
|
|
469
|
-
// Check for explicit commands
|
|
470
|
-
if (lower.startsWith('/')) {
|
|
416
|
+
async _tryExecuteToolFromMessage(message) {
|
|
417
|
+
const lower = message.toLowerCase().trim();
|
|
418
|
+
const normalized = lower
|
|
419
|
+
.replace(/[çÇ]/g, 'c')
|
|
420
|
+
.replace(/[ğĞ]/g, 'g')
|
|
421
|
+
.replace(/[ıİ]/g, 'i')
|
|
422
|
+
.replace(/[öÖ]/g, 'o')
|
|
423
|
+
.replace(/[şŞ]/g, 's')
|
|
424
|
+
.replace(/[üÜ]/g, 'u');
|
|
425
|
+
|
|
426
|
+
// Check for explicit commands
|
|
427
|
+
if (lower.startsWith('/')) {
|
|
471
428
|
const parts = lower.substring(1).split(' ');
|
|
472
429
|
const command = parts[0];
|
|
473
430
|
const args = parts.slice(1);
|
|
@@ -485,63 +442,63 @@ export class VantuzEngine {
|
|
|
485
442
|
case 'help':
|
|
486
443
|
return "Kullanabileceğin komutlar: /rakip, /stok-durumu";
|
|
487
444
|
default:
|
|
488
|
-
return `Bilinmeyen komut: /${command}. Yardım için /help yazabilirsin.`;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Natural language shortcuts (no hallucination)
|
|
493
|
-
if (
|
|
494
|
-
lower.includes('hangi pazaryerleri bağlı') ||
|
|
495
|
-
lower.includes('hangi pazaryeri bağlı') ||
|
|
496
|
-
lower.includes('hangi platformlar bağlı') ||
|
|
497
|
-
normalized.includes('hangi pazaryerleri bagli') ||
|
|
498
|
-
normalized.includes('hangi platformlar bagli')
|
|
499
|
-
) {
|
|
500
|
-
const connected = this.context.connectedPlatforms;
|
|
501
|
-
if (connected.length === 0) return 'Şu an bağlı pazaryeri yok.';
|
|
502
|
-
return `Bağlı pazaryerleri: ${connected.map(p => p.toUpperCase()).join(', ')}`;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const orderKeywords = [
|
|
506
|
-
'sipariş',
|
|
507
|
-
'siparis'
|
|
508
|
-
];
|
|
509
|
-
const hasOrderKeyword = orderKeywords.some(k => lower.includes(k) || normalized.includes(k));
|
|
510
|
-
|
|
511
|
-
if (hasOrderKeyword) {
|
|
512
|
-
const orders = await this.getOrders({ size: 50, allStatuses: true });
|
|
513
|
-
if (!orders || orders.length === 0) {
|
|
514
|
-
return 'Sipariş verisine ulaşılamadı. Lütfen platform API bağlantılarını kontrol edin.';
|
|
515
|
-
}
|
|
516
|
-
const summary = this._summarizeOrdersByStatus(orders);
|
|
517
|
-
return `Şu an bağlı platformlardan gelen toplam ${orders.length} sipariş var.${summary ? ` Durum kırılımı: ${summary}` : ''}`;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
if (lower.includes('onaylanan')) {
|
|
521
|
-
const orders = await this.getOrders({ size: 100, status: 'Picking' });
|
|
522
|
-
return `Şu an onaylanan (Picking) ${orders.length} sipariş var.`;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
if (lower.includes('kargoya verilmemiş') || lower.includes('henüz kargoya') || lower.includes('kargoya verilmedi') || normalized.includes('kargoya verilmemis')) {
|
|
526
|
-
const orders = await this.getOrders({ size: 100, status: 'Created' });
|
|
527
|
-
return `Şu an kargoya verilmemiş (Created) ${orders.length} sipariş var.`;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
return null;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
_summarizeOrdersByStatus(orders = []) {
|
|
534
|
-
if (!Array.isArray(orders) || orders.length === 0) return '';
|
|
535
|
-
const counts = {};
|
|
536
|
-
orders.forEach(o => {
|
|
537
|
-
const s = (o.status || o.shipmentPackageStatus || o.orderStatus || 'UNKNOWN').toString();
|
|
538
|
-
counts[s] = (counts[s] || 0) + 1;
|
|
539
|
-
});
|
|
540
|
-
const entries = Object.entries(counts)
|
|
541
|
-
.sort((a, b) => b[1] - a[1])
|
|
542
|
-
.map(([s, n]) => `${s}:${n}`);
|
|
543
|
-
return entries.join(', ');
|
|
544
|
-
}
|
|
445
|
+
return `Bilinmeyen komut: /${command}. Yardım için /help yazabilirsin.`;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Natural language shortcuts (no hallucination)
|
|
450
|
+
if (
|
|
451
|
+
lower.includes('hangi pazaryerleri bağlı') ||
|
|
452
|
+
lower.includes('hangi pazaryeri bağlı') ||
|
|
453
|
+
lower.includes('hangi platformlar bağlı') ||
|
|
454
|
+
normalized.includes('hangi pazaryerleri bagli') ||
|
|
455
|
+
normalized.includes('hangi platformlar bagli')
|
|
456
|
+
) {
|
|
457
|
+
const connected = this.context.connectedPlatforms;
|
|
458
|
+
if (connected.length === 0) return 'Şu an bağlı pazaryeri yok.';
|
|
459
|
+
return `Bağlı pazaryerleri: ${connected.map(p => p.toUpperCase()).join(', ')}`;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const orderKeywords = [
|
|
463
|
+
'sipariş',
|
|
464
|
+
'siparis'
|
|
465
|
+
];
|
|
466
|
+
const hasOrderKeyword = orderKeywords.some(k => lower.includes(k) || normalized.includes(k));
|
|
467
|
+
|
|
468
|
+
if (hasOrderKeyword) {
|
|
469
|
+
const orders = await this.getOrders({ size: 50, allStatuses: true });
|
|
470
|
+
if (!orders || orders.length === 0) {
|
|
471
|
+
return 'Sipariş verisine ulaşılamadı. Lütfen platform API bağlantılarını kontrol edin.';
|
|
472
|
+
}
|
|
473
|
+
const summary = this._summarizeOrdersByStatus(orders);
|
|
474
|
+
return `Şu an bağlı platformlardan gelen toplam ${orders.length} sipariş var.${summary ? ` Durum kırılımı: ${summary}` : ''}`;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (lower.includes('onaylanan')) {
|
|
478
|
+
const orders = await this.getOrders({ size: 100, status: 'Picking' });
|
|
479
|
+
return `Şu an onaylanan (Picking) ${orders.length} sipariş var.`;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (lower.includes('kargoya verilmemiş') || lower.includes('henüz kargoya') || lower.includes('kargoya verilmedi') || normalized.includes('kargoya verilmemis')) {
|
|
483
|
+
const orders = await this.getOrders({ size: 100, status: 'Created' });
|
|
484
|
+
return `Şu an kargoya verilmemiş (Created) ${orders.length} sipariş var.`;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return null;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
_summarizeOrdersByStatus(orders = []) {
|
|
491
|
+
if (!Array.isArray(orders) || orders.length === 0) return '';
|
|
492
|
+
const counts = {};
|
|
493
|
+
orders.forEach(o => {
|
|
494
|
+
const s = (o.status || o.shipmentPackageStatus || o.orderStatus || 'UNKNOWN').toString();
|
|
495
|
+
counts[s] = (counts[s] || 0) + 1;
|
|
496
|
+
});
|
|
497
|
+
const entries = Object.entries(counts)
|
|
498
|
+
.sort((a, b) => b[1] - a[1])
|
|
499
|
+
.map(([s, n]) => `${s}:${n}`);
|
|
500
|
+
return entries.join(', ');
|
|
501
|
+
}
|
|
545
502
|
|
|
546
503
|
/**
|
|
547
504
|
* Context bilgisi oluştur (AI system prompt için)
|
|
@@ -609,7 +566,7 @@ export class VantuzEngine {
|
|
|
609
566
|
return {
|
|
610
567
|
engine: this.initialized ? 'active' : 'inactive',
|
|
611
568
|
version: '3.2',
|
|
612
|
-
aiProvider: this.config.aiProvider || 'gemini',
|
|
569
|
+
aiProvider: this.env.AI_PROVIDER || this.config.aiProvider || 'gemini',
|
|
613
570
|
gateway: gatewayInfo,
|
|
614
571
|
platforms: status,
|
|
615
572
|
channels: channelStatus,
|
package/core/gateway.js
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* - Sistem durumu sorgulama
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import axios from 'axios';
|
|
13
|
-
import fs from 'fs';
|
|
14
|
-
import path from 'path';
|
|
15
|
-
import os from 'os';
|
|
16
|
-
import { log } from './ai-provider.js';
|
|
12
|
+
import axios from 'axios';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import os from 'os';
|
|
16
|
+
import { log } from './ai-provider.js';
|
|
17
17
|
|
|
18
18
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
19
19
|
// CONFIG - Gateway ayarları
|
|
@@ -42,15 +42,15 @@ function getGatewayToken(config) {
|
|
|
42
42
|
// GATEWAY CLIENT
|
|
43
43
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
44
|
|
|
45
|
-
export class VantuzGateway {
|
|
45
|
+
export class VantuzGateway {
|
|
46
46
|
constructor() {
|
|
47
47
|
this.config = loadGatewayConfig();
|
|
48
48
|
const port = this.config?.gateway?.port || 18789;
|
|
49
49
|
this.baseUrl = `http://localhost:${port}`;
|
|
50
50
|
this.token = getGatewayToken(this.config);
|
|
51
51
|
this.connected = false;
|
|
52
|
-
this.version = null;
|
|
53
|
-
}
|
|
52
|
+
this.version = null;
|
|
53
|
+
}
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* HTTP Headers (token auth)
|
|
@@ -101,66 +101,137 @@ export class VantuzGateway {
|
|
|
101
101
|
/**
|
|
102
102
|
* Gateway sağlık kontrolü
|
|
103
103
|
*/
|
|
104
|
-
async health() {
|
|
105
|
-
const result = await this._request('GET', '/health');
|
|
106
|
-
this.connected = result.success;
|
|
107
|
-
if (result.success) {
|
|
108
|
-
this.version = result.data?.version || 'unknown';
|
|
109
|
-
}
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Gateway sürecini başlat
|
|
115
|
-
*/
|
|
116
|
-
async start() {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
104
|
+
async health() {
|
|
105
|
+
const result = await this._request('GET', '/health');
|
|
106
|
+
this.connected = result.success;
|
|
107
|
+
if (result.success) {
|
|
108
|
+
this.version = result.data?.version || 'unknown';
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gateway sürecini başlat
|
|
115
|
+
*/
|
|
116
|
+
async start() {
|
|
117
|
+
const cwd = process.cwd();
|
|
118
|
+
const gatewayCmd = path.join(cwd, '.openclaw', 'gateway.cmd');
|
|
119
|
+
const isWin = process.platform === 'win32';
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const { spawn } = await import('child_process');
|
|
123
|
+
let child;
|
|
124
|
+
|
|
125
|
+
if (isWin && fs.existsSync(gatewayCmd)) {
|
|
126
|
+
// Windows: Use generated CMD (has config env vars)
|
|
127
|
+
child = spawn(gatewayCmd, [], {
|
|
128
|
+
detached: true,
|
|
129
|
+
stdio: 'ignore', // Keep it in background
|
|
130
|
+
shell: true,
|
|
131
|
+
cwd // Ensure CWD is correct for finding node_modules
|
|
132
|
+
});
|
|
133
|
+
} else {
|
|
134
|
+
// Linux/Mac or missing CMD: Use npx directly
|
|
135
|
+
// We try to load token from config if possible to pass as ENV
|
|
136
|
+
const env = { ...process.env };
|
|
137
|
+
if (this.config?.gateway?.auth?.token) {
|
|
138
|
+
env.OPENCLAW_GATEWAY_TOKEN = this.config.gateway.auth.token;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
child = spawn('npx', ['openclaw', 'gateway', '--port', '18789', '--allow-unconfigured'], {
|
|
142
|
+
detached: true,
|
|
143
|
+
stdio: 'ignore',
|
|
144
|
+
shell: true,
|
|
145
|
+
cwd,
|
|
146
|
+
env
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (child) {
|
|
151
|
+
child.unref(); // Detach process so it outlives parent
|
|
152
|
+
return { success: true };
|
|
153
|
+
}
|
|
154
|
+
return { success: false, error: 'Child process could not be spawned' };
|
|
155
|
+
|
|
156
|
+
} catch (e) {
|
|
157
|
+
return { success: false, error: e.message };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Vantuz API Server (server/app.js) başlat
|
|
163
|
+
*/
|
|
164
|
+
async startServer() {
|
|
165
|
+
const serverPath = path.join(process.cwd(), 'server', 'app.js');
|
|
166
|
+
if (!fs.existsSync(serverPath)) {
|
|
167
|
+
return { success: false, error: 'Server dosyası bulunamadı: server/app.js' };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
const { spawn } = await import('child_process');
|
|
172
|
+
const child = spawn('node', [serverPath], {
|
|
173
|
+
detached: true,
|
|
174
|
+
stdio: 'ignore',
|
|
175
|
+
shell: true,
|
|
176
|
+
cwd: process.cwd(),
|
|
177
|
+
env: { ...process.env, PORT: '3001' } // Ensure default port
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
child.unref();
|
|
181
|
+
return { success: true };
|
|
182
|
+
} catch (e) {
|
|
183
|
+
return { success: false, error: e.message };
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Tüm sistemi başlat (Gateway + Server)
|
|
189
|
+
*/
|
|
190
|
+
async startFullStack() {
|
|
191
|
+
// 1. Start Gateway
|
|
192
|
+
const gwResult = await this.start();
|
|
193
|
+
|
|
194
|
+
// 2. Wait for Gateway to initialize (approx 3s)
|
|
195
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
196
|
+
|
|
197
|
+
// 3. Start Server
|
|
198
|
+
const serverResult = await this.startServer();
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
success: gwResult.success && serverResult.success,
|
|
202
|
+
gateway: gwResult,
|
|
203
|
+
server: serverResult
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Gateway çalışmıyorsa başlat ve sağlık kontrolü yap
|
|
209
|
+
*/
|
|
210
|
+
async ensureRunning(options = {}) {
|
|
211
|
+
const {
|
|
212
|
+
retries = 5,
|
|
213
|
+
intervalMs = 1000
|
|
214
|
+
} = options;
|
|
215
|
+
|
|
216
|
+
if (this.isConnected()) {
|
|
217
|
+
return { success: true, already: true };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const started = await this.start();
|
|
221
|
+
if (!started.success) {
|
|
222
|
+
return started;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for (let i = 0; i < retries; i++) {
|
|
226
|
+
await new Promise(r => setTimeout(r, intervalMs));
|
|
227
|
+
const health = await this.health();
|
|
228
|
+
if (health.success) {
|
|
229
|
+
return { success: true, started: true };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return { success: false, error: 'Gateway başlatıldı ancak sağlık kontrolü geçmedi' };
|
|
234
|
+
}
|
|
164
235
|
|
|
165
236
|
/**
|
|
166
237
|
* Detaylı sistem durumu
|
package/package.json
CHANGED
package/platforms/amazon.js
CHANGED
|
@@ -4,7 +4,10 @@ export default {
|
|
|
4
4
|
description: 'Global E-ticaret Platformu',
|
|
5
5
|
requiredFields: [
|
|
6
6
|
{ key: 'sellerId', label: 'Seller ID', env: 'AMAZON_SELLER_ID' },
|
|
7
|
-
{ key: '
|
|
7
|
+
{ key: 'clientId', label: 'Client ID (LWA)', env: 'AMAZON_CLIENT_ID' },
|
|
8
|
+
{ key: 'clientSecret', label: 'Client Secret (LWA)', env: 'AMAZON_CLIENT_SECRET' },
|
|
9
|
+
{ key: 'refreshToken', label: 'Refresh Token', env: 'AMAZON_REFRESH_TOKEN' },
|
|
10
|
+
{ key: 'region', label: 'Bölge (eu/na/tr)', env: 'AMAZON_REGION', default: 'eu' }
|
|
8
11
|
],
|
|
9
12
|
async getOrders(creds) {
|
|
10
13
|
// Stub
|
package/platforms/ciceksepeti.js
CHANGED
|
@@ -3,7 +3,8 @@ export default {
|
|
|
3
3
|
icon: '🌸', // Flower icon for ÇiçekSepeti
|
|
4
4
|
description: 'Entegre Çevrimiçi Çiçek ve Hediye Platformu',
|
|
5
5
|
requiredFields: [
|
|
6
|
-
{ key: 'apiKey', label: 'API Key', env: 'CICEKSEPETI_API_KEY' }
|
|
6
|
+
{ key: 'apiKey', label: 'API Key', env: 'CICEKSEPETI_API_KEY' },
|
|
7
|
+
{ key: 'supplierId', label: 'Supplier ID', env: 'CICEKSEPETI_SUPPLIER_ID' }
|
|
7
8
|
],
|
|
8
9
|
async getOrders(creds) {
|
|
9
10
|
// Stub
|
package/platforms/n11.js
CHANGED
|
@@ -3,8 +3,8 @@ export default {
|
|
|
3
3
|
icon: '🔵', // Blue circle icon for N11
|
|
4
4
|
description: 'Alternatif E-ticaret Platformu',
|
|
5
5
|
requiredFields: [
|
|
6
|
-
{ key: 'apiKey', label: '
|
|
7
|
-
{ key: 'apiSecret', label: '
|
|
6
|
+
{ key: 'apiKey', label: 'App Key', env: 'N11_API_KEY' },
|
|
7
|
+
{ key: 'apiSecret', label: 'App Secret', env: 'N11_API_SECRET' }
|
|
8
8
|
],
|
|
9
9
|
async getOrders(creds) {
|
|
10
10
|
// Stub
|
package/platforms/pazarama.js
CHANGED
|
@@ -3,7 +3,8 @@ export default {
|
|
|
3
3
|
icon: '🛒', // Shopping cart icon for Pazarama
|
|
4
4
|
description: 'Yeni Nesil Mobil Alışveriş Platformu',
|
|
5
5
|
requiredFields: [
|
|
6
|
-
{ key: '
|
|
6
|
+
{ key: 'clientId', label: 'Client ID', env: 'PAZARAMA_CLIENT_ID' },
|
|
7
|
+
{ key: 'clientSecret', label: 'Client Secret', env: 'PAZARAMA_CLIENT_SECRET' }
|
|
7
8
|
],
|
|
8
9
|
async getOrders(creds) {
|
|
9
10
|
// Stub
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
name: 'PttAVM',
|
|
3
|
+
icon: '📮', // Postbox icon for PttAVM
|
|
4
|
+
description: 'Türkiye\'nin Güvenilir E-ticaret Platformu',
|
|
5
|
+
requiredFields: [
|
|
6
|
+
{ key: 'apiKey', label: 'API Key', env: 'PTTAVM_API_KEY' },
|
|
7
|
+
{ key: 'token', label: 'Token', env: 'PTTAVM_TOKEN' },
|
|
8
|
+
{ key: 'shopId', label: 'Shop ID', env: 'PTTAVM_SHOP_ID' }
|
|
9
|
+
],
|
|
10
|
+
async getOrders(creds) {
|
|
11
|
+
// Stub
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
};
|