openzoo 0.50.23 → 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 +54 -15
- package/package.json +1 -1
package/lib/cursorbackend.js
CHANGED
|
@@ -542,12 +542,13 @@ async function proxyPodHttp(req, res, full, body, log) {
|
|
|
542
542
|
if (!realPod?.agent) return false;
|
|
543
543
|
const agent = new URL(realPod.agent);
|
|
544
544
|
const headers = copyReqHeaders(req, agent.host);
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}
|
|
545
|
+
// Incoming Authorization is Grok Bot oauth to api2. 1340 wants EnsureSandBox
|
|
546
|
+
// field 11. Leaving oauth in place 401s listAgents (measured: tails via
|
|
547
|
+
// podJson with field-11 worked, roster proxy with copied oauth 401ed).
|
|
548
|
+
delete headers.authorization;
|
|
549
|
+
delete headers.Authorization;
|
|
550
|
+
if (realPod.accessToken) headers.authorization = `Bearer ${realPod.accessToken}`;
|
|
551
|
+
if (realPod.token) headers['x-anyrun-network-token'] = realPod.token;
|
|
551
552
|
if (!headers['x-sand-slim-avatars']) headers['x-sand-slim-avatars'] = '1';
|
|
552
553
|
const path0 = (full || '').split('?')[0];
|
|
553
554
|
const interesting = /sendPrompt|Transcript|listAgents|promptAcceptance|openAgentTail|createAgent/i.test(path0);
|
|
@@ -1256,6 +1257,7 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1256
1257
|
'Tools: read_file, write_file, exec, list_dir. USE THEM. Write files to disk instead of pasting giant HTML into chat.',
|
|
1257
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.',
|
|
1258
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.',
|
|
1259
1261
|
'A spend footer is appended after your reply by the host — ignore it.',
|
|
1260
1262
|
].join(' '),
|
|
1261
1263
|
},
|
|
@@ -1284,14 +1286,8 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1284
1286
|
const maxTok = Number(process.env.OPENZOO_ASK_MAX_TOKENS || 4096);
|
|
1285
1287
|
let lastData = {};
|
|
1286
1288
|
let text = '';
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
model,
|
|
1290
|
-
messages,
|
|
1291
|
-
tools: LOCAL_TOOLS,
|
|
1292
|
-
tool_choice: 'auto',
|
|
1293
|
-
max_tokens: maxTok,
|
|
1294
|
-
};
|
|
1289
|
+
const usedTools = [];
|
|
1290
|
+
const zooPost = async (payload) => {
|
|
1295
1291
|
const post = () => fetch('http://127.0.0.1:8402/v1/chat/completions', {
|
|
1296
1292
|
method: 'POST',
|
|
1297
1293
|
headers: { 'content-type': 'application/json', authorization: 'Bearer sk-openzoo' },
|
|
@@ -1305,6 +1301,16 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1305
1301
|
r = await post();
|
|
1306
1302
|
}
|
|
1307
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
|
+
});
|
|
1308
1314
|
lastData = data;
|
|
1309
1315
|
const msg = data.choices?.[0]?.message || {};
|
|
1310
1316
|
const calls = Array.isArray(msg.tool_calls) ? msg.tool_calls : [];
|
|
@@ -1316,6 +1322,12 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1316
1322
|
try { args = JSON.parse(c.function?.arguments || c.arguments || '{}'); } catch { args = {}; }
|
|
1317
1323
|
const name = c.function?.name || c.name || '';
|
|
1318
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
|
+
});
|
|
1319
1331
|
messages.push({
|
|
1320
1332
|
role: 'tool',
|
|
1321
1333
|
tool_call_id: c.id,
|
|
@@ -1324,10 +1336,37 @@ async function zooComplete(prompt, log, agentId, parsed = {}) {
|
|
|
1324
1336
|
}
|
|
1325
1337
|
continue;
|
|
1326
1338
|
}
|
|
1327
|
-
text = zooTextFromMessage(msg, data)
|
|
1339
|
+
text = zooTextFromMessage(msg, data);
|
|
1328
1340
|
log(`cursor-backend: << zoo ${r.status} ${text.length}c model=${data.model || model} finish=${data.choices?.[0]?.finish_reason || '?'}`);
|
|
1329
1341
|
break;
|
|
1330
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
|
+
}
|
|
1331
1370
|
try { text += await zooSpendOverlay(lastData); } catch { /* overlay must never eat the reply */ }
|
|
1332
1371
|
return { text, data: lastData };
|
|
1333
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",
|