vantuz 3.3.5 → 3.3.7
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/README.md +62 -26
- package/config.js +55 -8
- package/core/agent-loop.js +190 -0
- package/core/ai-provider.js +41 -7
- package/core/automation.js +43 -24
- package/core/dashboard.js +230 -0
- package/core/engine.js +323 -339
- package/core/gateway.js +139 -68
- package/core/learning.js +214 -0
- package/core/marketplace-adapter.js +168 -0
- package/core/memory.js +190 -0
- package/core/queue.js +120 -0
- package/core/scheduler.js +111 -31
- package/core/self-healer.js +314 -0
- package/core/unified-product.js +214 -0
- package/core/vector-db.js +83 -17
- package/core/vision-service.js +113 -0
- 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/server/app.js +142 -29
package/core/engine.js
CHANGED
|
@@ -16,11 +16,13 @@ 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';
|
|
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';
|
|
21
|
+
import AutomationManager from './automation.js';
|
|
22
|
+
import OpenClawBridge from './openclaw-bridge.js';
|
|
23
|
+
import { executeTool } from './agent.js';
|
|
24
|
+
import { getCriticalQueue } from './queue.js';
|
|
25
|
+
import { getMemory } from './memory.js';
|
|
24
26
|
|
|
25
27
|
// Tools
|
|
26
28
|
import { repricerTool } from '../plugins/vantuz/tools/repricer.js';
|
|
@@ -40,32 +42,25 @@ const PLATFORM_CONFIG_MAP = {
|
|
|
40
42
|
envPrefix: 'HEPSIBURADA',
|
|
41
43
|
keys: ['merchantId', 'username', 'password']
|
|
42
44
|
},
|
|
43
|
-
n11: {
|
|
44
|
-
envPrefix: 'N11',
|
|
45
|
-
keys: ['apiKey', 'apiSecret']
|
|
46
|
-
},
|
|
45
|
+
n11: {
|
|
46
|
+
envPrefix: 'N11',
|
|
47
|
+
keys: ['apiKey', 'apiSecret']
|
|
48
|
+
},
|
|
47
49
|
amazon: {
|
|
48
50
|
envPrefix: 'AMAZON',
|
|
49
|
-
|
|
50
|
-
eu: {
|
|
51
|
-
keys: ['sellerId', 'clientId', 'refreshToken']
|
|
52
|
-
},
|
|
53
|
-
us: {
|
|
54
|
-
keys: ['sellerId', 'clientId', 'refreshToken']
|
|
55
|
-
}
|
|
56
|
-
}
|
|
51
|
+
keys: ['sellerId', 'clientId', 'clientSecret', 'refreshToken', 'region']
|
|
57
52
|
},
|
|
58
53
|
ciceksepeti: {
|
|
59
54
|
envPrefix: 'CICEKSEPETI',
|
|
60
|
-
keys: ['apiKey', '
|
|
55
|
+
keys: ['apiKey', 'supplierId']
|
|
61
56
|
},
|
|
62
57
|
pttavm: {
|
|
63
58
|
envPrefix: 'PTTAVM',
|
|
64
|
-
keys: ['apiKey', '
|
|
59
|
+
keys: ['apiKey', 'token', 'shopId']
|
|
65
60
|
},
|
|
66
61
|
pazarama: {
|
|
67
62
|
envPrefix: 'PAZARAMA',
|
|
68
|
-
keys: ['
|
|
63
|
+
keys: ['clientId', 'clientSecret']
|
|
69
64
|
}
|
|
70
65
|
};
|
|
71
66
|
|
|
@@ -82,7 +77,7 @@ const CONFIG_JSON = path.join(VANTUZ_HOME, 'config.json');
|
|
|
82
77
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
83
78
|
|
|
84
79
|
export class VantuzEngine {
|
|
85
|
-
constructor() {
|
|
80
|
+
constructor() {
|
|
86
81
|
this.initialized = false;
|
|
87
82
|
this.config = {};
|
|
88
83
|
this.env = {};
|
|
@@ -93,9 +88,9 @@ export class VantuzEngine {
|
|
|
93
88
|
products: [],
|
|
94
89
|
connectedPlatforms: []
|
|
95
90
|
};
|
|
96
|
-
this.eiaMonitor = null; // New property
|
|
97
|
-
this.automation = null;
|
|
98
|
-
this.bridge = null;
|
|
91
|
+
this.eiaMonitor = null; // New property
|
|
92
|
+
this.automation = null;
|
|
93
|
+
this.bridge = null;
|
|
99
94
|
|
|
100
95
|
// Tool Registry
|
|
101
96
|
this.tools = {
|
|
@@ -107,34 +102,38 @@ export class VantuzEngine {
|
|
|
107
102
|
analytics: analyticsTool,
|
|
108
103
|
quickReport: quickReportTool
|
|
109
104
|
};
|
|
105
|
+
|
|
106
|
+
// Critical Operation Queue (Lane Queue)
|
|
107
|
+
this.queue = getCriticalQueue();
|
|
108
|
+
this.memory = getMemory();
|
|
110
109
|
}
|
|
111
110
|
|
|
112
111
|
/**
|
|
113
112
|
* Engine'i başlat
|
|
114
113
|
*/
|
|
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
|
-
}
|
|
114
|
+
async initialize() {
|
|
115
|
+
log('INFO', 'Vantuz Engine v3.2 başlatılıyor...');
|
|
116
|
+
|
|
117
|
+
// Config ve env yükle
|
|
118
|
+
this._loadConfig();
|
|
119
|
+
this._loadEnv();
|
|
120
|
+
|
|
121
|
+
// Vantuz Gateway bağlantısı
|
|
122
|
+
try {
|
|
123
|
+
this.gateway = await getGateway();
|
|
124
|
+
if (this.gateway.isConnected()) {
|
|
125
|
+
log('INFO', 'Vantuz Gateway bağlı', this.gateway.getInfo());
|
|
126
|
+
} else if (this._shouldAutoStartGateway()) {
|
|
127
|
+
const started = await this.gateway.ensureRunning();
|
|
128
|
+
if (started.success) {
|
|
129
|
+
log('INFO', 'Vantuz Gateway otomatik başlatıldı', this.gateway.getInfo());
|
|
130
|
+
} else {
|
|
131
|
+
log('WARN', 'Gateway otomatik başlatılamadı', { error: started.error });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
} catch (e) {
|
|
135
|
+
log('WARN', 'Gateway bağlantısı başarısız, direkt mod', { error: e.message });
|
|
136
|
+
}
|
|
138
137
|
|
|
139
138
|
// Channel Manager'ı başlat
|
|
140
139
|
this.channels = await getChannelManager();
|
|
@@ -146,70 +145,70 @@ export class VantuzEngine {
|
|
|
146
145
|
await this._buildContext();
|
|
147
146
|
|
|
148
147
|
// 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;
|
|
148
|
+
this.eiaMonitor = getEIAMonitor(this.config, this.env);
|
|
149
|
+
await this.eiaMonitor.initMonitoringTasks(); // New line
|
|
150
|
+
|
|
151
|
+
// Automation manager
|
|
152
|
+
this.automation = new AutomationManager(this);
|
|
153
|
+
this.automation.init();
|
|
154
|
+
|
|
155
|
+
// Gateway WS bridge (inbound)
|
|
156
|
+
if (this._shouldStartBridge()) {
|
|
157
|
+
try {
|
|
158
|
+
this.bridge = new OpenClawBridge(this, this.gateway);
|
|
159
|
+
this.bridge.start();
|
|
160
|
+
} catch (e) {
|
|
161
|
+
log('WARN', 'Gateway bridge başlatılamadı', { error: e.message });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
this.initialized = true;
|
|
167
166
|
log('INFO', 'Vantuz Engine hazır', {
|
|
168
167
|
platforms: this.context.connectedPlatforms.length,
|
|
169
168
|
gateway: this.gateway?.isConnected() || false
|
|
170
169
|
});
|
|
171
170
|
|
|
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
|
-
}
|
|
171
|
+
return this;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Gelişmiş mesaj işleme (otomasyon + onay)
|
|
176
|
+
*/
|
|
177
|
+
async handleMessage(message, meta = { channel: 'local', from: 'local' }) {
|
|
178
|
+
if (!this.initialized) await this.initialize();
|
|
179
|
+
if (this.automation) {
|
|
180
|
+
const result = await this.automation.handleMessage(message, meta);
|
|
181
|
+
if (result?.handled) {
|
|
182
|
+
return result.response;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return await this.chat(message);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Gateway otomatik başlatılsın mı?
|
|
190
|
+
*/
|
|
191
|
+
_shouldAutoStartGateway() {
|
|
192
|
+
const envValue = this.env.VANTUZ_GATEWAY_AUTOSTART;
|
|
193
|
+
if (envValue !== undefined) {
|
|
194
|
+
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
195
|
+
}
|
|
196
|
+
if (this.config && this.config.gatewayAutoStart !== undefined) {
|
|
197
|
+
return this.config.gatewayAutoStart !== false;
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
_shouldStartBridge() {
|
|
203
|
+
const envValue = this.env.VANTUZ_OPENCLAW_BRIDGE;
|
|
204
|
+
if (envValue !== undefined) {
|
|
205
|
+
return !['0', 'false', 'no'].includes(String(envValue).toLowerCase());
|
|
206
|
+
}
|
|
207
|
+
if (this.config && this.config.openclawBridge !== undefined) {
|
|
208
|
+
return this.config.openclawBridge !== false;
|
|
209
|
+
}
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
213
212
|
|
|
214
213
|
/**
|
|
215
214
|
* Config dosyasını yükle
|
|
@@ -252,60 +251,23 @@ export class VantuzEngine {
|
|
|
252
251
|
for (const platformName in PLATFORM_CONFIG_MAP) {
|
|
253
252
|
const platformMap = PLATFORM_CONFIG_MAP[platformName];
|
|
254
253
|
|
|
255
|
-
if (
|
|
256
|
-
const
|
|
257
|
-
let
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
if (hasEuEnv) {
|
|
270
|
-
amazonConfig.eu = euConfig;
|
|
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;
|
|
254
|
+
if (platformMap.envPrefix && platformMap.keys) { // Handle all platforms with direct keys
|
|
255
|
+
const config = {};
|
|
256
|
+
let hasRequiredEnv = false;
|
|
257
|
+
for (const key of platformMap.keys) {
|
|
258
|
+
const upper = key.toUpperCase();
|
|
259
|
+
const snake = key.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toUpperCase();
|
|
260
|
+
const envKey = `${platformMap.envPrefix}_${upper}`;
|
|
261
|
+
const altEnvKey = `${platformMap.envPrefix}_${snake}`;
|
|
262
|
+
const value = this.env[envKey] || this.env[altEnvKey];
|
|
263
|
+
if (value) {
|
|
264
|
+
config[key] = value;
|
|
265
|
+
hasRequiredEnv = true;
|
|
282
266
|
}
|
|
283
267
|
}
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
hasAmazonEnv = true;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (hasAmazonEnv) {
|
|
290
|
-
platformConfig[platformName] = amazonConfig;
|
|
268
|
+
if (hasRequiredEnv) {
|
|
269
|
+
platformConfig[platformName] = config;
|
|
291
270
|
}
|
|
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
271
|
}
|
|
310
272
|
}
|
|
311
273
|
|
|
@@ -324,50 +286,50 @@ export class VantuzEngine {
|
|
|
324
286
|
async _buildContext() {
|
|
325
287
|
this.context.connectedPlatforms = platformHub.getConnected();
|
|
326
288
|
|
|
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
|
-
}
|
|
289
|
+
for (const platform of this.context.connectedPlatforms) {
|
|
290
|
+
try {
|
|
291
|
+
const api = platformHub.resolve(platform);
|
|
292
|
+
if (api && typeof api.getProducts === 'function') {
|
|
293
|
+
const result = await api.getProducts({ page: 0, size: 10 });
|
|
294
|
+
if (result?.success) {
|
|
295
|
+
const data = result.data;
|
|
296
|
+
let products = [];
|
|
297
|
+
if (Array.isArray(data?.content)) products = data.content;
|
|
298
|
+
else if (Array.isArray(data)) products = data;
|
|
299
|
+
else if (Array.isArray(data?.productList?.product)) products = data.productList.product;
|
|
300
|
+
if (products.length > 0) {
|
|
301
|
+
this.context.products.push(...products.map(p => ({
|
|
302
|
+
...p,
|
|
303
|
+
_platform: platform
|
|
304
|
+
})));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
} catch (e) {
|
|
309
|
+
log('ERROR', `${platform} veri çekme hatası`, { error: e.message });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
350
312
|
}
|
|
351
313
|
|
|
352
314
|
/**
|
|
353
315
|
* AI ile sohbet - Tool destekli
|
|
354
316
|
*/
|
|
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()
|
|
317
|
+
async chat(message) {
|
|
318
|
+
if (!this.initialized) await this.initialize();
|
|
319
|
+
|
|
320
|
+
// 1. Basit komut kontrolü (Tool çağırma)
|
|
321
|
+
const toolResult = await this._tryExecuteToolFromMessage(message);
|
|
322
|
+
if (toolResult) return toolResult;
|
|
323
|
+
|
|
324
|
+
// 1.5 Gelişmiş ajan (araç çağrıları)
|
|
325
|
+
const agentResult = await this._tryAgent(message);
|
|
326
|
+
if (agentResult) return agentResult;
|
|
327
|
+
|
|
328
|
+
// 2. Gateway üzerinden AI (Eğer varsa)
|
|
329
|
+
if (this.gateway?.isConnected()) {
|
|
330
|
+
try {
|
|
331
|
+
const gatewayResult = await this.gateway.chat(message, {
|
|
332
|
+
systemPrompt: this._buildContextInfo()
|
|
371
333
|
});
|
|
372
334
|
if (gatewayResult.success) return gatewayResult.response;
|
|
373
335
|
} catch (e) { }
|
|
@@ -376,98 +338,99 @@ export class VantuzEngine {
|
|
|
376
338
|
// 3. Direkt API (Fallback)
|
|
377
339
|
const enrichedConfig = {
|
|
378
340
|
...this.config,
|
|
341
|
+
aiProvider: this.env.AI_PROVIDER || this.config.aiProvider || 'gemini',
|
|
379
342
|
systemContext: this._buildContextInfo()
|
|
380
343
|
};
|
|
381
344
|
|
|
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
|
-
}
|
|
345
|
+
return await aiChat(message, enrichedConfig, this.env);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
async _tryAgent(message) {
|
|
349
|
+
const mode = this.config?.agentMode || this.env.VANTUZ_AGENT_MODE;
|
|
350
|
+
if (!mode || mode === 'off') return null;
|
|
351
|
+
|
|
352
|
+
const systemPrompt = [
|
|
353
|
+
'Sen Vantuz gelişmiş ajanısın.',
|
|
354
|
+
'Gerekirse aşağıdaki araçlardan birini çağır:',
|
|
355
|
+
'exec, readFile, listDir, httpGet, apiQuery',
|
|
356
|
+
'Sadece JSON döndür.',
|
|
357
|
+
'Şema: { "tool": "exec|readFile|listDir|httpGet|apiQuery", "args": { ... } }',
|
|
358
|
+
'apiQuery args: { "platform": "n11|trendyol|hepsiburada|amazon|ciceksepeti|pazarama|pttavm", "action": "orders|products|stock|categories", "params": { ... } }',
|
|
359
|
+
'Eğer araç gerekmezse: { "final": "cevap" }',
|
|
360
|
+
'Dosya yollarını ve komutları kısa tut.'
|
|
361
|
+
].join('\n');
|
|
362
|
+
|
|
363
|
+
const plan = await aiChat(message, {
|
|
364
|
+
aiProvider: this.config.aiProvider || 'gemini',
|
|
365
|
+
systemContext: systemPrompt
|
|
366
|
+
}, this.env);
|
|
367
|
+
|
|
368
|
+
const jsonMatch = plan.match(/\{[\s\S]*\}/);
|
|
369
|
+
if (!jsonMatch) return null;
|
|
370
|
+
let obj;
|
|
371
|
+
try { obj = JSON.parse(jsonMatch[0]); } catch { return null; }
|
|
372
|
+
if (obj.final) return obj.final;
|
|
373
|
+
if (!obj.tool) return null;
|
|
374
|
+
|
|
375
|
+
let toolResult;
|
|
376
|
+
if (obj.tool === 'apiQuery') {
|
|
377
|
+
toolResult = await this._runApiQuery(obj.args || {});
|
|
378
|
+
} else {
|
|
379
|
+
toolResult = await executeTool(obj.tool, obj.args || {}, this.config);
|
|
380
|
+
}
|
|
381
|
+
const followup = await aiChat(
|
|
382
|
+
`Kullanıcı mesajı: ${message}\nAraç çıktısı:\n${toolResult.output}\nCevap ver.`,
|
|
383
|
+
{ aiProvider: this.config.aiProvider || 'gemini' },
|
|
384
|
+
this.env
|
|
385
|
+
);
|
|
386
|
+
return followup;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async _runApiQuery(args = {}) {
|
|
390
|
+
const platform = (args.platform || '').toLowerCase();
|
|
391
|
+
const action = (args.action || '').toLowerCase();
|
|
392
|
+
const params = args.params || {};
|
|
393
|
+
const api = platformHub.resolve(platform);
|
|
394
|
+
if (!api) return { success: false, output: 'Platform bulunamadı.' };
|
|
395
|
+
|
|
396
|
+
try {
|
|
397
|
+
if (action === 'orders' && api.getOrders) {
|
|
398
|
+
const result = await api.getOrders(params);
|
|
399
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
400
|
+
}
|
|
401
|
+
if (action === 'products' && api.getProducts) {
|
|
402
|
+
const result = await api.getProducts(params);
|
|
403
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
404
|
+
}
|
|
405
|
+
if (action === 'stock' && api.getProducts) {
|
|
406
|
+
const result = await api.getProducts(params);
|
|
407
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
408
|
+
}
|
|
409
|
+
if (action === 'categories' && api.getTopCategories) {
|
|
410
|
+
const result = await api.getTopCategories(params);
|
|
411
|
+
return { success: true, output: JSON.stringify(result?.data || result || {}, null, 2) };
|
|
412
|
+
}
|
|
413
|
+
return { success: false, output: 'Bu platform için istenen action desteklenmiyor.' };
|
|
414
|
+
} catch (e) {
|
|
415
|
+
return { success: false, output: e.message };
|
|
416
|
+
}
|
|
417
|
+
}
|
|
455
418
|
|
|
456
419
|
/**
|
|
457
420
|
* Mesajdan Tool tespiti (Basit NLP)
|
|
458
421
|
*/
|
|
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('/')) {
|
|
422
|
+
async _tryExecuteToolFromMessage(message) {
|
|
423
|
+
const lower = message.toLowerCase().trim();
|
|
424
|
+
const normalized = lower
|
|
425
|
+
.replace(/[çÇ]/g, 'c')
|
|
426
|
+
.replace(/[ğĞ]/g, 'g')
|
|
427
|
+
.replace(/[ıİ]/g, 'i')
|
|
428
|
+
.replace(/[öÖ]/g, 'o')
|
|
429
|
+
.replace(/[şŞ]/g, 's')
|
|
430
|
+
.replace(/[üÜ]/g, 'u');
|
|
431
|
+
|
|
432
|
+
// Check for explicit commands
|
|
433
|
+
if (lower.startsWith('/')) {
|
|
471
434
|
const parts = lower.substring(1).split(' ');
|
|
472
435
|
const command = parts[0];
|
|
473
436
|
const args = parts.slice(1);
|
|
@@ -485,63 +448,79 @@ export class VantuzEngine {
|
|
|
485
448
|
case 'help':
|
|
486
449
|
return "Kullanabileceğin komutlar: /rakip, /stok-durumu";
|
|
487
450
|
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:
|
|
513
|
-
if (!orders || orders.length === 0) {
|
|
514
|
-
return 'Sipariş verisine ulaşılamadı. Lütfen platform API bağlantılarını kontrol edin.';
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
.
|
|
543
|
-
|
|
544
|
-
|
|
451
|
+
return `Bilinmeyen komut: /${command}. Yardım için /help yazabilirsin.`;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Natural language shortcuts (no hallucination)
|
|
456
|
+
if (
|
|
457
|
+
lower.includes('hangi pazaryerleri bağlı') ||
|
|
458
|
+
lower.includes('hangi pazaryeri bağlı') ||
|
|
459
|
+
lower.includes('hangi platformlar bağlı') ||
|
|
460
|
+
normalized.includes('hangi pazaryerleri bagli') ||
|
|
461
|
+
normalized.includes('hangi platformlar bagli')
|
|
462
|
+
) {
|
|
463
|
+
const connected = this.context.connectedPlatforms;
|
|
464
|
+
if (connected.length === 0) return 'Şu an bağlı pazaryeri yok.';
|
|
465
|
+
return `Bağlı pazaryerleri: ${connected.map(p => p.toUpperCase()).join(', ')}`;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const orderKeywords = [
|
|
469
|
+
'sipariş',
|
|
470
|
+
'siparis'
|
|
471
|
+
];
|
|
472
|
+
const hasOrderKeyword = orderKeywords.some(k => lower.includes(k) || normalized.includes(k));
|
|
473
|
+
|
|
474
|
+
if (hasOrderKeyword) {
|
|
475
|
+
const orders = await this.getOrders({ size: 100, allStatuses: true });
|
|
476
|
+
if (!orders || orders.length === 0) {
|
|
477
|
+
return 'Sipariş verisine ulaşılamadı. Lütfen platform API bağlantılarını kontrol edin.';
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const active = orders.filter(o => this.isActiveStatus(o.status || o.shipmentPackageStatus || o.orderStatus));
|
|
481
|
+
const completed = orders.filter(o => !this.isActiveStatus(o.status || o.shipmentPackageStatus || o.orderStatus));
|
|
482
|
+
|
|
483
|
+
let message = '';
|
|
484
|
+
if (active.length > 0) {
|
|
485
|
+
const summary = this._summarizeOrdersByStatus(active);
|
|
486
|
+
message += `Şu an bağlı platformlardan gelen toplam ${active.length} YENİ/AKTİF sipariş var.${summary ? ` (${summary})` : ''}`;
|
|
487
|
+
} else {
|
|
488
|
+
message += 'Şu an aktif (yeni/hazırlanan) sipariş yok.';
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
if (completed.length > 0) {
|
|
492
|
+
const summary = this._summarizeOrdersByStatus(completed);
|
|
493
|
+
message += `\n(Geçmiş Siparişler: ${completed.length} adet - ${summary})`;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return message;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (lower.includes('onaylanan')) {
|
|
500
|
+
const orders = await this.getOrders({ size: 100, status: 'Picking' });
|
|
501
|
+
return `Şu an onaylanan (Picking) ${orders.length} sipariş var.`;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (lower.includes('kargoya verilmemiş') || lower.includes('henüz kargoya') || lower.includes('kargoya verilmedi') || normalized.includes('kargoya verilmemis')) {
|
|
505
|
+
const orders = await this.getOrders({ size: 100, status: 'Created' });
|
|
506
|
+
return `Şu an kargoya verilmemiş (Created) ${orders.length} sipariş var.`;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return null;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
_summarizeOrdersByStatus(orders = []) {
|
|
513
|
+
if (!Array.isArray(orders) || orders.length === 0) return '';
|
|
514
|
+
const counts = {};
|
|
515
|
+
orders.forEach(o => {
|
|
516
|
+
const s = (o.status || o.shipmentPackageStatus || o.orderStatus || 'UNKNOWN').toString();
|
|
517
|
+
counts[s] = (counts[s] || 0) + 1;
|
|
518
|
+
});
|
|
519
|
+
const entries = Object.entries(counts)
|
|
520
|
+
.sort((a, b) => b[1] - a[1])
|
|
521
|
+
.map(([s, n]) => `${s}:${n}`);
|
|
522
|
+
return entries.join(', ');
|
|
523
|
+
}
|
|
545
524
|
|
|
546
525
|
/**
|
|
547
526
|
* Context bilgisi oluştur (AI system prompt için)
|
|
@@ -564,6 +543,11 @@ export class VantuzEngine {
|
|
|
564
543
|
|
|
565
544
|
// --- Helper Methods ---
|
|
566
545
|
|
|
546
|
+
isActiveStatus(status) {
|
|
547
|
+
const s = String(status || '').toLowerCase();
|
|
548
|
+
return s === 'created' || s === 'picking' || s === 'unpacked' || s === 'shipped';
|
|
549
|
+
}
|
|
550
|
+
|
|
567
551
|
async getStock(platform = 'all') {
|
|
568
552
|
const results = [];
|
|
569
553
|
const targets = platform === 'all'
|
|
@@ -609,7 +593,7 @@ export class VantuzEngine {
|
|
|
609
593
|
return {
|
|
610
594
|
engine: this.initialized ? 'active' : 'inactive',
|
|
611
595
|
version: '3.2',
|
|
612
|
-
aiProvider: this.config.aiProvider || 'gemini',
|
|
596
|
+
aiProvider: this.env.AI_PROVIDER || this.config.aiProvider || 'gemini',
|
|
613
597
|
gateway: gatewayInfo,
|
|
614
598
|
platforms: status,
|
|
615
599
|
channels: channelStatus,
|