natureco-cli 2.23.27 → 2.23.29
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/bin/natureco.js +68 -6
- package/package.json +10 -6
- package/src/commands/channels.js +94 -4
- package/src/commands/chat.js +11 -25
- package/src/commands/code.js +12 -11
- package/src/commands/config.js +111 -68
- package/src/commands/doctor.js +121 -16
- package/src/commands/gateway-server.js +35 -21
- package/src/commands/gateway.js +11 -20
- package/src/commands/help.js +6 -0
- package/src/commands/imessage.js +55 -0
- package/src/commands/irc.js +70 -0
- package/src/commands/mattermost.js +62 -0
- package/src/commands/message.js +24 -4
- package/src/commands/models.js +584 -216
- package/src/commands/plugins.js +415 -172
- package/src/commands/security.js +149 -1
- package/src/commands/setup.js +1 -3
- package/src/commands/signal.js +66 -0
- package/src/commands/skills.js +20 -29
- package/src/commands/sms.js +64 -0
- package/src/commands/tasks.js +328 -79
- package/src/commands/webhooks.js +79 -0
- package/src/commands/whatsapp.js +7 -21
- package/src/tools/bash.js +63 -29
- package/src/utils/api.js +3 -20
- package/src/utils/approvals.js +297 -0
- package/src/utils/background.js +223 -66
- package/src/utils/baileys.js +21 -0
- package/src/utils/config.js +141 -10
- package/src/utils/errors.js +148 -0
- package/src/utils/inquirer-wrapper.js +1 -2
- package/src/utils/path-utils.js +13 -13
- package/src/utils/plugin-registry.js +238 -0
- package/src/utils/secrets.js +177 -0
- package/src/utils/skills.js +10 -23
package/src/commands/tasks.js
CHANGED
|
@@ -1,79 +1,328 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (
|
|
67
|
-
console.log(
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { listTasks, getTask, cancelTask, auditTasks, maintenanceTasks, getTaskSummary, TASK_STATUSES, RUNTIME_TYPES } = require('../utils/background');
|
|
3
|
+
|
|
4
|
+
function parseFlags(args) {
|
|
5
|
+
return {
|
|
6
|
+
json: args.includes('--json') || args.includes('-j'),
|
|
7
|
+
apply: args.includes('--apply'),
|
|
8
|
+
runtime: extractFlag(args, '--runtime'),
|
|
9
|
+
status: extractFlag(args, '--status'),
|
|
10
|
+
limit: parseInt(extractFlag(args, '--limit') || '50', 10),
|
|
11
|
+
severity: extractFlag(args, '--severity'),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function extractFlag(params, name) {
|
|
16
|
+
const idx = params.indexOf(name);
|
|
17
|
+
return idx >= 0 && idx + 1 < params.length ? params[idx + 1] : null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const STATUS_ICONS = {
|
|
21
|
+
queued: '⏳',
|
|
22
|
+
running: '🔄',
|
|
23
|
+
succeeded: '✅',
|
|
24
|
+
failed: '❌',
|
|
25
|
+
timed_out: '⏰',
|
|
26
|
+
cancelled: '🚫',
|
|
27
|
+
lost: '👻',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const STATUS_COLORS = {
|
|
31
|
+
queued: chalk.yellow,
|
|
32
|
+
running: chalk.cyan,
|
|
33
|
+
succeeded: chalk.green,
|
|
34
|
+
failed: chalk.red,
|
|
35
|
+
timed_out: chalk.red,
|
|
36
|
+
cancelled: chalk.gray,
|
|
37
|
+
lost: chalk.magenta,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
async function tasks(args) {
|
|
41
|
+
const [action, ...params] = (args || []);
|
|
42
|
+
const opts = parseFlags(params);
|
|
43
|
+
|
|
44
|
+
if (!action || action === 'list') return listTasksHandler(opts);
|
|
45
|
+
if (action === 'show') return showTaskHandler(params[0], opts);
|
|
46
|
+
if (action === 'cancel') return cancelTaskHandler(params[0]);
|
|
47
|
+
if (action === 'audit') return auditHandler(opts);
|
|
48
|
+
if (action === 'maintenance') return maintenanceHandler(opts);
|
|
49
|
+
if (action === 'flow' && params[0]) {
|
|
50
|
+
const flowAction = params[0];
|
|
51
|
+
const flowParams = params.slice(1);
|
|
52
|
+
if (flowAction === 'list') return flowListHandler(parseFlags(flowParams));
|
|
53
|
+
if (flowAction === 'show') return flowShowHandler(flowParams[0], parseFlags(flowParams));
|
|
54
|
+
if (flowAction === 'cancel') return flowCancelHandler(flowParams[0]);
|
|
55
|
+
}
|
|
56
|
+
if (action === 'summary' || action === 'status') return summaryHandler(opts);
|
|
57
|
+
|
|
58
|
+
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
59
|
+
console.log(chalk.gray(' Kullanım: natureco tasks [list|show|cancel|audit|maintenance|flow|summary]\n'));
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function listTasksHandler(opts) {
|
|
64
|
+
const tasks = listTasks({ runtime: opts.runtime, status: opts.status, limit: opts.limit });
|
|
65
|
+
|
|
66
|
+
if (opts.json) {
|
|
67
|
+
console.log(JSON.stringify({ tasks, total: tasks.length, filters: { runtime: opts.runtime, status: opts.status } }, null, 2));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log('');
|
|
72
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
73
|
+
console.log(chalk.cyan.bold('\n Background Tasks\n'));
|
|
74
|
+
|
|
75
|
+
if (tasks.length === 0) {
|
|
76
|
+
console.log(chalk.gray(' Hiç task bulunamadı.\n'));
|
|
77
|
+
if (opts.runtime) console.log(chalk.gray(` Filtre: runtime=${opts.runtime}`));
|
|
78
|
+
if (opts.status) console.log(chalk.gray(` Filtre: status=${opts.status}`));
|
|
79
|
+
console.log('');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
tasks.forEach(t => {
|
|
84
|
+
const icon = STATUS_ICONS[t.status] || '❓';
|
|
85
|
+
const color = STATUS_COLORS[t.status] || chalk.white;
|
|
86
|
+
const runtimeIcon = t.runtime === 'cron' ? '⏰' : t.runtime === 'subagent' ? '🧑💻' : t.runtime === 'acp' ? '🔄' : '💻';
|
|
87
|
+
const age = getAgeString(t.createdAt);
|
|
88
|
+
console.log(` ${icon} ${chalk.white(t.id.slice(0, 12))} ${color(t.status)} ${runtimeIcon}${t.runtime}`);
|
|
89
|
+
if (t.message) {
|
|
90
|
+
const msg = t.message.length > 50 ? t.message.slice(0, 50) + '...' : t.message;
|
|
91
|
+
console.log(chalk.gray(` ${msg}`));
|
|
92
|
+
}
|
|
93
|
+
console.log(chalk.gray(` ${age} | notify: ${t.notifyPolicy || 'done_only'}`));
|
|
94
|
+
console.log('');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const summary = getTaskSummary();
|
|
98
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
99
|
+
console.log(chalk.gray(` Toplam: ${tasks.length} (gösterilen) | Aktif: ${summary.active} | Hata: ${summary.failures}`));
|
|
100
|
+
console.log(chalk.gray(' Filtre: ') + chalk.cyan('--runtime <type> --status <status>'));
|
|
101
|
+
console.log(chalk.gray(" JSON: ") + chalk.cyan('natureco tasks list --json\n'));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function showTaskHandler(id, opts) {
|
|
105
|
+
if (!id) {
|
|
106
|
+
console.log(chalk.red('\n ❌ Task ID gerekli\n'));
|
|
107
|
+
console.log(chalk.gray(' Kullanım: natureco tasks show <id>\n'));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const task = getTask(id);
|
|
112
|
+
if (!task) {
|
|
113
|
+
console.log(chalk.red(`\n ❌ Task bulunamadı: ${id}\n`));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (opts.json) {
|
|
118
|
+
console.log(JSON.stringify(task, null, 2));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const color = STATUS_COLORS[task.status] || chalk.white;
|
|
123
|
+
const icon = STATUS_ICONS[task.status] || '❓';
|
|
124
|
+
|
|
125
|
+
console.log('');
|
|
126
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
127
|
+
console.log(`\n ${icon} ${chalk.white('Task:')} ${chalk.cyan(task.id)}`);
|
|
128
|
+
console.log(` ${chalk.gray('Durum :')} ${color(task.status)}`);
|
|
129
|
+
console.log(` ${chalk.gray('Runtime :')} ${chalk.white(task.runtime)}`);
|
|
130
|
+
console.log(` ${chalk.gray('Bot :')} ${chalk.white(task.botName)}`);
|
|
131
|
+
if (task.message) console.log(` ${chalk.gray('Mesaj :')} ${chalk.white(task.message)}`);
|
|
132
|
+
console.log(` ${chalk.gray('Oluşturma:')} ${chalk.white(formatTime(task.createdAt))}`);
|
|
133
|
+
if (task.startedAt) console.log(` ${chalk.gray('Başlangıç:')} ${chalk.white(formatTime(task.startedAt))}`);
|
|
134
|
+
if (task.endedAt) console.log(` ${chalk.gray('Bitiş :')} ${chalk.white(formatTime(task.endedAt))}`);
|
|
135
|
+
if (task.notifyPolicy) console.log(` ${chalk.gray('Bildirim :')} ${chalk.white(task.notifyPolicy)}`);
|
|
136
|
+
if (task.childSessionKey) console.log(` ${chalk.gray('Çocuk :')} ${chalk.gray(task.childSessionKey)}`);
|
|
137
|
+
if (task.runId) console.log(` ${chalk.gray('Run ID :')} ${chalk.gray(task.runId)}`);
|
|
138
|
+
|
|
139
|
+
if (task.result) {
|
|
140
|
+
console.log(`\n ${chalk.cyan('Sonuç:')}`);
|
|
141
|
+
console.log(` ${chalk.white(task.result)}`);
|
|
142
|
+
}
|
|
143
|
+
if (task.error) {
|
|
144
|
+
console.log(`\n ${chalk.red('Hata:')}`);
|
|
145
|
+
console.log(` ${chalk.white(task.error)}`);
|
|
146
|
+
}
|
|
147
|
+
if (task.cleanupAfter) {
|
|
148
|
+
console.log(`\n ${chalk.gray(`Temizlik: ${formatTime(task.cleanupAfter)}`)}`);
|
|
149
|
+
}
|
|
150
|
+
if (task.metadata && Object.keys(task.metadata).length > 0) {
|
|
151
|
+
console.log(`\n ${chalk.gray('Metadata:')}`);
|
|
152
|
+
Object.entries(task.metadata).forEach(([k, v]) => console.log(` ${k}: ${v}`));
|
|
153
|
+
}
|
|
154
|
+
console.log('');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function cancelTaskHandler(id) {
|
|
158
|
+
if (!id) {
|
|
159
|
+
console.log(chalk.red('\n ❌ Task ID gerekli\n'));
|
|
160
|
+
console.log(chalk.gray(' Kullanım: natureco tasks cancel <id>\n'));
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const result = cancelTask(id);
|
|
165
|
+
if (!result) {
|
|
166
|
+
console.log(chalk.red(`\n ❌ Task bulunamadı: ${id}\n`));
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (result.status === 'cancelled') {
|
|
171
|
+
console.log(chalk.green(`\n ✓ Task iptal edildi: ${id}\n`));
|
|
172
|
+
} else {
|
|
173
|
+
console.log(chalk.yellow(`\n ⚠ Task zaten terminal durumda: ${result.status}\n`));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function auditHandler(opts) {
|
|
178
|
+
const findings = auditTasks();
|
|
179
|
+
|
|
180
|
+
if (opts.json) {
|
|
181
|
+
console.log(JSON.stringify({ findings, total: findings.length }, null, 2));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.log('');
|
|
186
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
187
|
+
console.log(chalk.cyan.bold('\n Task Denetimi\n'));
|
|
188
|
+
|
|
189
|
+
if (findings.length === 0) {
|
|
190
|
+
console.log(chalk.green(' ✓ Sorun bulunamadı.\n'));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let filtered = findings;
|
|
195
|
+
if (opts.severity) {
|
|
196
|
+
filtered = findings.filter(f => f.severity === opts.severity);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const errors = filtered.filter(f => f.severity === 'error');
|
|
200
|
+
const warnings = filtered.filter(f => f.severity === 'warn');
|
|
201
|
+
|
|
202
|
+
if (errors.length > 0) {
|
|
203
|
+
console.log(chalk.red(`\n ${errors.length} HATA\n`));
|
|
204
|
+
errors.forEach(f => {
|
|
205
|
+
console.log(` ${chalk.red('✗')} ${chalk.white(f.id.slice(0, 12))} ${chalk.red(f.code)}`);
|
|
206
|
+
console.log(chalk.gray(` ${f.message}`));
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (warnings.length > 0) {
|
|
211
|
+
console.log(chalk.yellow(`\n ${warnings.length} UYARI\n`));
|
|
212
|
+
warnings.forEach(f => {
|
|
213
|
+
console.log(` ${chalk.yellow('⚠')} ${chalk.white(f.id.slice(0, 12))} ${chalk.yellow(f.code)}`);
|
|
214
|
+
console.log(chalk.gray(` ${f.message}`));
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
console.log(chalk.gray(`\n Toplam: ${filtered.length} bulgu`));
|
|
219
|
+
console.log(chalk.gray(` Bakım: natureco tasks maintenance --apply\n`));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function maintenanceHandler(opts) {
|
|
223
|
+
console.log(chalk.cyan('\n Task Bakımı\n'));
|
|
224
|
+
|
|
225
|
+
const dryRun = !opts.apply;
|
|
226
|
+
const result = maintenanceTasks(dryRun);
|
|
227
|
+
|
|
228
|
+
if (dryRun) {
|
|
229
|
+
console.log(chalk.gray(' Kuru çalışma (--apply ile uygula)\n'));
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log(chalk.gray(` Temizlenen : ${result.pruned}`));
|
|
233
|
+
console.log(chalk.gray(` Düzeltilen : ${result.reconciled}`));
|
|
234
|
+
console.log(chalk.gray(` Etiketlenen : ${result.cleaned}`));
|
|
235
|
+
console.log(chalk.gray(` Kalan task : ${result.remaining}`));
|
|
236
|
+
|
|
237
|
+
if (result.pruned > 0 || result.reconciled > 0 || result.cleaned > 0) {
|
|
238
|
+
if (dryRun) {
|
|
239
|
+
console.log(chalk.gray(`\n Uygulamak için: natureco tasks maintenance --apply`));
|
|
240
|
+
} else {
|
|
241
|
+
console.log(chalk.green(`\n ✓ Bakım uygulandı.\n`));
|
|
242
|
+
}
|
|
243
|
+
} else {
|
|
244
|
+
console.log(chalk.green(`\n ✓ Bakım gerekmiyor.\n`));
|
|
245
|
+
}
|
|
246
|
+
console.log('');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function flowListHandler(opts) {
|
|
250
|
+
const tasks = listTasks({ runtime: 'acp', limit: opts.limit || 50 });
|
|
251
|
+
|
|
252
|
+
if (opts.json) {
|
|
253
|
+
console.log(JSON.stringify({ flows: tasks, total: tasks.length }, null, 2));
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
console.log('');
|
|
258
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
259
|
+
console.log(chalk.cyan.bold('\n Task Flow\n'));
|
|
260
|
+
|
|
261
|
+
if (tasks.length === 0) {
|
|
262
|
+
console.log(chalk.gray(' Task Flow kaydı yok.\n'));
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
tasks.forEach(t => {
|
|
267
|
+
const icon = STATUS_ICONS[t.status] || '❓';
|
|
268
|
+
const color = STATUS_COLORS[t.status] || chalk.white;
|
|
269
|
+
console.log(` ${icon} ${chalk.white(t.id.slice(0, 12))} ${color(t.status)}`);
|
|
270
|
+
if (t.message) console.log(chalk.gray(` ${t.message.slice(0, 60)}`));
|
|
271
|
+
});
|
|
272
|
+
console.log(chalk.gray(`\n Toplam: ${tasks.length} flow\n`));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function flowShowHandler(id, opts) {
|
|
276
|
+
if (!id) {
|
|
277
|
+
console.log(chalk.red('\n ❌ Flow ID gerekli\n'));
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
return showTaskHandler(id, opts);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function flowCancelHandler(id) {
|
|
284
|
+
if (!id) {
|
|
285
|
+
console.log(chalk.red('\n ❌ Flow ID gerekli\n'));
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
return cancelTaskHandler(id);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function summaryHandler(opts) {
|
|
292
|
+
const summary = getTaskSummary();
|
|
293
|
+
|
|
294
|
+
if (opts.json) {
|
|
295
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
console.log('');
|
|
300
|
+
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
301
|
+
console.log(chalk.cyan.bold('\n Task Özeti\n'));
|
|
302
|
+
console.log(chalk.gray(' Aktif : ') + (summary.active > 0 ? chalk.yellow(summary.active) : chalk.green('0')));
|
|
303
|
+
console.log(chalk.gray(' Hatalı : ') + (summary.failures > 0 ? chalk.red(summary.failures) : chalk.green('0')));
|
|
304
|
+
console.log(chalk.gray(' Toplam : ') + chalk.white(summary.total));
|
|
305
|
+
console.log(chalk.gray('\n Runtime Dağılımı'));
|
|
306
|
+
Object.entries(summary.byRuntime).forEach(([rt, count]) => {
|
|
307
|
+
if (count > 0) console.log(chalk.gray(` ${rt.padEnd(10)}: ${count}`));
|
|
308
|
+
});
|
|
309
|
+
console.log('');
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function getAgeString(dateStr) {
|
|
313
|
+
const ms = Date.now() - new Date(dateStr).getTime();
|
|
314
|
+
const sec = Math.floor(ms / 1000);
|
|
315
|
+
if (sec < 60) return `${sec}s önce`;
|
|
316
|
+
const min = Math.floor(sec / 60);
|
|
317
|
+
if (min < 60) return `${min}dk önce`;
|
|
318
|
+
const hr = Math.floor(min / 60);
|
|
319
|
+
if (hr < 24) return `${hr}sa önce`;
|
|
320
|
+
const days = Math.floor(hr / 24);
|
|
321
|
+
return `${days}g önce`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function formatTime(dateStr) {
|
|
325
|
+
return new Date(dateStr).toLocaleString('tr-TR');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
module.exports = tasks;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('../utils/inquirer-wrapper');
|
|
3
|
+
const { getConfig, saveConfig } = require('../utils/config');
|
|
4
|
+
|
|
5
|
+
async function webhooks(action) {
|
|
6
|
+
if (!action || action === 'connect') return connectWebhook();
|
|
7
|
+
if (action === 'disconnect') return disconnectWebhook();
|
|
8
|
+
if (action === 'status') return statusWebhooks();
|
|
9
|
+
if (action === 'list') return listWebhooks();
|
|
10
|
+
console.log(chalk.red('\n❌ Unknown action\n'));
|
|
11
|
+
console.log(chalk.gray('Available actions: connect, disconnect, status, list\n'));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function connectWebhook() {
|
|
16
|
+
const config = getConfig();
|
|
17
|
+
if (!config.providerUrl) { console.log(chalk.red('\n❌ Setup yapılmamış. Önce "natureco setup" çalıştırın.\n')); process.exit(1); }
|
|
18
|
+
console.log(chalk.yellow('\n⏳ Webhook bağlantısı hazırlanıyor...\n'));
|
|
19
|
+
console.log(chalk.gray('Gelen webhook\'lar NatureCo\'nun gateway\'ine yönlendirilir.\n'));
|
|
20
|
+
const answers = await inquirer.prompt([
|
|
21
|
+
{ type: 'input', name: 'name', message: 'Webhook adı:', validate: v => v.trim() ? true : 'Gerekli' },
|
|
22
|
+
{ type: 'input', name: 'path', message: 'Webhook yolu (örn: /my-webhook):', validate: v => v.startsWith('/') ? true : 'Yol / ile başlamalı' },
|
|
23
|
+
{ type: 'input', name: 'secret', message: 'Webhook secret (opsiyonel):' },
|
|
24
|
+
]);
|
|
25
|
+
const webhooks = config.webhooks || [];
|
|
26
|
+
const entry = {
|
|
27
|
+
id: `webhook_${Date.now()}`,
|
|
28
|
+
name: answers.name.trim(),
|
|
29
|
+
path: answers.path.trim(),
|
|
30
|
+
secret: answers.secret.trim() || '',
|
|
31
|
+
createdAt: new Date().toISOString(),
|
|
32
|
+
};
|
|
33
|
+
webhooks.push(entry);
|
|
34
|
+
config.webhooks = webhooks;
|
|
35
|
+
config.webhookEnabled = true;
|
|
36
|
+
saveConfig(config);
|
|
37
|
+
console.log(chalk.green('\n✅ Webhook eklendi!\n'));
|
|
38
|
+
console.log(chalk.cyan('ID:'), chalk.white(entry.id));
|
|
39
|
+
console.log(chalk.cyan('İsim:'), chalk.white(entry.name));
|
|
40
|
+
console.log(chalk.cyan('Yol:'), chalk.white(entry.path));
|
|
41
|
+
console.log(chalk.gray('\nGateway ile başlatmak için: natureco gateway start\n'));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function disconnectWebhook() {
|
|
45
|
+
const config = getConfig();
|
|
46
|
+
const webhooks = config.webhooks || [];
|
|
47
|
+
if (webhooks.length === 0) { console.log(chalk.gray('\n⚠️ No webhooks configured\n')); return; }
|
|
48
|
+
const { confirm } = await inquirer.prompt([{ type: 'confirm', name: 'confirm', message: 'Tüm webhook\'ları kaldırmak istediğinize emin misiniz?', default: false }]);
|
|
49
|
+
if (!confirm) { console.log(chalk.gray('\nCancelled\n')); return; }
|
|
50
|
+
delete config.webhooks;
|
|
51
|
+
delete config.webhookEnabled;
|
|
52
|
+
saveConfig(config);
|
|
53
|
+
console.log(chalk.green('\n✅ All webhooks removed\n'));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function listWebhooks() {
|
|
57
|
+
const config = getConfig();
|
|
58
|
+
const webhooks = config.webhooks || [];
|
|
59
|
+
if (webhooks.length === 0) { console.log(chalk.gray('\n⚠️ No webhooks configured\n')); return; }
|
|
60
|
+
console.log(chalk.green(`\n✅ ${webhooks.length} webhook(s) configured\n`));
|
|
61
|
+
webhooks.forEach(w => {
|
|
62
|
+
console.log(chalk.cyan(' ID:'), chalk.white(w.id));
|
|
63
|
+
console.log(chalk.cyan(' İsim:'), chalk.white(w.name));
|
|
64
|
+
console.log(chalk.cyan(' Yol:'), chalk.white(w.path));
|
|
65
|
+
if (w.secret) console.log(chalk.cyan(' Secret:'), chalk.gray('✓ ayarlı'));
|
|
66
|
+
console.log('');
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function statusWebhooks() {
|
|
71
|
+
const config = getConfig();
|
|
72
|
+
const webhooks = config.webhooks || [];
|
|
73
|
+
if (webhooks.length === 0) { console.log(chalk.gray('\n⚠️ No webhooks configured\n')); console.log(chalk.gray('Add with: natureco webhooks connect\n')); return; }
|
|
74
|
+
console.log(chalk.green(`\n✅ Webhooks active (${webhooks.length} route(s))\n`));
|
|
75
|
+
webhooks.forEach(w => console.log(chalk.white(` ${w.path} → ${w.name}`)));
|
|
76
|
+
console.log(chalk.gray('\nDisconnect with: natureco webhooks disconnect\n'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = webhooks;
|
package/src/commands/whatsapp.js
CHANGED
|
@@ -7,25 +7,11 @@ const os = require('os');
|
|
|
7
7
|
const pino = require('pino');
|
|
8
8
|
const { getApiKey, getConfig, saveConfig } = require('../utils/config');
|
|
9
9
|
const { getBots, sendMessage } = require('../utils/api');
|
|
10
|
+
const { loadBaileys } = require('../utils/baileys');
|
|
11
|
+
const { NatureCoError, ChannelError, handleError } = require('../utils/errors');
|
|
10
12
|
|
|
11
|
-
// Baileys imports
|
|
12
|
-
let makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers;
|
|
13
|
-
|
|
14
|
-
// Logger
|
|
15
13
|
const logger = pino({ level: 'silent' });
|
|
16
14
|
|
|
17
|
-
// Lazy load Baileys (only when needed)
|
|
18
|
-
function loadBaileys() {
|
|
19
|
-
if (!makeWASocket) {
|
|
20
|
-
const baileys = require('@whiskeysockets/baileys');
|
|
21
|
-
makeWASocket = baileys.default;
|
|
22
|
-
useMultiFileAuthState = baileys.useMultiFileAuthState;
|
|
23
|
-
DisconnectReason = baileys.DisconnectReason;
|
|
24
|
-
fetchLatestBaileysVersion = baileys.fetchLatestBaileysVersion;
|
|
25
|
-
Browsers = baileys.Browsers;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
15
|
// WhatsApp session directory
|
|
30
16
|
const WHATSAPP_SESSION_DIR = path.join(os.homedir(), '.natureco', 'whatsapp-sessions');
|
|
31
17
|
|
|
@@ -73,9 +59,6 @@ async function connectWhatsApp() {
|
|
|
73
59
|
console.log(chalk.cyan('\n📱 WhatsApp bağlantısı başlatılıyor...'));
|
|
74
60
|
console.log(chalk.gray('Telefonunuzda WhatsApp\'ı açın ve QR kodu taratın.\n'));
|
|
75
61
|
|
|
76
|
-
// Load Baileys
|
|
77
|
-
loadBaileys();
|
|
78
|
-
|
|
79
62
|
// Create session directory
|
|
80
63
|
const sessionDir = path.join(WHATSAPP_SESSION_DIR, botId);
|
|
81
64
|
if (!fs.existsSync(sessionDir)) {
|
|
@@ -88,6 +71,8 @@ async function connectWhatsApp() {
|
|
|
88
71
|
|
|
89
72
|
async function startWhatsAppConnection(sessionDir, botId, selectedBot, config) {
|
|
90
73
|
try {
|
|
74
|
+
const { makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion, Browsers } = loadBaileys();
|
|
75
|
+
|
|
91
76
|
// Create auth state
|
|
92
77
|
const { state, saveCreds } = await useMultiFileAuthState(sessionDir);
|
|
93
78
|
|
|
@@ -197,8 +182,9 @@ async function startWhatsAppConnection(sessionDir, botId, selectedBot, config) {
|
|
|
197
182
|
});
|
|
198
183
|
|
|
199
184
|
} catch (err) {
|
|
200
|
-
|
|
201
|
-
|
|
185
|
+
const msg = err instanceof NatureCoError ? err.message : err?.message ?? 'Unknown error';
|
|
186
|
+
console.log(chalk.red(`\n❌ Connection failed: ${msg}\n`));
|
|
187
|
+
if (err?.message?.includes('Cannot find module')) {
|
|
202
188
|
console.log(chalk.yellow('⚠️ Baileys paketi yüklü değil. Yükleniyor...\n'));
|
|
203
189
|
console.log(chalk.gray('Lütfen şu komutu çalıştırın:\n'));
|
|
204
190
|
console.log(chalk.cyan('npm install -g @whiskeysockets/baileys pino\n'));
|
package/src/tools/bash.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
2
|
const os = require('os');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { isDangerousCommand, checkCommand, isSafeCommand } = require('../utils/approvals');
|
|
3
5
|
|
|
4
6
|
module.exports = {
|
|
5
7
|
name: 'bash',
|
|
@@ -17,43 +19,75 @@ module.exports = {
|
|
|
17
19
|
|
|
18
20
|
async execute(params) {
|
|
19
21
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
if (!params.command || !params.command.trim()) {
|
|
23
|
+
return { success: false, error: 'No command provided' };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const command = params.command;
|
|
27
|
+
|
|
28
|
+
// Skip approval checks for safe commands
|
|
29
|
+
if (isSafeCommand(command)) {
|
|
30
|
+
return runCommand(command);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check command against approvals policy
|
|
34
|
+
const approval = await checkCommand(command, { agentId: 'default' });
|
|
35
|
+
|
|
36
|
+
if (!approval.allowed) {
|
|
37
|
+
if (approval.reason === 'denied-by-policy') {
|
|
38
|
+
return {
|
|
39
|
+
success: false,
|
|
40
|
+
error: 'Command execution is denied by security policy. Use "natureco security allowlist add" to allow specific commands.',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (approval.reason === 'not-in-allowlist') {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
error: 'Command is not in the allowlist. Use "natureco security allowlist add" to add it, or set a less restrictive policy.',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return { success: false, error: `Command rejected: ${approval.reason}` };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check for dangerous commands that weren't already user-approved
|
|
53
|
+
if (isDangerousCommand(command)) {
|
|
54
|
+
console.log(chalk.yellow('\n ⚠️ Potentially dangerous command'));
|
|
55
|
+
console.log(chalk.gray(' ') + command);
|
|
56
|
+
console.log('');
|
|
25
57
|
return {
|
|
26
58
|
success: false,
|
|
27
|
-
error: '
|
|
59
|
+
error: 'Dangerous command blocked. Run manually after review.',
|
|
28
60
|
};
|
|
29
61
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Handles: /home, /home/Documents, /home/anything
|
|
33
|
-
let command = params.command;
|
|
34
|
-
if (process.platform !== 'win32') {
|
|
35
|
-
command = command.replace(/\/home(\/[^\s]*)?/g, (match, subpath) => {
|
|
36
|
-
return os.homedir() + (subpath || '');
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const output = execSync(command, {
|
|
41
|
-
encoding: 'utf-8',
|
|
42
|
-
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
43
|
-
timeout: 30000, // 30 seconds
|
|
44
|
-
shell: true // Use shell for command execution
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
success: true,
|
|
49
|
-
output: output.trim()
|
|
50
|
-
};
|
|
62
|
+
|
|
63
|
+
return runCommand(approval.editedCommand || command);
|
|
51
64
|
} catch (error) {
|
|
52
65
|
return {
|
|
53
66
|
success: false,
|
|
54
|
-
error: error
|
|
55
|
-
stderr: error
|
|
67
|
+
error: error?.message ?? 'Unknown error',
|
|
68
|
+
stderr: error?.stderr?.toString() ?? '',
|
|
56
69
|
};
|
|
57
70
|
}
|
|
58
71
|
}
|
|
59
72
|
};
|
|
73
|
+
|
|
74
|
+
function runCommand(command) {
|
|
75
|
+
let cmd = command;
|
|
76
|
+
if (process.platform !== 'win32') {
|
|
77
|
+
cmd = cmd.replace(/\/home(\/[^\s]*)?/g, (match, subpath) => {
|
|
78
|
+
return os.homedir() + (subpath || '');
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const output = execSync(cmd, {
|
|
83
|
+
encoding: 'utf-8',
|
|
84
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
85
|
+
timeout: 30000,
|
|
86
|
+
shell: true,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
output: output.trim(),
|
|
92
|
+
};
|
|
93
|
+
}
|