vantuz 3.2.7 → 3.3.0
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/core/ai-provider.js +95 -141
- package/core/database.js +70 -60
- package/core/eia-brain.js +102 -0
- package/core/eia-monitor.js +220 -0
- package/core/engine.js +99 -39
- package/core/gateway.js +5 -21
- package/core/migrations/001-initial-schema.js +28 -0
- package/core/scheduler.js +80 -0
- package/core/scrapers/Scraper.js +61 -0
- package/core/scrapers/TrendyolScraper.js +76 -0
- package/core/vector-db.js +97 -0
- package/onboard.js +27 -1
- package/package.json +7 -5
- package/plugins/vantuz/platforms/index.js +13 -9
- package/server/app.js +2 -2
package/core/ai-provider.js
CHANGED
|
@@ -10,6 +10,75 @@ import os from 'os';
|
|
|
10
10
|
|
|
11
11
|
const LOG_FILE = path.join(os.homedir(), '.vantuz', 'vantuz.log');
|
|
12
12
|
|
|
13
|
+
const PROVIDER_CONFIG = {
|
|
14
|
+
gemini: {
|
|
15
|
+
url: (apiKey) => `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`,
|
|
16
|
+
body: (systemPrompt, message) => ({
|
|
17
|
+
contents: [{ parts: [{ text: `${systemPrompt}\n\nKullanıcı: ${message}` }] }]
|
|
18
|
+
}),
|
|
19
|
+
headers: { 'Content-Type': 'application/json' },
|
|
20
|
+
parseResponse: (data) => data?.candidates?.[0]?.content?.parts?.[0]?.text,
|
|
21
|
+
errorMsg: 'Gemini yanıt vermedi'
|
|
22
|
+
},
|
|
23
|
+
groq: {
|
|
24
|
+
url: 'https://api.groq.com/openai/v1/chat/completions',
|
|
25
|
+
body: (systemPrompt, message) => ({
|
|
26
|
+
model: 'llama-3.3-70b-versatile',
|
|
27
|
+
messages: [
|
|
28
|
+
{ role: 'system', content: systemPrompt },
|
|
29
|
+
{ role: 'user', content: message }
|
|
30
|
+
],
|
|
31
|
+
max_tokens: 1000,
|
|
32
|
+
temperature: 0.7
|
|
33
|
+
}),
|
|
34
|
+
headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
|
|
35
|
+
parseResponse: (data) => data?.choices?.[0]?.message?.content,
|
|
36
|
+
errorMsg: 'Groq yanıt vermedi'
|
|
37
|
+
},
|
|
38
|
+
openai: {
|
|
39
|
+
url: 'https://api.openai.com/v1/chat/completions',
|
|
40
|
+
body: (systemPrompt, message) => ({
|
|
41
|
+
model: 'gpt-4o-mini',
|
|
42
|
+
messages: [
|
|
43
|
+
{ role: 'system', content: systemPrompt },
|
|
44
|
+
{ role: 'user', content: message }
|
|
45
|
+
],
|
|
46
|
+
max_tokens: 1000
|
|
47
|
+
}),
|
|
48
|
+
headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
|
|
49
|
+
parseResponse: (data) => data?.choices?.[0]?.message?.content,
|
|
50
|
+
errorMsg: 'OpenAI yanıt vermedi'
|
|
51
|
+
},
|
|
52
|
+
anthropic: {
|
|
53
|
+
url: 'https://api.anthropic.com/v1/messages',
|
|
54
|
+
body: (systemPrompt, message) => ({
|
|
55
|
+
model: 'claude-3-haiku-20240307',
|
|
56
|
+
max_tokens: 1000,
|
|
57
|
+
messages: [
|
|
58
|
+
{ role: 'user', content: message }
|
|
59
|
+
],
|
|
60
|
+
system: systemPrompt
|
|
61
|
+
}),
|
|
62
|
+
headers: (apiKey) => ({ 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'Content-Type': 'application/json' }),
|
|
63
|
+
parseResponse: (data) => data?.content?.[0]?.text,
|
|
64
|
+
errorMsg: 'Anthropic yanıt vermedi'
|
|
65
|
+
},
|
|
66
|
+
deepseek: {
|
|
67
|
+
url: 'https://api.deepseek.com/v1/chat/completions',
|
|
68
|
+
body: (systemPrompt, message) => ({
|
|
69
|
+
model: 'deepseek-chat',
|
|
70
|
+
messages: [
|
|
71
|
+
{ role: 'system', content: systemPrompt },
|
|
72
|
+
{ role: 'user', content: message }
|
|
73
|
+
],
|
|
74
|
+
max_tokens: 1000
|
|
75
|
+
}),
|
|
76
|
+
headers: (apiKey) => ({ 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }),
|
|
77
|
+
parseResponse: (data) => data?.choices?.[0]?.message?.content,
|
|
78
|
+
errorMsg: 'DeepSeek yanıt vermedi'
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
13
82
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
14
83
|
// LOGGING
|
|
15
84
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -91,8 +160,28 @@ const VANTUZ_SYSTEM_PROMPT = `Sen Vantuz AI, e-ticaret operasyonlarını yönete
|
|
|
91
160
|
// AI CHAT
|
|
92
161
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
93
162
|
|
|
163
|
+
async function _makeApiRequest(providerName, providerConfig, message, apiKey, systemPrompt) {
|
|
164
|
+
if (!apiKey) throw new Error(`${providerName.toUpperCase()}_API_KEY ayarlanmamış`);
|
|
165
|
+
|
|
166
|
+
const url = typeof providerConfig.url === 'function' ? providerConfig.url(apiKey) : providerConfig.url;
|
|
167
|
+
const headers = typeof providerConfig.headers === 'function' ? providerConfig.headers(apiKey) : providerConfig.headers;
|
|
168
|
+
const body = providerConfig.body(systemPrompt, message);
|
|
169
|
+
|
|
170
|
+
const response = await axios.post(url, body, {
|
|
171
|
+
headers,
|
|
172
|
+
timeout: 30000
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const text = providerConfig.parseResponse(response.data);
|
|
176
|
+
if (!text) throw new Error(providerConfig.errorMsg);
|
|
177
|
+
|
|
178
|
+
log('INFO', `${providerName} yanıtı alındı`, { chars: text.length });
|
|
179
|
+
return text;
|
|
180
|
+
}
|
|
181
|
+
|
|
94
182
|
export async function chat(message, config, env) {
|
|
95
183
|
const provider = config.aiProvider || 'gemini';
|
|
184
|
+
const providerConfig = PROVIDER_CONFIG[provider];
|
|
96
185
|
|
|
97
186
|
// Context bilgisi ekle
|
|
98
187
|
const contextInfo = config.systemContext || '';
|
|
@@ -100,154 +189,19 @@ export async function chat(message, config, env) {
|
|
|
100
189
|
|
|
101
190
|
log('INFO', `AI isteği: ${provider}`, { message: message.slice(0, 100) });
|
|
102
191
|
|
|
192
|
+
if (!providerConfig) {
|
|
193
|
+
return 'Desteklenmeyen AI sağlayıcı: ' + provider;
|
|
194
|
+
}
|
|
195
|
+
|
|
103
196
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return await chatGemini(message, env.GEMINI_API_KEY, fullSystemPrompt);
|
|
107
|
-
case 'groq':
|
|
108
|
-
return await chatGroq(message, env.GROQ_API_KEY, fullSystemPrompt);
|
|
109
|
-
case 'openai':
|
|
110
|
-
return await chatOpenAI(message, env.OPENAI_API_KEY, fullSystemPrompt);
|
|
111
|
-
case 'anthropic':
|
|
112
|
-
return await chatAnthropic(message, env.ANTHROPIC_API_KEY, fullSystemPrompt);
|
|
113
|
-
case 'deepseek':
|
|
114
|
-
return await chatDeepSeek(message, env.DEEPSEEK_API_KEY, fullSystemPrompt);
|
|
115
|
-
default:
|
|
116
|
-
return 'Desteklenmeyen AI sağlayıcı: ' + provider;
|
|
117
|
-
}
|
|
197
|
+
const apiKey = env[`${provider.toUpperCase()}_API_KEY`];
|
|
198
|
+
return await _makeApiRequest(provider, providerConfig, message, apiKey, fullSystemPrompt);
|
|
118
199
|
} catch (error) {
|
|
119
200
|
log('ERROR', `AI hatası: ${error.message}`, { provider });
|
|
120
201
|
return `AI hatası: ${error.message}. /logs komutu ile detay görün.`;
|
|
121
202
|
}
|
|
122
203
|
}
|
|
123
204
|
|
|
124
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
125
|
-
// PROVIDER IMPLEMENTATIONS
|
|
126
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
127
|
-
|
|
128
|
-
async function chatGemini(message, apiKey, systemPrompt) {
|
|
129
|
-
if (!apiKey) throw new Error('GEMINI_API_KEY ayarlanmamış');
|
|
130
|
-
|
|
131
|
-
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey}`;
|
|
132
|
-
|
|
133
|
-
const response = await axios.post(url, {
|
|
134
|
-
contents: [{
|
|
135
|
-
parts: [{
|
|
136
|
-
text: `${systemPrompt}\n\nKullanıcı: ${message}`
|
|
137
|
-
}]
|
|
138
|
-
}]
|
|
139
|
-
}, {
|
|
140
|
-
headers: { 'Content-Type': 'application/json' },
|
|
141
|
-
timeout: 30000
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const text = response.data?.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
145
|
-
if (!text) throw new Error('Gemini yanıt vermedi');
|
|
146
|
-
|
|
147
|
-
log('INFO', 'Gemini yanıtı alındı', { chars: text.length });
|
|
148
|
-
return text;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async function chatGroq(message, apiKey, systemPrompt) {
|
|
152
|
-
if (!apiKey) throw new Error('GROQ_API_KEY ayarlanmamış');
|
|
153
|
-
|
|
154
|
-
const response = await axios.post('https://api.groq.com/openai/v1/chat/completions', {
|
|
155
|
-
model: 'llama-3.3-70b-versatile',
|
|
156
|
-
messages: [
|
|
157
|
-
{ role: 'system', content: systemPrompt },
|
|
158
|
-
{ role: 'user', content: message }
|
|
159
|
-
],
|
|
160
|
-
max_tokens: 1000,
|
|
161
|
-
temperature: 0.7
|
|
162
|
-
}, {
|
|
163
|
-
headers: {
|
|
164
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
165
|
-
'Content-Type': 'application/json'
|
|
166
|
-
},
|
|
167
|
-
timeout: 30000
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const text = response.data?.choices?.[0]?.message?.content;
|
|
171
|
-
if (!text) throw new Error('Groq yanıt vermedi');
|
|
172
|
-
|
|
173
|
-
log('INFO', 'Groq yanıtı alındı', { chars: text.length });
|
|
174
|
-
return text;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function chatOpenAI(message, apiKey, systemPrompt) {
|
|
178
|
-
if (!apiKey) throw new Error('OPENAI_API_KEY ayarlanmamış');
|
|
179
|
-
|
|
180
|
-
const response = await axios.post('https://api.openai.com/v1/chat/completions', {
|
|
181
|
-
model: 'gpt-4o-mini',
|
|
182
|
-
messages: [
|
|
183
|
-
{ role: 'system', content: systemPrompt },
|
|
184
|
-
{ role: 'user', content: message }
|
|
185
|
-
],
|
|
186
|
-
max_tokens: 1000
|
|
187
|
-
}, {
|
|
188
|
-
headers: {
|
|
189
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
190
|
-
'Content-Type': 'application/json'
|
|
191
|
-
},
|
|
192
|
-
timeout: 30000
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
const text = response.data?.choices?.[0]?.message?.content;
|
|
196
|
-
if (!text) throw new Error('OpenAI yanıt vermedi');
|
|
197
|
-
|
|
198
|
-
log('INFO', 'OpenAI yanıtı alındı', { chars: text.length });
|
|
199
|
-
return text;
|
|
200
|
-
}
|
|
201
205
|
|
|
202
|
-
async function chatAnthropic(message, apiKey, systemPrompt) {
|
|
203
|
-
if (!apiKey) throw new Error('ANTHROPIC_API_KEY ayarlanmamış');
|
|
204
|
-
|
|
205
|
-
const response = await axios.post('https://api.anthropic.com/v1/messages', {
|
|
206
|
-
model: 'claude-3-haiku-20240307',
|
|
207
|
-
max_tokens: 1000,
|
|
208
|
-
messages: [
|
|
209
|
-
{ role: 'user', content: message }
|
|
210
|
-
],
|
|
211
|
-
system: systemPrompt
|
|
212
|
-
}, {
|
|
213
|
-
headers: {
|
|
214
|
-
'x-api-key': apiKey,
|
|
215
|
-
'anthropic-version': '2023-06-01',
|
|
216
|
-
'Content-Type': 'application/json'
|
|
217
|
-
},
|
|
218
|
-
timeout: 30000
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
const text = response.data?.content?.[0]?.text;
|
|
222
|
-
if (!text) throw new Error('Anthropic yanıt vermedi');
|
|
223
|
-
|
|
224
|
-
log('INFO', 'Anthropic yanıtı alındı', { chars: text.length });
|
|
225
|
-
return text;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
async function chatDeepSeek(message, apiKey, systemPrompt) {
|
|
229
|
-
if (!apiKey) throw new Error('DEEPSEEK_API_KEY ayarlanmamış');
|
|
230
|
-
|
|
231
|
-
const response = await axios.post('https://api.deepseek.com/v1/chat/completions', {
|
|
232
|
-
model: 'deepseek-chat',
|
|
233
|
-
messages: [
|
|
234
|
-
{ role: 'system', content: systemPrompt },
|
|
235
|
-
{ role: 'user', content: message }
|
|
236
|
-
],
|
|
237
|
-
max_tokens: 1000
|
|
238
|
-
}, {
|
|
239
|
-
headers: {
|
|
240
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
241
|
-
'Content-Type': 'application/json'
|
|
242
|
-
},
|
|
243
|
-
timeout: 30000
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
const text = response.data?.choices?.[0]?.message?.content;
|
|
247
|
-
if (!text) throw new Error('DeepSeek yanıt vermedi');
|
|
248
|
-
|
|
249
|
-
log('INFO', 'DeepSeek yanıtı alındı', { chars: text.length });
|
|
250
|
-
return text;
|
|
251
|
-
}
|
|
252
206
|
|
|
253
207
|
export default { chat, log, getLogs, clearLogs };
|
package/core/database.js
CHANGED
|
@@ -1,73 +1,83 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Sequelize, DataTypes } from 'sequelize';
|
|
1
|
+
// core/database.js
|
|
2
|
+
import sqlite3 from 'sqlite3';
|
|
3
|
+
import { open } from 'sqlite';
|
|
7
4
|
import path from 'path';
|
|
8
5
|
import os from 'os';
|
|
6
|
+
import { fileURLToPath } from 'url'; // Import fileURLToPath
|
|
7
|
+
import { log } from './ai-provider.js';
|
|
9
8
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url); // Define __filename
|
|
10
|
+
const __dirname = path.dirname(__filename); // Define __dirname
|
|
12
11
|
|
|
13
|
-
const
|
|
14
|
-
dialect: 'sqlite',
|
|
15
|
-
storage: dbPath,
|
|
16
|
-
logging: false
|
|
17
|
-
});
|
|
12
|
+
const DB_PATH = path.join(os.homedir(), '.vantuz', 'eia_data.db');
|
|
18
13
|
|
|
19
|
-
|
|
14
|
+
class Database {
|
|
15
|
+
constructor() {
|
|
16
|
+
this.db = null;
|
|
17
|
+
}
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
name: { type: DataTypes.STRING, allowNull: false },
|
|
24
|
-
platform: { type: DataTypes.STRING, allowNull: false },
|
|
25
|
-
credentials: { type: DataTypes.JSON, allowNull: false },
|
|
26
|
-
isActive: { type: DataTypes.BOOLEAN, defaultValue: true }
|
|
27
|
-
});
|
|
19
|
+
async init() {
|
|
20
|
+
if (this.db) return this.db;
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
})
|
|
22
|
+
try {
|
|
23
|
+
this.db = await open({
|
|
24
|
+
filename: DB_PATH,
|
|
25
|
+
driver: sqlite3.Database
|
|
26
|
+
});
|
|
27
|
+
await this.db.migrate({
|
|
28
|
+
migrationsPath: path.join(__dirname, 'migrations')
|
|
29
|
+
});
|
|
30
|
+
log('INFO', 'SQLite database initialized and migrated');
|
|
31
|
+
return this.db;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
log('ERROR', `Failed to initialize database: ${error.message}`, { error });
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
status: { type: DataTypes.STRING },
|
|
49
|
-
orderDate: { type: DataTypes.DATE },
|
|
50
|
-
items: { type: DataTypes.JSON }
|
|
51
|
-
});
|
|
38
|
+
async close() {
|
|
39
|
+
if (this.db) {
|
|
40
|
+
await this.db.close();
|
|
41
|
+
this.db = null;
|
|
42
|
+
log('INFO', 'SQLite database closed');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
52
45
|
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
46
|
+
// Example: Save product data
|
|
47
|
+
async saveProduct(product) {
|
|
48
|
+
const { id, name, price, cost, platform } = product;
|
|
49
|
+
await this.db.run(
|
|
50
|
+
`INSERT OR REPLACE INTO products (id, name, price, cost, platform, lastUpdated) VALUES (?, ?, ?, ?, ?, ?)`,
|
|
51
|
+
id, name, price, cost, platform, new Date().toISOString()
|
|
52
|
+
);
|
|
53
|
+
log('INFO', `Product ${name} saved/updated`);
|
|
54
|
+
}
|
|
60
55
|
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
// Example: Get product by ID
|
|
57
|
+
async getProduct(id) {
|
|
58
|
+
return this.db.get(`SELECT * FROM products WHERE id = ?`, id);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Example: Save historical price
|
|
62
|
+
async saveHistoricalPrice(productId, price, timestamp) {
|
|
63
|
+
await this.db.run(
|
|
64
|
+
`INSERT INTO historical_prices (productId, price, timestamp) VALUES (?, ?, ?)`,
|
|
65
|
+
productId, price, timestamp
|
|
66
|
+
);
|
|
67
|
+
log('INFO', `Historical price for product ${productId} saved`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Example: Get historical prices for a product
|
|
71
|
+
async getHistoricalPrices(productId) {
|
|
72
|
+
return this.db.all(`SELECT * FROM historical_prices WHERE productId = ? ORDER BY timestamp ASC`, productId);
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
let dbInstance = null;
|
|
77
|
+
|
|
78
|
+
export function getDatabase() {
|
|
79
|
+
if (!dbInstance) {
|
|
80
|
+
dbInstance = new Database();
|
|
81
|
+
}
|
|
82
|
+
return dbInstance;
|
|
83
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// core/eia-brain.js
|
|
2
|
+
import { chat as aiChat, log } from './ai-provider.js';
|
|
3
|
+
|
|
4
|
+
class EIABrain {
|
|
5
|
+
constructor(config, env) {
|
|
6
|
+
this.config = config;
|
|
7
|
+
this.env = env;
|
|
8
|
+
this.systemPrompt = this._buildSystemPrompt();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_buildSystemPrompt() {
|
|
12
|
+
return `Sen bir E-Ticaret Yönetim Ajansı'nın (EIA) beynisin. Görevin, e-ticaret operasyonlarını 7/24 izlemek, analiz etmek ve **şirketin karlılığını ve büyümesini maksimize edecek proaktif aksiyon önerileri** sunmaktır. Veriye dayalı kararlar alan, sonuç odaklı ve iş stratejilerine hakim bir yönetici kişiliğine sahipsin.
|
|
13
|
+
|
|
14
|
+
Aşağıdaki bilgilerle karar ver:
|
|
15
|
+
- Güncel durum verileri (stok, fiyat, buybox durumu, yorumlar vb.)
|
|
16
|
+
- Şirket kuralları ve hedefleri (bellekten alınacak)
|
|
17
|
+
- Geçmiş stratejik kararlar (bellekten alınacak)
|
|
18
|
+
|
|
19
|
+
Yanıtların kısa, öz, **iş değerine odaklı** ve eyleme yönelik olmalı. Gerekirse ek bilgi veya onay istemelisin.`;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async analyzeAndDecide(context) {
|
|
23
|
+
const fullPrompt = `${this.systemPrompt}
|
|
24
|
+
|
|
25
|
+
--- GÜNCEL DURUM ---
|
|
26
|
+
${context.currentSituation}
|
|
27
|
+
|
|
28
|
+
--- ŞİRKET KURALLARI VE HEDEFLERİ ---
|
|
29
|
+
${context.companyRules}
|
|
30
|
+
|
|
31
|
+
--- GEÇMİŞ KARARLAR ---
|
|
32
|
+
${context.pastDecisions}
|
|
33
|
+
|
|
34
|
+
Durumu analiz et ve en uygun aksiyon önerisini veya içgörüyü sun.`;
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const response = await aiChat(fullPrompt, this.config, this.env);
|
|
38
|
+
log('INFO', 'EIA Brain analysis complete', { response: response.slice(0, 100) });
|
|
39
|
+
return response;
|
|
40
|
+
} catch (error) {
|
|
41
|
+
log('ERROR', 'EIA Brain analysis failed', { error: error.message });
|
|
42
|
+
return `Analiz sırasında bir hata oluştu: ${error.message}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Scraper'lardan gelen ham veriyi işleyip ticari içgörülere dönüştürür.
|
|
48
|
+
* Bu metod, veri modelleme ve iş mantığı kurallarını içerecektir.
|
|
49
|
+
*/
|
|
50
|
+
async processRawData(rawData, dataType) {
|
|
51
|
+
log('INFO', `Processing raw data for type: ${dataType}`, { rawData: JSON.stringify(rawData).slice(0, 200) });
|
|
52
|
+
|
|
53
|
+
let insights = {};
|
|
54
|
+
switch (dataType) {
|
|
55
|
+
case 'price_changes':
|
|
56
|
+
insights = {
|
|
57
|
+
type: 'price_change_insight',
|
|
58
|
+
summary: `Fiyat değişikliği verisi işlendi. ${rawData.length} adet kayıt mevcut.`,
|
|
59
|
+
details: rawData.map(item => `Ürün: ${item.productName}, Eski Fiyat: ${item.oldPrice}, Yeni Fiyat: ${item.newPrice}, Platform: ${item.platform}`)
|
|
60
|
+
};
|
|
61
|
+
break;
|
|
62
|
+
case 'buybox_status':
|
|
63
|
+
insights = {
|
|
64
|
+
type: 'buybox_insight',
|
|
65
|
+
summary: `Buybox durumu verisi işlendi.`,
|
|
66
|
+
details: rawData.map(item => `Ürün: ${item.productName}, Durum: ${item.status}, Platform: ${item.platform}`)
|
|
67
|
+
};
|
|
68
|
+
break;
|
|
69
|
+
case 'stock_movements':
|
|
70
|
+
insights = {
|
|
71
|
+
type: 'stock_insight',
|
|
72
|
+
summary: `Stok hareketi verisi işlendi.`,
|
|
73
|
+
details: rawData.map(item => `Ürün: ${item.productName}, Miktar: ${item.quantityChange}, Platform: ${item.platform}`)
|
|
74
|
+
};
|
|
75
|
+
break;
|
|
76
|
+
case 'product_reviews':
|
|
77
|
+
insights = {
|
|
78
|
+
type: 'review_insight',
|
|
79
|
+
summary: `Ürün yorumları verisi işlendi.`,
|
|
80
|
+
details: rawData.map(item => `Ürün: ${item.productName}, Yorum: ${item.reviewText.slice(0, 50)}, Puan: ${item.rating}`)
|
|
81
|
+
};
|
|
82
|
+
break;
|
|
83
|
+
default:
|
|
84
|
+
insights = {
|
|
85
|
+
type: 'general_insight',
|
|
86
|
+
summary: 'Bilinen bir veri tipi değil, ham veri olarak işlendi.',
|
|
87
|
+
rawData: rawData
|
|
88
|
+
};
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
return insights;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let eiaBrainInstance = null;
|
|
96
|
+
|
|
97
|
+
export function getEIABrain(config, env) {
|
|
98
|
+
if (!eiaBrainInstance) {
|
|
99
|
+
eiaBrainInstance = new EIABrain(config, env);
|
|
100
|
+
}
|
|
101
|
+
return eiaBrainInstance;
|
|
102
|
+
}
|