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 +1 -1
- package/src/commands/cron.js +34 -13
- package/src/commands/doctor.js +24 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "4.5.
|
|
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"
|
package/src/commands/cron.js
CHANGED
|
@@ -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
|
-
|
|
144
|
-
|
|
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
|
|
167
|
-
|
|
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
|
-
|
|
171
|
-
|
|
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) {
|
package/src/commands/doctor.js
CHANGED
|
@@ -238,16 +238,33 @@ function runCheck(name) {
|
|
|
238
238
|
|
|
239
239
|
case 'secretsClean': {
|
|
240
240
|
try {
|
|
241
|
-
// Mevcut çalışma dizinini tara —
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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 =
|
|
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: `${
|
|
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 };
|