openzoo 0.50.22 → 0.50.24
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 +100 -14
- 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);
|
|
@@ -771,9 +772,33 @@ function expandUserPath(p) {
|
|
|
771
772
|
const transcripts = new Map();
|
|
772
773
|
const tailedAgents = new Set();
|
|
773
774
|
let lastSendEchoId = `oz-${Date.now()}`;
|
|
775
|
+
const TX_FILE = path.join(os.homedir(), '.openzoo', 'grokbot-transcripts.json');
|
|
776
|
+
function loadTranscripts() {
|
|
777
|
+
try {
|
|
778
|
+
const o = JSON.parse(fs.readFileSync(TX_FILE, 'utf8'));
|
|
779
|
+
for (const [id, t] of Object.entries(o || {})) {
|
|
780
|
+
transcripts.set(id, {
|
|
781
|
+
seq: Number(t.seq) || (t.entries || []).length,
|
|
782
|
+
entries: Array.isArray(t.entries) ? t.entries : [],
|
|
783
|
+
pulledRemote: false,
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
} catch { /* first run */ }
|
|
787
|
+
}
|
|
788
|
+
function saveTranscripts() {
|
|
789
|
+
try {
|
|
790
|
+
const o = {};
|
|
791
|
+
for (const [id, t] of transcripts) {
|
|
792
|
+
o[id] = { seq: t.seq, entries: t.entries.slice(-200) };
|
|
793
|
+
}
|
|
794
|
+
fs.mkdirSync(path.dirname(TX_FILE), { recursive: true });
|
|
795
|
+
fs.writeFileSync(TX_FILE, JSON.stringify(o));
|
|
796
|
+
} catch { /* */ }
|
|
797
|
+
}
|
|
798
|
+
loadTranscripts();
|
|
774
799
|
function agentTranscript(id) {
|
|
775
800
|
let t = transcripts.get(id);
|
|
776
|
-
if (!t) { t = { seq: 0, entries: [] }; transcripts.set(id, t); }
|
|
801
|
+
if (!t) { t = { seq: 0, entries: [], pulledRemote: false }; transcripts.set(id, t); }
|
|
777
802
|
return t;
|
|
778
803
|
}
|
|
779
804
|
function appendLine(agentId, role, text, extra = {}) {
|
|
@@ -809,6 +834,7 @@ function appendLine(agentId, role, text, extra = {}) {
|
|
|
809
834
|
};
|
|
810
835
|
}
|
|
811
836
|
t.entries.push(e);
|
|
837
|
+
saveTranscripts();
|
|
812
838
|
return e;
|
|
813
839
|
}
|
|
814
840
|
function fanoutLine(primaryId, role, text, extra = {}) {
|
|
@@ -853,9 +879,63 @@ function mergeAgentLists(remote) {
|
|
|
853
879
|
return out;
|
|
854
880
|
}
|
|
855
881
|
function gatewayEntry(e) {
|
|
856
|
-
const { seq, ...rest } = e;
|
|
882
|
+
const { seq, pulledRemote, ...rest } = e;
|
|
857
883
|
return rest;
|
|
858
884
|
}
|
|
885
|
+
async function podJson(path0, bodyObj, log) {
|
|
886
|
+
if (!realPod?.agent) return null;
|
|
887
|
+
let agent;
|
|
888
|
+
try { agent = new URL(realPod.agent); } catch { return null; }
|
|
889
|
+
const headers = {
|
|
890
|
+
'content-type': 'application/json',
|
|
891
|
+
accept: 'application/json',
|
|
892
|
+
authorization: `Bearer ${realPod.accessToken || realPod.token || ''}`,
|
|
893
|
+
'x-anyrun-network-token': realPod.token || '',
|
|
894
|
+
'x-sand-slim-avatars': '1',
|
|
895
|
+
};
|
|
896
|
+
try {
|
|
897
|
+
const cap = await upstreamUnary({
|
|
898
|
+
host: agent.hostname,
|
|
899
|
+
path: path0,
|
|
900
|
+
method: 'POST',
|
|
901
|
+
headers,
|
|
902
|
+
body: Buffer.from(JSON.stringify(bodyObj || {})),
|
|
903
|
+
timeoutMs: 20000,
|
|
904
|
+
});
|
|
905
|
+
if (cap.status !== 200) {
|
|
906
|
+
log(`cursor-backend: podJson ${path0} ${cap.status}`);
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
const raw = inflateBody(cap.buf, cap.respHeaders);
|
|
910
|
+
return JSON.parse(String(raw));
|
|
911
|
+
} catch (e) {
|
|
912
|
+
log(`cursor-backend: podJson ${path0} ${e.message}`);
|
|
913
|
+
return null;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
function ingestRemoteEntries(agentId, entries) {
|
|
917
|
+
if (!Array.isArray(entries) || !entries.length) return 0;
|
|
918
|
+
const t = agentTranscript(agentId);
|
|
919
|
+
const have = new Set(t.entries.map((e) => e.id || e.clientNonce || '').filter(Boolean));
|
|
920
|
+
const incoming = [];
|
|
921
|
+
for (const e of entries) {
|
|
922
|
+
if (!e || typeof e !== 'object') continue;
|
|
923
|
+
const k = e.id || e.clientNonce || '';
|
|
924
|
+
if (k && have.has(k)) continue;
|
|
925
|
+
incoming.push(e);
|
|
926
|
+
}
|
|
927
|
+
if (!incoming.length) return 0;
|
|
928
|
+
const local = t.entries;
|
|
929
|
+
t.entries = [];
|
|
930
|
+
t.seq = 0;
|
|
931
|
+
for (const e of [...incoming, ...local]) {
|
|
932
|
+
t.seq += 1;
|
|
933
|
+
const { seq: _s, ...rest } = e;
|
|
934
|
+
t.entries.push({ ...rest, seq: t.seq });
|
|
935
|
+
}
|
|
936
|
+
saveTranscripts();
|
|
937
|
+
return incoming.length;
|
|
938
|
+
}
|
|
859
939
|
|
|
860
940
|
function promptFromSendBody(raw) {
|
|
861
941
|
let obj = raw;
|
|
@@ -1419,16 +1499,22 @@ async function handleHijackedPodHttp(req, res, full, body, log) {
|
|
|
1419
1499
|
const id = String(parsed.id || parsed.agentId || 'openzoo');
|
|
1420
1500
|
tailedAgents.add(id);
|
|
1421
1501
|
const t = agentTranscript(id);
|
|
1502
|
+
if (!t.pulledRemote && realPod?.agent) {
|
|
1503
|
+
const remote = await podJson('/api/getAgentTranscriptTail', {
|
|
1504
|
+
id, agentId: id, limit: 200, beforeSeq: parsed.beforeSeq,
|
|
1505
|
+
}, log);
|
|
1506
|
+
const n = ingestRemoteEntries(id, remote?.entries);
|
|
1507
|
+
t.pulledRemote = true;
|
|
1508
|
+
if (n) log(`cursor-backend: hydrated ${id} +${n} from 1340`);
|
|
1509
|
+
}
|
|
1510
|
+
const t2 = agentTranscript(id);
|
|
1422
1511
|
const limit = Math.min(Number(parsed.limit) || 50, 200);
|
|
1423
1512
|
const before = parsed.beforeSeq != null ? Number(parsed.beforeSeq) : Infinity;
|
|
1424
|
-
const sliced =
|
|
1513
|
+
const sliced = t2.entries.filter((e) => e.seq < before).slice(-limit);
|
|
1425
1514
|
const page = { entries: sliced.map(gatewayEntry) };
|
|
1426
|
-
if (
|
|
1427
|
-
// Live pod returns RAW {entries, nextBeforeSeq} — no CVr envelope
|
|
1428
|
-
// (measured 1340 getAgentTranscriptTail 2026-08-29). Wrapping {status,value}
|
|
1429
|
-
// made transcript-page validation fail and the canvas stayed empty.
|
|
1515
|
+
if (t2.entries.length > sliced.length && sliced.length) page.nextBeforeSeq = sliced[0].seq;
|
|
1430
1516
|
jsonSend(res, page);
|
|
1431
|
-
log(`cursor-backend: -> transcript ${id} n=${sliced.length}/${
|
|
1517
|
+
log(`cursor-backend: -> transcript ${id} n=${sliced.length}/${t2.seq}`);
|
|
1432
1518
|
return true;
|
|
1433
1519
|
}
|
|
1434
1520
|
if (name === 'promptAcceptanceStatus') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.50.
|
|
3
|
+
"version": "0.50.24",
|
|
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",
|