vantuz 4.0.0 → 4.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +9 -9
- package/config.js +6 -6
- package/core/agent-loop.js +6 -6
- package/core/agent.js +6 -6
- package/core/ai-copilot.js +461 -0
- package/core/ai-provider.js +60 -10
- package/core/automation.js +8 -8
- package/core/cache-manager.js +232 -0
- package/core/channels.js +8 -8
- package/core/dashboard.js +5 -5
- package/core/database-manager.js +331 -0
- package/core/database.js +124 -83
- package/core/eia-brain.js +2 -2
- package/core/eia-monitor.js +7 -7
- package/core/engine.js +24 -24
- package/core/error-handler.js +203 -0
- package/core/gateway.js +9 -9
- package/core/learning.js +7 -7
- package/core/license-manager.js +1 -1
- package/core/license.js +6 -6
- package/core/logger.js +228 -0
- package/core/marketplace-adapter.js +5 -5
- package/core/memory.js +6 -6
- package/core/multi-agent.js +180 -0
- package/core/openclaw-bridge.js +6 -6
- package/core/queue.js +3 -3
- package/core/scheduler.js +6 -6
- package/core/scrapers/Scraper.js +1 -1
- package/core/scrapers/TrendyolScraper.js +1 -1
- package/core/self-healer.js +8 -6
- package/core/unified-product.js +8 -8
- package/core/vector-db.js +5 -5
- package/core/vision-service.js +5 -5
- package/desktop/index.html +2804 -0
- package/desktop/main.js +97 -0
- package/desktop/preload.js +30 -0
- package/dev.sh +5 -0
- package/index.js +483 -115
- package/modules/crm/sentiment-crm.js +4 -4
- package/modules/healer/listing-healer.js +2 -2
- package/modules/oracle/predictor.js +5 -5
- package/modules/researcher/agent.js +4 -4
- package/modules/war-room/competitor-tracker.js +5 -5
- package/modules/war-room/pricing-engine.js +5 -5
- package/nodes/warehouse.js +5 -5
- package/onboard.js +1 -1
- package/package.json +11 -3
- package/pkg.json +26 -0
- package/plugins/vantuz/index.js +16 -17
- package/plugins/vantuz/memory/hippocampus.js +3 -3
- package/plugins/vantuz/platforms/_request.js +1 -1
- package/plugins/vantuz/platforms/_template.js +2 -2
- package/plugins/vantuz/platforms/amazon.js +3 -3
- package/plugins/vantuz/platforms/ciceksepeti.js +2 -2
- package/plugins/vantuz/platforms/hepsiburada.js +2 -2
- package/plugins/vantuz/platforms/index.js +9 -24
- package/plugins/vantuz/platforms/n11.js +3 -3
- package/plugins/vantuz/platforms/pazarama.js +2 -2
- package/plugins/vantuz/platforms/pttavm.js +2 -2
- package/plugins/vantuz/platforms/trendyol.js +3 -3
- package/plugins/vantuz/services/alerts.js +1 -1
- package/plugins/vantuz/services/scheduler.js +1 -1
- package/plugins/vantuz/tools/nl-parser.js +1 -1
- package/plugins/vantuz/tools/quick-report.js +2 -2
- package/plugins/vantuz/tools/repricer.js +1 -1
- package/plugins/vantuz/tools/vision.js +3 -3
- package/server/app.js +8 -8
- package/DOCS_TR.md +0 -80
- package/modules/team/agents/base.js +0 -92
- package/modules/team/agents/dev.js +0 -33
- package/modules/team/agents/josh.js +0 -40
- package/modules/team/agents/marketing.js +0 -33
- package/modules/team/agents/milo.js +0 -36
- package/modules/team/index.js +0 -78
- package/modules/team/shared-memory.js +0 -87
- package/n11docs.md +0 -1680
- package/openclawdocs.md +0 -3
- package/vantuz.sqlite +0 -0
- package/workspace/AGENTS.md +0 -73
- package/workspace/BRAND.md +0 -29
- package/workspace/SOUL.md +0 -72
- package/workspace/team/DECISIONS.md +0 -3
- package/workspace/team/GOALS.md +0 -3
- package/workspace/team/PROJECT_STATUS.md +0 -3
- package/workspace/team/agents/dev/SOUL.md +0 -12
- package/workspace/team/agents/josh/SOUL.md +0 -12
- package/workspace/team/agents/marketing/SOUL.md +0 -12
- package/workspace/team/agents/milo/SOUL.md +0 -12
package/core/database.js
CHANGED
|
@@ -1,18 +1,69 @@
|
|
|
1
|
-
const
|
|
1
|
+
const initSqlJs = require('sql.js');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
|
|
5
5
|
const dbPath = path.join(process.cwd(), 'vantuz.sqlite');
|
|
6
6
|
let db;
|
|
7
|
+
let SQL;
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
// Initialize and create models synchronously
|
|
10
|
+
let Store, Product, Order, Insight;
|
|
11
|
+
|
|
12
|
+
async function init() {
|
|
13
|
+
try {
|
|
14
|
+
SQL = await initSqlJs();
|
|
15
|
+
|
|
16
|
+
if (fs.existsSync(dbPath)) {
|
|
17
|
+
const buffer = fs.readFileSync(dbPath);
|
|
18
|
+
db = new SQL.Database(buffer);
|
|
19
|
+
} else {
|
|
20
|
+
db = new SQL.Database();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
createModels();
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.error('❌ Veritabanı bağlantısı başarısız:', e.message);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function run(sql, params = []) {
|
|
30
|
+
if (!db) return;
|
|
31
|
+
db.run(sql, params);
|
|
32
|
+
saveDB();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function get(sql, params = []) {
|
|
36
|
+
if (!db) return null;
|
|
37
|
+
const stmt = db.prepare(sql);
|
|
38
|
+
stmt.bind(params);
|
|
39
|
+
if (stmt.step()) {
|
|
40
|
+
const row = stmt.getAsObject();
|
|
41
|
+
stmt.free();
|
|
42
|
+
return row;
|
|
43
|
+
}
|
|
44
|
+
stmt.free();
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function all(sql, params = []) {
|
|
49
|
+
if (!db) return [];
|
|
50
|
+
const stmt = db.prepare(sql);
|
|
51
|
+
stmt.bind(params);
|
|
52
|
+
const results = [];
|
|
53
|
+
while (stmt.step()) {
|
|
54
|
+
results.push(stmt.getAsObject());
|
|
55
|
+
}
|
|
56
|
+
stmt.free();
|
|
57
|
+
return results;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function saveDB() {
|
|
61
|
+
if (!db) return;
|
|
62
|
+
const data = db.export();
|
|
63
|
+
const buffer = Buffer.from(data);
|
|
64
|
+
fs.writeFileSync(dbPath, buffer);
|
|
13
65
|
}
|
|
14
66
|
|
|
15
|
-
// Simple Model Wrapper to mimic Sequelize API partially
|
|
16
67
|
class Model {
|
|
17
68
|
constructor(tableName, schema) {
|
|
18
69
|
this.tableName = tableName;
|
|
@@ -21,12 +72,11 @@ class Model {
|
|
|
21
72
|
}
|
|
22
73
|
|
|
23
74
|
_initTable() {
|
|
24
|
-
// Basic schema to SQL
|
|
25
75
|
const cols = Object.entries(this.schema).map(([key, props]) => {
|
|
26
76
|
let type = 'TEXT';
|
|
27
77
|
if (props.type === 'INTEGER') type = 'INTEGER';
|
|
28
78
|
if (props.type === 'FLOAT') type = 'REAL';
|
|
29
|
-
if (props.type === 'BOOLEAN') type = 'INTEGER';
|
|
79
|
+
if (props.type === 'BOOLEAN') type = 'INTEGER';
|
|
30
80
|
|
|
31
81
|
let def = `${key} ${type}`;
|
|
32
82
|
if (props.allowNull === false) def += ' NOT NULL';
|
|
@@ -39,13 +89,11 @@ class Model {
|
|
|
39
89
|
}).join(', ');
|
|
40
90
|
|
|
41
91
|
const sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} (id INTEGER PRIMARY KEY AUTOINCREMENT, ${cols}, createdAt TEXT, updatedAt TEXT)`;
|
|
42
|
-
|
|
92
|
+
run(sql);
|
|
43
93
|
}
|
|
44
94
|
|
|
45
95
|
async findAll(query = {}) {
|
|
46
|
-
|
|
47
|
-
const stmt = db.prepare(`SELECT * FROM ${this.tableName}`);
|
|
48
|
-
const rows = stmt.all();
|
|
96
|
+
const rows = all(`SELECT * FROM ${this.tableName}`);
|
|
49
97
|
return rows.map(r => this._parseRow(r));
|
|
50
98
|
}
|
|
51
99
|
|
|
@@ -57,8 +105,7 @@ class Model {
|
|
|
57
105
|
const whereClause = keys.map(k => `${k} = ?`).join(' AND ');
|
|
58
106
|
const values = keys.map(k => query.where[k]);
|
|
59
107
|
|
|
60
|
-
const
|
|
61
|
-
const row = stmt.get(...values);
|
|
108
|
+
const row = get(`SELECT * FROM ${this.tableName} WHERE ${whereClause} LIMIT 1`, values);
|
|
62
109
|
return row ? this._parseRow(row) : null;
|
|
63
110
|
}
|
|
64
111
|
|
|
@@ -71,42 +118,38 @@ class Model {
|
|
|
71
118
|
});
|
|
72
119
|
|
|
73
120
|
const now = new Date().toISOString();
|
|
74
|
-
// Add timestamps
|
|
75
121
|
const allKeys = [...keys, 'createdAt', 'updatedAt'];
|
|
76
|
-
const allPlaceholders = [...keys.map(() => '?'), '?', '?'];
|
|
77
122
|
const allValues = [...values, now, now];
|
|
78
123
|
|
|
79
|
-
const sql = `INSERT INTO ${this.tableName} (${allKeys.join(', ')}) VALUES (${
|
|
80
|
-
|
|
81
|
-
|
|
124
|
+
const sql = `INSERT INTO ${this.tableName} (${allKeys.join(', ')}) VALUES (${placeholders}, ?, ?)`;
|
|
125
|
+
run(sql, allValues);
|
|
126
|
+
|
|
127
|
+
const idResult = get(`SELECT last_insert_rowid() as id`);
|
|
128
|
+
const id = idResult ? idResult.id : 0;
|
|
129
|
+
return { ...data, id, createdAt: now, updatedAt: now };
|
|
82
130
|
}
|
|
83
131
|
|
|
84
132
|
async count() {
|
|
85
|
-
const
|
|
86
|
-
return
|
|
133
|
+
const result = get(`SELECT COUNT(*) as count FROM ${this.tableName}`);
|
|
134
|
+
return result ? result.count : 0;
|
|
87
135
|
}
|
|
88
136
|
|
|
89
137
|
async destroy(query = {}) {
|
|
90
138
|
if (!query.where) return;
|
|
91
139
|
const whereClause = Object.keys(query.where).map(k => `${k} = ?`).join(' AND ');
|
|
92
140
|
const values = Object.values(query.where);
|
|
93
|
-
|
|
94
|
-
const stmt = db.prepare(sql);
|
|
95
|
-
return stmt.run(...values);
|
|
141
|
+
run(`DELETE FROM ${this.tableName} WHERE ${whereClause}`, values);
|
|
96
142
|
}
|
|
97
143
|
|
|
98
144
|
async update(data, query = {}) {
|
|
99
145
|
if (!query.where) return;
|
|
100
146
|
const updateClause = Object.keys(data).map(k => `${k} = ?`).join(', ');
|
|
101
147
|
const whereClause = Object.keys(query.where).map(k => `${k} = ?`).join(' AND ');
|
|
102
|
-
const values = [...Object.values(data), ...Object.values(query.where)];
|
|
103
|
-
|
|
104
|
-
const stmt = db.prepare(sql);
|
|
105
|
-
return stmt.run(...values, new Date().toISOString());
|
|
148
|
+
const values = [...Object.values(data), ...Object.values(query.where), new Date().toISOString()];
|
|
149
|
+
run(`UPDATE ${this.tableName} SET ${updateClause}, updatedAt = ? WHERE ${whereClause}`, values);
|
|
106
150
|
}
|
|
107
151
|
|
|
108
152
|
_parseRow(row) {
|
|
109
|
-
// Convert JSON fields back to objects
|
|
110
153
|
for (const [key, props] of Object.entries(this.schema)) {
|
|
111
154
|
if (props.type === 'JSON' && row[key]) {
|
|
112
155
|
try { row[key] = JSON.parse(row[key]); } catch {}
|
|
@@ -119,7 +162,6 @@ class Model {
|
|
|
119
162
|
}
|
|
120
163
|
}
|
|
121
164
|
|
|
122
|
-
// Define Models manually with simple types
|
|
123
165
|
const DataTypes = {
|
|
124
166
|
STRING: 'TEXT',
|
|
125
167
|
TEXT: 'TEXT',
|
|
@@ -130,62 +172,61 @@ const DataTypes = {
|
|
|
130
172
|
DATE: 'TEXT'
|
|
131
173
|
};
|
|
132
174
|
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async function initDB() {
|
|
170
|
-
return true; // Tables created in constructor
|
|
175
|
+
function createModels() {
|
|
176
|
+
Store = new Model('Stores', {
|
|
177
|
+
name: { type: DataTypes.STRING, allowNull: false },
|
|
178
|
+
platform: { type: DataTypes.STRING, allowNull: false },
|
|
179
|
+
credentials: { type: DataTypes.JSON, allowNull: false },
|
|
180
|
+
isActive: { type: DataTypes.BOOLEAN, defaultValue: 1 }
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
Product = new Model('Products', {
|
|
184
|
+
name: { type: DataTypes.STRING, allowNull: false },
|
|
185
|
+
barcode: { type: DataTypes.STRING, unique: true },
|
|
186
|
+
sku: { type: DataTypes.STRING },
|
|
187
|
+
description: { type: DataTypes.TEXT },
|
|
188
|
+
brand: { type: DataTypes.STRING },
|
|
189
|
+
images: { type: DataTypes.JSON },
|
|
190
|
+
marketData: { type: DataTypes.JSON },
|
|
191
|
+
aiAnalysis: { type: DataTypes.TEXT }
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
Order = new Model('Orders', {
|
|
195
|
+
platform: { type: DataTypes.STRING, allowNull: false },
|
|
196
|
+
orderNumber: { type: DataTypes.STRING, unique: true },
|
|
197
|
+
customerName: { type: DataTypes.STRING },
|
|
198
|
+
totalAmount: { type: DataTypes.FLOAT },
|
|
199
|
+
currency: { type: DataTypes.STRING, defaultValue: 'TRY' },
|
|
200
|
+
status: { type: DataTypes.STRING },
|
|
201
|
+
orderDate: { type: DataTypes.DATE },
|
|
202
|
+
items: { type: DataTypes.JSON }
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
Insight = new Model('Insights', {
|
|
206
|
+
type: { type: DataTypes.STRING },
|
|
207
|
+
message: { type: DataTypes.TEXT },
|
|
208
|
+
priority: { type: DataTypes.INTEGER },
|
|
209
|
+
isRead: { type: DataTypes.BOOLEAN, defaultValue: 0 }
|
|
210
|
+
});
|
|
171
211
|
}
|
|
172
212
|
|
|
173
|
-
|
|
174
|
-
|
|
213
|
+
// Initialize immediately
|
|
214
|
+
init();
|
|
215
|
+
|
|
216
|
+
// Export models directly (they'll be null initially but populated after init)
|
|
217
|
+
module.exports = {
|
|
218
|
+
dbPath, // Export dbPath for database-manager.js
|
|
219
|
+
get Store() { return Store; },
|
|
220
|
+
get Product() { return Product; },
|
|
221
|
+
get Order() { return Order; },
|
|
222
|
+
get Insight() { return Insight; },
|
|
223
|
+
init,
|
|
224
|
+
initDB: init,
|
|
225
|
+
getDatabase: async () => ({
|
|
175
226
|
Store,
|
|
176
227
|
Product,
|
|
177
228
|
Order,
|
|
178
229
|
Insight,
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
module.exports = {
|
|
185
|
-
Store,
|
|
186
|
-
Product,
|
|
187
|
-
Order,
|
|
188
|
-
Insight,
|
|
189
|
-
initDB,
|
|
190
|
-
getDatabase
|
|
230
|
+
isAvailable: !!db
|
|
231
|
+
})
|
|
191
232
|
};
|
package/core/eia-brain.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// core/eia-brain.js
|
|
2
|
-
|
|
2
|
+
const { chat as aiChat, log } = require('./ai-provider.js');
|
|
3
3
|
|
|
4
4
|
class EIABrain {
|
|
5
5
|
constructor(config, env) {
|
|
@@ -94,7 +94,7 @@ Durumu analiz et ve en uygun aksiyon önerisini veya içgörüyü sun.`;
|
|
|
94
94
|
|
|
95
95
|
let eiaBrainInstance = null;
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
module.exports.getE = functionIABrain(config, env) {
|
|
98
98
|
if (!eiaBrainInstance) {
|
|
99
99
|
eiaBrainInstance = new EIABrain(config, env);
|
|
100
100
|
}
|
package/core/eia-monitor.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// core/eia-monitor.js
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
const { getScheduler } = require('./scheduler.js');
|
|
3
|
+
const { TrendyolScraper } = require('./scrapers/TrendyolScraper.js'); // Example scraper
|
|
4
|
+
const { getEIABrain } = require('./eia-brain.js');
|
|
5
|
+
const dbPkg = require('./database.js'); // CommonJS uyumluluğu için default import
|
|
6
|
+
const { getVectorDB } = require('./vector-db.js'); // Import vector DB
|
|
7
|
+
const { log } = require('./ai-provider.js');
|
|
8
8
|
|
|
9
9
|
const { getDatabase } = dbPkg;
|
|
10
10
|
|
|
@@ -222,7 +222,7 @@ Veri Tipi: ${dataType}`;
|
|
|
222
222
|
|
|
223
223
|
let eiaMonitorInstance = null;
|
|
224
224
|
|
|
225
|
-
|
|
225
|
+
module.exports.getE = functionIAMonitor(config, env) {
|
|
226
226
|
if (!eiaMonitorInstance) {
|
|
227
227
|
eiaMonitorInstance = new EIAMonitor(config, env);
|
|
228
228
|
}
|
package/core/engine.js
CHANGED
|
@@ -6,35 +6,35 @@
|
|
|
6
6
|
* Entegre Tool Sistemi
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const os = require('os');
|
|
12
12
|
|
|
13
13
|
// Platform Hub
|
|
14
|
-
|
|
14
|
+
const platformHub = require('../plugins/vantuz/platforms/index.js');
|
|
15
15
|
|
|
16
16
|
// AI Provider & Gateway
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
const { getChannelManager } = require('./channels.js');
|
|
18
|
+
const { chat as aiChat, log } = require('./ai-provider.js');
|
|
19
|
+
const { getGateway } = require('./gateway.js');
|
|
20
|
+
const { getEIAMonitor } = require('./eia-monitor.js');
|
|
21
|
+
const AutomationManager = require('./automation.js');
|
|
22
|
+
const OpenClawBridge = require('./openclaw-bridge.js');
|
|
23
|
+
const { executeTool } = require('./agent.js');
|
|
24
|
+
const { getCriticalQueue } = require('./queue.js');
|
|
25
|
+
const { getMemory } = require('./memory.js');
|
|
26
26
|
|
|
27
27
|
// Multi-Agent Team
|
|
28
|
-
|
|
28
|
+
const TeamModule = require('../modules/team/index.js');
|
|
29
29
|
|
|
30
30
|
// Tools
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
const { repricerTool } = require('../plugins/vantuz/tools/repricer.js');
|
|
32
|
+
const { visionTool } = require('../plugins/vantuz/tools/vision.js');
|
|
33
|
+
const { sentimentTool } = require('../plugins/vantuz/tools/sentiment.js');
|
|
34
|
+
const { crossborderTool } = require('../plugins/vantuz/tools/crossborder.js');
|
|
35
|
+
const { productTool } = require('../plugins/vantuz/tools/product.js');
|
|
36
|
+
const { analyticsTool } = require('../plugins/vantuz/tools/analytics.js');
|
|
37
|
+
const { quickReportTool } = require('../plugins/vantuz/tools/quick-report.js');
|
|
38
38
|
|
|
39
39
|
const PLATFORM_CONFIG_MAP = {
|
|
40
40
|
trendyol: {
|
|
@@ -79,7 +79,7 @@ const CONFIG_JSON = path.join(VANTUZ_HOME, 'config.json');
|
|
|
79
79
|
// ENGINE CLASS
|
|
80
80
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
module.exports = VantuzEngine {
|
|
83
83
|
constructor() {
|
|
84
84
|
this.initialized = false;
|
|
85
85
|
this.config = {};
|
|
@@ -637,7 +637,7 @@ export class VantuzEngine {
|
|
|
637
637
|
// Singleton instance
|
|
638
638
|
let engineInstance = null;
|
|
639
639
|
|
|
640
|
-
|
|
640
|
+
module.exports.getEng = async functionine() {
|
|
641
641
|
if (!engineInstance) {
|
|
642
642
|
engineInstance = new VantuzEngine();
|
|
643
643
|
await engineInstance.initialize();
|
|
@@ -645,4 +645,4 @@ export async function getEngine() {
|
|
|
645
645
|
return engineInstance;
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
-
|
|
648
|
+
module.exports = VantuzEngine;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🐙 VANTUZ Error Handler - Graceful Shutdown & Error Reporting
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const logger = require('./logger');
|
|
8
|
+
|
|
9
|
+
const SHUTDOWN_TIMEOUT = 10000; // 10 seconds
|
|
10
|
+
let isShuttingDown = false;
|
|
11
|
+
let pendingOperations = 0;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Graceful shutdown handler
|
|
15
|
+
*/
|
|
16
|
+
async function setupGracefulShutdown(server, db) {
|
|
17
|
+
const shutdown = async (signal) => {
|
|
18
|
+
if (isShuttingDown) return;
|
|
19
|
+
isShuttingDown = true;
|
|
20
|
+
|
|
21
|
+
logger.warn(`Alınan sinyal: ${signal}`, { signal });
|
|
22
|
+
console.log(`\n🛑 ${signal} alındı. Graceful shutdown başlıyor...\n`);
|
|
23
|
+
|
|
24
|
+
// Yeni işlemleri engelle
|
|
25
|
+
pendingOperations = 0;
|
|
26
|
+
|
|
27
|
+
// HTTP server kapat
|
|
28
|
+
if (server) {
|
|
29
|
+
console.log('🌐 HTTP server kapatılıyor...');
|
|
30
|
+
await new Promise((resolve) => {
|
|
31
|
+
server.close(resolve);
|
|
32
|
+
});
|
|
33
|
+
console.log('✅ HTTP server kapatıldı');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Veritabanı kaydet
|
|
37
|
+
if (db && typeof db.saveDB === 'function') {
|
|
38
|
+
console.log('💾 Veritabanı kaydediliyor...');
|
|
39
|
+
db.saveDB();
|
|
40
|
+
console.log('✅ Veritabanı kaydedildi');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Session log
|
|
44
|
+
const startTime = process.env.SESSION_START || Date.now();
|
|
45
|
+
const duration = Date.now() - startTime;
|
|
46
|
+
logger.endSession(process.env.SESSION_ID || 'unknown', duration);
|
|
47
|
+
|
|
48
|
+
console.log('👋 Güvenli çıkış yapılıyor...\n');
|
|
49
|
+
process.exit(0);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
53
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
54
|
+
|
|
55
|
+
// Unhandled rejection
|
|
56
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
57
|
+
logger.error('Unhandled Rejection', { reason: String(reason), stack: reason?.stack });
|
|
58
|
+
console.error('❌ Unhandled Rejection:', reason);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Uncaught exception
|
|
62
|
+
process.on('uncaughtException', (error) => {
|
|
63
|
+
logger.fatal('Uncaught Exception', {
|
|
64
|
+
message: error.message,
|
|
65
|
+
stack: error.stack
|
|
66
|
+
});
|
|
67
|
+
console.error('❌ Uncaught Exception:', error);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log('✅ Graceful shutdown handler kuruldu');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Async işlem wrapper - try-catch
|
|
76
|
+
*/
|
|
77
|
+
async function withErrorHandler(fn, context = {}) {
|
|
78
|
+
try {
|
|
79
|
+
pendingOperations++;
|
|
80
|
+
const result = await fn();
|
|
81
|
+
pendingOperations--;
|
|
82
|
+
return result;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
pendingOperations--;
|
|
85
|
+
logger.error(`Hata [${context.operation || 'unknown'}]`, {
|
|
86
|
+
message: error.message,
|
|
87
|
+
stack: error.stack,
|
|
88
|
+
...context
|
|
89
|
+
});
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Timeout wrapper
|
|
96
|
+
*/
|
|
97
|
+
function withTimeout(promise, timeoutMs = 30000, operation = 'operation') {
|
|
98
|
+
return Promise.race([
|
|
99
|
+
promise,
|
|
100
|
+
new Promise((_, reject) =>
|
|
101
|
+
setTimeout(() => reject(new Error(`${operation} timeout (${timeoutMs}ms)`)), timeoutMs)
|
|
102
|
+
)
|
|
103
|
+
]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Database auto-reconnect
|
|
108
|
+
*/
|
|
109
|
+
class DatabaseAutoReconnect {
|
|
110
|
+
constructor(db, maxRetries = 5, retryDelay = 1000) {
|
|
111
|
+
this.db = db;
|
|
112
|
+
this.maxRetries = maxRetries;
|
|
113
|
+
this.retryDelay = retryDelay;
|
|
114
|
+
this.retries = 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async ensureConnected() {
|
|
118
|
+
if (this.db && this.db.isAvailable) return true;
|
|
119
|
+
|
|
120
|
+
if (this.retries >= this.maxRetries) {
|
|
121
|
+
throw new Error('Veritabanı bağlantısı maksimum deneme sayısına ulaşıldı');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
logger.warn('Veritabanı bağlantısı kopuk, yeniden deneniyor...', {
|
|
125
|
+
attempt: this.retries + 1,
|
|
126
|
+
maxRetries: this.maxRetries
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
await new Promise(r => setTimeout(r, this.retryDelay));
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
await this.db.initDB();
|
|
133
|
+
this.retries = 0;
|
|
134
|
+
logger.info('Veritabanı yeniden bağlandı');
|
|
135
|
+
return true;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
this.retries++;
|
|
138
|
+
return this.ensureConnected();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* API Timeout Handler
|
|
145
|
+
*/
|
|
146
|
+
class APITimeoutHandler {
|
|
147
|
+
constructor(defaultTimeout = 30000) {
|
|
148
|
+
this.defaultTimeout = defaultTimeout;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async request(fn, timeout = null) {
|
|
152
|
+
const timeoutMs = timeout || this.defaultTimeout;
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
return await withTimeout(
|
|
156
|
+
Promise.resolve(fn()),
|
|
157
|
+
timeoutMs,
|
|
158
|
+
'API Request'
|
|
159
|
+
);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
if (error.message.includes('timeout')) {
|
|
162
|
+
logger.warn('API Timeout', { timeoutMs });
|
|
163
|
+
throw new Error(`API isteği zaman aşımına uğradı (${timeoutMs}ms)`);
|
|
164
|
+
}
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Error reporting
|
|
172
|
+
*/
|
|
173
|
+
function reportError(error, context = {}) {
|
|
174
|
+
const report = logger.reportError(error, {
|
|
175
|
+
...context,
|
|
176
|
+
timestamp: new Date().toISOString(),
|
|
177
|
+
platform: process.platform,
|
|
178
|
+
arch: process.arch,
|
|
179
|
+
nodeVersion: process.version,
|
|
180
|
+
memoryUsage: process.memoryUsage(),
|
|
181
|
+
environment: process.env.NODE_ENV
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Crash dump dosyası oluştur
|
|
185
|
+
const crashDir = path.join(process.cwd(), 'crashes');
|
|
186
|
+
if (!fs.existsSync(crashDir)) {
|
|
187
|
+
fs.mkdirSync(crashDir, { recursive: true });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const crashFile = path.join(crashDir, `crash-${Date.now()}.json`);
|
|
191
|
+
fs.writeFileSync(crashFile, JSON.stringify(report, null, 2));
|
|
192
|
+
|
|
193
|
+
return report;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
module.exports = {
|
|
197
|
+
setupGracefulShutdown,
|
|
198
|
+
withErrorHandler,
|
|
199
|
+
withTimeout,
|
|
200
|
+
DatabaseAutoReconnect,
|
|
201
|
+
APITimeoutHandler,
|
|
202
|
+
reportError
|
|
203
|
+
};
|
package/core/gateway.js
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
* - Sistem durumu sorgulama
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const axios = require('axios');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const os = require('os');
|
|
16
|
+
const { log } = require('./ai-provider.js');
|
|
17
17
|
|
|
18
18
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
19
19
|
// CONFIG - Gateway ayarları
|
|
@@ -42,7 +42,7 @@ function getGatewayToken(config) {
|
|
|
42
42
|
// GATEWAY CLIENT
|
|
43
43
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
module.exports = VantuzGateway {
|
|
46
46
|
constructor() {
|
|
47
47
|
this.config = loadGatewayConfig();
|
|
48
48
|
const port = this.config?.gateway?.port || 18789;
|
|
@@ -417,7 +417,7 @@ let gatewayInstance = null;
|
|
|
417
417
|
* Vantuz Gateway singleton instance
|
|
418
418
|
* Otomatik bağlantı kontrolü yapar
|
|
419
419
|
*/
|
|
420
|
-
|
|
420
|
+
module.exports.getGateway = async function() {
|
|
421
421
|
if (!gatewayInstance) {
|
|
422
422
|
gatewayInstance = new VantuzGateway();
|
|
423
423
|
|
|
@@ -440,8 +440,8 @@ export async function getGateway() {
|
|
|
440
440
|
/**
|
|
441
441
|
* Gateway durumunu sıfırla (reconnect için)
|
|
442
442
|
*/
|
|
443
|
-
|
|
443
|
+
module.exports.resetGateway = function() {
|
|
444
444
|
gatewayInstance = null;
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
-
|
|
447
|
+
module.exports = VantuzGateway;
|