natureco-cli 5.14.0 → 5.14.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": "5.14.0",
3
+ "version": "5.14.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"
@@ -1029,9 +1029,15 @@ async function startRepl(args) {
1029
1029
  messages[0] = { role: 'system', content: systemPrompt, _internal: true };
1030
1030
 
1031
1031
  // v5.13.0: Run workflow FIRST for every request
1032
+ process.stdout.write(tui.styled('\r 🔧 workflow... ', { color: tui.PALETTE.muted }));
1032
1033
  const wfToolDefs = getToolDefs();
1033
1034
  const wfResult = await executeTool('workflow', { action: 'run', task: line }, wfToolDefs);
1034
1035
  const wf = wfResult?.result || {};
1036
+ if (wf.success !== false) {
1037
+ process.stdout.write(tui.styled(' ✓ workflow\n', { color: tui.PALETTE.success }));
1038
+ } else {
1039
+ process.stdout.write(tui.styled(' ✗ workflow\n', { color: tui.PALETTE.danger }));
1040
+ }
1035
1041
 
1036
1042
  if (wf.passthrough && wf.reply) {
1037
1043
  // Simple chat — workflow handled it directly
@@ -73,14 +73,14 @@ async function workflow(params) {
73
73
  // Phase 0: Check if simple chat (passthrough) — no planning needed
74
74
  const simpleCheckPrompt = {
75
75
  role: 'system',
76
- content: 'Gorevin basit bir selamlasma/sohbet mi yoksa arac gerektiren bir islem mi oldugunu belirle. Sadece "simple" veya "complex" yaz, baska bir sey yazma.\n\nSimple: selamlasma, nasilsin, bugun ne yaptin, havadan sudan, genel bilgi sorusu\nComplex: dosya islemleri, kod yazma, arastirma, karsilastirma, duzenleme, otomasyon, proje yonetimi, debug'
76
+ 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. Noktalama isareti koyma.\n\nSimple: selamlasma, nasilsin, bugun ne yaptin, havadan sudan, genel bilgi sorusu\nComplex: dosya islemleri, kod yazma, arastirma, karsilastirma, duzenleme, otomasyon, proje yonetimi, debug'
77
77
  };
78
- const simpleBody = { model, stream: false, messages: [simpleCheckPrompt, { role: 'user', content: task }], temperature: 0, max_tokens: 10 };
78
+ const simpleBody = { model, stream: false, messages: [simpleCheckPrompt, { role: 'user', content: task }], temperature: 0, max_tokens: 20 };
79
79
  let isSimple = false;
80
80
  try {
81
81
  const simpleResult = await apiCall(providerUrl, providerApiKey, simpleBody);
82
- const simpleAnswer = (simpleResult.choices?.[0]?.message?.content || '').trim().toLowerCase();
83
- isSimple = simpleAnswer === 'simple';
82
+ const raw = (simpleResult.choices?.[0]?.message?.content || '').trim().toLowerCase().replace(/[^a-z]/g, '');
83
+ isSimple = raw === 'simple';
84
84
  } catch {}
85
85
 
86
86
  if (isSimple) {
@@ -115,11 +115,29 @@ async function workflow(params) {
115
115
  return { success: false, error: 'Plan olusturulamadi: ' + e.message, phase: 'planning' };
116
116
  }
117
117
 
118
+ // v5.14.2: Brace-balanced JSON extraction (handles explanatory text around JSON)
119
+ function extractJSON(str) {
120
+ const start = str.indexOf('{');
121
+ if (start === -1) return null;
122
+ let depth = 0, inString = false, escape = false;
123
+ for (let i = start; i < str.length; i++) {
124
+ const ch = str[i];
125
+ if (escape) { escape = false; continue; }
126
+ if (ch === '\\' && inString) { escape = true; continue; }
127
+ if (ch === '"') { inString = !inString; continue; }
128
+ if (!inString) {
129
+ if (ch === '{') depth++;
130
+ else if (ch === '}') { depth--; if (depth === 0) return str.slice(start, i + 1); }
131
+ }
132
+ }
133
+ return null;
134
+ }
118
135
  let plan;
119
136
  try {
120
137
  const content = planResult.choices?.[0]?.message?.content || '';
121
- const jsonMatch = content.match(/\{[\s\S]*\}/);
122
- plan = JSON.parse(jsonMatch ? jsonMatch[0] : content);
138
+ const jsonStr = extractJSON(content);
139
+ if (!jsonStr) throw new Error('JSON bloku bulunamadi');
140
+ plan = JSON.parse(jsonStr);
123
141
  if (!plan.steps || !Array.isArray(plan.steps)) throw new Error('Steps bulunamadi');
124
142
  } catch (e) {
125
143
  return { success: false, error: 'Plan cozumlenemedi: ' + e.message, raw: planResult.choices?.[0]?.message?.content?.slice(0, 500) };