natureco-cli 5.22.0 → 5.23.0
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/tools/workflow.js +79 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to NatureCo CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [5.23.0] - 2026-07-02 — "NON-TOOL-CALLING FIX" (MiniMax dosya yazma)
|
|
6
|
+
|
|
7
|
+
### 🐛 Düzeltme
|
|
8
|
+
- **MiniMax (non-tool-calling) dosya oluşturamıyordu**: workflow non-tool-calling path'inde simple/complex ayrımı yoktu — LLM yanıtını doğrudan sohbete yazıp geçiyordu. Artık complex görevlerde LLM'den JSON plan istenir, dosyalar Node.js tarafında yazılır.
|
|
9
|
+
|
|
10
|
+
## [5.22.0] - 2026-07-02
|
|
11
|
+
|
|
5
12
|
## [5.21.0] - 2026-07-02 — "GÜVENİLİRLİK SPRİNTİ" (gerçek API E2E denetimi)
|
|
6
13
|
|
|
7
14
|
Gerçek MiniMax API anahtarıyla uçtan uca canlı test turu; bulunan her hata düzeltilip yine canlı doğrulandı. 461 test yeşil.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.23.0",
|
|
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/tools/workflow.js
CHANGED
|
@@ -126,14 +126,88 @@ async function workflow(params) {
|
|
|
126
126
|
if (action === 'run') {
|
|
127
127
|
if (!task) return { success: false, error: 'task gerekli' };
|
|
128
128
|
|
|
129
|
-
// Non-tool-calling modellerde
|
|
129
|
+
// Non-tool-calling modellerde once simple/complex kontrolu yap
|
|
130
130
|
if (!supportsToolCalls()) {
|
|
131
131
|
const memCtx = memoryContext();
|
|
132
|
-
|
|
133
|
-
const
|
|
132
|
+
// Phase 0: Check if simple chat or complex task
|
|
133
|
+
const simpleCheckPrompt = {
|
|
134
|
+
role: 'system',
|
|
135
|
+
content: 'Gorevin basit bir selamlasma/sohbet mi yoksa arac gerektiren bir islem mi oldugunu belirle. Sadece "simple" veya "complex" yaz, kesinlikle baska bir sey yazma.\n\nSimple: selamlasma, nasilsin, bugun ne yaptin, havadan sudan, genel bilgi sorusu, ben kimim, adim ne, kullanici bilgisi sorgulama, hatirlatma talebi\nComplex: dosya islemleri, kod yazma, arastirma, karsilastirma, duzenleme, otomasyon'
|
|
136
|
+
};
|
|
137
|
+
let isComplex = true;
|
|
134
138
|
try {
|
|
135
|
-
const
|
|
136
|
-
const
|
|
139
|
+
const checkBody = { model, stream: false, messages: [simpleCheckPrompt, { role: 'user', content: task }], temperature: 0, max_tokens: 20 };
|
|
140
|
+
const checkResult = await apiCall(providerUrl, providerApiKey, checkBody);
|
|
141
|
+
const raw = (checkResult.choices?.[0]?.message?.content || '').trim().toLowerCase().replace(/[^a-z]/g, '');
|
|
142
|
+
isComplex = raw !== 'simple';
|
|
143
|
+
} catch {}
|
|
144
|
+
|
|
145
|
+
if (!isComplex) {
|
|
146
|
+
// Simple chat — passthrough
|
|
147
|
+
const sysMsg = 'Sen yardimci bir asistansin. Kisa ve oz yanit ver. Konusma gecmisi varsa onceki mesajlari dikkate al.' + (memCtx ? '\n\nKullanici bilgisi:\n' + memCtx : '') + '\n\n' + skillsIndexBlock;
|
|
148
|
+
const chatBody = { model, stream: false, messages: chatMessages(sysMsg, task), temperature: 0.7, max_tokens: 1000 };
|
|
149
|
+
try {
|
|
150
|
+
const chatResult = await apiCall(providerUrl, providerApiKey, chatBody);
|
|
151
|
+
const reply = chatResult.choices?.[0]?.message?.content || '';
|
|
152
|
+
return { success: true, workflowId: 'passthrough', name: 'Direct Chat', status: 'completed', totalSteps: 0, completedSteps: 0, results: [], passthrough: true, reply };
|
|
153
|
+
} catch (e) {
|
|
154
|
+
return { success: false, error: 'Sohbet yaniti alinamadi: ' + e.message };
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Complex task for non-tool-calling model: ask LLM for structured file ops
|
|
159
|
+
const execSysMsg = 'Gorevi tamamlamak icin hangi dosyalarin olusturulacagini JSON olarak belirt. SADECE JSON yaz.\n\n' +
|
|
160
|
+
'Kullanici bilgisi:\n' + (memCtx || '') +
|
|
161
|
+
'\n\nMasaustu yolu: ' + require('path').join(require('os').homedir(), 'Desktop') +
|
|
162
|
+
'\n\nKullanici home: ' + require('os').homedir() +
|
|
163
|
+
'\n\nJSON format:\n{"files": [{"path": "/tam/dosya/yolu/dosya.html", "content": "dosya icerigi buraya"}]}\n\nHer dosya icin path ve content zorunlu. path TAM yol olmali (~ veya goreceli degil). Birden fazla dosya olusturulabilir.' +
|
|
164
|
+
'\n\n' + skillsIndexBlock;
|
|
165
|
+
const execBody = { model, stream: false, messages: chatMessages(execSysMsg, task), temperature: 0.3, max_tokens: 8000 };
|
|
166
|
+
try {
|
|
167
|
+
const execResult = await apiCall(providerUrl, providerApiKey, execBody);
|
|
168
|
+
const reply = execResult.choices?.[0]?.message?.content || '';
|
|
169
|
+
|
|
170
|
+
// Try to extract JSON with file operations
|
|
171
|
+
const jsonStart = reply.indexOf('{');
|
|
172
|
+
const jsonEnd = reply.lastIndexOf('}');
|
|
173
|
+
let stepResults = [];
|
|
174
|
+
let fileWriteSuccess = false;
|
|
175
|
+
|
|
176
|
+
if (jsonStart !== -1 && jsonEnd > jsonStart) {
|
|
177
|
+
try {
|
|
178
|
+
const plan = JSON.parse(reply.slice(jsonStart, jsonEnd + 1));
|
|
179
|
+
if (plan.files && Array.isArray(plan.files)) {
|
|
180
|
+
// Execute file writes locally
|
|
181
|
+
for (const f of plan.files) {
|
|
182
|
+
try {
|
|
183
|
+
const wfPath = f.path ? require('path').resolve(f.path.replace(/^~/, require('os').homedir())) : '';
|
|
184
|
+
if (!wfPath) continue;
|
|
185
|
+
require('fs').mkdirSync(require('path').dirname(wfPath), { recursive: true });
|
|
186
|
+
require('fs').writeFileSync(wfPath, f.content || '', 'utf-8');
|
|
187
|
+
const stats = require('fs').statSync(wfPath);
|
|
188
|
+
stepResults.push({ step: 1, tool: 'write_file', status: 'done', args: { path: wfPath }, result: { success: true, path: wfPath, size: stats.size } });
|
|
189
|
+
fileWriteSuccess = true;
|
|
190
|
+
} catch (wfErr) {
|
|
191
|
+
stepResults.push({ step: 1, tool: 'write_file', status: 'error', error: wfErr.message });
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} catch {}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (fileWriteSuccess) {
|
|
199
|
+
const lines = stepResults.map(r => { const p = r.result?.path || ''; const s = r.result?.size || 0; const name = require('path').basename(p); return ` ✓ ${name} oluşturuldu (${s} bytes)`; }).join('\n');
|
|
200
|
+
const reply = `Dosya(lar) başarıyla oluşturuldu:\n${lines}`;
|
|
201
|
+
return {
|
|
202
|
+
success: true, workflowId: 'file_write_' + Date.now().toString(36),
|
|
203
|
+
name: 'File Operations', status: 'completed',
|
|
204
|
+
totalSteps: stepResults.length, completedSteps: stepResults.length,
|
|
205
|
+
results: stepResults,
|
|
206
|
+
passthrough: true, reply,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// If no structured file ops detected, return LLM reply as passthrough
|
|
137
211
|
return { success: true, workflowId: 'passthrough', name: 'Direct Generation', status: 'completed', totalSteps: 0, completedSteps: 0, results: [{ step: 0, tool: 'chat', status: 'done', result: { reply } }], passthrough: true, reply };
|
|
138
212
|
} catch (e) {
|
|
139
213
|
return { success: false, error: 'Yanit alinamadi: ' + e.message };
|