natureco-cli 2.23.28 → 2.23.30

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 (96) hide show
  1. package/README.md +94 -11
  2. package/bin/natureco.js +470 -10
  3. package/package.json +10 -6
  4. package/src/commands/admin-rpc.js +219 -0
  5. package/src/commands/agent.js +89 -0
  6. package/src/commands/approvals.js +53 -0
  7. package/src/commands/backup.js +124 -0
  8. package/src/commands/bonjour.js +167 -0
  9. package/src/commands/capability.js +64 -0
  10. package/src/commands/channels.js +94 -4
  11. package/src/commands/chat.js +11 -25
  12. package/src/commands/clickclack.js +130 -0
  13. package/src/commands/commitments.js +32 -0
  14. package/src/commands/completion.js +76 -0
  15. package/src/commands/config.js +111 -68
  16. package/src/commands/configure.js +93 -0
  17. package/src/commands/crestodian.js +92 -0
  18. package/src/commands/daemon.js +60 -0
  19. package/src/commands/device-pair.js +248 -0
  20. package/src/commands/devices.js +110 -0
  21. package/src/commands/directory.js +47 -0
  22. package/src/commands/dns.js +58 -0
  23. package/src/commands/docs.js +43 -0
  24. package/src/commands/doctor.js +121 -16
  25. package/src/commands/exec-policy.js +71 -0
  26. package/src/commands/gateway-server.js +1175 -30
  27. package/src/commands/gateway.js +11 -20
  28. package/src/commands/health.js +18 -0
  29. package/src/commands/help.js +6 -0
  30. package/src/commands/imessage.js +169 -0
  31. package/src/commands/infer.js +73 -0
  32. package/src/commands/irc.js +119 -0
  33. package/src/commands/mattermost.js +164 -0
  34. package/src/commands/memory-cmd.js +134 -1
  35. package/src/commands/message.js +30 -4
  36. package/src/commands/migrate.js +213 -2
  37. package/src/commands/models.js +584 -216
  38. package/src/commands/node.js +98 -0
  39. package/src/commands/nodes.js +106 -0
  40. package/src/commands/oc-path.js +200 -0
  41. package/src/commands/onboard.js +70 -0
  42. package/src/commands/open-prose.js +67 -0
  43. package/src/commands/plugins.js +415 -172
  44. package/src/commands/policy.js +176 -0
  45. package/src/commands/proxy.js +155 -0
  46. package/src/commands/qr.js +28 -0
  47. package/src/commands/sandbox.js +125 -0
  48. package/src/commands/secrets.js +118 -0
  49. package/src/commands/security.js +149 -1
  50. package/src/commands/setup.js +114 -10
  51. package/src/commands/signal.js +495 -0
  52. package/src/commands/skills.js +20 -29
  53. package/src/commands/sms.js +168 -0
  54. package/src/commands/system.js +53 -0
  55. package/src/commands/tasks.js +328 -79
  56. package/src/commands/terminal.js +21 -0
  57. package/src/commands/thread-ownership.js +157 -0
  58. package/src/commands/transcripts.js +72 -0
  59. package/src/commands/voice.js +82 -0
  60. package/src/commands/vydra.js +98 -0
  61. package/src/commands/webhooks.js +79 -0
  62. package/src/commands/whatsapp.js +7 -21
  63. package/src/commands/workboard.js +207 -0
  64. package/src/tools/audio_understanding.js +154 -0
  65. package/src/tools/bash.js +63 -29
  66. package/src/tools/browser.js +112 -0
  67. package/src/tools/canvas.js +104 -0
  68. package/src/tools/document_extract.js +84 -0
  69. package/src/tools/duckduckgo.js +54 -0
  70. package/src/tools/exa_search.js +66 -0
  71. package/src/tools/firecrawl.js +104 -0
  72. package/src/tools/image_generation.js +99 -0
  73. package/src/tools/llm_task.js +118 -0
  74. package/src/tools/media_understanding.js +128 -0
  75. package/src/tools/music_generation.js +113 -0
  76. package/src/tools/parallel_search.js +77 -0
  77. package/src/tools/phone_control.js +80 -0
  78. package/src/tools/phone_control_enhanced.js +184 -0
  79. package/src/tools/searxng.js +61 -0
  80. package/src/tools/speech_to_text.js +135 -0
  81. package/src/tools/text_to_speech.js +105 -0
  82. package/src/tools/thread_ownership.js +88 -0
  83. package/src/tools/video_generation.js +72 -0
  84. package/src/tools/web_readability.js +104 -0
  85. package/src/utils/api.js +3 -20
  86. package/src/utils/approvals.js +297 -0
  87. package/src/utils/background.js +223 -66
  88. package/src/utils/baileys.js +21 -0
  89. package/src/utils/config.js +141 -10
  90. package/src/utils/errors.js +148 -0
  91. package/src/utils/inquirer-wrapper.js +1 -2
  92. package/src/utils/memory.js +200 -0
  93. package/src/utils/path-utils.js +13 -13
  94. package/src/utils/plugin-registry.js +238 -0
  95. package/src/utils/secrets.js +177 -0
  96. package/src/utils/skills.js +10 -23
@@ -3,18 +3,128 @@ const fs = require('fs');
3
3
  const path = require('path');
4
4
  const os = require('os');
5
5
  const { getConfig, CONFIG_FILE, CONFIG_DIR } = require('../utils/config');
6
+ const { listSecretRefs, resolveSecretRef, coerceSecretRef } = require('../utils/secrets');
7
+ const { NatureCoError, handleError } = require('../utils/errors');
6
8
 
7
9
  async function security(args) {
8
10
  const [action, ...params] = (args || []);
9
11
 
10
12
  if (!action || action === 'audit') return audit(args);
11
13
 
14
+ if (action === 'allowlist') return allowlistAction(args);
15
+
16
+ if (action === 'policy') return policyAction(args);
17
+
18
+ if (action === 'secrets') return scanSecrets(args);
19
+
12
20
  console.log(chalk.red(`\n ❌ Bilinmeyen komut: ${action}\n`));
13
- console.log(chalk.gray(' Kullanım: natureco security [audit]\n'));
21
+ console.log(chalk.gray(' Kullanım: natureco security [audit|allowlist|policy|secrets]\n'));
14
22
  process.exit(1);
15
23
  }
16
24
 
25
+ async function allowlistAction(args) {
26
+ const { loadApprovals, addAllowlistEntry, listAllowlist, removeAllowlistEntry } = require('../utils/approvals');
27
+ const sub = args[1];
28
+
29
+ if (!sub || sub === 'list') {
30
+ const entries = listAllowlist('default');
31
+ console.log('');
32
+ console.log(chalk.cyan.bold('\n Exec Allowlist\n'));
33
+ if (entries.length === 0) {
34
+ console.log(chalk.gray(' No entries. Add with: natureco security allowlist add "<command>"'));
35
+ } else {
36
+ entries.forEach((e, i) => {
37
+ console.log(chalk.gray(` ${i + 1}. `) + chalk.white(e.lastUsedCommand || e.pattern));
38
+ console.log(chalk.gray(` id: ${e.id} · source: ${e.source || 'manual'}`));
39
+ });
40
+ }
41
+ console.log('');
42
+ return;
43
+ }
44
+
45
+ if (sub === 'add' && args[2]) {
46
+ addAllowlistEntry('default', args.slice(2).join(' '));
47
+ console.log(chalk.green('\n ✓ Command added to allowlist\n'));
48
+ return;
49
+ }
50
+
51
+ if (sub === 'remove' && args[2]) {
52
+ const removed = removeAllowlistEntry('default', args[2]);
53
+ if (removed) {
54
+ console.log(chalk.green('\n ✓ Entry removed from allowlist\n'));
55
+ } else {
56
+ console.log(chalk.yellow('\n ⚠️ Entry not found\n'));
57
+ }
58
+ return;
59
+ }
60
+
61
+ console.log(chalk.gray('\n Kullanım:'));
62
+ console.log(chalk.gray(' natureco security allowlist list'));
63
+ console.log(chalk.gray(' natureco security allowlist add "<command>"'));
64
+ console.log(chalk.gray(' natureco security allowlist remove <id>\n'));
65
+ }
66
+
67
+ async function policyAction(args) {
68
+ const { setSecurityPolicy } = require('../utils/approvals');
69
+ const sub = args[1];
70
+
71
+ if (sub === 'set' && args[2]) {
72
+ const value = args[2];
73
+ if (['deny', 'allowlist', 'full'].includes(value)) {
74
+ setSecurityPolicy('default', { security: value });
75
+ console.log(chalk.green(`\n ✓ Security policy set to: ${value}\n`));
76
+ } else {
77
+ console.log(chalk.red(`\n ❌ Invalid policy: ${value}. Use: deny, allowlist, full\n`));
78
+ }
79
+ return;
80
+ }
81
+
82
+ console.log(chalk.gray('\n Kullanım:'));
83
+ console.log(chalk.gray(' natureco security policy set deny|allowlist|full'));
84
+ console.log(chalk.gray('\n Policy levels:'));
85
+ console.log(chalk.gray(' deny - Block all command execution'));
86
+ console.log(chalk.gray(' allowlist - Only allowlisted commands'));
87
+ console.log(chalk.gray(' full - Allow all commands (default)\n'));
88
+ }
89
+
90
+ async function scanSecrets(args) {
91
+ const config = getConfig();
92
+ const refs = listSecretRefs(config);
93
+ const fix = args.includes('--fix');
94
+
95
+ console.log('');
96
+ console.log(chalk.cyan.bold('\n Secret Reference Scan\n'));
97
+
98
+ if (refs.length === 0) {
99
+ console.log(chalk.green(' ✓ No secret references found in config\n'));
100
+ return;
101
+ }
102
+
103
+ let resolved = 0;
104
+ let unresolved = 0;
105
+
106
+ for (const ref of refs) {
107
+ try {
108
+ const value = resolveSecretRef(ref.ref, { throwOnMissing: true });
109
+ console.log(chalk.green(` ✓ ${ref.path} → resolved (${ref.ref.source}:${ref.ref.id})`));
110
+ resolved++;
111
+ } catch {
112
+ console.log(chalk.yellow(` ⚠️ ${ref.path} → ${ref.ref.source}:${ref.ref.id} (unresolved)`));
113
+ unresolved++;
114
+ }
115
+ }
116
+
117
+ console.log('');
118
+ console.log(chalk.gray(` ${resolved} resolved · ${unresolved} unresolved`));
119
+
120
+ if (unresolved > 0) {
121
+ console.log(chalk.gray('\n Set environment variables or use .env file to resolve secrets.\n'));
122
+ }
123
+ console.log('');
124
+ }
125
+
17
126
  async function audit(args) {
127
+ const { DANGEROUS_PATTERNS, loadApprovals } = require('../utils/approvals');
18
128
  const fix = args.includes('--fix');
19
129
  const json = args.includes('--json');
20
130
 
@@ -90,6 +200,44 @@ async function audit(args) {
90
200
  }
91
201
  }
92
202
 
203
+ // 7. Secret refs in config
204
+ const secretRefs = listSecretRefs(config);
205
+ if (secretRefs.length > 0) {
206
+ let unresolvedCount = 0;
207
+ for (const ref of secretRefs) {
208
+ try {
209
+ resolveSecretRef(ref.ref, { throwOnMissing: true });
210
+ } catch {
211
+ unresolvedCount++;
212
+ }
213
+ }
214
+ if (unresolvedCount > 0) {
215
+ warnings.push({ id: 'unresolved-secrets', msg: `${unresolvedCount}/${secretRefs.length} secret reference(s) unresolved` });
216
+ } else {
217
+ ok.push('Secret references resolvable');
218
+ }
219
+ }
220
+
221
+ // 8. Exec approvals policy
222
+ const approvals = loadApprovals();
223
+ if (approvals.defaults?.security === 'deny') {
224
+ warnings.push({ id: 'deny-policy', msg: 'Exec approvals: all commands denied' });
225
+ } else if (approvals.defaults?.security === 'allowlist') {
226
+ const entries = Object.values(approvals.agents || {}).reduce((a, ag) => a + (ag.allowlist?.length || 0), 0);
227
+ ok.push(`Exec approvals: allowlist mode (${entries} entries)`);
228
+ } else {
229
+ ok.push('Exec approvals: full mode');
230
+ }
231
+
232
+ // 9. Config backup status
233
+ const { listBackups } = require('../utils/config');
234
+ const backups = listBackups();
235
+ if (backups.length > 0) {
236
+ ok.push(`Config backups: ${backups.length} available`);
237
+ } else {
238
+ warnings.push({ id: 'no-backups', msg: 'No config backups found. Backups are created automatically on config changes.' });
239
+ }
240
+
93
241
  if (json) {
94
242
  console.log(JSON.stringify({ ok, warnings: warnings.map(w => w.msg), issues: issues.map(i => i.msg) }, null, 2));
95
243
  return;
@@ -41,6 +41,12 @@ const LANG = {
41
41
  WhatsApp: 'natureco whatsapp connect',
42
42
  Discord: 'natureco discord connect',
43
43
  Slack: 'natureco slack connect',
44
+ Signal: 'natureco signal connect',
45
+ IRC: 'natureco irc connect',
46
+ Mattermost:'natureco mattermost connect',
47
+ iMessage: 'natureco imessage connect',
48
+ SMS: 'natureco sms connect',
49
+ Webhooks: 'natureco webhooks connect',
44
50
  },
45
51
  // Adım 5
46
52
  gatewayTitle: 'Gateway',
@@ -99,6 +105,12 @@ const LANG = {
99
105
  WhatsApp: 'natureco whatsapp connect',
100
106
  Discord: 'natureco discord connect',
101
107
  Slack: 'natureco slack connect',
108
+ Signal: 'natureco signal connect',
109
+ IRC: 'natureco irc connect',
110
+ Mattermost:'natureco mattermost connect',
111
+ iMessage: 'natureco imessage connect',
112
+ SMS: 'natureco sms connect',
113
+ Webhooks: 'natureco webhooks connect',
102
114
  },
103
115
  // Step 5
104
116
  gatewayTitle: 'Gateway',
@@ -360,6 +372,12 @@ async function setup() {
360
372
  { name: 'WhatsApp', value: 'WhatsApp' },
361
373
  { name: 'Discord', value: 'Discord' },
362
374
  { name: 'Slack', value: 'Slack' },
375
+ { name: 'Signal', value: 'Signal' },
376
+ { name: 'IRC', value: 'IRC' },
377
+ { name: 'Mattermost', value: 'Mattermost' },
378
+ { name: 'iMessage', value: 'iMessage' },
379
+ { name: 'SMS (Twilio)', value: 'SMS' },
380
+ { name: 'Webhooks', value: 'Webhooks' },
363
381
  ],
364
382
  }]);
365
383
 
@@ -425,14 +443,86 @@ async function setup() {
425
443
  printDone(L, 'Discord');
426
444
  }
427
445
 
446
+ if (integrations.includes('Signal')) {
447
+ console.log('');
448
+ console.log(chalk.cyan(' Signal kurulumu (signal-cli REST API):'));
449
+ const { sigUrl, sigAccount } = await inquirer.prompt([
450
+ { type: 'input', name: 'sigUrl', message: lang === 'tr' ? ' signal-cli REST API URL (örn: http://localhost:8080):' : ' signal-cli REST API URL (e.g. http://localhost:8080):', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
451
+ { type: 'input', name: 'sigAccount', message: lang === 'tr' ? ' Signal hesap numarası:' : ' Signal account number:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
452
+ ]);
453
+ const sigBotId = `signal_${Date.now()}`;
454
+ integConfig.signalHttpUrl = sigUrl.trim();
455
+ integConfig.signalAccount = sigAccount.trim();
456
+ integConfig.signalBotId = sigBotId;
457
+ printDone(L, 'Signal');
458
+ }
459
+
460
+ if (integrations.includes('IRC')) {
461
+ console.log('');
462
+ console.log(chalk.cyan(' IRC kurulumu:'));
463
+ const { ircHost, ircPort, ircNick } = await inquirer.prompt([
464
+ { type: 'input', name: 'ircHost', message: lang === 'tr' ? ' IRC sunucusu (örn: irc.libera.chat):' : ' IRC server (e.g. irc.libera.chat):', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
465
+ { type: 'input', name: 'ircPort', message: lang === 'tr' ? ' Port:' : ' Port:', default: '6697' },
466
+ { type: 'input', name: 'ircNick', message: lang === 'tr' ? ' Nick:' : ' Nick:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
467
+ ]);
468
+ integConfig.ircHost = ircHost.trim();
469
+ integConfig.ircPort = parseInt(ircPort) || 6697;
470
+ integConfig.ircNick = ircNick.trim();
471
+ integConfig.ircBotId = `irc_${Date.now()}`;
472
+ printDone(L, 'IRC');
473
+ }
474
+
475
+ if (integrations.includes('Mattermost')) {
476
+ console.log('');
477
+ console.log(chalk.cyan(' Mattermost kurulumu:'));
478
+ const { mmUrl, mmToken } = await inquirer.prompt([
479
+ { type: 'input', name: 'mmUrl', message: lang === 'tr' ? ' Mattermost sunucu URL:' : ' Mattermost server URL:', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
480
+ { type: 'password', name: 'mmToken', message: lang === 'tr' ? ' Bot token:' : ' Bot token:', mask: '*', validate: v => v.trim() ? true : (lang === 'tr' ? 'Gerekli' : 'Required') },
481
+ ]);
482
+ integConfig.mattermostBaseUrl = mmUrl.trim().replace(/\/$/, '');
483
+ integConfig.mattermostToken = mmToken.trim();
484
+ integConfig.mattermostBotId = `mattermost_${Date.now()}`;
485
+ printDone(L, 'Mattermost');
486
+ }
487
+
488
+ if (integrations.includes('iMessage')) {
489
+ console.log('');
490
+ console.log(chalk.cyan(lang === 'tr' ? ' iMessage (sadece macOS):' : ' iMessage (macOS only):'));
491
+ const { imCliPath } = await inquirer.prompt([{ type: 'input', name: 'imCliPath', message: lang === 'tr' ? ' imsg CLI yolu (opsiyonel):' : ' imsg CLI path (optional):' }]);
492
+ integConfig.imessageCliPath = imCliPath.trim() || '';
493
+ integConfig.imessageBotId = `imessage_${Date.now()}`;
494
+ printDone(L, 'iMessage');
495
+ }
496
+
497
+ if (integrations.includes('SMS')) {
498
+ console.log('');
499
+ console.log(chalk.cyan(' SMS (Twilio) kurulumu:'));
500
+ const { smsSid, smsToken, smsFrom } = await inquirer.prompt([
501
+ { type: 'input', name: 'smsSid', message: ' Twilio Account SID:', validate: v => v.trim() ? true : 'Required' },
502
+ { type: 'password', name: 'smsToken', message: ' Twilio Auth Token:', mask: '*', validate: v => v.trim() ? true : 'Required' },
503
+ { type: 'input', name: 'smsFrom', message: ' Twilio telefon numarası (E.164):', validate: v => v.trim() ? true : 'Required' },
504
+ ]);
505
+ integConfig.smsAccountSid = smsSid.trim();
506
+ integConfig.smsAuthToken = smsToken.trim();
507
+ integConfig.smsFromNumber = smsFrom.trim();
508
+ integConfig.smsBotId = `sms_${Date.now()}`;
509
+ printDone(L, 'SMS');
510
+ }
511
+
512
+ if (integrations.includes('Webhooks')) {
513
+ printDone(L, 'Webhooks');
514
+ console.log(chalk.gray(lang === 'tr'
515
+ ? ' → Webhook eklemek için: natureco webhooks connect'
516
+ : ' → To add a webhook: natureco webhooks connect'));
517
+ }
518
+
428
519
  if (integrations.length > 0) {
429
- if (!integrations.includes('Telegram') && !integrations.includes('WhatsApp') && !integrations.includes('Discord')) {
520
+ const subflowChannels = ['Telegram', 'WhatsApp', 'Discord', 'Signal', 'IRC', 'Mattermost', 'iMessage', 'SMS', 'Webhooks'];
521
+ const hasSubflow = subflowChannels.some(ch => integrations.includes(ch));
522
+ if (!hasSubflow) {
430
523
  printDone(L, integrations.join(', '));
431
524
  }
432
525
  console.log('');
433
- if (integrations.includes('Slack')) {
434
- console.log(chalk.gray(` → natureco slack connect`));
435
- }
436
526
  } else {
437
527
  printDone(L, L.integSkip);
438
528
  }
@@ -454,17 +544,31 @@ async function setup() {
454
544
  language: lang,
455
545
  providerUrl,
456
546
  providerApiKey: providerApiKey.trim(),
457
- providerModel,
458
- apiKey: providerApiKey.trim(), // login bypass — chat doğrudan çalışsın
459
- botName: safeBotName,
547
+ botName: safeBotName,
460
548
  userName: userName.trim(),
461
549
  debug: existingConfig.debug || false,
462
550
  skills: existingConfig.skills || { enabled: true, list: [] },
463
551
  mcpServers: existingConfig.mcpServers || {},
464
552
  // Entegrasyon config'leri
465
- ...(integConfig.telegramToken && { telegramToken: integConfig.telegramToken }),
466
- ...(integConfig.telegramChatId && { telegramChatId: integConfig.telegramChatId }),
467
- ...(integConfig.discordToken && { discordToken: integConfig.discordToken }),
553
+ ...(integConfig.telegramToken && { telegramToken: integConfig.telegramToken }),
554
+ ...(integConfig.telegramChatId && { telegramChatId: integConfig.telegramChatId }),
555
+ ...(integConfig.discordToken && { discordToken: integConfig.discordToken }),
556
+ ...(integConfig.signalHttpUrl && { signalHttpUrl: integConfig.signalHttpUrl }),
557
+ ...(integConfig.signalAccount && { signalAccount: integConfig.signalAccount }),
558
+ ...(integConfig.signalBotId && { signalBotId: integConfig.signalBotId }),
559
+ ...(integConfig.ircHost && { ircHost: integConfig.ircHost }),
560
+ ...(integConfig.ircPort && { ircPort: integConfig.ircPort }),
561
+ ...(integConfig.ircNick && { ircNick: integConfig.ircNick }),
562
+ ...(integConfig.ircBotId && { ircBotId: integConfig.ircBotId }),
563
+ ...(integConfig.mattermostBaseUrl && { mattermostBaseUrl: integConfig.mattermostBaseUrl }),
564
+ ...(integConfig.mattermostToken && { mattermostToken: integConfig.mattermostToken }),
565
+ ...(integConfig.mattermostBotId && { mattermostBotId: integConfig.mattermostBotId }),
566
+ ...(integConfig.imessageCliPath && { imessageCliPath: integConfig.imessageCliPath }),
567
+ ...(integConfig.imessageBotId && { imessageBotId: integConfig.imessageBotId }),
568
+ ...(integConfig.smsAccountSid && { smsAccountSid: integConfig.smsAccountSid }),
569
+ ...(integConfig.smsAuthToken && { smsAuthToken: integConfig.smsAuthToken }),
570
+ ...(integConfig.smsFromNumber && { smsFromNumber: integConfig.smsFromNumber }),
571
+ ...(integConfig.smsBotId && { smsBotId: integConfig.smsBotId }),
468
572
  };
469
573
 
470
574
  saveConfig(config);