vantuz 3.4.2 → 3.5.1
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/.env.example +21 -0
- package/.openclaw/completions/openclaw.bash +227 -0
- package/.openclaw/completions/openclaw.fish +1552 -0
- package/.openclaw/completions/openclaw.ps1 +1966 -0
- package/.openclaw/completions/openclaw.zsh +3571 -0
- package/.openclaw/gateway.cmd +10 -0
- package/.openclaw/identity/device.json +7 -0
- package/.openclaw/openclaw.json +40 -0
- package/.windsurf/workflows/vantuz-dev.md +31 -0
- package/DOCS_TR.md +80 -0
- package/LICENSE +45 -45
- package/README.md +52 -21
- package/cli.js +685 -585
- package/config.js +733 -733
- package/core/agent-loop.js +190 -190
- package/core/ai-provider.js +298 -261
- package/core/automation.js +523 -523
- package/core/brand-analyst.js +101 -0
- package/core/channels.js +167 -167
- package/core/dashboard.js +230 -230
- package/core/database.js +135 -37
- package/core/eia-monitor.js +3 -1
- package/core/engine.js +648 -636
- package/core/gateway.js +447 -447
- package/core/learning.js +214 -214
- package/core/license.js +113 -0
- package/core/marketplace-adapter.js +168 -168
- package/core/memory.js +190 -190
- package/core/migrations/001-initial-schema.sql +1 -1
- package/core/queue.js +120 -120
- package/core/self-healer.js +314 -314
- package/core/unified-product.js +214 -214
- package/core/vision-service.js +113 -113
- package/index.js +217 -174
- package/modules/crm/sentiment-crm.js +231 -231
- package/modules/healer/listing-healer.js +201 -201
- package/modules/oracle/predictor.js +214 -214
- package/modules/researcher/agent.js +169 -169
- package/modules/team/agents/base.js +92 -92
- package/modules/team/agents/dev.js +33 -33
- package/modules/team/agents/josh.js +40 -40
- package/modules/team/agents/marketing.js +33 -33
- package/modules/team/agents/milo.js +36 -36
- package/modules/team/index.js +78 -78
- package/modules/team/shared-memory.js +87 -87
- package/modules/war-room/competitor-tracker.js +250 -250
- package/modules/war-room/pricing-engine.js +308 -308
- package/n11docs.md +1680 -0
- package/nodes/warehouse.js +238 -238
- package/onboard.js +1 -1
- package/openclawdocs.md +3 -0
- package/package.json +7 -5
- package/platforms/pttavm.js +14 -14
- package/plugins/vantuz/index.js +528 -528
- package/plugins/vantuz/memory/hippocampus.js +465 -465
- package/plugins/vantuz/package.json +20 -20
- package/plugins/vantuz/platforms/_template.js +118 -118
- package/plugins/vantuz/platforms/amazon.js +236 -236
- package/plugins/vantuz/platforms/ciceksepeti.js +166 -166
- package/plugins/vantuz/platforms/hepsiburada.js +180 -180
- package/plugins/vantuz/platforms/index.js +165 -165
- package/plugins/vantuz/platforms/n11.js +229 -229
- package/plugins/vantuz/platforms/pazarama.js +154 -154
- package/plugins/vantuz/platforms/pttavm.js +127 -127
- package/plugins/vantuz/platforms/trendyol.js +326 -326
- package/plugins/vantuz/services/alerts.js +253 -253
- package/plugins/vantuz/services/license.js +34 -34
- package/plugins/vantuz/services/scheduler.js +232 -232
- package/plugins/vantuz/tools/analytics.js +152 -152
- package/plugins/vantuz/tools/crossborder.js +187 -187
- package/plugins/vantuz/tools/nl-parser.js +211 -211
- package/plugins/vantuz/tools/product.js +110 -110
- package/plugins/vantuz/tools/quick-report.js +175 -175
- package/plugins/vantuz/tools/repricer.js +314 -314
- package/plugins/vantuz/tools/sentiment.js +115 -115
- package/plugins/vantuz/tools/vision.js +257 -257
- package/public.pem +9 -0
- package/server/app.js +260 -260
- package/server/public/index.html +514 -514
- package/start.bat +33 -33
- package/vantuz.sqlite +0 -0
- package/workspace/AGENTS.md +73 -0
- package/workspace/BRAND.md +29 -0
- package/workspace/SOUL.md +72 -0
- package/workspace/team/DECISIONS.md +3 -0
- package/workspace/team/GOALS.md +3 -0
- package/workspace/team/PROJECT_STATUS.md +3 -0
- package/workspace/team/agents/dev/SOUL.md +12 -0
- package/workspace/team/agents/josh/SOUL.md +12 -0
- package/workspace/team/agents/marketing/SOUL.md +12 -0
- package/workspace/team/agents/milo/SOUL.md +12 -0
- package/vantuz-3.3.4.tgz +0 -0
package/core/gateway.js
CHANGED
|
@@ -1,447 +1,447 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 🌐 VANTUZ GATEWAY BRIDGE v1.0
|
|
3
|
-
* Vantuz ↔ Vantuz Gateway iletişim katmanı
|
|
4
|
-
*
|
|
5
|
-
* Gateway üzerinden:
|
|
6
|
-
* - AI model yönlendirmesi
|
|
7
|
-
* - Kanal yönetimi (WhatsApp, Telegram)
|
|
8
|
-
* - Plugin RPC çağrıları
|
|
9
|
-
* - Sistem durumu sorgulama
|
|
10
|
-
*/
|
|
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';
|
|
17
|
-
|
|
18
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
19
|
-
// CONFIG - Gateway ayarları
|
|
20
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
21
|
-
|
|
22
|
-
const OPENCLAW_HOME = path.join(process.cwd(), '.openclaw');
|
|
23
|
-
const OPENCLAW_CONFIG = path.join(OPENCLAW_HOME, 'openclaw.json');
|
|
24
|
-
const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
|
|
25
|
-
|
|
26
|
-
function loadGatewayConfig() {
|
|
27
|
-
try {
|
|
28
|
-
if (fs.existsSync(OPENCLAW_CONFIG)) {
|
|
29
|
-
return JSON.parse(fs.readFileSync(OPENCLAW_CONFIG, 'utf-8'));
|
|
30
|
-
}
|
|
31
|
-
} catch (e) {
|
|
32
|
-
log('WARN', 'Gateway config okunamadı', { error: e.message });
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function getGatewayToken(config) {
|
|
38
|
-
return config?.gateway?.auth?.token || null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
-
// GATEWAY CLIENT
|
|
43
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
-
|
|
45
|
-
export class VantuzGateway {
|
|
46
|
-
constructor() {
|
|
47
|
-
this.config = loadGatewayConfig();
|
|
48
|
-
const port = this.config?.gateway?.port || 18789;
|
|
49
|
-
this.baseUrl = `http://localhost:${port}`;
|
|
50
|
-
this.token = getGatewayToken(this.config);
|
|
51
|
-
this.connected = false;
|
|
52
|
-
this.version = null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* HTTP Headers (token auth)
|
|
57
|
-
*/
|
|
58
|
-
_headers() {
|
|
59
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
60
|
-
if (this.token) {
|
|
61
|
-
headers['Authorization'] = `Bearer ${this.token}`;
|
|
62
|
-
}
|
|
63
|
-
return headers;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Gateway'e HTTP isteği gönder
|
|
68
|
-
*/
|
|
69
|
-
async _request(method, endpoint, data = null, timeout = 10000) {
|
|
70
|
-
try {
|
|
71
|
-
const config = {
|
|
72
|
-
method,
|
|
73
|
-
url: `${this.baseUrl}${endpoint}`,
|
|
74
|
-
headers: this._headers(),
|
|
75
|
-
timeout
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
if (data) config.data = data;
|
|
79
|
-
|
|
80
|
-
const response = await axios(config);
|
|
81
|
-
return { success: true, data: response.data };
|
|
82
|
-
} catch (error) {
|
|
83
|
-
if (error.code === 'ECONNREFUSED') {
|
|
84
|
-
return { success: false, error: 'Gateway çalışmıyor', code: 'NOT_RUNNING' };
|
|
85
|
-
}
|
|
86
|
-
if (error.response?.status === 401) {
|
|
87
|
-
return { success: false, error: 'Token geçersiz', code: 'AUTH_FAILED' };
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
success: false,
|
|
91
|
-
error: error.message,
|
|
92
|
-
code: error.code || 'UNKNOWN'
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
98
|
-
// SAĞLIK & DURUM
|
|
99
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Gateway sağlık kontrolü
|
|
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 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
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Detaylı sistem durumu
|
|
238
|
-
*/
|
|
239
|
-
async status() {
|
|
240
|
-
const result = await this._request('GET', '/status');
|
|
241
|
-
if (result.success) {
|
|
242
|
-
this.connected = true;
|
|
243
|
-
}
|
|
244
|
-
return result;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Gateway bağlı mı?
|
|
249
|
-
*/
|
|
250
|
-
isConnected() {
|
|
251
|
-
return this.connected;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Gateway bilgileri
|
|
256
|
-
*/
|
|
257
|
-
getInfo() {
|
|
258
|
-
return {
|
|
259
|
-
url: this.baseUrl,
|
|
260
|
-
connected: this.connected,
|
|
261
|
-
version: this.version,
|
|
262
|
-
hasToken: !!this.token,
|
|
263
|
-
configFound: !!this.config
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
268
|
-
// AI MODEL YÖNLENDİRME
|
|
269
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Gateway üzerinden AI chat
|
|
273
|
-
* Gateway AI model routing sağlıyorsa kullan
|
|
274
|
-
*/
|
|
275
|
-
async chat(message, options = {}) {
|
|
276
|
-
const result = await this._request('POST', '/v1/chat/completions', {
|
|
277
|
-
messages: [
|
|
278
|
-
...(options.systemPrompt ? [{ role: 'system', content: options.systemPrompt }] : []),
|
|
279
|
-
{ role: 'user', content: message }
|
|
280
|
-
],
|
|
281
|
-
model: options.model || 'default',
|
|
282
|
-
max_tokens: options.maxTokens || 1000,
|
|
283
|
-
temperature: options.temperature || 0.7
|
|
284
|
-
}, 30000);
|
|
285
|
-
|
|
286
|
-
if (result.success) {
|
|
287
|
-
const text = result.data?.choices?.[0]?.message?.content;
|
|
288
|
-
return { success: true, response: text };
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
return { success: false, error: result.error };
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Kullanılabilir AI modelleri
|
|
296
|
-
*/
|
|
297
|
-
async getModels() {
|
|
298
|
-
return await this._request('GET', '/v1/models');
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
302
|
-
// KANAL YÖNETİMİ
|
|
303
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Kanal listesi ve durumları
|
|
307
|
-
*/
|
|
308
|
-
async getChannels() {
|
|
309
|
-
return await this._request('GET', '/channels');
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
/**
|
|
313
|
-
* Kanal bağlantı durumu
|
|
314
|
-
*/
|
|
315
|
-
async getChannelStatus(channelName) {
|
|
316
|
-
return await this._request('GET', `/channels/${channelName}/status`);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Kanal üzerinden mesaj gönder
|
|
321
|
-
*/
|
|
322
|
-
async sendMessage(channel, to, message) {
|
|
323
|
-
return await this._request('POST', `/channels/${channel}/send`, {
|
|
324
|
-
to,
|
|
325
|
-
message,
|
|
326
|
-
type: 'text'
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
331
|
-
// RPC - Plugin Gateway Methodları
|
|
332
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Gateway RPC çağrısı
|
|
336
|
-
*/
|
|
337
|
-
async call(method, params = {}) {
|
|
338
|
-
return await this._request('POST', '/rpc', {
|
|
339
|
-
method,
|
|
340
|
-
params
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Vantuz plugin durumu
|
|
346
|
-
*/
|
|
347
|
-
async getPluginStatus() {
|
|
348
|
-
return await this.call('vantuz.status');
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Vantuz plugin config
|
|
353
|
-
*/
|
|
354
|
-
async getPluginConfig() {
|
|
355
|
-
return await this.call('vantuz.config', { action: 'get' });
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
359
|
-
// CRON & ZAMANLAMA
|
|
360
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* Zamanlanmış görev listesi
|
|
364
|
-
*/
|
|
365
|
-
async getCronJobs() {
|
|
366
|
-
return await this._request('GET', '/cron');
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Zamanlanmış görev ekle
|
|
371
|
-
*/
|
|
372
|
-
async addCronJob(schedule, command, description) {
|
|
373
|
-
return await this._request('POST', '/cron', {
|
|
374
|
-
schedule,
|
|
375
|
-
command,
|
|
376
|
-
description
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
381
|
-
// HAFIZA (Memory)
|
|
382
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Gateway hafıza durumu
|
|
386
|
-
*/
|
|
387
|
-
async getMemoryStatus() {
|
|
388
|
-
return await this._request('GET', '/memory/status');
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Hafıza araması
|
|
393
|
-
*/
|
|
394
|
-
async searchMemory(query) {
|
|
395
|
-
return await this._request('POST', '/memory/search', { query });
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
399
|
-
// LOGLAR
|
|
400
|
-
// ═══════════════════════════════════════════════════════════════════════
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* Gateway logları
|
|
404
|
-
*/
|
|
405
|
-
async getLogs(limit = 50) {
|
|
406
|
-
return await this._request('GET', `/logs?limit=${limit}`);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
411
|
-
// SINGLETON & FACTORY
|
|
412
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
413
|
-
|
|
414
|
-
let gatewayInstance = null;
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Vantuz Gateway singleton instance
|
|
418
|
-
* Otomatik bağlantı kontrolü yapar
|
|
419
|
-
*/
|
|
420
|
-
export async function getGateway() {
|
|
421
|
-
if (!gatewayInstance) {
|
|
422
|
-
gatewayInstance = new VantuzGateway();
|
|
423
|
-
|
|
424
|
-
// İlk bağlantı denemesi
|
|
425
|
-
const health = await gatewayInstance.health();
|
|
426
|
-
if (health.success) {
|
|
427
|
-
log('INFO', 'Vantuz Gateway bağlantısı başarılı', {
|
|
428
|
-
url: gatewayInstance.baseUrl,
|
|
429
|
-
version: gatewayInstance.version
|
|
430
|
-
});
|
|
431
|
-
} else {
|
|
432
|
-
log('WARN', 'Vantuz Gateway erişilemez, direkt mod kullanılacak', {
|
|
433
|
-
error: health.error
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
return gatewayInstance;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Gateway durumunu sıfırla (reconnect için)
|
|
442
|
-
*/
|
|
443
|
-
export function resetGateway() {
|
|
444
|
-
gatewayInstance = null;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
export default VantuzGateway;
|
|
1
|
+
/**
|
|
2
|
+
* 🌐 VANTUZ GATEWAY BRIDGE v1.0
|
|
3
|
+
* Vantuz ↔ Vantuz Gateway iletişim katmanı
|
|
4
|
+
*
|
|
5
|
+
* Gateway üzerinden:
|
|
6
|
+
* - AI model yönlendirmesi
|
|
7
|
+
* - Kanal yönetimi (WhatsApp, Telegram)
|
|
8
|
+
* - Plugin RPC çağrıları
|
|
9
|
+
* - Sistem durumu sorgulama
|
|
10
|
+
*/
|
|
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';
|
|
17
|
+
|
|
18
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
19
|
+
// CONFIG - Gateway ayarları
|
|
20
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
21
|
+
|
|
22
|
+
const OPENCLAW_HOME = path.join(process.cwd(), '.openclaw');
|
|
23
|
+
const OPENCLAW_CONFIG = path.join(OPENCLAW_HOME, 'openclaw.json');
|
|
24
|
+
const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
|
|
25
|
+
|
|
26
|
+
function loadGatewayConfig() {
|
|
27
|
+
try {
|
|
28
|
+
if (fs.existsSync(OPENCLAW_CONFIG)) {
|
|
29
|
+
return JSON.parse(fs.readFileSync(OPENCLAW_CONFIG, 'utf-8'));
|
|
30
|
+
}
|
|
31
|
+
} catch (e) {
|
|
32
|
+
log('WARN', 'Gateway config okunamadı', { error: e.message });
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getGatewayToken(config) {
|
|
38
|
+
return config?.gateway?.auth?.token || null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
+
// GATEWAY CLIENT
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
export class VantuzGateway {
|
|
46
|
+
constructor() {
|
|
47
|
+
this.config = loadGatewayConfig();
|
|
48
|
+
const port = this.config?.gateway?.port || 18789;
|
|
49
|
+
this.baseUrl = `http://localhost:${port}`;
|
|
50
|
+
this.token = getGatewayToken(this.config);
|
|
51
|
+
this.connected = false;
|
|
52
|
+
this.version = null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* HTTP Headers (token auth)
|
|
57
|
+
*/
|
|
58
|
+
_headers() {
|
|
59
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
60
|
+
if (this.token) {
|
|
61
|
+
headers['Authorization'] = `Bearer ${this.token}`;
|
|
62
|
+
}
|
|
63
|
+
return headers;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gateway'e HTTP isteği gönder
|
|
68
|
+
*/
|
|
69
|
+
async _request(method, endpoint, data = null, timeout = 10000) {
|
|
70
|
+
try {
|
|
71
|
+
const config = {
|
|
72
|
+
method,
|
|
73
|
+
url: `${this.baseUrl}${endpoint}`,
|
|
74
|
+
headers: this._headers(),
|
|
75
|
+
timeout
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (data) config.data = data;
|
|
79
|
+
|
|
80
|
+
const response = await axios(config);
|
|
81
|
+
return { success: true, data: response.data };
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error.code === 'ECONNREFUSED') {
|
|
84
|
+
return { success: false, error: 'Gateway çalışmıyor', code: 'NOT_RUNNING' };
|
|
85
|
+
}
|
|
86
|
+
if (error.response?.status === 401) {
|
|
87
|
+
return { success: false, error: 'Token geçersiz', code: 'AUTH_FAILED' };
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: error.message,
|
|
92
|
+
code: error.code || 'UNKNOWN'
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
98
|
+
// SAĞLIK & DURUM
|
|
99
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Gateway sağlık kontrolü
|
|
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 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
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Detaylı sistem durumu
|
|
238
|
+
*/
|
|
239
|
+
async status() {
|
|
240
|
+
const result = await this._request('GET', '/status');
|
|
241
|
+
if (result.success) {
|
|
242
|
+
this.connected = true;
|
|
243
|
+
}
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Gateway bağlı mı?
|
|
249
|
+
*/
|
|
250
|
+
isConnected() {
|
|
251
|
+
return this.connected;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Gateway bilgileri
|
|
256
|
+
*/
|
|
257
|
+
getInfo() {
|
|
258
|
+
return {
|
|
259
|
+
url: this.baseUrl,
|
|
260
|
+
connected: this.connected,
|
|
261
|
+
version: this.version,
|
|
262
|
+
hasToken: !!this.token,
|
|
263
|
+
configFound: !!this.config
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
268
|
+
// AI MODEL YÖNLENDİRME
|
|
269
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Gateway üzerinden AI chat
|
|
273
|
+
* Gateway AI model routing sağlıyorsa kullan
|
|
274
|
+
*/
|
|
275
|
+
async chat(message, options = {}) {
|
|
276
|
+
const result = await this._request('POST', '/v1/chat/completions', {
|
|
277
|
+
messages: [
|
|
278
|
+
...(options.systemPrompt ? [{ role: 'system', content: options.systemPrompt }] : []),
|
|
279
|
+
{ role: 'user', content: message }
|
|
280
|
+
],
|
|
281
|
+
model: options.model || 'default',
|
|
282
|
+
max_tokens: options.maxTokens || 1000,
|
|
283
|
+
temperature: options.temperature || 0.7
|
|
284
|
+
}, 30000);
|
|
285
|
+
|
|
286
|
+
if (result.success) {
|
|
287
|
+
const text = result.data?.choices?.[0]?.message?.content;
|
|
288
|
+
return { success: true, response: text };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return { success: false, error: result.error };
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Kullanılabilir AI modelleri
|
|
296
|
+
*/
|
|
297
|
+
async getModels() {
|
|
298
|
+
return await this._request('GET', '/v1/models');
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
302
|
+
// KANAL YÖNETİMİ
|
|
303
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Kanal listesi ve durumları
|
|
307
|
+
*/
|
|
308
|
+
async getChannels() {
|
|
309
|
+
return await this._request('GET', '/channels');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Kanal bağlantı durumu
|
|
314
|
+
*/
|
|
315
|
+
async getChannelStatus(channelName) {
|
|
316
|
+
return await this._request('GET', `/channels/${channelName}/status`);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Kanal üzerinden mesaj gönder
|
|
321
|
+
*/
|
|
322
|
+
async sendMessage(channel, to, message) {
|
|
323
|
+
return await this._request('POST', `/channels/${channel}/send`, {
|
|
324
|
+
to,
|
|
325
|
+
message,
|
|
326
|
+
type: 'text'
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
331
|
+
// RPC - Plugin Gateway Methodları
|
|
332
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Gateway RPC çağrısı
|
|
336
|
+
*/
|
|
337
|
+
async call(method, params = {}) {
|
|
338
|
+
return await this._request('POST', '/rpc', {
|
|
339
|
+
method,
|
|
340
|
+
params
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Vantuz plugin durumu
|
|
346
|
+
*/
|
|
347
|
+
async getPluginStatus() {
|
|
348
|
+
return await this.call('vantuz.status');
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Vantuz plugin config
|
|
353
|
+
*/
|
|
354
|
+
async getPluginConfig() {
|
|
355
|
+
return await this.call('vantuz.config', { action: 'get' });
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
359
|
+
// CRON & ZAMANLAMA
|
|
360
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Zamanlanmış görev listesi
|
|
364
|
+
*/
|
|
365
|
+
async getCronJobs() {
|
|
366
|
+
return await this._request('GET', '/cron');
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Zamanlanmış görev ekle
|
|
371
|
+
*/
|
|
372
|
+
async addCronJob(schedule, command, description) {
|
|
373
|
+
return await this._request('POST', '/cron', {
|
|
374
|
+
schedule,
|
|
375
|
+
command,
|
|
376
|
+
description
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
381
|
+
// HAFIZA (Memory)
|
|
382
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Gateway hafıza durumu
|
|
386
|
+
*/
|
|
387
|
+
async getMemoryStatus() {
|
|
388
|
+
return await this._request('GET', '/memory/status');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Hafıza araması
|
|
393
|
+
*/
|
|
394
|
+
async searchMemory(query) {
|
|
395
|
+
return await this._request('POST', '/memory/search', { query });
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
399
|
+
// LOGLAR
|
|
400
|
+
// ═══════════════════════════════════════════════════════════════════════
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Gateway logları
|
|
404
|
+
*/
|
|
405
|
+
async getLogs(limit = 50) {
|
|
406
|
+
return await this._request('GET', `/logs?limit=${limit}`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
411
|
+
// SINGLETON & FACTORY
|
|
412
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
413
|
+
|
|
414
|
+
let gatewayInstance = null;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Vantuz Gateway singleton instance
|
|
418
|
+
* Otomatik bağlantı kontrolü yapar
|
|
419
|
+
*/
|
|
420
|
+
export async function getGateway() {
|
|
421
|
+
if (!gatewayInstance) {
|
|
422
|
+
gatewayInstance = new VantuzGateway();
|
|
423
|
+
|
|
424
|
+
// İlk bağlantı denemesi
|
|
425
|
+
const health = await gatewayInstance.health();
|
|
426
|
+
if (health.success) {
|
|
427
|
+
log('INFO', 'Vantuz Gateway bağlantısı başarılı', {
|
|
428
|
+
url: gatewayInstance.baseUrl,
|
|
429
|
+
version: gatewayInstance.version
|
|
430
|
+
});
|
|
431
|
+
} else {
|
|
432
|
+
log('WARN', 'Vantuz Gateway erişilemez, direkt mod kullanılacak', {
|
|
433
|
+
error: health.error
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return gatewayInstance;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Gateway durumunu sıfırla (reconnect için)
|
|
442
|
+
*/
|
|
443
|
+
export function resetGateway() {
|
|
444
|
+
gatewayInstance = null;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export default VantuzGateway;
|