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