vantuz 3.4.1 → 3.5.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.
Files changed (70) hide show
  1. package/LICENSE +45 -45
  2. package/admin-keygen.js +51 -0
  3. package/cli.js +685 -585
  4. package/config.js +733 -733
  5. package/core/agent-loop.js +190 -190
  6. package/core/ai-provider.js +298 -261
  7. package/core/automation.js +523 -523
  8. package/core/brand-analyst.js +101 -0
  9. package/core/channels.js +167 -167
  10. package/core/dashboard.js +230 -230
  11. package/core/database.js +135 -36
  12. package/core/eia-monitor.js +3 -1
  13. package/core/engine.js +648 -636
  14. package/core/gateway.js +447 -447
  15. package/core/learning.js +214 -214
  16. package/core/license.js +113 -0
  17. package/core/marketplace-adapter.js +168 -168
  18. package/core/memory.js +190 -190
  19. package/core/migrations/001-initial-schema.sql +1 -1
  20. package/core/queue.js +120 -120
  21. package/core/self-healer.js +314 -314
  22. package/core/unified-product.js +214 -214
  23. package/core/vision-service.js +113 -113
  24. package/index.js +217 -174
  25. package/modules/crm/sentiment-crm.js +231 -231
  26. package/modules/healer/listing-healer.js +201 -201
  27. package/modules/oracle/predictor.js +214 -214
  28. package/modules/researcher/agent.js +169 -169
  29. package/modules/team/agents/base.js +92 -92
  30. package/modules/team/agents/dev.js +33 -33
  31. package/modules/team/agents/josh.js +40 -40
  32. package/modules/team/agents/marketing.js +33 -33
  33. package/modules/team/agents/milo.js +36 -36
  34. package/modules/team/index.js +78 -78
  35. package/modules/team/shared-memory.js +87 -87
  36. package/modules/war-room/competitor-tracker.js +250 -250
  37. package/modules/war-room/pricing-engine.js +308 -308
  38. package/nodes/warehouse.js +238 -238
  39. package/onboard.js +1 -1
  40. package/package.json +7 -6
  41. package/platforms/pttavm.js +14 -14
  42. package/plugins/vantuz/index.js +528 -528
  43. package/plugins/vantuz/memory/hippocampus.js +465 -464
  44. package/plugins/vantuz/package.json +20 -20
  45. package/plugins/vantuz/platforms/_template.js +118 -118
  46. package/plugins/vantuz/platforms/amazon.js +236 -236
  47. package/plugins/vantuz/platforms/ciceksepeti.js +166 -166
  48. package/plugins/vantuz/platforms/hepsiburada.js +180 -180
  49. package/plugins/vantuz/platforms/index.js +165 -165
  50. package/plugins/vantuz/platforms/n11.js +229 -229
  51. package/plugins/vantuz/platforms/pazarama.js +154 -154
  52. package/plugins/vantuz/platforms/pttavm.js +127 -127
  53. package/plugins/vantuz/platforms/trendyol.js +326 -326
  54. package/plugins/vantuz/services/alerts.js +253 -253
  55. package/plugins/vantuz/services/license.js +34 -34
  56. package/plugins/vantuz/services/scheduler.js +232 -232
  57. package/plugins/vantuz/tools/analytics.js +152 -152
  58. package/plugins/vantuz/tools/crossborder.js +187 -187
  59. package/plugins/vantuz/tools/nl-parser.js +211 -211
  60. package/plugins/vantuz/tools/product.js +110 -110
  61. package/plugins/vantuz/tools/quick-report.js +175 -175
  62. package/plugins/vantuz/tools/repricer.js +314 -314
  63. package/plugins/vantuz/tools/sentiment.js +115 -115
  64. package/plugins/vantuz/tools/vision.js +257 -257
  65. package/private.pem +28 -0
  66. package/public.pem +9 -0
  67. package/server/app.js +260 -260
  68. package/server/public/index.html +514 -514
  69. package/start.bat +33 -33
  70. package/vantuz.sqlite +0 -0
@@ -0,0 +1,101 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+ const ora = require('ora');
5
+
6
+ module.exports = {
7
+ /**
8
+ * Analyzes the store name and creates a BRAND.md file.
9
+ * @param {string} storeName - The name of the store (e.g., "TechMaster")
10
+ * @param {Object} config - The Conf instance
11
+ */
12
+ async analyzeAndSave(storeName, config) {
13
+ const spinner = ora('Yapay Zeka marka kimliğini analiz ediyor...').start();
14
+
15
+ try {
16
+ // Dynamic import because ai-provider is ESM
17
+ const { default: ai } = await import('./ai-provider.js');
18
+
19
+ // Get API configuration
20
+ // index.js uses 'vantuz' key for plugin config, but product-manager uses 'ai'.
21
+ // We'll inspect both or default to what's available.
22
+ const aiConfig = config.get('ai') || {};
23
+ const vantuzConfig = config.get('vantuz') || {};
24
+
25
+ // Prepare environment variables for the provider
26
+ // The AI provider expects env vars like GEMINI_API_KEY
27
+ const env = {};
28
+ if (aiConfig.apiKey) {
29
+ // Guess the key name based on provider or default to OPENAI
30
+ const provider = aiConfig.provider || 'openai';
31
+ env[`${provider.toUpperCase()}_API_KEY`] = aiConfig.apiKey;
32
+ } else if (process.env.OPENAI_API_KEY) {
33
+ env.OPENAI_API_KEY = process.env.OPENAI_API_KEY;
34
+ }
35
+
36
+ // If no key found, we can't analyze
37
+ if (Object.keys(env).length === 0 && !process.env.GEMINI_API_KEY) {
38
+ spinner.warn(chalk.yellow('AI API Anahtarı bulunamadı. Marka analizi atlanıyor.'));
39
+ return;
40
+ }
41
+
42
+ const prompt = `
43
+ Analyze the store name: "${storeName}".
44
+ Based on this name, infer:
45
+ 1. The likely Industry (Electronic, Fashion, Home, etc.)
46
+ 2. Target Audience (Young, Professional, Budget, Luxury)
47
+ 3. Brand Voice (Professional, Friendly, Tech-savvy, Traditional)
48
+
49
+ Then, generate the content for a "BRAND.md" file.
50
+ The content should look like this:
51
+
52
+ # Brand Identity: ${storeName}
53
+
54
+ ## Industry
55
+ [Industry]
56
+
57
+ ## Target Audience
58
+ [Audience]
59
+
60
+ ## Brand Voice
61
+ [Voice Description]
62
+
63
+ ## Communication Guidelines
64
+ - Rule 1
65
+ - Rule 2
66
+
67
+ Return ONLY the markdown content.
68
+ `;
69
+
70
+ const aiOptions = {
71
+ aiProvider: aiConfig.provider || 'openai',
72
+ systemContext: 'You are a Brand Strategist.'
73
+ };
74
+
75
+ const response = await ai.chat(prompt, aiOptions, env);
76
+
77
+ // Clean response (remove markdown code blocks if any)
78
+ const cleanContent = response.replace(/^```markdown/, '').replace(/^```/, '').trim();
79
+
80
+ // Setup workspace
81
+ const workspaceDir = path.join(process.cwd(), 'workspace');
82
+ if (!fs.existsSync(workspaceDir)) {
83
+ fs.mkdirSync(workspaceDir, { recursive: true });
84
+ }
85
+
86
+ const brandPath = path.join(workspaceDir, 'BRAND.md');
87
+ fs.writeFileSync(brandPath, cleanContent, 'utf-8');
88
+
89
+ spinner.succeed(chalk.green('Marka kimliği oluşturuldu: workspace/BRAND.md'));
90
+
91
+ // Show a preview
92
+ console.log(chalk.gray('----------------------------------------'));
93
+ console.log(cleanContent.split('\n').slice(0, 10).join('\n') + '\n...');
94
+ console.log(chalk.gray('----------------------------------------'));
95
+
96
+ } catch (error) {
97
+ spinner.fail('Marka analizi başarısız.');
98
+ console.error(chalk.red(error.message));
99
+ }
100
+ }
101
+ };
package/core/channels.js CHANGED
@@ -1,169 +1,169 @@
1
- /**
2
- * 📱 CHANNEL MANAGER v3.2
1
+ /**
2
+ * 📱 CHANNEL MANAGER v3.2
3
3
  * Gateway üzerinden kanal yönetimi
4
- *
5
- * Desteklenen kanallar:
6
- * - WhatsApp (Meta Business API / Gateway)
7
- * - Telegram (Bot API / Gateway)
8
- */
9
-
10
- import fs from 'fs';
11
- import path from 'path';
12
- import os from 'os';
13
- import { log } from './ai-provider.js';
14
- import { getGateway } from './gateway.js';
15
-
16
- const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
17
- const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
18
-
19
- export class ChannelManager {
20
- constructor() {
21
- this.gateway = null;
22
- this.status = {
23
- whatsapp: { connected: false, mode: 'gateway', info: '' },
24
- telegram: { connected: false, mode: 'gateway', info: '' }
25
- };
26
- }
27
-
28
- /**
29
- * Tüm kanalları başlat
30
- */
31
- async initAll() {
32
- const env = this._loadEnv();
33
-
4
+ *
5
+ * Desteklenen kanallar:
6
+ * - WhatsApp (Meta Business API / Gateway)
7
+ * - Telegram (Bot API / Gateway)
8
+ */
9
+
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ import os from 'os';
13
+ import { log } from './ai-provider.js';
14
+ import { getGateway } from './gateway.js';
15
+
16
+ const VANTUZ_HOME = path.join(os.homedir(), '.vantuz');
17
+ const CONFIG_PATH = path.join(VANTUZ_HOME, '.env');
18
+
19
+ export class ChannelManager {
20
+ constructor() {
21
+ this.gateway = null;
22
+ this.status = {
23
+ whatsapp: { connected: false, mode: 'gateway', info: '' },
24
+ telegram: { connected: false, mode: 'gateway', info: '' }
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Tüm kanalları başlat
30
+ */
31
+ async initAll() {
32
+ const env = this._loadEnv();
33
+
34
34
  // Gateway üzerinden kanal durumu kontrol et
35
- try {
36
- this.gateway = await getGateway();
37
-
38
- if (this.gateway.isConnected()) {
39
- const channelResult = await this.gateway.getChannels();
40
- if (channelResult.success && channelResult.data) {
41
- this._syncGatewayChannels(channelResult.data);
42
- log('INFO', 'Kanal durumları gateway üzerinden alındı');
43
- return this.status;
44
- }
45
- }
46
- } catch (e) {
47
- log('WARN', 'Gateway kanal kontrolü başarısız, lokal mod', { error: e.message });
48
- }
49
-
50
- // Fallback: Lokal env kontrolü
51
- if (env.TELEGRAM_BOT_TOKEN) {
52
- this.status.telegram.connected = true;
53
- this.status.telegram.info = 'Bot Token Configured (local)';
54
- } else {
55
- this.status.telegram.info = 'Token yapılandırılmamış';
56
- }
57
-
58
- if (env.WHATSAPP_ACCESS_TOKEN) {
59
- this.status.whatsapp.connected = true;
60
- this.status.whatsapp.info = 'Access Token Configured (local)';
61
- } else {
62
- this.status.whatsapp.info = 'Bağlanmak için: vantuz channels login';
63
- }
64
-
65
- return this.status;
66
- }
67
-
68
- /**
69
- * Gateway'den gelen kanal verilerini senkronize et
70
- */
71
- _syncGatewayChannels(gatewayData) {
72
- if (Array.isArray(gatewayData)) {
73
- for (const ch of gatewayData) {
74
- const name = ch.name?.toLowerCase();
75
- if (name === 'whatsapp' || name === 'telegram') {
76
- this.status[name] = {
77
- connected: ch.connected || ch.status === 'connected',
78
- mode: 'gateway',
79
- info: ch.info || ch.status || 'Gateway üzerinden bağlı',
80
- capabilities: ch.capabilities || []
81
- };
82
- }
83
- }
84
- } else if (typeof gatewayData === 'object') {
85
- // Object format: { whatsapp: {...}, telegram: {...} }
86
- for (const [name, data] of Object.entries(gatewayData)) {
87
- const key = name.toLowerCase();
88
- if (this.status[key]) {
89
- this.status[key] = {
90
- connected: data.connected || data.status === 'connected',
91
- mode: 'gateway',
92
- info: data.info || data.status || 'Gateway üzerinden bağlı',
93
- capabilities: data.capabilities || []
94
- };
95
- }
96
- }
97
- }
98
- }
99
-
100
- /**
101
- * Mesaj gönder (gateway üzerinden)
102
- */
103
- async sendMessage(channel, to, message) {
104
- if (!this.gateway?.isConnected()) {
105
- return { success: false, error: 'Gateway bağlı değil' };
106
- }
107
-
108
- const result = await this.gateway.sendMessage(channel, to, message);
109
- if (result.success) {
110
- log('INFO', `Mesaj gönderildi: ${channel} → ${to}`);
111
- } else {
112
- log('ERROR', `Mesaj gönderilemedi: ${channel}`, { error: result.error });
113
- }
114
- return result;
115
- }
116
-
117
- /**
118
- * Kanal durumunu yenile
119
- */
120
- async refresh() {
121
- return await this.initAll();
122
- }
123
-
124
- /**
125
- * Env dosyasını yükle
126
- */
127
- _loadEnv() {
128
- const env = {};
129
- try {
130
- if (fs.existsSync(CONFIG_PATH)) {
131
- const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
132
- content.split('\n').forEach(line => {
133
- const match = line.match(/^([^=]+)=(.*)$/);
134
- if (match) {
135
- env[match[1].trim()] = match[2].trim();
136
- }
137
- });
138
- }
139
- } catch (e) { }
140
- return env;
141
- }
142
-
143
- /**
144
- * Kanal durumları
145
- */
146
- getStatus() {
147
- return this.status;
148
- }
149
-
150
- /**
151
- * Gateway bağlı mı?
152
- */
153
- isGatewayMode() {
154
- return this.gateway?.isConnected() || false;
155
- }
156
- }
157
-
158
- // Singleton
159
- let managerInstance = null;
160
-
161
- export async function getChannelManager() {
162
- if (!managerInstance) {
163
- managerInstance = new ChannelManager();
164
- await managerInstance.initAll();
165
- }
166
- return managerInstance;
167
- }
168
-
169
- export default ChannelManager;
35
+ try {
36
+ this.gateway = await getGateway();
37
+
38
+ if (this.gateway.isConnected()) {
39
+ const channelResult = await this.gateway.getChannels();
40
+ if (channelResult.success && channelResult.data) {
41
+ this._syncGatewayChannels(channelResult.data);
42
+ log('INFO', 'Kanal durumları gateway üzerinden alındı');
43
+ return this.status;
44
+ }
45
+ }
46
+ } catch (e) {
47
+ log('WARN', 'Gateway kanal kontrolü başarısız, lokal mod', { error: e.message });
48
+ }
49
+
50
+ // Fallback: Lokal env kontrolü
51
+ if (env.TELEGRAM_BOT_TOKEN) {
52
+ this.status.telegram.connected = true;
53
+ this.status.telegram.info = 'Bot Token Configured (local)';
54
+ } else {
55
+ this.status.telegram.info = 'Token yapılandırılmamış';
56
+ }
57
+
58
+ if (env.WHATSAPP_ACCESS_TOKEN) {
59
+ this.status.whatsapp.connected = true;
60
+ this.status.whatsapp.info = 'Access Token Configured (local)';
61
+ } else {
62
+ this.status.whatsapp.info = 'Bağlanmak için: vantuz channels login';
63
+ }
64
+
65
+ return this.status;
66
+ }
67
+
68
+ /**
69
+ * Gateway'den gelen kanal verilerini senkronize et
70
+ */
71
+ _syncGatewayChannels(gatewayData) {
72
+ if (Array.isArray(gatewayData)) {
73
+ for (const ch of gatewayData) {
74
+ const name = ch.name?.toLowerCase();
75
+ if (name === 'whatsapp' || name === 'telegram') {
76
+ this.status[name] = {
77
+ connected: ch.connected || ch.status === 'connected',
78
+ mode: 'gateway',
79
+ info: ch.info || ch.status || 'Gateway üzerinden bağlı',
80
+ capabilities: ch.capabilities || []
81
+ };
82
+ }
83
+ }
84
+ } else if (typeof gatewayData === 'object') {
85
+ // Object format: { whatsapp: {...}, telegram: {...} }
86
+ for (const [name, data] of Object.entries(gatewayData)) {
87
+ const key = name.toLowerCase();
88
+ if (this.status[key]) {
89
+ this.status[key] = {
90
+ connected: data.connected || data.status === 'connected',
91
+ mode: 'gateway',
92
+ info: data.info || data.status || 'Gateway üzerinden bağlı',
93
+ capabilities: data.capabilities || []
94
+ };
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Mesaj gönder (gateway üzerinden)
102
+ */
103
+ async sendMessage(channel, to, message) {
104
+ if (!this.gateway?.isConnected()) {
105
+ return { success: false, error: 'Gateway bağlı değil' };
106
+ }
107
+
108
+ const result = await this.gateway.sendMessage(channel, to, message);
109
+ if (result.success) {
110
+ log('INFO', `Mesaj gönderildi: ${channel} → ${to}`);
111
+ } else {
112
+ log('ERROR', `Mesaj gönderilemedi: ${channel}`, { error: result.error });
113
+ }
114
+ return result;
115
+ }
116
+
117
+ /**
118
+ * Kanal durumunu yenile
119
+ */
120
+ async refresh() {
121
+ return await this.initAll();
122
+ }
123
+
124
+ /**
125
+ * Env dosyasını yükle
126
+ */
127
+ _loadEnv() {
128
+ const env = {};
129
+ try {
130
+ if (fs.existsSync(CONFIG_PATH)) {
131
+ const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
132
+ content.split('\n').forEach(line => {
133
+ const match = line.match(/^([^=]+)=(.*)$/);
134
+ if (match) {
135
+ env[match[1].trim()] = match[2].trim();
136
+ }
137
+ });
138
+ }
139
+ } catch (e) { }
140
+ return env;
141
+ }
142
+
143
+ /**
144
+ * Kanal durumları
145
+ */
146
+ getStatus() {
147
+ return this.status;
148
+ }
149
+
150
+ /**
151
+ * Gateway bağlı mı?
152
+ */
153
+ isGatewayMode() {
154
+ return this.gateway?.isConnected() || false;
155
+ }
156
+ }
157
+
158
+ // Singleton
159
+ let managerInstance = null;
160
+
161
+ export async function getChannelManager() {
162
+ if (!managerInstance) {
163
+ managerInstance = new ChannelManager();
164
+ await managerInstance.initAll();
165
+ }
166
+ return managerInstance;
167
+ }
168
+
169
+ export default ChannelManager;