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.
Files changed (92) hide show
  1. package/.env.example +21 -0
  2. package/.openclaw/completions/openclaw.bash +227 -0
  3. package/.openclaw/completions/openclaw.fish +1552 -0
  4. package/.openclaw/completions/openclaw.ps1 +1966 -0
  5. package/.openclaw/completions/openclaw.zsh +3571 -0
  6. package/.openclaw/gateway.cmd +10 -0
  7. package/.openclaw/identity/device.json +7 -0
  8. package/.openclaw/openclaw.json +40 -0
  9. package/.windsurf/workflows/vantuz-dev.md +31 -0
  10. package/DOCS_TR.md +80 -0
  11. package/LICENSE +45 -45
  12. package/README.md +52 -21
  13. package/cli.js +685 -585
  14. package/config.js +733 -733
  15. package/core/agent-loop.js +190 -190
  16. package/core/ai-provider.js +298 -261
  17. package/core/automation.js +523 -523
  18. package/core/brand-analyst.js +101 -0
  19. package/core/channels.js +167 -167
  20. package/core/dashboard.js +230 -230
  21. package/core/database.js +135 -37
  22. package/core/eia-monitor.js +3 -1
  23. package/core/engine.js +648 -636
  24. package/core/gateway.js +447 -447
  25. package/core/learning.js +214 -214
  26. package/core/license.js +113 -0
  27. package/core/marketplace-adapter.js +168 -168
  28. package/core/memory.js +190 -190
  29. package/core/migrations/001-initial-schema.sql +1 -1
  30. package/core/queue.js +120 -120
  31. package/core/self-healer.js +314 -314
  32. package/core/unified-product.js +214 -214
  33. package/core/vision-service.js +113 -113
  34. package/index.js +217 -174
  35. package/modules/crm/sentiment-crm.js +231 -231
  36. package/modules/healer/listing-healer.js +201 -201
  37. package/modules/oracle/predictor.js +214 -214
  38. package/modules/researcher/agent.js +169 -169
  39. package/modules/team/agents/base.js +92 -92
  40. package/modules/team/agents/dev.js +33 -33
  41. package/modules/team/agents/josh.js +40 -40
  42. package/modules/team/agents/marketing.js +33 -33
  43. package/modules/team/agents/milo.js +36 -36
  44. package/modules/team/index.js +78 -78
  45. package/modules/team/shared-memory.js +87 -87
  46. package/modules/war-room/competitor-tracker.js +250 -250
  47. package/modules/war-room/pricing-engine.js +308 -308
  48. package/n11docs.md +1680 -0
  49. package/nodes/warehouse.js +238 -238
  50. package/onboard.js +1 -1
  51. package/openclawdocs.md +3 -0
  52. package/package.json +7 -5
  53. package/platforms/pttavm.js +14 -14
  54. package/plugins/vantuz/index.js +528 -528
  55. package/plugins/vantuz/memory/hippocampus.js +465 -465
  56. package/plugins/vantuz/package.json +20 -20
  57. package/plugins/vantuz/platforms/_template.js +118 -118
  58. package/plugins/vantuz/platforms/amazon.js +236 -236
  59. package/plugins/vantuz/platforms/ciceksepeti.js +166 -166
  60. package/plugins/vantuz/platforms/hepsiburada.js +180 -180
  61. package/plugins/vantuz/platforms/index.js +165 -165
  62. package/plugins/vantuz/platforms/n11.js +229 -229
  63. package/plugins/vantuz/platforms/pazarama.js +154 -154
  64. package/plugins/vantuz/platforms/pttavm.js +127 -127
  65. package/plugins/vantuz/platforms/trendyol.js +326 -326
  66. package/plugins/vantuz/services/alerts.js +253 -253
  67. package/plugins/vantuz/services/license.js +34 -34
  68. package/plugins/vantuz/services/scheduler.js +232 -232
  69. package/plugins/vantuz/tools/analytics.js +152 -152
  70. package/plugins/vantuz/tools/crossborder.js +187 -187
  71. package/plugins/vantuz/tools/nl-parser.js +211 -211
  72. package/plugins/vantuz/tools/product.js +110 -110
  73. package/plugins/vantuz/tools/quick-report.js +175 -175
  74. package/plugins/vantuz/tools/repricer.js +314 -314
  75. package/plugins/vantuz/tools/sentiment.js +115 -115
  76. package/plugins/vantuz/tools/vision.js +257 -257
  77. package/public.pem +9 -0
  78. package/server/app.js +260 -260
  79. package/server/public/index.html +514 -514
  80. package/start.bat +33 -33
  81. package/vantuz.sqlite +0 -0
  82. package/workspace/AGENTS.md +73 -0
  83. package/workspace/BRAND.md +29 -0
  84. package/workspace/SOUL.md +72 -0
  85. package/workspace/team/DECISIONS.md +3 -0
  86. package/workspace/team/GOALS.md +3 -0
  87. package/workspace/team/PROJECT_STATUS.md +3 -0
  88. package/workspace/team/agents/dev/SOUL.md +12 -0
  89. package/workspace/team/agents/josh/SOUL.md +12 -0
  90. package/workspace/team/agents/marketing/SOUL.md +12 -0
  91. package/workspace/team/agents/milo/SOUL.md +12 -0
  92. package/vantuz-3.3.4.tgz +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;