natureco-cli 4.5.0 → 4.5.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "4.5.0",
3
+ "version": "4.5.2",
4
4
  "description": "OpenClaw'dan daha güvenli, daha hızlı, daha ucuz AI agent CLI. Multi-agent, self-evolving skills, audit log, maliyet optimizasyonu ve NatureCo platform-native.",
5
5
  "bin": {
6
6
  "natureco": "bin/natureco.js"
@@ -1,4 +1,5 @@
1
1
  const chalk = require('chalk');
2
+ const tui = require('../utils/tui');
2
3
  const F = require('../utils/format');
3
4
  const fs = require('fs');
4
5
  const path = require('path');
@@ -138,18 +139,21 @@ async function addCron(options) {
138
139
 
139
140
  function listCrons() {
140
141
  const crons = loadCrons();
141
-
142
+
142
143
  if (crons.length === 0) {
143
- F.header('Cron Jobs');
144
- F.meta('Kayıtlı cron yok');
144
+ console.log('\n' + tui.styled(' ⏰ Zamanlanmış Görevler', { color: tui.PALETTE.primary, bold: true }));
145
+ console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
146
+ console.log('\n ' + tui.C.muted('Henüz cron tanımlı değil. Eklemek için:'));
147
+ console.log(' ' + tui.C.brand('natureco cron add --name "görev" --schedule "0 9 * * *" --action telegram --prompt "..."'));
148
+ console.log('');
145
149
  return;
146
150
  }
147
-
151
+
148
152
  const { getConfig } = require('../utils/config');
149
153
  const config = getConfig();
150
154
  const defaultWhatsappTarget = normalizeWhatsAppNumber(config.whatsappPhone) || 'N/A';
151
155
  const defaultTelegramTarget = (config.telegramAllowedChats && config.telegramAllowedChats[0]) || 'N/A';
152
-
156
+
153
157
  const runs = loadRuns();
154
158
  const rows = crons.map(c => {
155
159
  let target = c.target;
@@ -160,15 +164,32 @@ function listCrons() {
160
164
  }
161
165
  const cronRuns = runs.filter(r => r.name === c.name);
162
166
  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
- ];
167
+ return {
168
+ name: c.name,
169
+ schedule: c.schedule,
170
+ status: c.enabled,
171
+ target,
172
+ lastRun: lastRun ? lastRun.timestamp.slice(0, 16).replace('T', ' ') : '—',
173
+ };
169
174
  });
170
- F.header('Cron Jobs');
171
- F.table(['Name', 'Schedule', 'Status', 'LastRun'], rows);
175
+
176
+ console.log('\n' + tui.styled(' ⏰ Zamanlanmış Görevler (' + crons.length + ')', { color: tui.PALETTE.primary, bold: true }));
177
+ console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
178
+
179
+ console.log('\n' + tui.table(rows, [
180
+ { key: 'name', label: 'İsim', minWidth: 20, render: r => tui.styled(r.name, { color: tui.PALETTE.primary, bold: true }) },
181
+ { key: 'schedule', label: 'Zamanlama', minWidth: 18, render: r => tui.C.muted(r.schedule) },
182
+ {
183
+ key: 'status', label: 'Durum', minWidth: 10,
184
+ render: r => r.status
185
+ ? tui.styled(' ✓ Aktif ', { bg: tui.PALETTE.success, color: '#000', bold: true })
186
+ : tui.styled(' ✗ Pasif ', { bg: tui.PALETTE.muted, color: '#000', bold: true }),
187
+ },
188
+ { key: 'target', label: 'Hedef', minWidth: 18, render: r => tui.C.text(r.target) },
189
+ { key: 'lastRun', label: 'Son Çalışma', minWidth: 18, render: r => tui.C.muted(r.lastRun) },
190
+ ], { borderStyle: 'round', zebra: true }));
191
+
192
+ console.log('');
172
193
  }
173
194
 
174
195
  function removeCron(options) {
@@ -238,16 +238,33 @@ function runCheck(name) {
238
238
 
239
239
  case 'secretsClean': {
240
240
  try {
241
- // Mevcut çalışma dizinini tara — secret var mı?
242
- const findings = secrets.scanDir(process.cwd());
243
- const critical = findings.filter(f => f.severity === 'critical' || f.severity === 'high');
244
- if (critical.length === 0) {
245
- return { pass: true, message: 'Çalışma dizininde secret bulunamadı ✓' };
241
+ // Mevcut çalışma dizinini tara — sadece kritik bulguları rapor et
242
+ // Whitelist: .git, node_modules, .DS_Store, dist, build, *.md (dokümanlar),
243
+ // *.example, *.test, package-lock.json, audit-*.jsonl
244
+ // SKIP_DIRS secret-scanner.js'de zaten var (.git, node_modules, dist, build)
245
+ // Ama .DS_Store, .env.example gibi dosyaları atlamamız gerek
246
+ const findings = secrets.scanDir(process.cwd(), { maxFiles: 500 });
247
+ // False positive azaltma: sadece severity critical VEYA (.env/.key/secret içeren dosyalar)
248
+ const realSecrets = findings.filter(f => {
249
+ // .DS_Store, .md, .txt gibi dokümanları atla
250
+ const fname = (f.file || '').toLowerCase();
251
+ if (fname.endsWith('.md') || fname.endsWith('.txt')) return false;
252
+ if (fname.includes('.ds_store') || fname.includes('package-lock')) return false;
253
+ if (fname.includes('changelog') || fname.includes('readme')) return false;
254
+ // 'high' severity çoğunlukla false positive (40-char hex gibi)
255
+ // Sadece 'critical' VEYA bilinen provider pattern'i kabul et
256
+ if (f.severity === 'critical') return true;
257
+ // .env dosyalarında yüksek severity kabul
258
+ if (fname.includes('.env') && !fname.includes('.example')) return true;
259
+ return false;
260
+ });
261
+ if (realSecrets.length === 0) {
262
+ return { pass: true, message: 'Çalışma dizininde gerçek secret bulunamadı ✓' };
246
263
  }
247
- const sample = critical.slice(0, 3).map(f => `${f.type}@${path.basename(f.file || '?')}`).join(', ');
264
+ const sample = realSecrets.slice(0, 3).map(f => `${f.type}@${path.basename(f.file || '?')}`).join(', ');
248
265
  return {
249
266
  pass: false,
250
- message: `${critical.length} potansiyel secret: ${sample}${critical.length > 3 ? '...' : ''}`,
267
+ message: `${realSecrets.length} gerçek secret: ${sample}${realSecrets.length > 3 ? '...' : ''}`,
251
268
  };
252
269
  } catch (e) {
253
270
  return { pass: false, message: e.message };