openzoo 0.50.25 → 0.50.26
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 +71 -2
- package/package.json +1 -1
package/lib/cursorbackend.js
CHANGED
|
@@ -663,6 +663,56 @@ function ssePush(channel, payload) {
|
|
|
663
663
|
}
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
+
let focusedAgentId = null;
|
|
667
|
+
const agentActivity = new Map(); // id -> { updatedAt, unreadCount, hasUnread, preview }
|
|
668
|
+
function noteFocus(id) {
|
|
669
|
+
if (!id) return;
|
|
670
|
+
focusedAgentId = id;
|
|
671
|
+
const a = agentActivity.get(id) || {};
|
|
672
|
+
a.hasUnread = false;
|
|
673
|
+
a.unreadCount = 0;
|
|
674
|
+
agentActivity.set(id, a);
|
|
675
|
+
}
|
|
676
|
+
function stampActivity(agent) {
|
|
677
|
+
const a = agentActivity.get(agent.id) || {};
|
|
678
|
+
const updatedAt = a.updatedAt || agent.updatedAt || agent.createdAt || 0;
|
|
679
|
+
return {
|
|
680
|
+
...agent,
|
|
681
|
+
updatedAt,
|
|
682
|
+
hasUnread: !!a.hasUnread,
|
|
683
|
+
unreadCount: a.unreadCount || 0,
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function sortAgentsByActivity(list) {
|
|
687
|
+
return [...list].sort((x, y) => {
|
|
688
|
+
const ax = agentActivity.get(x.id)?.updatedAt || x.updatedAt || x.createdAt || 0;
|
|
689
|
+
const ay = agentActivity.get(y.id)?.updatedAt || y.updatedAt || y.createdAt || 0;
|
|
690
|
+
return ay - ax;
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
function bumpAgent(id, { preview = '', notify = true } = {}) {
|
|
694
|
+
const now = Date.now();
|
|
695
|
+
const a = agentActivity.get(id) || { unreadCount: 0 };
|
|
696
|
+
a.updatedAt = now;
|
|
697
|
+
if (preview) a.preview = String(preview).slice(0, 120);
|
|
698
|
+
const other = notify && focusedAgentId && focusedAgentId !== id;
|
|
699
|
+
if (other) {
|
|
700
|
+
a.hasUnread = true;
|
|
701
|
+
a.unreadCount = (a.unreadCount || 0) + 1;
|
|
702
|
+
}
|
|
703
|
+
agentActivity.set(id, a);
|
|
704
|
+
const list = cachedAgentList() || [];
|
|
705
|
+
const idx = list.findIndex((x) => x.id === id);
|
|
706
|
+
const base = idx >= 0 ? list[idx] : { id, name: id };
|
|
707
|
+
const agent = stampActivity({ ...base, updatedAt: now });
|
|
708
|
+
if (idx >= 0) list[idx] = agent;
|
|
709
|
+
else list.unshift(agent);
|
|
710
|
+
saveAgents(sortAgentsByActivity(list));
|
|
711
|
+
// asar handleGatewaySseEvent: channel agent-upserted → {agent, activeAgentId}
|
|
712
|
+
ssePush('agent-upserted', { agent, activeAgentId: focusedAgentId || id });
|
|
713
|
+
ssePush('agents', { agents: sortAgentsByActivity(cachedAgentList() || []).slice(0, 80).map(stampActivity), activeAgentId: focusedAgentId || id });
|
|
714
|
+
}
|
|
715
|
+
|
|
666
716
|
/** Grok Bot Helper daemon: GET /local-exec/requests is SSE, POST /local-exec/responses
|
|
667
717
|
* is `{providerId, frames}`. We used to JSON-[] the GET which is "disconnected"
|
|
668
718
|
* (measured: Grok Bot "can't see files on your local computer"). */
|
|
@@ -874,9 +924,9 @@ function mergeAgentLists(remote) {
|
|
|
874
924
|
for (const a of [...local, ...(Array.isArray(remote) ? remote : [])]) {
|
|
875
925
|
if (!a?.id || seen.has(a.id)) continue;
|
|
876
926
|
seen.add(a.id);
|
|
877
|
-
out.push(a);
|
|
927
|
+
out.push(stampActivity(a));
|
|
878
928
|
}
|
|
879
|
-
return out;
|
|
929
|
+
return sortAgentsByActivity(out);
|
|
880
930
|
}
|
|
881
931
|
function gatewayEntry(e) {
|
|
882
932
|
const { seq, pulledRemote, ...rest } = e;
|
|
@@ -1452,6 +1502,21 @@ async function handleHijackedPodHttp(req, res, full, body, log) {
|
|
|
1452
1502
|
log(`cursor-backend: updateAgent local id=${agent.id}`);
|
|
1453
1503
|
return true;
|
|
1454
1504
|
}
|
|
1505
|
+
if (name === 'setAgentUnread') {
|
|
1506
|
+
let parsed = {};
|
|
1507
|
+
try { parsed = JSON.parse(String(body || '{}')); } catch { parsed = {}; }
|
|
1508
|
+
const id = String(parsed.id || '');
|
|
1509
|
+
const unread = parsed.isUnread === true;
|
|
1510
|
+
if (id) {
|
|
1511
|
+
const a = agentActivity.get(id) || {};
|
|
1512
|
+
a.hasUnread = unread;
|
|
1513
|
+
a.unreadCount = unread ? Math.max(1, a.unreadCount || 1) : 0;
|
|
1514
|
+
agentActivity.set(id, a);
|
|
1515
|
+
if (!unread) noteFocus(id);
|
|
1516
|
+
}
|
|
1517
|
+
jsonSend(res, { ok: true });
|
|
1518
|
+
return true;
|
|
1519
|
+
}
|
|
1455
1520
|
if (name === 'deleteAgents') {
|
|
1456
1521
|
let parsed = {};
|
|
1457
1522
|
try { parsed = JSON.parse(String(body || '{}')); } catch { parsed = {}; }
|
|
@@ -1495,6 +1560,8 @@ async function handleHijackedPodHttp(req, res, full, body, log) {
|
|
|
1495
1560
|
requestId: nonce,
|
|
1496
1561
|
richText: parsed.richText,
|
|
1497
1562
|
});
|
|
1563
|
+
noteFocus(agentId);
|
|
1564
|
+
bumpAgent(agentId, { preview: prompt, notify: false });
|
|
1498
1565
|
ssePush('transcript', { ...gatewayEntry(userLine), agentId });
|
|
1499
1566
|
jsonSend(res, { accepted: true });
|
|
1500
1567
|
const modelCmd = /^\s*\/model(?:\s+(\S+))?\s*$/i.exec(prompt || '');
|
|
@@ -1527,6 +1594,7 @@ async function handleHijackedPodHttp(req, res, full, body, log) {
|
|
|
1527
1594
|
}
|
|
1528
1595
|
const line = fanoutLine(agentId, 'assistant', text, { clientNonce: nonce, requestId: nonce });
|
|
1529
1596
|
ssePush('transcript', { ...gatewayEntry(line), agentId });
|
|
1597
|
+
bumpAgent(agentId, { preview: text, notify: true });
|
|
1530
1598
|
log(`cursor-backend: sendPrompt done agent=${agentId} seq=${line.seq} text=${JSON.stringify(text.slice(0, 80))}`);
|
|
1531
1599
|
});
|
|
1532
1600
|
return true;
|
|
@@ -1535,6 +1603,7 @@ async function handleHijackedPodHttp(req, res, full, body, log) {
|
|
|
1535
1603
|
let parsed = {};
|
|
1536
1604
|
try { parsed = JSON.parse(String(body || '{}')); } catch { parsed = {}; }
|
|
1537
1605
|
const id = String(parsed.id || parsed.agentId || 'openzoo');
|
|
1606
|
+
noteFocus(id);
|
|
1538
1607
|
tailedAgents.add(id);
|
|
1539
1608
|
const t = agentTranscript(id);
|
|
1540
1609
|
if (!t.pulledRemote && realPod?.agent) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openzoo",
|
|
3
|
-
"version": "0.50.
|
|
3
|
+
"version": "0.50.26",
|
|
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",
|