natureco-cli 5.6.19 → 5.6.21
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/code_v5.js +157 -6
- package/src/commands/repl.js +12 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.6.
|
|
3
|
+
"version": "5.6.21",
|
|
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/code_v5.js
CHANGED
|
@@ -81,13 +81,159 @@ async function sendMessageWithTools(providerUrl, providerKey, model, messages, t
|
|
|
81
81
|
function confirm(prompt) {
|
|
82
82
|
return new Promise(resolve => {
|
|
83
83
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
84
|
-
rl.question(chalk.yellow("\n ⚠ " + prompt + "
|
|
84
|
+
rl.question(chalk.yellow("\n ⚠ " + prompt + " "), ans => {
|
|
85
85
|
rl.close();
|
|
86
86
|
resolve(!ans || ans.toLowerCase().startsWith("y"));
|
|
87
87
|
});
|
|
88
88
|
});
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* v5.6.21: Risk seviyesi tespiti - sadece riskli işlemlerde onay iste
|
|
93
|
+
* @param {string} tool - tool adı
|
|
94
|
+
* @param {object} args - tool parametreleri
|
|
95
|
+
* @returns {{requiresApproval: boolean, reason: string, level: string}}
|
|
96
|
+
*/
|
|
97
|
+
function assessRisk(tool, args) {
|
|
98
|
+
const argsStr = JSON.stringify(args || {});
|
|
99
|
+
|
|
100
|
+
// ============================================================
|
|
101
|
+
// YÜKSEK RİSK - Mutlaka onay iste
|
|
102
|
+
// ============================================================
|
|
103
|
+
|
|
104
|
+
// bash / shell_command: Tehlikeli komutlar
|
|
105
|
+
if (tool === "bash" || tool === "shell_command") {
|
|
106
|
+
const cmd = (args.command || args.cmd || "").toLowerCase();
|
|
107
|
+
|
|
108
|
+
// Dosya/klasör silme
|
|
109
|
+
if (/\brm\s+(-[rf]+\s+)*/.test(cmd) || /rmdir/.test(cmd)) {
|
|
110
|
+
return { requiresApproval: true, level: "high", reason: `Dosya silme komutu: ${args.command}` };
|
|
111
|
+
}
|
|
112
|
+
if (cmd.includes("sudo ") || cmd.includes("doas ")) {
|
|
113
|
+
return { requiresApproval: true, level: "high", reason: `Yetki yükseltme: ${args.command}` };
|
|
114
|
+
}
|
|
115
|
+
if (cmd.includes("dd if=") || cmd.includes("mkfs") || cmd.includes("fdisk")) {
|
|
116
|
+
return { requiresApproval: true, level: "high", reason: `Disk işlemi: ${args.command}` };
|
|
117
|
+
}
|
|
118
|
+
if (cmd.match(/^\s*mv\s+.*\/(?:\.|\.\.)/)) {
|
|
119
|
+
return { requiresApproval: true, level: "medium", reason: `Üzerine yazma riski: ${args.command}` };
|
|
120
|
+
}
|
|
121
|
+
// chmod 777 veya chown -R
|
|
122
|
+
if (/chmod\s+(-[rR]+\s+)*777/.test(cmd) || /chown\s+-R/.test(cmd)) {
|
|
123
|
+
return { requiresApproval: true, level: "medium", reason: `İzin değişikliği: ${args.command}` };
|
|
124
|
+
}
|
|
125
|
+
// git push --force
|
|
126
|
+
if (/git\s+push.*--force/.test(cmd) || /git\s+push.*-f\s/.test(cmd)) {
|
|
127
|
+
return { requiresApproval: true, level: "high", reason: `Zorla push: ${args.command}` };
|
|
128
|
+
}
|
|
129
|
+
// git reset --hard
|
|
130
|
+
if (/git\s+reset\s+--hard/.test(cmd)) {
|
|
131
|
+
return { requiresApproval: true, level: "high", reason: `Hard reset: ${args.command}` };
|
|
132
|
+
}
|
|
133
|
+
// Üretim/kök dizin
|
|
134
|
+
if (cmd.includes("/etc/") || cmd.includes("/usr/") || cmd.includes("/var/") || cmd.includes("/System/")) {
|
|
135
|
+
return { requiresApproval: true, level: "high", reason: `Sistem dizinine erişim: ${args.command}` };
|
|
136
|
+
}
|
|
137
|
+
// curl/wget internet download
|
|
138
|
+
if (/curl.*\|\s*(bash|sh)/.test(cmd) || /wget.*\|\s*(bash|sh)/.test(cmd)) {
|
|
139
|
+
return { requiresApproval: true, level: "high", reason: `İnternet üzerinden script çalıştırma: ${args.command}` };
|
|
140
|
+
}
|
|
141
|
+
// mac_app_quit veya killall
|
|
142
|
+
if (cmd.includes("killall") || cmd.includes("pkill") || cmd.includes("kill -9")) {
|
|
143
|
+
return { requiresApproval: true, level: "high", reason: `Süreç sonlandırma: ${args.command}` };
|
|
144
|
+
}
|
|
145
|
+
// .natureco veya önemli dosyalara dokunma
|
|
146
|
+
if (cmd.includes(".natureco") && (cmd.includes("rm") || cmd.includes("mv"))) {
|
|
147
|
+
return { requiresApproval: true, level: "high", reason: `NatureCo dizininde tehlikeli işlem: ${args.command}` };
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ============================================================
|
|
152
|
+
// ORTA RİSK - Onay iste (bilgilendir)
|
|
153
|
+
// ============================================================
|
|
154
|
+
|
|
155
|
+
// mac_app_quit - uygulama kapatma
|
|
156
|
+
if (tool === "mac_app_quit") {
|
|
157
|
+
return { requiresApproval: true, level: "medium", reason: `Uygulama kapatma: ${args.app || args.name || "?"}` };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// write_file / edit_file - kritik yollara yazma
|
|
161
|
+
if (tool === "write_file" || tool === "edit_file") {
|
|
162
|
+
const path = (args.path || args.file || "").toLowerCase();
|
|
163
|
+
// Hassas dosyalar
|
|
164
|
+
if (path.includes(".env") || path.includes("credentials") || path.includes("secret")) {
|
|
165
|
+
return { requiresApproval: true, level: "high", reason: `Hassas dosya: ${args.path}` };
|
|
166
|
+
}
|
|
167
|
+
if (path.includes("/etc/") || path.includes("/usr/") || path.includes("~/.ssh/")) {
|
|
168
|
+
return { requiresApproval: true, level: "high", reason: `Sistem dosyası: ${args.path}` };
|
|
169
|
+
}
|
|
170
|
+
if (path.includes(".natureco/config.json") || path.includes(".natureco/soul/")) {
|
|
171
|
+
return { requiresApproval: true, level: "medium", reason: `NatureCo config dosyası: ${args.path}` };
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ============================================================
|
|
176
|
+
// GÜVENLİ - Onay isteme
|
|
177
|
+
// ============================================================
|
|
178
|
+
|
|
179
|
+
// Normal tool'lar (read_file, list_dir, grep_search, vs.)
|
|
180
|
+
return { requiresApproval: false, level: "low", reason: "" };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* v5.6.21: Tool call sonucunu güvenli yazdir - yol/size gizle
|
|
186
|
+
* Sadece status, success/error ve kisaltilmis onizleme gosterir
|
|
187
|
+
*/
|
|
188
|
+
function printToolCallSafe(name, args, result) {
|
|
189
|
+
console.log(" " + tui.styled("🔧 Tool: " + name, { color: tui.PALETTE.accent, bold: true }));
|
|
190
|
+
// Args'dan sadece ana bilgiyi goster
|
|
191
|
+
const argsShort = summarizeArgs(name, args);
|
|
192
|
+
if (argsShort) {
|
|
193
|
+
console.log(tui.styled(" Args: " + argsShort, { color: tui.PALETTE.muted }));
|
|
194
|
+
}
|
|
195
|
+
// Result'tan sadece status goster, yol/size gizle
|
|
196
|
+
if (!result) return;
|
|
197
|
+
if (result.error) {
|
|
198
|
+
console.log(tui.styled(" ✗ Hata: " + result.error.slice(0, 100), { color: tui.PALETTE.danger }));
|
|
199
|
+
} else {
|
|
200
|
+
const success = result.success !== false;
|
|
201
|
+
const resultStr = typeof result.result === "string"
|
|
202
|
+
? result.result.slice(0, 200)
|
|
203
|
+
: JSON.stringify(result.result || {}).slice(0, 200);
|
|
204
|
+
// Yol/size gizle
|
|
205
|
+
const cleanResult = resultStr
|
|
206
|
+
.replace(/\/?Users\/[^"\\\s]+/g, "~")
|
|
207
|
+
.replace(/\/?home\/[^"\\\s]+/g, "~")
|
|
208
|
+
.replace(/"\w:\\\[^"\\\s]*/g, "...")
|
|
209
|
+
.replace(/"size":\d+/g, "")
|
|
210
|
+
.replace(/"path":"[^"]*"/g, "")
|
|
211
|
+
.replace(/"fileCount":\d+/g, "");
|
|
212
|
+
const statusIcon = success ? "✓" : "✗";
|
|
213
|
+
const statusColor = success ? tui.PALETTE.success : tui.PALETTE.danger;
|
|
214
|
+
console.log(tui.styled(` ${statusIcon} Sonuç: ${cleanResult.trim()}`, { color: statusColor }));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Tool args'dan ana bilgiyi özetle
|
|
220
|
+
*/
|
|
221
|
+
function summarizeArgs(name, args) {
|
|
222
|
+
if (!args || Object.keys(args).length === 0) return null;
|
|
223
|
+
// Path varsa ~ olarak kisalt
|
|
224
|
+
if (args.path) {
|
|
225
|
+
const shortPath = (args.path || "")
|
|
226
|
+
.replace(/\/Users\/[^\/]+/g, "~")
|
|
227
|
+
.replace(/\/home\/[^\/]+/g, "~")
|
|
228
|
+
.replace(/^[A-Z]:\\Users\\[^\\]+/, "~");
|
|
229
|
+
return JSON.stringify({...args, path: shortPath}).slice(0, 120);
|
|
230
|
+
}
|
|
231
|
+
if (args.command) {
|
|
232
|
+
return JSON.stringify({command: args.command.slice(0, 80)}).slice(0, 120);
|
|
233
|
+
}
|
|
234
|
+
return JSON.stringify(args).slice(0, 120);
|
|
235
|
+
}
|
|
236
|
+
|
|
91
237
|
function printToolCall(name, args, result) {
|
|
92
238
|
const argsStr = JSON.stringify(args).slice(0, 100);
|
|
93
239
|
console.log("\n " + tui.styled(" 🔧 Tool: " + name, { color: tui.PALETTE.accent, bold: true }));
|
|
@@ -215,13 +361,17 @@ async function codeV5(targetPath) {
|
|
|
215
361
|
}
|
|
216
362
|
|
|
217
363
|
if (reply.tool_calls && reply.tool_calls.length > 0) {
|
|
218
|
-
//
|
|
364
|
+
// v5.6.21: Akıllı onay - sadece riskli işlemlerde onay iste
|
|
219
365
|
let approved = true;
|
|
220
|
-
const dangerous = ["bash", "write_file", "edit_file", "mac_app_quit"];
|
|
221
366
|
for (const tc of reply.tool_calls) {
|
|
222
|
-
|
|
367
|
+
let args = {};
|
|
368
|
+
try { args = JSON.parse(tc.function.arguments || "{}"); } catch {}
|
|
369
|
+
const risk = assessRisk(tc.function.name, args);
|
|
370
|
+
if (risk.requiresApproval) {
|
|
223
371
|
process.stdout.write("\n");
|
|
224
|
-
approved = await confirm(
|
|
372
|
+
approved = await confirm(
|
|
373
|
+
`⚠ ${tc.function.name}: ${risk.reason}\n Devam edilsin mi? (Y/n) `
|
|
374
|
+
);
|
|
225
375
|
if (!approved) break;
|
|
226
376
|
}
|
|
227
377
|
}
|
|
@@ -239,7 +389,8 @@ async function codeV5(targetPath) {
|
|
|
239
389
|
if (name === "bash" || name === "shell_command") commandsRun++;
|
|
240
390
|
if (name === "write_file" || name === "edit_file") filesChanged++;
|
|
241
391
|
const result = await executeTool(name, args, toolDefs);
|
|
242
|
-
|
|
392
|
+
// v5.6.21: Sonuç gizleme - sadece status goster, yol/size gizle
|
|
393
|
+
printToolCallSafe(name, args, result);
|
|
243
394
|
const out = result.error
|
|
244
395
|
? "ERROR: " + result.error
|
|
245
396
|
: (typeof result.result === "string" ? result.result : JSON.stringify(result.result));
|
package/src/commands/repl.js
CHANGED
|
@@ -464,8 +464,10 @@ async function startRepl(args) {
|
|
|
464
464
|
// Memory yükle
|
|
465
465
|
let memory = loadMemory(cfg.userName);
|
|
466
466
|
|
|
467
|
-
// v5.
|
|
468
|
-
if (!memory.botName)
|
|
467
|
+
// v5.6.19: Oncelik config.botName, sonra memory.botName
|
|
468
|
+
if (!memory.botName) {
|
|
469
|
+
memory.botName = cfg.botName || 'İchigo';
|
|
470
|
+
}
|
|
469
471
|
// BotName'i memory'ye persist et (her oturumda ayni kalsin)
|
|
470
472
|
try {
|
|
471
473
|
const fs = require('fs');
|
|
@@ -884,7 +886,14 @@ async function startRepl(args) {
|
|
|
884
886
|
const resultStr = typeof toolEvent.result.result === 'string'
|
|
885
887
|
? toolEvent.result.result.slice(0, 200)
|
|
886
888
|
: JSON.stringify(toolEvent.result.result).slice(0, 200);
|
|
887
|
-
|
|
889
|
+
// v5.6.21: Yol gizleme
|
|
890
|
+
const cleanResult = (resultStr || '')
|
|
891
|
+
.replace(/\/?Users\/[^"\s]+/g, '~')
|
|
892
|
+
.replace(/\/?home\/[^"\s]+/g, '~')
|
|
893
|
+
.replace(/"size":\d+/g, '')
|
|
894
|
+
.replace(/"path":"[^"]*"/g, '')
|
|
895
|
+
.replace(/"fileCount":\d+/g, '');
|
|
896
|
+
console.log(tui.styled(' ✓ Sonuç: ' + cleanResult.trim(), { color: tui.PALETTE.success }));
|
|
888
897
|
}
|
|
889
898
|
process.stdout.write(tui.styled(' AI ', { color: tui.PALETTE.secondary, bold: true }));
|
|
890
899
|
}
|