natureco-cli 5.64.6 → 5.64.7
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 +10 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/tools/computer_use_loop.js +39 -13
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to NatureCo CLI will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [5.64.7] - 2026-07-13 — Resilient GUI vision decisions
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- GUI actions now validate required coordinates, text, and keys before generating macOS AppleScript, preventing `undefined değişkeni tanımlanmamış` failures.
|
|
9
|
+
- Truncated, malformed, empty, or Markdown-wrapped vision JSON is handled safely; invalid decisions trigger another visual-analysis step instead of crashing the GUI loop.
|
|
10
|
+
- The independent completion verifier now treats malformed JSON as failed evidence rather than throwing.
|
|
11
|
+
|
|
12
|
+
### Tests
|
|
13
|
+
- Added regressions for missing GUI parameters, Markdown JSON responses, and the exact unterminated-string response reported with MiniMax vision.
|
|
14
|
+
|
|
5
15
|
## [5.64.6] - 2026-07-13 — Typed MiniMax tool arguments
|
|
6
16
|
|
|
7
17
|
### Fixed
|
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ natureco code
|
|
|
51
51
|
|
|
52
52
|
| Version | Highlights |
|
|
53
53
|
|---------|-----------|
|
|
54
|
+
| **v5.64.7** | **Resilient GUI vision:** invalid action parameters and truncated vision JSON are rejected safely and retried instead of crashing macOS automation. |
|
|
54
55
|
| **v5.64.6** | **Reliable MiniMax tool calls:** XML parameters are converted to their declared schema types, fixing `computer_use_loop` failures such as `maxSteps: expected number, got string`. |
|
|
55
56
|
| **v5.64.5** | **Deterministic GUI recovery:** visible web tasks use one verified GUI loop; failures expose their concrete reason and stop blind browser/AppleScript fallback chains. |
|
|
56
57
|
| **v5.64.4** | **Unified MiniMax media:** the existing MiniMax key now powers `MiniMax-VL-01` analysis, `image-01` generation, `MiniMax-Hailuo-2.3` video, and verified GUI vision—no second key required. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natureco-cli",
|
|
3
|
-
"version": "5.64.
|
|
3
|
+
"version": "5.64.7",
|
|
4
4
|
"description": "Terminal-native AI agent CLI with bilingual TR/EN UI, multi-agent orchestration, persistent memory, secure tools and messaging integrations.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"natureco": "bin/natureco.js"
|
|
@@ -133,17 +133,41 @@ function evaluateCompletionEvidence({ mutationCount, initialHash, currentHash, v
|
|
|
133
133
|
async function verifyGoal(providerUrl, apiKey, model, goal, screenshot) {
|
|
134
134
|
const prompt = `You are a strict independent verifier. Inspect only the screenshot. Goal: ${goal}\nReturn JSON only: {"verified":boolean,"confidence":0..1,"evidence":"exact visible evidence","reason":"why not"}. Never infer success from the goal text. If the requested sent message, booking, purchase, or confirmation is not visibly present, verified must be false.`;
|
|
135
135
|
const reply = await visionCall(providerUrl, apiKey, model, prompt, screenshot);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
const parsed = parseVisionDecision(reply);
|
|
137
|
+
return parsed.success ? parsed.value : { verified: false, confidence: 0, reason: 'Verifier returned invalid JSON: ' + parsed.error };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function parseVisionDecision(reply) {
|
|
141
|
+
const raw = String(reply || '').trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '');
|
|
142
|
+
const candidates = [raw];
|
|
143
|
+
const start = raw.indexOf('{');
|
|
144
|
+
const end = raw.lastIndexOf('}');
|
|
145
|
+
if (start >= 0 && end > start) candidates.push(raw.slice(start, end + 1));
|
|
146
|
+
for (const candidate of candidates) {
|
|
147
|
+
try {
|
|
148
|
+
const value = JSON.parse(candidate);
|
|
149
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) return { success: true, value };
|
|
150
|
+
} catch {}
|
|
140
151
|
}
|
|
152
|
+
return { success: false, error: raw ? 'malformed or truncated JSON' : 'empty vision response' };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function validateAction(action, params = {}) {
|
|
156
|
+
const finite = value => typeof value === 'number' && Number.isFinite(value);
|
|
157
|
+
if (!['click', 'type', 'keypress', 'mouse_move', 'scroll', 'wait', 'done'].includes(action)) return 'Unknown action: ' + action;
|
|
158
|
+
if ((action === 'click' || action === 'mouse_move') && (!finite(params.x) || !finite(params.y))) return action + ' requires finite numeric x and y';
|
|
159
|
+
if (action === 'scroll' && !finite(params.y)) return 'scroll requires a finite numeric y';
|
|
160
|
+
if (action === 'type' && typeof params.text !== 'string') return 'type requires text';
|
|
161
|
+
if (action === 'keypress' && (typeof params.key !== 'string' || !params.key.trim())) return 'keypress requires key';
|
|
162
|
+
return null;
|
|
141
163
|
}
|
|
142
164
|
|
|
143
165
|
function executeAction(action, params) {
|
|
144
166
|
const { spawnSync } = require('child_process');
|
|
145
167
|
const PLATFORM = os.platform();
|
|
146
168
|
|
|
169
|
+
const invalid = validateAction(action, params);
|
|
170
|
+
if (invalid) return { success: false, error: invalid };
|
|
147
171
|
const ESC = (s) => s.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
148
172
|
|
|
149
173
|
function osaScript(script, timeoutMs = 10000) {
|
|
@@ -232,15 +256,17 @@ async function loop(goal, maxSteps) {
|
|
|
232
256
|
const history = steps.filter(s => s.action && s.action !== 'screenshot' && s.action !== 'done').slice(-5);
|
|
233
257
|
const historyText = history.length > 0 ? '\nOnceki adimlar:\n' + history.map(h => 'Adim ' + h.step + ': ' + JSON.stringify(h)).join('\n') : '';
|
|
234
258
|
const reply = await visionCall(providerUrl, apiKey, model, SYSTEM_PROMPT + '\n\nGorev: ' + goal + historyText + '\n\nEkran goruntusunu analiz et. Siradaki action ne?', screenshot);
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
259
|
+
const parsedDecision = parseVisionDecision(reply);
|
|
260
|
+
if (!parsedDecision.success) {
|
|
261
|
+
steps.push({ step: i + 1, action: 'vision_retry', error: parsedDecision.error });
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
const decision = parsedDecision.value;
|
|
265
|
+
const invalidDecision = validateAction(decision.action, decision);
|
|
266
|
+
if (invalidDecision) {
|
|
267
|
+
steps.push({ step: i + 1, action: 'vision_retry', error: invalidDecision });
|
|
268
|
+
continue;
|
|
241
269
|
}
|
|
242
|
-
|
|
243
|
-
if (!decision.action) decision.action = 'wait';
|
|
244
270
|
|
|
245
271
|
// 3. Execute
|
|
246
272
|
if (decision.action === 'done') {
|
|
@@ -307,4 +333,4 @@ async function execute(params) {
|
|
|
307
333
|
return await loop(params.goal, params.maxSteps || 30);
|
|
308
334
|
}
|
|
309
335
|
|
|
310
|
-
module.exports = { name, description, parameters, execute, executeAction, evaluateCompletionEvidence, resolveVisionConfig, visionCall };
|
|
336
|
+
module.exports = { name, description, parameters, execute, executeAction, evaluateCompletionEvidence, resolveVisionConfig, visionCall, parseVisionDecision, validateAction };
|