natureco-cli 2.23.30 → 2.23.32
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 +178 -167
- package/package.json +1 -1
- package/src/commands/acp.js +39 -0
- package/src/commands/admin-rpc.js +83 -0
- package/src/commands/agent.js +214 -23
- package/src/commands/agents.js +114 -30
- package/src/commands/approvals.js +172 -11
- package/src/commands/ask.js +1 -1
- package/src/commands/browser.js +815 -0
- package/src/commands/capability.js +195 -22
- package/src/commands/channels.js +422 -267
- package/src/commands/chat.js +5 -8
- package/src/commands/clawbot.js +19 -0
- package/src/commands/code.js +3 -2
- package/src/commands/commitments.js +125 -9
- package/src/commands/completion.js +40 -32
- package/src/commands/config.js +228 -30
- package/src/commands/configure.js +84 -67
- package/src/commands/cron.js +239 -19
- package/src/commands/daemon.js +34 -4
- package/src/commands/dashboard.js +47 -374
- package/src/commands/devices.js +53 -26
- package/src/commands/directory.js +146 -14
- package/src/commands/dns.js +148 -10
- package/src/commands/docs.js +119 -26
- package/src/commands/doctor.js +143 -492
- package/src/commands/exec-policy.js +57 -48
- package/src/commands/gateway.js +492 -249
- package/src/commands/health.js +141 -11
- package/src/commands/help.js +24 -25
- package/src/commands/hooks.js +141 -87
- package/src/commands/infer.js +1442 -41
- package/src/commands/logs.js +122 -99
- package/src/commands/mcp.js +121 -309
- package/src/commands/memory.js +128 -0
- package/src/commands/message.js +720 -140
- package/src/commands/models.js +39 -1
- package/src/commands/node.js +77 -77
- package/src/commands/nodes.js +278 -22
- package/src/commands/onboard.js +115 -56
- package/src/commands/pairing.js +108 -107
- package/src/commands/path.js +206 -0
- package/src/commands/plugins.js +35 -1
- package/src/commands/proxy.js +159 -8
- package/src/commands/qr.js +55 -13
- package/src/commands/reset.js +101 -94
- package/src/commands/secrets.js +104 -21
- package/src/commands/sessions.js +110 -51
- package/src/commands/setup.js +229 -649
- package/src/commands/skills.js +67 -1
- package/src/commands/status.js +101 -127
- package/src/commands/tasks.js +208 -100
- package/src/commands/terminal.js +130 -12
- package/src/commands/transcripts.js +24 -1
- package/src/commands/tui.js +41 -0
- package/src/commands/uninstall.js +73 -92
- package/src/commands/update.js +146 -91
- package/src/commands/web-fetch.js +34 -0
- package/src/commands/webhooks.js +58 -66
- package/src/commands/wiki.js +783 -0
- package/src/utils/agents-md.js +85 -0
- package/src/utils/api.js +40 -41
- package/src/utils/format.js +144 -0
- package/src/utils/headless.js +2 -1
- package/src/utils/parallel-tools.js +106 -0
- package/src/utils/sub-agent.js +148 -0
- package/src/utils/token-budget.js +304 -0
- package/src/utils/tool-runner.js +7 -5
- package/src/utils/web-fetch.js +107 -0
package/src/commands/cron.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const F = require('../utils/format');
|
|
2
3
|
const fs = require('fs');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
const os = require('os');
|
|
5
6
|
|
|
6
7
|
const CRONS_FILE = path.join(os.homedir(), '.natureco', 'crons.json');
|
|
8
|
+
const CRONS_RUNS_FILE = path.join(os.homedir(), '.natureco', 'cron-runs.json');
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Normalize WhatsApp number from JID format to clean phone number
|
|
@@ -36,12 +38,18 @@ function saveCrons(crons) {
|
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
async function cron(action, options) {
|
|
39
|
-
if (!action || !['add', 'list', 'remove'].includes(action)) {
|
|
41
|
+
if (!action || !['add', 'list', 'remove', 'get', 'edit', 'enable', 'disable', 'runs', 'run'].includes(action)) {
|
|
40
42
|
console.log(chalk.red('\n❌ Geçersiz aksiyon\n'));
|
|
41
43
|
console.log(chalk.gray('Kullanım:'));
|
|
42
44
|
console.log(chalk.cyan(' natureco cron add --name <name> --schedule <cron> --action <channel> --target <target> --prompt <prompt>'));
|
|
43
45
|
console.log(chalk.cyan(' natureco cron list'));
|
|
46
|
+
console.log(chalk.cyan(' natureco cron get <name>'));
|
|
47
|
+
console.log(chalk.cyan(' natureco cron edit <name> [--name <name>] [--schedule <cron>] [--action <channel>] [--target <target>] [--prompt <prompt>]'));
|
|
44
48
|
console.log(chalk.cyan(' natureco cron remove --name <name>'));
|
|
49
|
+
console.log(chalk.cyan(' natureco cron enable <name>'));
|
|
50
|
+
console.log(chalk.cyan(' natureco cron disable <name>'));
|
|
51
|
+
console.log(chalk.cyan(' natureco cron runs <name>'));
|
|
52
|
+
console.log(chalk.cyan(' natureco cron run <name>'));
|
|
45
53
|
console.log(chalk.gray('\nÖrnek:'));
|
|
46
54
|
console.log(chalk.cyan(' natureco cron add --name "bitcoin-fiyat" --schedule "0 9 * * *" --action "whatsapp" --target "+905422842631" --prompt "Bugünkü Bitcoin fiyatını öğren ve kısaca bildir"\n'));
|
|
47
55
|
process.exit(1);
|
|
@@ -53,6 +61,18 @@ async function cron(action, options) {
|
|
|
53
61
|
listCrons();
|
|
54
62
|
} else if (action === 'remove') {
|
|
55
63
|
removeCron(options);
|
|
64
|
+
} else if (action === 'get') {
|
|
65
|
+
getCron(options);
|
|
66
|
+
} else if (action === 'edit') {
|
|
67
|
+
editCron(options);
|
|
68
|
+
} else if (action === 'enable') {
|
|
69
|
+
enableCron(options);
|
|
70
|
+
} else if (action === 'disable') {
|
|
71
|
+
disableCron(options);
|
|
72
|
+
} else if (action === 'runs') {
|
|
73
|
+
showRuns(options);
|
|
74
|
+
} else if (action === 'run') {
|
|
75
|
+
runCron(options);
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
|
|
@@ -120,42 +140,42 @@ function listCrons() {
|
|
|
120
140
|
const crons = loadCrons();
|
|
121
141
|
|
|
122
142
|
if (crons.length === 0) {
|
|
123
|
-
|
|
143
|
+
F.header('Cron Jobs');
|
|
144
|
+
F.meta('Kayıtlı cron yok');
|
|
124
145
|
return;
|
|
125
146
|
}
|
|
126
147
|
|
|
127
|
-
// Load config for fallback targets
|
|
128
148
|
const { getConfig } = require('../utils/config');
|
|
129
149
|
const config = getConfig();
|
|
130
150
|
const defaultWhatsappTarget = normalizeWhatsAppNumber(config.whatsappPhone) || 'N/A';
|
|
131
151
|
const defaultTelegramTarget = (config.telegramAllowedChats && config.telegramAllowedChats[0]) || 'N/A';
|
|
132
152
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
crons.forEach((c, i) => {
|
|
136
|
-
// Use target from cron or fallback to config
|
|
153
|
+
const runs = loadRuns();
|
|
154
|
+
const rows = crons.map(c => {
|
|
137
155
|
let target = c.target;
|
|
138
156
|
if (!target || target === 'undefined') {
|
|
139
157
|
target = c.action === 'telegram' ? defaultTelegramTarget : defaultWhatsappTarget;
|
|
140
158
|
} else if (c.action === 'whatsapp') {
|
|
141
|
-
// Normalize WhatsApp JID format
|
|
142
159
|
target = normalizeWhatsAppNumber(target);
|
|
143
160
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
161
|
+
const cronRuns = runs.filter(r => r.name === c.name);
|
|
162
|
+
const lastRun = cronRuns.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))[0];
|
|
163
|
+
return [
|
|
164
|
+
c.name,
|
|
165
|
+
c.schedule,
|
|
166
|
+
c.enabled ? 'Aktif' : 'Pasif',
|
|
167
|
+
lastRun ? lastRun.timestamp.slice(0, 10) : '—'
|
|
168
|
+
];
|
|
151
169
|
});
|
|
170
|
+
F.header('Cron Jobs');
|
|
171
|
+
F.table(['Name', 'Schedule', 'Status', 'LastRun'], rows);
|
|
152
172
|
}
|
|
153
173
|
|
|
154
174
|
function removeCron(options) {
|
|
155
175
|
const { name } = options;
|
|
156
176
|
|
|
157
177
|
if (!name) {
|
|
158
|
-
|
|
178
|
+
F.error('--name parametresi gerekli');
|
|
159
179
|
process.exit(1);
|
|
160
180
|
}
|
|
161
181
|
|
|
@@ -163,15 +183,215 @@ function removeCron(options) {
|
|
|
163
183
|
const index = crons.findIndex(c => c.name === name);
|
|
164
184
|
|
|
165
185
|
if (index === -1) {
|
|
166
|
-
|
|
186
|
+
F.error('Bu isimde bir cron bulunamadı');
|
|
167
187
|
process.exit(1);
|
|
168
188
|
}
|
|
169
189
|
|
|
170
190
|
crons.splice(index, 1);
|
|
171
191
|
saveCrons(crons);
|
|
172
192
|
|
|
173
|
-
|
|
174
|
-
|
|
193
|
+
F.success('Cron silindi!');
|
|
194
|
+
F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function getCron(options) {
|
|
198
|
+
const { name } = options;
|
|
199
|
+
if (!name) {
|
|
200
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron get <name>');
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const crons = loadCrons();
|
|
205
|
+
const cron = crons.find(c => c.name === name);
|
|
206
|
+
if (!cron) {
|
|
207
|
+
F.error('"' + name + '" isminde bir cron bulunamadı');
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
F.header('Cron: ' + cron.name);
|
|
212
|
+
F.kv('İsim', cron.name);
|
|
213
|
+
F.kv('Zamanlama', cron.schedule);
|
|
214
|
+
F.kv('Kanal', cron.action);
|
|
215
|
+
F.kv('Hedef', cron.target);
|
|
216
|
+
F.kv('Prompt', cron.prompt);
|
|
217
|
+
F.kv('Oluşturulma', cron.createdAt);
|
|
218
|
+
F.kv('Durum', cron.enabled ? 'Aktif' : 'Pasif');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function editCron(options) {
|
|
222
|
+
const { name, schedule, action, target, prompt } = options;
|
|
223
|
+
const newName = options['newName'];
|
|
224
|
+
|
|
225
|
+
if (!name) {
|
|
226
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron edit <name> [--name <newName>] [--schedule <cron>] [--action <channel>] [--target <target>] [--prompt <prompt>]');
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const crons = loadCrons();
|
|
231
|
+
const cron = crons.find(c => c.name === name);
|
|
232
|
+
if (!cron) {
|
|
233
|
+
F.error('"' + name + '" isminde bir cron bulunamadı');
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (newName) cron.name = newName;
|
|
238
|
+
if (schedule) {
|
|
239
|
+
try {
|
|
240
|
+
const nodeCron = require('node-cron');
|
|
241
|
+
if (!nodeCron.validate(schedule)) {
|
|
242
|
+
F.error('Geçersiz cron ifadesi');
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
} catch (err) {
|
|
246
|
+
F.error('node-cron yüklü değil');
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
cron.schedule = schedule;
|
|
250
|
+
}
|
|
251
|
+
if (action) {
|
|
252
|
+
if (!['whatsapp', 'telegram'].includes(action)) {
|
|
253
|
+
F.error('Geçersiz action. Sadece "whatsapp" veya "telegram" kullanılabilir');
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
cron.action = action;
|
|
257
|
+
}
|
|
258
|
+
if (target) cron.target = target;
|
|
259
|
+
if (prompt) cron.prompt = prompt;
|
|
260
|
+
|
|
261
|
+
saveCrons(crons);
|
|
262
|
+
|
|
263
|
+
F.success('Cron güncellendi!');
|
|
264
|
+
F.kv('İsim', cron.name);
|
|
265
|
+
F.kv('Zamanlama', cron.schedule);
|
|
266
|
+
F.kv('Kanal', cron.action);
|
|
267
|
+
F.kv('Hedef', cron.target);
|
|
268
|
+
F.kv('Prompt', cron.prompt);
|
|
269
|
+
F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function enableCron(options) {
|
|
273
|
+
const { name } = options;
|
|
274
|
+
if (!name) {
|
|
275
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron enable <name>');
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const crons = loadCrons();
|
|
280
|
+
const cron = crons.find(c => c.name === name);
|
|
281
|
+
if (!cron) {
|
|
282
|
+
F.error('"' + name + '" isminde bir cron bulunamadı');
|
|
283
|
+
process.exit(1);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (cron.enabled) {
|
|
287
|
+
F.warning('"' + name + '" cron zaten aktif');
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
cron.enabled = true;
|
|
292
|
+
saveCrons(crons);
|
|
293
|
+
F.dot(true, name);
|
|
294
|
+
F.success('"' + name + '" cron aktifleştirildi');
|
|
295
|
+
F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function disableCron(options) {
|
|
299
|
+
const { name } = options;
|
|
300
|
+
if (!name) {
|
|
301
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron disable <name>');
|
|
302
|
+
process.exit(1);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const crons = loadCrons();
|
|
306
|
+
const cron = crons.find(c => c.name === name);
|
|
307
|
+
if (!cron) {
|
|
308
|
+
F.error('"' + name + '" isminde bir cron bulunamadı');
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (!cron.enabled) {
|
|
313
|
+
F.warning('"' + name + '" cron zaten pasif');
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
cron.enabled = false;
|
|
318
|
+
saveCrons(crons);
|
|
319
|
+
F.dot(false, name);
|
|
320
|
+
F.success('"' + name + '" cron pasifleştirildi');
|
|
321
|
+
F.meta('Gateway çalışıyorsa yeniden başlatın: natureco gateway stop && natureco gateway start');
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function loadRuns() {
|
|
325
|
+
try {
|
|
326
|
+
if (!fs.existsSync(CRONS_RUNS_FILE)) {
|
|
327
|
+
return [];
|
|
328
|
+
}
|
|
329
|
+
return JSON.parse(fs.readFileSync(CRONS_RUNS_FILE, 'utf-8'));
|
|
330
|
+
} catch {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function showRuns(options) {
|
|
336
|
+
const { name } = options;
|
|
337
|
+
if (!name) {
|
|
338
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron runs <name>');
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const runs = loadRuns().filter(r => r.name === name);
|
|
343
|
+
|
|
344
|
+
F.header('Cron Runs: ' + name);
|
|
345
|
+
|
|
346
|
+
if (runs.length === 0) {
|
|
347
|
+
F.meta('"' + name + '" için kayıtlı çalışma geçmişi yok');
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const rows = runs.map(r => [
|
|
352
|
+
r.timestamp,
|
|
353
|
+
r.status,
|
|
354
|
+
r.output ? r.output.substring(0, 60) : '—'
|
|
355
|
+
]);
|
|
356
|
+
F.table(['Time', 'Status', 'Output'], rows);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function runCron(options) {
|
|
360
|
+
const { name } = options;
|
|
361
|
+
if (!name) {
|
|
362
|
+
F.error('Cron adı gerekli. Kullanım: natureco cron run <name>');
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const crons = loadCrons();
|
|
367
|
+
const cron = crons.find(c => c.name === name);
|
|
368
|
+
if (!cron) {
|
|
369
|
+
F.error('"' + name + '" isminde bir cron bulunamadı');
|
|
370
|
+
process.exit(1);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const timestamp = new Date().toISOString();
|
|
374
|
+
|
|
375
|
+
F.info('"' + name + '" cron manuel olarak çalıştırılıyor...');
|
|
376
|
+
F.kv('Zamanlama', cron.schedule);
|
|
377
|
+
F.kv('Kanal', cron.action);
|
|
378
|
+
F.kv('Hedef', cron.target);
|
|
379
|
+
F.kv('Prompt', cron.prompt);
|
|
380
|
+
F.success('Cron tetiklendi (mock)');
|
|
381
|
+
|
|
382
|
+
// Log the run
|
|
383
|
+
const runs = loadRuns();
|
|
384
|
+
runs.push({
|
|
385
|
+
name,
|
|
386
|
+
timestamp,
|
|
387
|
+
status: 'success',
|
|
388
|
+
output: `Mock run of ${name} (${cron.action} → ${cron.target})`
|
|
389
|
+
});
|
|
390
|
+
const dir = path.dirname(CRONS_RUNS_FILE);
|
|
391
|
+
if (!fs.existsSync(dir)) {
|
|
392
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
393
|
+
}
|
|
394
|
+
fs.writeFileSync(CRONS_RUNS_FILE, JSON.stringify(runs, null, 2), 'utf-8');
|
|
175
395
|
}
|
|
176
396
|
|
|
177
397
|
module.exports = cron;
|
package/src/commands/daemon.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const { execSync, spawn } = require('child_process');
|
|
3
3
|
const path = require('path');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
4
6
|
|
|
5
7
|
const GATEWAY_SCRIPT = path.join(__dirname, 'gateway-server.js');
|
|
6
8
|
|
|
@@ -11,18 +13,38 @@ function daemon(args) {
|
|
|
11
13
|
if (action === 'start') return startDaemon();
|
|
12
14
|
if (action === 'stop') return stopDaemon();
|
|
13
15
|
if (action === 'restart') return restartDaemon();
|
|
16
|
+
if (action === 'install') return installDaemon();
|
|
17
|
+
if (action === 'uninstall') return uninstallDaemon();
|
|
14
18
|
|
|
15
19
|
console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
|
|
16
|
-
console.log(chalk.gray(' Kullanım: natureco daemon [status|start|stop|restart]\n'));
|
|
20
|
+
console.log(chalk.gray(' Kullanım: natureco daemon [status|start|stop|restart|install|uninstall]\n'));
|
|
17
21
|
process.exit(1);
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
function statusDaemon() {
|
|
25
|
+
const pidFile = path.join(os.homedir(), '.natureco', 'daemon.pid');
|
|
26
|
+
let running = false;
|
|
27
|
+
let pid = null;
|
|
28
|
+
|
|
29
|
+
if (fs.existsSync(pidFile)) {
|
|
30
|
+
try {
|
|
31
|
+
pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
|
|
32
|
+
process.kill(pid, 0);
|
|
33
|
+
running = true;
|
|
34
|
+
} catch {
|
|
35
|
+
running = false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
console.log(chalk.cyan('\n ⚙️ Gateway Daemon\n'));
|
|
22
40
|
console.log(chalk.gray(' ' + '─'.repeat(48)));
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
41
|
+
if (running) {
|
|
42
|
+
console.log(` ${chalk.white('Status:')} ${chalk.green('running')}`);
|
|
43
|
+
console.log(` ${chalk.white('PID:')} ${pid}`);
|
|
44
|
+
} else {
|
|
45
|
+
console.log(` ${chalk.white('Status:')} ${chalk.yellow('not running')}`);
|
|
46
|
+
console.log(` ${chalk.white('PID:')} ${chalk.gray('N/A')}`);
|
|
47
|
+
}
|
|
26
48
|
console.log(chalk.gray('\n Manage with:') + chalk.cyan(' natureco gateway start|stop|status'));
|
|
27
49
|
console.log();
|
|
28
50
|
}
|
|
@@ -57,4 +79,12 @@ function restartDaemon() {
|
|
|
57
79
|
setTimeout(() => startDaemon(), 1000);
|
|
58
80
|
}
|
|
59
81
|
|
|
82
|
+
function installDaemon() {
|
|
83
|
+
console.log(chalk.yellow('\n daemon install would register as a system service\n'));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function uninstallDaemon() {
|
|
87
|
+
console.log(chalk.yellow('\n daemon uninstall would remove system service registration\n'));
|
|
88
|
+
}
|
|
89
|
+
|
|
60
90
|
module.exports = daemon;
|