natureco-cli 5.6.20 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "natureco-cli",
3
- "version": "5.6.20",
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"
@@ -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 + "\n Devam edilsin mi? (Y/n) "), ans => {
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
- // Approval for dangerous tools
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
- if (dangerous.includes(tc.function.name)) {
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(tc.function.name + " çalıştırılsın mı?");
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
- printToolCall(name, args, result);
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));
@@ -886,7 +886,14 @@ async function startRepl(args) {
886
886
  const resultStr = typeof toolEvent.result.result === 'string'
887
887
  ? toolEvent.result.result.slice(0, 200)
888
888
  : JSON.stringify(toolEvent.result.result).slice(0, 200);
889
- console.log(tui.styled(' ✓ Sonuç: ' + resultStr, { color: tui.PALETTE.success }));
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 }));
890
897
  }
891
898
  process.stdout.write(tui.styled(' AI ', { color: tui.PALETTE.secondary, bold: true }));
892
899
  }