openzoo 0.50.24 → 0.50.25
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/lib/cursorbackend.js +47 -9
- package/package.json +1 -1
package/lib/cursorbackend.js
CHANGED
|
@@ -1257,6 +1257,7 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1257
1257
|
'Tools: read_file, write_file, exec, list_dir. USE THEM. Write files to disk instead of pasting giant HTML into chat.',
|
|
1258
1258
|
'Pasted images arrive as attachments — you can see them when present. Do not claim you cannot see images if they are in this turn.',
|
|
1259
1259
|
'Never claim you lack filesystem access or local-exec. If a tool errors, report the error.',
|
|
1260
|
+
'After using tools you MUST still write a normal chat reply: what you did, file paths written, and what to open. Empty content is a bug.',
|
|
1260
1261
|
'A spend footer is appended after your reply by the host — ignore it.',
|
|
1261
1262
|
].join(' '),
|
|
1262
1263
|
},
|
|
@@ -1285,14 +1286,8 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1285
1286
|
const maxTok = Number(process.env.OPENZOO_ASK_MAX_TOKENS || 4096);
|
|
1286
1287
|
let lastData = {};
|
|
1287
1288
|
let text = '';
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
model,
|
|
1291
|
-
messages,
|
|
1292
|
-
tools: LOCAL_TOOLS,
|
|
1293
|
-
tool_choice: 'auto',
|
|
1294
|
-
max_tokens: maxTok,
|
|
1295
|
-
};
|
|
1289
|
+
const usedTools = [];
|
|
1290
|
+
const zooPost = async (payload) => {
|
|
1296
1291
|
const post = () => fetch('http://127.0.0.1:8402/v1/chat/completions', {
|
|
1297
1292
|
method: 'POST',
|
|
1298
1293
|
headers: { 'content-type': 'application/json', authorization: 'Bearer sk-openzoo' },
|
|
@@ -1306,6 +1301,16 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1306
1301
|
r = await post();
|
|
1307
1302
|
}
|
|
1308
1303
|
const data = await r.json();
|
|
1304
|
+
return { r, data };
|
|
1305
|
+
};
|
|
1306
|
+
for (let step = 0; step < 8; step++) {
|
|
1307
|
+
const { r, data } = await zooPost({
|
|
1308
|
+
model,
|
|
1309
|
+
messages,
|
|
1310
|
+
tools: LOCAL_TOOLS,
|
|
1311
|
+
tool_choice: 'auto',
|
|
1312
|
+
max_tokens: maxTok,
|
|
1313
|
+
});
|
|
1309
1314
|
lastData = data;
|
|
1310
1315
|
const msg = data.choices?.[0]?.message || {};
|
|
1311
1316
|
const calls = Array.isArray(msg.tool_calls) ? msg.tool_calls : [];
|
|
@@ -1317,6 +1322,12 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1317
1322
|
try { args = JSON.parse(c.function?.arguments || c.arguments || '{}'); } catch { args = {}; }
|
|
1318
1323
|
const name = c.function?.name || c.name || '';
|
|
1319
1324
|
const result = await runLocalTool(name, args, log);
|
|
1325
|
+
usedTools.push({
|
|
1326
|
+
name,
|
|
1327
|
+
path: args.path,
|
|
1328
|
+
command: args.command ? String(args.command).slice(0, 120) : undefined,
|
|
1329
|
+
note: String(result).slice(0, 200),
|
|
1330
|
+
});
|
|
1320
1331
|
messages.push({
|
|
1321
1332
|
role: 'tool',
|
|
1322
1333
|
tool_call_id: c.id,
|
|
@@ -1325,10 +1336,37 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1325
1336
|
}
|
|
1326
1337
|
continue;
|
|
1327
1338
|
}
|
|
1328
|
-
text = zooTextFromMessage(msg, data)
|
|
1339
|
+
text = zooTextFromMessage(msg, data);
|
|
1329
1340
|
log(`cursor-backend: << zoo ${r.status} ${text.length}c model=${data.model || model} finish=${data.choices?.[0]?.finish_reason || '?'}`);
|
|
1330
1341
|
break;
|
|
1331
1342
|
}
|
|
1343
|
+
if (usedTools.length && !String(text || '').trim()) {
|
|
1344
|
+
messages.push({
|
|
1345
|
+
role: 'user',
|
|
1346
|
+
content: 'Stop calling tools. Write a short chat reply summarizing what you did: files written (full paths), commands that mattered, and what the user should open. No empty message.',
|
|
1347
|
+
});
|
|
1348
|
+
const { r, data } = await zooPost({
|
|
1349
|
+
model,
|
|
1350
|
+
messages,
|
|
1351
|
+
max_tokens: Math.max(800, Math.min(maxTok, 2048)),
|
|
1352
|
+
});
|
|
1353
|
+
lastData = data;
|
|
1354
|
+
text = zooTextFromMessage(data.choices?.[0]?.message, data);
|
|
1355
|
+
log(`cursor-backend: << zoo summary ${r.status} ${text.length}c`);
|
|
1356
|
+
}
|
|
1357
|
+
if (!String(text || '').trim()) {
|
|
1358
|
+
if (usedTools.length) {
|
|
1359
|
+
const writes = usedTools.filter((t) => t.name === 'write_file' && t.path).map((t) => t.path);
|
|
1360
|
+
const execs = usedTools.filter((t) => t.name === 'exec' && t.command).map((t) => t.command);
|
|
1361
|
+
const lines = ['Did local work (no model chat text came back):'];
|
|
1362
|
+
if (writes.length) lines.push(`wrote: ${[...new Set(writes)].join(', ')}`);
|
|
1363
|
+
if (execs.length) lines.push(`ran: ${execs.slice(-6).join(' · ')}`);
|
|
1364
|
+
if (lines.length === 1) lines.push(`${usedTools.length} tool calls.`);
|
|
1365
|
+
text = lines.join('\n');
|
|
1366
|
+
} else {
|
|
1367
|
+
text = '(empty zoo reply)';
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1332
1370
|
try { text += await zooSpendOverlay(lastData); } catch { /* overlay must never eat the reply */ }
|
|
1333
1371
|
return { text, data: lastData };
|
|
1334
1372
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.50.
|
|
3
|
+
"version": "0.50.25",
|
|
4
4
|
"description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|