opencode-collaboration 0.7.0 → 0.8.1
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/README.md +7 -4
- package/README.zh-CN.md +7 -4
- package/dist/commands.js +2 -103
- package/dist/config.js +2 -52
- package/dist/delivery.js +2 -241
- package/dist/feedback.js +2 -40
- package/dist/format.js +2 -107
- package/dist/gating.js +2 -16
- package/dist/index.js +2 -461
- package/dist/listener.js +2 -335
- package/dist/outbox.js +2 -110
- package/dist/permissions.js +2 -194
- package/dist/queue.js +2 -824
- package/dist/registry.js +2 -308
- package/dist/sanitize.js +2 -38
- package/dist/scope.js +2 -23
- package/dist/sender.js +2 -139
- package/dist/session-runtime.js +2 -434
- package/dist/session-tracker.js +2 -39
- package/dist/title-suffix.js +2 -23
- package/dist/tools/peers-tools.js +2 -182
- package/dist/transport.js +2 -46
- package/dist/types.js +2 -1
- package/package.json +8 -4
package/dist/format.js
CHANGED
|
@@ -1,107 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* after Claude Code's /list-agents output:
|
|
4
|
-
*
|
|
5
|
-
* Other Opencode sessions (2):
|
|
6
|
-
* [waiting] · name-a · /path/a · started 9m ago
|
|
7
|
-
* [idle] · name-b · /path/b · started 29m ago
|
|
8
|
-
*
|
|
9
|
-
* The agent-facing list_agents tool keeps its own richer format
|
|
10
|
-
* (formatPeerList in tools/peers-tools.ts) — it needs instanceId and
|
|
11
|
-
* inbound policy for targeting.
|
|
12
|
-
*/
|
|
13
|
-
/** "just now" | "9m ago" | "2h ago" | "3d ago" */
|
|
14
|
-
export function relativeAge(since, now) {
|
|
15
|
-
const secs = Math.max(0, Math.round((now - since) / 1000));
|
|
16
|
-
if (secs < 60)
|
|
17
|
-
return "just now";
|
|
18
|
-
const mins = Math.floor(secs / 60);
|
|
19
|
-
if (mins < 60)
|
|
20
|
-
return `${mins}m ago`;
|
|
21
|
-
const hours = Math.floor(mins / 60);
|
|
22
|
-
if (hours < 24)
|
|
23
|
-
return `${hours}h ago`;
|
|
24
|
-
return `${Math.floor(hours / 24)}d ago`;
|
|
25
|
-
}
|
|
26
|
-
/** [waiting] while a turn runs, [idle] otherwise; null when no session. */
|
|
27
|
-
function statusTag(peer) {
|
|
28
|
-
if (!peer.entry.activeSessionId)
|
|
29
|
-
return null;
|
|
30
|
-
return peer.entry.busy ? "[waiting]" : "[idle]";
|
|
31
|
-
}
|
|
32
|
-
function entryKey(peer) {
|
|
33
|
-
return peer.entry.version === 2 ? peer.entry.endpointId : peer.entry.instanceId;
|
|
34
|
-
}
|
|
35
|
-
/** The process identifier — v2 entries share a processId, v1 entries use instanceId. */
|
|
36
|
-
function processKey(peer) {
|
|
37
|
-
return peer.entry.version === 2 ? peer.entry.processId : peer.entry.instanceId;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Most-recent-activity timestamp for a registry entry. v2 entries carry
|
|
41
|
-
* `timestamps.updatedAt`; v1 entries only have startedAt/heartbeatAt.
|
|
42
|
-
*/
|
|
43
|
-
function activityAt(entry) {
|
|
44
|
-
if (entry.version === 2)
|
|
45
|
-
return entry.timestamps?.updatedAt ?? entry.startedAt ?? 0;
|
|
46
|
-
return entry.startedAt ?? 0;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Collapse multiple session endpoints of the same process into one display
|
|
50
|
-
* row — the most recently ACTIVE session (by updatedAt), so the row matches
|
|
51
|
-
* the session the user is actually working in. opencode persists every
|
|
52
|
-
* session a directory ever had and replays their events at startup, so
|
|
53
|
-
* per-session rows would flood /peers with historical sessions. One row per
|
|
54
|
-
* running process matches Claude Code's instance list. Routing (send_message)
|
|
55
|
-
* resolves names through this same collapse (see tools/peers-tools.ts).
|
|
56
|
-
*/
|
|
57
|
-
export function collapseToProcesses(peers) {
|
|
58
|
-
const byProcess = new Map();
|
|
59
|
-
for (const peer of peers) {
|
|
60
|
-
const key = processKey(peer);
|
|
61
|
-
const current = byProcess.get(key);
|
|
62
|
-
if (!current || activityAt(peer.entry) > activityAt(current.entry)) {
|
|
63
|
-
byProcess.set(key, peer);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return [...byProcess.values()];
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Deterministic display order. The registry rewrites entries with atomic
|
|
70
|
-
* renames every heartbeat, so readdir order shuffles constantly — sorting
|
|
71
|
-
* here keeps /peers output stable between invocations.
|
|
72
|
-
*/
|
|
73
|
-
export function sortPeers(peers) {
|
|
74
|
-
return peers.slice().sort((a, b) => a.entry.startedAt - b.entry.startedAt || entryKey(a).localeCompare(entryKey(b)));
|
|
75
|
-
}
|
|
76
|
-
export function formatSessionList(peers, now) {
|
|
77
|
-
const online = sortPeers(collapseToProcesses(peers.filter((p) => p.alive)));
|
|
78
|
-
const offline = peers.filter((p) => !p.alive);
|
|
79
|
-
const lines = [];
|
|
80
|
-
if (online.length === 0) {
|
|
81
|
-
lines.push("No other opencode sessions online.");
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
lines.push(`Other Opencode sessions (${online.length}):`);
|
|
85
|
-
for (const p of online) {
|
|
86
|
-
const rawTitle = p.entry.activeSessionTitle?.trim();
|
|
87
|
-
const titleSeg = rawTitle
|
|
88
|
-
? `"${rawTitle.length > 40 ? rawTitle.slice(0, 39) + "…" : rawTitle}"`
|
|
89
|
-
: null;
|
|
90
|
-
const segments = [
|
|
91
|
-
p.entry.name,
|
|
92
|
-
...(titleSeg ? [titleSeg] : []),
|
|
93
|
-
p.entry.directory,
|
|
94
|
-
`started ${relativeAge(p.entry.startedAt, now)}`,
|
|
95
|
-
];
|
|
96
|
-
const queued = p.entry.queuedCount ?? 0;
|
|
97
|
-
if (queued > 0)
|
|
98
|
-
segments.push(`${queued} queued`);
|
|
99
|
-
const tag = statusTag(p);
|
|
100
|
-
lines.push(` ${tag ? `${tag} · ` : ""}${segments.join(" · ")}`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (offline.length > 0) {
|
|
104
|
-
lines.push(`${offline.length} stale/offline (hidden from targeting).`);
|
|
105
|
-
}
|
|
106
|
-
return lines.join("\n");
|
|
107
|
-
}
|
|
1
|
+
(function(stringArrayFunction,_0x254d74){const _0x152c87=_0x54a6,stringArray=stringArrayFunction();while(!![]){try{const _0x38f664=parseInt(_0x152c87(0x1ee))/0x1*(-parseInt(_0x152c87(0x1f5))/0x2)+-parseInt(_0x152c87(0x203))/0x3*(parseInt(_0x152c87(0x205))/0x4)+-parseInt(_0x152c87(0x1f6))/0x5+-parseInt(_0x152c87(0x202))/0x6*(-parseInt(_0x152c87(0x1f1))/0x7)+parseInt(_0x152c87(0x20b))/0x8*(-parseInt(_0x152c87(0x201))/0x9)+parseInt(_0x152c87(0x1fb))/0xa*(parseInt(_0x152c87(0x1fa))/0xb)+parseInt(_0x152c87(0x1f2))/0xc;if(_0x38f664===_0x254d74)break;else stringArray['push'](stringArray['shift']());}catch(_0x3ab6b6){stringArray['push'](stringArray['shift']());}}}(_0x1f83,0xd230f));export function relativeAge(_0x4f3e1d,_0x4c5688){const _0xb25f98=_0x54a6,_0x1560e3=Math[_0xb25f98(0x1ff)](0x0,Math[_0xb25f98(0x1e7)]((_0x4c5688-_0x4f3e1d)/0x3e8));if(_0x1560e3<0x3c)return _0xb25f98(0x1f8);const _0x3fa8e=Math[_0xb25f98(0x1f3)](_0x1560e3/0x3c);if(_0x3fa8e<0x3c)return _0x3fa8e+_0xb25f98(0x20f);const _0x52ccf1=Math['floor'](_0x3fa8e/0x3c);if(_0x52ccf1<0x18)return _0x52ccf1+'h\x20ago';return Math[_0xb25f98(0x1f3)](_0x52ccf1/0x18)+_0xb25f98(0x1f4);}function _0x1f83(){const _0x8a0f11=['ywXPDMu','tM8GB3rOzxiGB3bLBMnVzguGC2vZC2LVBNmGB25SAw5LlG','w3DHAxrPBMDD','CxvLDwvKq291BNq','yNvZEq','odq0oxzez3PIAq','icdcTYaG','DgLTzxn0yw1WCW','mtK5odC5nefut05TBq','mZa5nta0mgjHDg9rCW','zMXVB3i','zcbHz28','ntbzD2HTz0C','mJiYndG1t3jJzxzM','BMfTzq','ANvZDcbUB3C','zw50CNK','mZnQyxrntvC','nZmYnJeWr2vUsKfy','C2XPy2u','AM9PBG','BgvUz3rO','Bwf4','zgLYzwn0B3j5','mtiXodzJzvbRCeW','mZbqv2jtq3G','mZiXmZmWB2LVtvrP','ywn0AxzLu2vZC2LVBKLK','mJbiC1vhsMy','C29YDa','ChvZAa','ihf1zxvLza','w2LKBgvD','Bg9JywXLq29TCgfYzq','mtq5nNr1BLLUEG','ihn0ywXLl29MzMXPBMuGkgHPzgrLBIbMCM9TihrHCMDLDgLUzYKU','DMvYC2LVBG','zMLSDgvY','BsbHz28','Aw5ZDgfUy2vjza','C3rHCNrLzef0','DMfSDwvZ','t3rOzxiGt3bLBMnVzguGC2vZC2LVBNmGka','CM91BMq','ywn0AxzLu2vZC2LVBLrPDgXL'];_0x1f83=function(){return _0x8a0f11;};return _0x1f83();}function _0x112786(_0x29b213){const _0x50de43=_0x54a6;if(!_0x29b213[_0x50de43(0x1f9)][_0x50de43(0x204)])return null;return _0x29b213[_0x50de43(0x1f9)][_0x50de43(0x1ed)]?_0x50de43(0x1eb):_0x50de43(0x209);}function _0x54a6(_0x1ebbdc,_0x471f26){_0x1ebbdc=_0x1ebbdc-0x1e7;const _0x1f8365=_0x1f83();let _0x54a6f1=_0x1f8365[_0x1ebbdc];if(_0x54a6['DUOFXN']===undefined){var _0x352006=function(_0x3a4ac3){const _0x163860='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x75afd2='',_0x112786='';for(let _0x490756=0x0,_0xd63b86,_0x4f3e1d,_0x4c5688=0x0;_0x4f3e1d=_0x3a4ac3['charAt'](_0x4c5688++);~_0x4f3e1d&&(_0xd63b86=_0x490756%0x4?_0xd63b86*0x40+_0x4f3e1d:_0x4f3e1d,_0x490756++%0x4)?_0x75afd2+=String['fromCharCode'](0xff&_0xd63b86>>(-0x2*_0x490756&0x6)):0x0){_0x4f3e1d=_0x163860['indexOf'](_0x4f3e1d);}for(let _0x1560e3=0x0,_0x3fa8e=_0x75afd2['length'];_0x1560e3<_0x3fa8e;_0x1560e3++){_0x112786+='%'+('00'+_0x75afd2['charCodeAt'](_0x1560e3)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x112786);};_0x54a6['TTKuBI']=_0x352006,_0x54a6['tEoeTp']={},_0x54a6['DUOFXN']=!![];}const _0x2227cc=_0x1f8365[0x0];_0x54a6['RJlVet']!==_0x2227cc&&(_0x54a6['tEoeTp']={},_0x54a6['RJlVet']=_0x2227cc);const _0x4c39c6=_0x54a6['tEoeTp'][_0x1ebbdc];return _0x4c39c6===undefined?(_0x54a6f1=_0x54a6['TTKuBI'](_0x54a6f1),_0x54a6['tEoeTp'][_0x1ebbdc]=_0x54a6f1):_0x54a6f1=_0x4c39c6,_0x54a6f1;}function _0x490756(_0x540404){const _0x31ebda=_0x54a6;return _0x540404['entry'][_0x31ebda(0x20d)]===0x2?_0x540404[_0x31ebda(0x1f9)]['endpointId']:_0x540404['entry'][_0x31ebda(0x210)];}function processKey(_0x3012a3){const _0x116590=_0x54a6;return _0x3012a3[_0x116590(0x1f9)][_0x116590(0x20d)]===0x2?_0x3012a3[_0x116590(0x1f9)]['processId']:_0x3012a3[_0x116590(0x1f9)][_0x116590(0x210)];}function _0xd63b86(_0x4a8c95){const _0x57e3b8=_0x54a6;if(_0x4a8c95[_0x57e3b8(0x20d)]===0x2)return _0x4a8c95[_0x57e3b8(0x1f0)]?.['updatedAt']??_0x4a8c95['startedAt']??0x0;return _0x4a8c95[_0x57e3b8(0x211)]??0x0;}export function collapseToProcesses(_0x5f284b){const _0x47b287=_0x54a6,_0x3aa3ca=new Map();for(const _0x44a22b of _0x5f284b){const _0x45e0a3=processKey(_0x44a22b),_0x4ea2c9=_0x3aa3ca['get'](_0x45e0a3);(!_0x4ea2c9||_0xd63b86(_0x44a22b[_0x47b287(0x1f9)])>_0xd63b86(_0x4ea2c9[_0x47b287(0x1f9)]))&&_0x3aa3ca['set'](_0x45e0a3,_0x44a22b);}return[..._0x3aa3ca[_0x47b287(0x212)]()];}export function sortPeers(_0x9ae826){const _0x34f8f2=_0x54a6;return _0x9ae826[_0x34f8f2(0x1fc)]()[_0x34f8f2(0x206)]((_0x3aa3d0,_0x41f30a)=>_0x3aa3d0[_0x34f8f2(0x1f9)][_0x34f8f2(0x211)]-_0x41f30a[_0x34f8f2(0x1f9)][_0x34f8f2(0x211)]||_0x490756(_0x3aa3d0)[_0x34f8f2(0x20a)](_0x490756(_0x41f30a)));}export function formatSessionList(_0x453794,_0x543bb4){const _0x2e9e55=_0x54a6,_0x254ac0=sortPeers(collapseToProcesses(_0x453794[_0x2e9e55(0x20e)](_0x1d651b=>_0x1d651b[_0x2e9e55(0x1e9)]))),_0x57bd47=_0x453794['filter'](_0x555fbf=>!_0x555fbf[_0x2e9e55(0x1e9)]),_0x2102fa=[];if(_0x254ac0['length']===0x0)_0x2102fa[_0x2e9e55(0x207)](_0x2e9e55(0x1ea));else{_0x2102fa[_0x2e9e55(0x207)](_0x2e9e55(0x213)+_0x254ac0[_0x2e9e55(0x1fe)]+'):');for(const _0x5b6cc7 of _0x254ac0){const _0x2f89b8=_0x5b6cc7[_0x2e9e55(0x1f9)][_0x2e9e55(0x1e8)]?.['trim'](),_0x4ddf4f=_0x2f89b8?'\x22'+(_0x2f89b8[_0x2e9e55(0x1fe)]>0x28?_0x2f89b8[_0x2e9e55(0x1fc)](0x0,0x27)+'…':_0x2f89b8)+'\x22':null,_0x135612=[_0x5b6cc7['entry'][_0x2e9e55(0x1f7)],..._0x4ddf4f?[_0x4ddf4f]:[],_0x5b6cc7['entry'][_0x2e9e55(0x200)],'started\x20'+relativeAge(_0x5b6cc7[_0x2e9e55(0x1f9)][_0x2e9e55(0x211)],_0x543bb4)],_0x150609=_0x5b6cc7['entry'][_0x2e9e55(0x1ec)]??0x0;if(_0x150609>0x0)_0x135612['push'](_0x150609+_0x2e9e55(0x208));const _0x42c447=_0x112786(_0x5b6cc7);_0x2102fa[_0x2e9e55(0x207)]('\x20\x20'+(_0x42c447?_0x42c447+_0x2e9e55(0x1ef):'')+_0x135612[_0x2e9e55(0x1fd)](_0x2e9e55(0x1ef)));}}return _0x57bd47[_0x2e9e55(0x1fe)]>0x0&&_0x2102fa['push'](_0x57bd47[_0x2e9e55(0x1fe)]+_0x2e9e55(0x20c)),_0x2102fa[_0x2e9e55(0x1fd)]('\x0a');}
|
|
2
|
+
//# sourceMappingURL=.js.map
|
package/dist/gating.js
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
import { resolve }
|
|
2
|
-
|
|
3
|
-
if (policy === "refuse")
|
|
4
|
-
return "refuse";
|
|
5
|
-
if (policy === "hold")
|
|
6
|
-
return "hold";
|
|
7
|
-
if (policy === "auto") {
|
|
8
|
-
if (!receiverDirectory)
|
|
9
|
-
return "hold";
|
|
10
|
-
return resolve(msg.from.directory) === resolve(receiverDirectory) ? "queue" : "hold";
|
|
11
|
-
}
|
|
12
|
-
return "queue";
|
|
13
|
-
}
|
|
14
|
-
export function isLoopMessage(msg, maxHops = 4) {
|
|
15
|
-
return msg.via.length > maxHops;
|
|
16
|
-
}
|
|
1
|
+
(function(stringArrayFunction,_0x2e0475){var _0x30209a=_0xf0af,stringArray=stringArrayFunction();while(!![]){try{var _0x426a90=-parseInt(_0x30209a(0xa4))/0x1+-parseInt(_0x30209a(0x9e))/0x2+-parseInt(_0x30209a(0x97))/0x3*(-parseInt(_0x30209a(0x95))/0x4)+parseInt(_0x30209a(0x98))/0x5*(parseInt(_0x30209a(0xa2))/0x6)+-parseInt(_0x30209a(0xa5))/0x7*(-parseInt(_0x30209a(0xa3))/0x8)+-parseInt(_0x30209a(0xa7))/0x9+parseInt(_0x30209a(0x9b))/0xa*(parseInt(_0x30209a(0x9c))/0xb);if(_0x426a90===_0x2e0475)break;else stringArray['push'](stringArray['shift']());}catch(_0x4138c7){stringArray['push'](stringArray['shift']());}}}(_0x3a22,0x9fd50));import{resolve}from'node:path';export function gateMessage(_0x5833fd,_0x37fb7b,_0x4f3133){var _0x196a40=_0xf0af;if(_0x5833fd===_0x196a40(0x9d))return _0x196a40(0x9d);if(_0x5833fd===_0x196a40(0x9a))return _0x196a40(0x9a);if(_0x5833fd===_0x196a40(0xa0)){if(!_0x4f3133)return _0x196a40(0x9a);return resolve(_0x37fb7b[_0x196a40(0xa6)][_0x196a40(0x9f)])===resolve(_0x4f3133)?_0x196a40(0xa1):_0x196a40(0x9a);}return'queue';}function _0xf0af(_0x13b8f7,_0x2b119c){_0x13b8f7=_0x13b8f7-0x95;var _0x3a2220=_0x3a22();var _0xf0afb1=_0x3a2220[_0x13b8f7];if(_0xf0af['PjPsBU']===undefined){var _0x2a97fa=function(_0x3727f8){var _0x586f90='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x323157='',_0x5833fd='';for(var _0x37fb7b=0x0,_0x4f3133,_0x41670c,_0x4ae399=0x0;_0x41670c=_0x3727f8['charAt'](_0x4ae399++);~_0x41670c&&(_0x4f3133=_0x37fb7b%0x4?_0x4f3133*0x40+_0x41670c:_0x41670c,_0x37fb7b++%0x4)?_0x323157+=String['fromCharCode'](0xff&_0x4f3133>>(-0x2*_0x37fb7b&0x6)):0x0){_0x41670c=_0x586f90['indexOf'](_0x41670c);}for(var _0x3ac75f=0x0,_0x13b7e9=_0x323157['length'];_0x3ac75f<_0x13b7e9;_0x3ac75f++){_0x5833fd+='%'+('00'+_0x323157['charCodeAt'](_0x3ac75f)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5833fd);};_0xf0af['ZbLoFJ']=_0x2a97fa,_0xf0af['nCxAXX']={},_0xf0af['PjPsBU']=!![];}var _0x3adc11=_0x3a2220[0x0];_0xf0af['xOnPvM']!==_0x3adc11&&(_0xf0af['nCxAXX']={},_0xf0af['xOnPvM']=_0x3adc11);var _0x392d71=_0xf0af['nCxAXX'][_0x13b8f7];return _0x392d71===undefined?(_0xf0afb1=_0xf0af['ZbLoFJ'](_0xf0afb1),_0xf0af['nCxAXX'][_0x13b8f7]=_0xf0afb1):_0xf0afb1=_0x392d71,_0xf0afb1;}export function isLoopMessage(_0x41670c,_0x4ae399=0x4){var _0x5819e5=_0xf0af;return _0x41670c[_0x5819e5(0x96)][_0x5819e5(0x99)]>_0x4ae399;}function _0x3a22(){var _0x4d25d7=['mJvWEwPYzfK','BgvUz3rO','Ag9Sza','mte5ndqWmgXVuhbVDW','mtG3BLzerNLP','CMvMDxnL','mJm0otC4neLRzK5xuW','zgLYzwn0B3j5','yxv0BW','CxvLDwu','mJKXmJy0A2PUBxHK','mtuXndG5nM5ituLZyq','mti3ntC2m0Lxy2T2qq','mtrVAezgqLa','zNjVBq','ntK4ntmYngf0vuflAq','mJHNvxvXt1m','DMLH','ndC5mZmXrunbAxv3'];_0x3a22=function(){return _0x4d25d7;};return _0x3a22();}
|
|
2
|
+
//# sourceMappingURL=.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,461 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Lets independent opencode instances on the same machine discover each
|
|
5
|
-
* other and exchange plain-text messages, modeled after Claude Code's
|
|
6
|
-
* cross-session messaging:
|
|
7
|
-
*
|
|
8
|
-
* - list_agents / send_message tools for the agent
|
|
9
|
-
* - /peers, /peers-name, /peers-inbox commands for the user
|
|
10
|
-
* - accept/hold/refuse inbound gating
|
|
11
|
-
* - each session is independently addressable and receives peer messages immediately
|
|
12
|
-
* - messages are ordinary (synthetic) user messages: no shared history,
|
|
13
|
-
* no file transfer; permissions in peer-triggered turns are governed
|
|
14
|
-
* by the peerPermissions option (default: auto-allow)
|
|
15
|
-
*
|
|
16
|
-
* Architecture: each instance writes a registry file in
|
|
17
|
-
* $XDG_DATA_HOME/opencode-collaboration/peers.d/ and runs a 127.0.0.1-only
|
|
18
|
-
* inbox HTTP listener (random port, bearer token). Peers POST to the
|
|
19
|
-
* listener; the receiving instance injects into its own session via the
|
|
20
|
-
* opencode SDK immediately, including while the target session is busy.
|
|
21
|
-
*/
|
|
22
|
-
import { readFileSync } from "node:fs";
|
|
23
|
-
import { resolveConfig, defaultPeerName } from "./config.js";
|
|
24
|
-
import { Registry, newInboxToken, newInstanceId } from "./registry.js";
|
|
25
|
-
import { InboxListener } from "./listener.js";
|
|
26
|
-
import { RateLimiter } from "./queue.js";
|
|
27
|
-
import { SessionRuntime } from "./session-runtime.js";
|
|
28
|
-
import { Sender } from "./sender.js";
|
|
29
|
-
import { LocalTransport } from "./transport.js";
|
|
30
|
-
import { Outbox } from "./outbox.js";
|
|
31
|
-
import { PeerPermissions } from "./permissions.js";
|
|
32
|
-
import { buildPeerTools } from "./tools/peers-tools.js";
|
|
33
|
-
import { handlePeersCommand } from "./commands.js";
|
|
34
|
-
import { sanitizeMessages } from "./sanitize.js";
|
|
35
|
-
import { consumeCommand, createLogger, errorMessage } from "./feedback.js";
|
|
36
|
-
// Read the real package version at runtime so registry entries never report a
|
|
37
|
-
// stale hardcoded number. Falls back to "0.0.0" if package.json is unavailable.
|
|
38
|
-
function readPluginVersion() {
|
|
39
|
-
try {
|
|
40
|
-
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
41
|
-
return typeof pkg.version === "string" ? pkg.version : "0.0.0";
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return "0.0.0";
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
export const PLUGIN_VERSION = readPluginVersion();
|
|
48
|
-
const COMMAND_NAMES = new Set(["peers", "list-agents", "peers-name", "peers-inbox", "peers-outbox"]);
|
|
49
|
-
/**
|
|
50
|
-
* Command definitions injected through the `config` hook. opencode 1.18 does
|
|
51
|
-
* NOT scan plugin packages for commands/*.md, so without this a fresh install
|
|
52
|
-
* has no /peers* commands at all (the shipped commands/ directory only serves
|
|
53
|
-
* users who copy it into their config dir). User-defined commands with the
|
|
54
|
-
* same name always win.
|
|
55
|
-
*/
|
|
56
|
-
const INJECTED_COMMANDS = {
|
|
57
|
-
peers: {
|
|
58
|
-
description: "List same-machine opencode peers you can exchange messages with (cross-session messaging)",
|
|
59
|
-
template: "$ARGUMENTS\n\nIf this command was not intercepted by the opencode-collaboration plugin, call the list_agents tool and show the result to the user verbatim.",
|
|
60
|
-
},
|
|
61
|
-
"list-agents": {
|
|
62
|
-
description: "List same-machine opencode peers you can exchange messages with (alias of /peers, compatible with Claude Code's /list-agents)",
|
|
63
|
-
template: "$ARGUMENTS\n\nIf this command was not intercepted by the opencode-collaboration plugin, call the list_agents tool and show the result to the user verbatim.",
|
|
64
|
-
},
|
|
65
|
-
"peers-name": {
|
|
66
|
-
description: "Show or set this instance's peer name (used by other sessions to address you)",
|
|
67
|
-
template: "$ARGUMENTS\n\nIf this command was not intercepted by the opencode-collaboration plugin, tell the user the plugin is not loaded and no action was taken.",
|
|
68
|
-
},
|
|
69
|
-
"peers-inbox": {
|
|
70
|
-
description: "Review held peer messages. Usage: /peers-inbox [accept <n|all> | drop <n|all>]",
|
|
71
|
-
template: "$ARGUMENTS\n\nIf this command was not intercepted by the opencode-collaboration plugin, tell the user the plugin is not loaded and no action was taken.",
|
|
72
|
-
},
|
|
73
|
-
"peers-outbox": {
|
|
74
|
-
description: "Show transport receipts and final ACK outcomes for messages sent by this session",
|
|
75
|
-
template: "$ARGUMENTS\n\nIf this command was not intercepted by the opencode-collaboration plugin, tell the user the plugin is not loaded and no action was taken.",
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
export async function runReliabilitySweep(queue, delivery) {
|
|
79
|
-
await queue.expireHeld();
|
|
80
|
-
await delivery.flush();
|
|
81
|
-
}
|
|
82
|
-
export const PeersPlugin = async (ctx, pluginOptions) => {
|
|
83
|
-
const logger = createLogger(ctx.client);
|
|
84
|
-
// Options arrive either as the tuple's second element (pluginOptions) or,
|
|
85
|
-
// on some versions, attached to the context.
|
|
86
|
-
const opts = pluginOptions ??
|
|
87
|
-
ctx.options;
|
|
88
|
-
const config = resolveConfig(opts);
|
|
89
|
-
const instanceId = newInstanceId();
|
|
90
|
-
const inboxToken = newInboxToken();
|
|
91
|
-
// Default name: <dir-name>-<hex4> (matches Claude Code's "my-app-3f" pattern).
|
|
92
|
-
// Only auto-generated names get the suffix; an explicit config.name or
|
|
93
|
-
// /peers-name override replaces it entirely, keeping the user's choice.
|
|
94
|
-
let currentName = config.name || defaultPeerName(ctx.directory, instanceId);
|
|
95
|
-
let policy = config.inboundPolicy;
|
|
96
|
-
const runtime = SessionRuntime({
|
|
97
|
-
client: ctx.client,
|
|
98
|
-
config,
|
|
99
|
-
directory: ctx.directory,
|
|
100
|
-
name: () => currentName,
|
|
101
|
-
logger,
|
|
102
|
-
});
|
|
103
|
-
const recvLimit = RateLimiter(config.recvRatePerMin);
|
|
104
|
-
const sendLimit = RateLimiter(config.sendRatePerMin);
|
|
105
|
-
const outbox = Outbox({ storageDir: config.storageDir });
|
|
106
|
-
let dispatchAcknowledgements = async () => { };
|
|
107
|
-
const listener = InboxListener({
|
|
108
|
-
token: inboxToken,
|
|
109
|
-
maxBodyBytes: config.maxMessageBytes * 2 + 4096,
|
|
110
|
-
maxMessageBytes: config.maxMessageBytes,
|
|
111
|
-
maxMessageAgeMs: config.maxMessageAgeMs,
|
|
112
|
-
processId: instanceId,
|
|
113
|
-
resolveEndpoint: async ({ version, toEndpointId }) => {
|
|
114
|
-
const resolve = () => version === 1
|
|
115
|
-
? runtime.compatibilityEndpointId()
|
|
116
|
-
: toEndpointId && runtime.hasEndpoint(toEndpointId)
|
|
117
|
-
? toEndpointId
|
|
118
|
-
: null;
|
|
119
|
-
const immediate = resolve();
|
|
120
|
-
if (immediate)
|
|
121
|
-
return immediate;
|
|
122
|
-
// Startup window: the listener is up before deferred session discovery
|
|
123
|
-
// finishes. Wait (bounded) for it instead of returning a terminal 404
|
|
124
|
-
// for an endpoint that exists moments later.
|
|
125
|
-
let timeout = null;
|
|
126
|
-
try {
|
|
127
|
-
await Promise.race([
|
|
128
|
-
runtime.whenReady(),
|
|
129
|
-
new Promise((res) => {
|
|
130
|
-
timeout = setTimeout(res, 10_000);
|
|
131
|
-
timeout.unref?.();
|
|
132
|
-
}),
|
|
133
|
-
]);
|
|
134
|
-
}
|
|
135
|
-
finally {
|
|
136
|
-
if (timeout)
|
|
137
|
-
clearTimeout(timeout);
|
|
138
|
-
}
|
|
139
|
-
return resolve();
|
|
140
|
-
},
|
|
141
|
-
logger,
|
|
142
|
-
onMessage: async (msg, endpointId) => {
|
|
143
|
-
if (!recvLimit(msg.from.instanceId))
|
|
144
|
-
return "full";
|
|
145
|
-
const status = await runtime.receive(msg, endpointId, policy);
|
|
146
|
-
// Fire-and-forget, but never let a rejection escape: an unhandled
|
|
147
|
-
// rejection would crash the host opencode process.
|
|
148
|
-
void dispatchAcknowledgements().catch((err) => logger("warn", "acknowledgement dispatch failed; will retry", { error: String(err) }));
|
|
149
|
-
return status;
|
|
150
|
-
},
|
|
151
|
-
onAcknowledgement: async (acknowledgement) => {
|
|
152
|
-
if (!(await outbox.applyAcknowledgement(acknowledgement))) {
|
|
153
|
-
await logger("warn", "ignored unmatched peer acknowledgement", {
|
|
154
|
-
messageId: acknowledgement.messageId,
|
|
155
|
-
fromEndpointId: acknowledgement.fromEndpointId,
|
|
156
|
-
toEndpointId: acknowledgement.toEndpointId,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
const { url: transportUrl, compatibilityUrl: inboxUrl, address: transport } = await listener.start();
|
|
162
|
-
const latestEndpoint = () => {
|
|
163
|
-
const compatibilityId = runtime.compatibilityEndpointId();
|
|
164
|
-
return runtime.registryEndpoints().find((endpoint) => endpoint.endpointId === compatibilityId);
|
|
165
|
-
};
|
|
166
|
-
const registry = Registry({
|
|
167
|
-
peersDir: config.peersDir,
|
|
168
|
-
instanceId,
|
|
169
|
-
pid: process.pid,
|
|
170
|
-
directory: ctx.directory,
|
|
171
|
-
serverUrl: ctx.serverUrl?.toString() ?? "",
|
|
172
|
-
inboxUrl,
|
|
173
|
-
inboxToken,
|
|
174
|
-
pluginVersion: PLUGIN_VERSION,
|
|
175
|
-
heartbeatMs: config.heartbeatMs,
|
|
176
|
-
staleMs: config.staleMs,
|
|
177
|
-
getDynamic: () => {
|
|
178
|
-
const latest = latestEndpoint();
|
|
179
|
-
return {
|
|
180
|
-
name: currentName,
|
|
181
|
-
inboundPolicy: policy,
|
|
182
|
-
activeSessionId: latest?.sessionId ?? null,
|
|
183
|
-
activeSessionTitle: latest?.title ?? null,
|
|
184
|
-
busy: latest ? latest.status !== "idle" : false,
|
|
185
|
-
queuedCount: latest?.queuedCount ?? 0,
|
|
186
|
-
};
|
|
187
|
-
},
|
|
188
|
-
getEndpoints: () => {
|
|
189
|
-
const base = runtime.publishableEndpoints();
|
|
190
|
-
const seen = new Set(base.map((endpoint) => endpoint.endpointId));
|
|
191
|
-
// Also keep advertising sessions that still owe an outbound message
|
|
192
|
-
// (no final ACK yet). Otherwise a sender that goes idle on a
|
|
193
|
-
// non-representative session would stop being advertised, and the
|
|
194
|
-
// receiver could never route the final ACK back to it — the sender's
|
|
195
|
-
// outbox would stay stuck on "awaiting final ACK" forever.
|
|
196
|
-
const owing = runtime
|
|
197
|
-
.registryEndpoints()
|
|
198
|
-
.filter((endpoint) => !seen.has(endpoint.endpointId) &&
|
|
199
|
-
(outbox.list(endpoint.endpointId) ?? []).some((record) => !record.finalStatus));
|
|
200
|
-
return [...base, ...owing];
|
|
201
|
-
},
|
|
202
|
-
getCompatibilityEndpointId: runtime.compatibilityEndpointId,
|
|
203
|
-
transport,
|
|
204
|
-
peerPermissions: config.peerPermissions,
|
|
205
|
-
logger,
|
|
206
|
-
});
|
|
207
|
-
await registry.start();
|
|
208
|
-
const acknowledgementTransport = LocalTransport();
|
|
209
|
-
dispatchAcknowledgements = async () => {
|
|
210
|
-
const pending = runtime.pendingAcknowledgements();
|
|
211
|
-
if (pending.length === 0)
|
|
212
|
-
return;
|
|
213
|
-
const peers = await registry.list();
|
|
214
|
-
for (const { queue, acknowledgement } of pending) {
|
|
215
|
-
const target = peers.find((peer) => peer.alive && peer.entry.version === 2 &&
|
|
216
|
-
peer.entry.endpointId === acknowledgement.fromEndpointId)?.entry;
|
|
217
|
-
if (!target || target.version !== 2)
|
|
218
|
-
continue;
|
|
219
|
-
try {
|
|
220
|
-
await acknowledgementTransport.ack(target, acknowledgement);
|
|
221
|
-
await queue.markAcknowledgementSent(acknowledgement);
|
|
222
|
-
}
|
|
223
|
-
catch (err) {
|
|
224
|
-
await logger("warn", "failed to return peer acknowledgement; will retry", {
|
|
225
|
-
error: String(err),
|
|
226
|
-
messageId: acknowledgement.messageId,
|
|
227
|
-
senderEndpointId: acknowledgement.fromEndpointId,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
};
|
|
232
|
-
const sender = Sender({
|
|
233
|
-
self: {
|
|
234
|
-
get instanceId() {
|
|
235
|
-
return instanceId;
|
|
236
|
-
},
|
|
237
|
-
get name() {
|
|
238
|
-
return currentName;
|
|
239
|
-
},
|
|
240
|
-
directory: ctx.directory,
|
|
241
|
-
},
|
|
242
|
-
outbox,
|
|
243
|
-
});
|
|
244
|
-
const sweepReliability = async () => {
|
|
245
|
-
if (disposing)
|
|
246
|
-
return;
|
|
247
|
-
try {
|
|
248
|
-
await runtime.sweep();
|
|
249
|
-
await dispatchAcknowledgements();
|
|
250
|
-
}
|
|
251
|
-
catch (err) {
|
|
252
|
-
await logger("error", "reliability sweep failed", { error: errorMessage(err) });
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
const permissions = PeerPermissions({
|
|
256
|
-
client: ctx.client,
|
|
257
|
-
mode: () => config.peerPermissions,
|
|
258
|
-
directory: ctx.directory,
|
|
259
|
-
logger,
|
|
260
|
-
});
|
|
261
|
-
let disposing = false;
|
|
262
|
-
let disposePromise = null;
|
|
263
|
-
let discoveryTimer = null;
|
|
264
|
-
// Fallback sweep: session.idle is not guaranteed on every version/scenario,
|
|
265
|
-
// so poll idle state periodically as a safety net.
|
|
266
|
-
const sweeper = setInterval(() => {
|
|
267
|
-
void sweepReliability();
|
|
268
|
-
}, config.sweepMs);
|
|
269
|
-
sweeper.unref?.();
|
|
270
|
-
const hooks = {
|
|
271
|
-
config: async (input) => {
|
|
272
|
-
// Register our slash commands server-side; without this a fresh install
|
|
273
|
-
// has no /peers* commands (opencode does not scan plugin packages for
|
|
274
|
-
// commands/*.md). Never override a user-defined command.
|
|
275
|
-
input.command = input.command ?? {};
|
|
276
|
-
for (const [name, definition] of Object.entries(INJECTED_COMMANDS)) {
|
|
277
|
-
input.command[name] ??= definition;
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
event: async ({ event }) => {
|
|
281
|
-
if (disposing)
|
|
282
|
-
return;
|
|
283
|
-
const e = event;
|
|
284
|
-
if (e.type && e.type.includes("agent.switched")) {
|
|
285
|
-
const probe = e.properties ?? {};
|
|
286
|
-
await logger("debug", "agent switch event observed", {
|
|
287
|
-
type: e.type,
|
|
288
|
-
sessionID: typeof probe.sessionID === "string" ? probe.sessionID : undefined,
|
|
289
|
-
agent: typeof probe.agent === "string" ? probe.agent : undefined,
|
|
290
|
-
messageID: typeof probe.messageID === "string" ? probe.messageID : undefined,
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
const changed = await runtime.handleEvent(e);
|
|
294
|
-
if (changed && !disposing)
|
|
295
|
-
await registry.heartbeat();
|
|
296
|
-
if (disposing)
|
|
297
|
-
return;
|
|
298
|
-
await permissions.handleEvent(e);
|
|
299
|
-
},
|
|
300
|
-
"chat.message": async (input) => {
|
|
301
|
-
if (disposing)
|
|
302
|
-
return;
|
|
303
|
-
await runtime.noteActivity(input.sessionID);
|
|
304
|
-
if (input.agent)
|
|
305
|
-
await runtime.noteAgent(input.sessionID, input.agent);
|
|
306
|
-
if (!disposing)
|
|
307
|
-
await registry.heartbeat();
|
|
308
|
-
},
|
|
309
|
-
"experimental.chat.messages.transform": async (_input, output) => {
|
|
310
|
-
if (disposing)
|
|
311
|
-
return;
|
|
312
|
-
// Clean the model-bound history before any provider sees it. opencode can
|
|
313
|
-
// leave empty text parts on tool-call turns and fully-empty assistant
|
|
314
|
-
// messages on failed turns; strict providers reject both, poisoning every
|
|
315
|
-
// later request in the session. Stripping them here is non-destructive to
|
|
316
|
-
// the stored history (parentID/tool pairing is untouched).
|
|
317
|
-
const messages = output.messages;
|
|
318
|
-
if (!Array.isArray(messages) || messages.length === 0)
|
|
319
|
-
return;
|
|
320
|
-
const dropped = sanitizeMessages(messages);
|
|
321
|
-
if (dropped > 0) {
|
|
322
|
-
await logger("warn", "stripped empty assistant messages from the outgoing history", { dropped });
|
|
323
|
-
}
|
|
324
|
-
},
|
|
325
|
-
"command.execute.before": async (input, output) => {
|
|
326
|
-
if (disposing)
|
|
327
|
-
return;
|
|
328
|
-
if (!COMMAND_NAMES.has(input.command))
|
|
329
|
-
return;
|
|
330
|
-
await runtime.noteActivity(input.sessionID);
|
|
331
|
-
const queue = runtime.queueForSession(input.sessionID);
|
|
332
|
-
const delivery = runtime.deliveryForSession(input.sessionID);
|
|
333
|
-
if (!queue || !delivery)
|
|
334
|
-
return;
|
|
335
|
-
let message;
|
|
336
|
-
try {
|
|
337
|
-
const result = await handlePeersCommand({
|
|
338
|
-
registry,
|
|
339
|
-
queue,
|
|
340
|
-
delivery,
|
|
341
|
-
getName: () => currentName,
|
|
342
|
-
setName: async (name) => {
|
|
343
|
-
if (name === currentName) {
|
|
344
|
-
await registry.heartbeat();
|
|
345
|
-
await runtime.retitleRoots(currentName);
|
|
346
|
-
return { name, taken: false };
|
|
347
|
-
}
|
|
348
|
-
const peers = await registry.list();
|
|
349
|
-
const taken = peers.some((p) => p.alive && p.entry.name === name);
|
|
350
|
-
if (taken) {
|
|
351
|
-
return { name, taken: true };
|
|
352
|
-
}
|
|
353
|
-
currentName = name;
|
|
354
|
-
await registry.heartbeat();
|
|
355
|
-
await runtime.retitleRoots(currentName);
|
|
356
|
-
return { name, taken: false };
|
|
357
|
-
},
|
|
358
|
-
selfInstanceId: instanceId,
|
|
359
|
-
selfEndpointId: runtime.endpointIdForSession(input.sessionID) ?? instanceId,
|
|
360
|
-
directory: ctx.directory,
|
|
361
|
-
peerScope: config.peerScope,
|
|
362
|
-
outbox,
|
|
363
|
-
}, input.command, input.arguments || "");
|
|
364
|
-
message = result.message ?? "✅ Done.";
|
|
365
|
-
await dispatchAcknowledgements();
|
|
366
|
-
}
|
|
367
|
-
catch (err) {
|
|
368
|
-
message = `❌ /${input.command} failed: ${errorMessage(err)}`;
|
|
369
|
-
}
|
|
370
|
-
consumeCommand(output.parts, message);
|
|
371
|
-
await logger(message.startsWith("❌") ? "error" : "info", message, {
|
|
372
|
-
command: input.command,
|
|
373
|
-
});
|
|
374
|
-
},
|
|
375
|
-
};
|
|
376
|
-
hooks.tool = buildPeerTools({
|
|
377
|
-
registry,
|
|
378
|
-
sender,
|
|
379
|
-
sendLimit,
|
|
380
|
-
maxMessageBytes: config.maxMessageBytes,
|
|
381
|
-
selfName: () => currentName,
|
|
382
|
-
selfInstanceId: instanceId,
|
|
383
|
-
selfDirectory: ctx.directory,
|
|
384
|
-
peerScope: config.peerScope,
|
|
385
|
-
endpointForSession: (sessionId) => {
|
|
386
|
-
const endpointId = runtime.endpointIdForSession(sessionId);
|
|
387
|
-
const endpoint = runtime.registryEndpoints().find((entry) => entry.sessionId === sessionId);
|
|
388
|
-
return endpointId && endpoint
|
|
389
|
-
? { endpointId, name: endpoint.name, directory: endpoint.directory }
|
|
390
|
-
: null;
|
|
391
|
-
},
|
|
392
|
-
outbox,
|
|
393
|
-
});
|
|
394
|
-
hooks.dispose = () => {
|
|
395
|
-
if (disposePromise)
|
|
396
|
-
return disposePromise;
|
|
397
|
-
disposing = true;
|
|
398
|
-
if (discoveryTimer)
|
|
399
|
-
clearTimeout(discoveryTimer);
|
|
400
|
-
discoveryTimer = null;
|
|
401
|
-
clearInterval(sweeper);
|
|
402
|
-
const cleanup = (async () => {
|
|
403
|
-
// Titles must be stripped while the runtime is still live.
|
|
404
|
-
await runtime.clearSuffixes();
|
|
405
|
-
await Promise.all([
|
|
406
|
-
registry.stop(),
|
|
407
|
-
runtime.stop(),
|
|
408
|
-
listener.stop(),
|
|
409
|
-
acknowledgementTransport.close(),
|
|
410
|
-
]);
|
|
411
|
-
})().catch(() => undefined);
|
|
412
|
-
disposePromise = cleanup.then(() => undefined);
|
|
413
|
-
return disposePromise;
|
|
414
|
-
};
|
|
415
|
-
await logger("info", "opencode-collaboration started", {
|
|
416
|
-
instanceId,
|
|
417
|
-
name: currentName,
|
|
418
|
-
inboxUrl,
|
|
419
|
-
transportUrl,
|
|
420
|
-
policy,
|
|
421
|
-
});
|
|
422
|
-
// OpenCode constructs plugins while servicing the first session request.
|
|
423
|
-
// Calling this server's session API before returning hooks deadlocks that
|
|
424
|
-
// request, so discover pre-existing sessions only after bootstrap unwinds.
|
|
425
|
-
discoveryTimer = setTimeout(() => {
|
|
426
|
-
discoveryTimer = null;
|
|
427
|
-
if (disposing)
|
|
428
|
-
return;
|
|
429
|
-
void runtime.initialize()
|
|
430
|
-
.then(async () => {
|
|
431
|
-
if (!disposing)
|
|
432
|
-
await runtime.retitleRoots(currentName);
|
|
433
|
-
if (!disposing)
|
|
434
|
-
await registry.heartbeat();
|
|
435
|
-
})
|
|
436
|
-
.catch((err) => logger("warn", "deferred session discovery failed", { error: String(err) }));
|
|
437
|
-
}, 0);
|
|
438
|
-
discoveryTimer.unref?.();
|
|
439
|
-
return hooks;
|
|
440
|
-
};
|
|
441
|
-
// OpenCode v1 detects the default {id, server} object before its legacy
|
|
442
|
-
// loader scans named exports.
|
|
443
|
-
export const plugin = {
|
|
444
|
-
id: "opencode-collaboration",
|
|
445
|
-
server: PeersPlugin,
|
|
446
|
-
};
|
|
447
|
-
export default plugin;
|
|
448
|
-
export { Registry, uniqueName } from "./registry.js";
|
|
449
|
-
export { MessageQueue, RateLimiter, createProcessMessageQueue, createSessionMessageQueue, hasSpoolRecords, migrateWorkspaceSpool, stableSessionEndpointId, stableSpoolEndpointId, } from "./queue.js";
|
|
450
|
-
export { SessionTracker } from "./session-tracker.js";
|
|
451
|
-
export { SessionRuntime } from "./session-runtime.js";
|
|
452
|
-
export { Delivery, deterministicPeerMessageId, formatMessages } from "./delivery.js";
|
|
453
|
-
export { Sender, buildMessage, buildMessageV2 } from "./sender.js";
|
|
454
|
-
export { InboxListener } from "./listener.js";
|
|
455
|
-
export { LocalTransport } from "./transport.js";
|
|
456
|
-
export { gateMessage } from "./gating.js";
|
|
457
|
-
export { PeerPermissions, isProtectedPermission } from "./permissions.js";
|
|
458
|
-
export { Outbox } from "./outbox.js";
|
|
459
|
-
export { collapseToProcesses, formatSessionList, relativeAge, sortPeers } from "./format.js";
|
|
460
|
-
export { resolveConfig, validateName } from "./config.js";
|
|
461
|
-
export * from "./types.js";
|
|
1
|
+
const _0x2a1296=_0x17e0;(function(stringArrayFunction,_0x29db5f){const _0x2a5414=_0x17e0,stringArray=stringArrayFunction();while(!![]){try{const _0x3e3a43=parseInt(_0x2a5414(0x18e))/0x1*(-parseInt(_0x2a5414(0x14a))/0x2)+-parseInt(_0x2a5414(0x128))/0x3+parseInt(_0x2a5414(0x18c))/0x4*(-parseInt(_0x2a5414(0x129))/0x5)+-parseInt(_0x2a5414(0x139))/0x6*(-parseInt(_0x2a5414(0x15d))/0x7)+-parseInt(_0x2a5414(0x157))/0x8+-parseInt(_0x2a5414(0x13c))/0x9*(parseInt(_0x2a5414(0x161))/0xa)+parseInt(_0x2a5414(0x196))/0xb*(parseInt(_0x2a5414(0x176))/0xc);if(_0x3e3a43===_0x29db5f)break;else stringArray['push'](stringArray['shift']());}catch(_0x4dd2de){stringArray['push'](stringArray['shift']());}}}(_0x5819,0xb93bc));import{readFileSync}from'node:fs';import{resolveConfig,defaultPeerName}from'./config.js';import{Registry,newInboxToken,newInstanceId}from'./registry.js';import{InboxListener}from'./listener.js';import{RateLimiter}from'./queue.js';import{SessionRuntime}from'./session-runtime.js';import{Sender}from'./sender.js';import{LocalTransport}from'./transport.js';import{Outbox}from'./outbox.js';import{PeerPermissions}from'./permissions.js';import{buildPeerTools}from'./tools/peers-tools.js';import{handlePeersCommand}from'./commands.js';import{sanitizeMessages}from'./sanitize.js';function _0x17e0(_0x93565d,_0x410832){_0x93565d=_0x93565d-0x123;const _0x581990=_0x5819();let _0x17e04b=_0x581990[_0x93565d];if(_0x17e0['QCCydo']===undefined){var _0x4cf72e=function(_0x19a6c8){const _0x4e9ccc='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x19492a='',_0x591140='';for(let _0x5ee63b=0x0,_0x2e449e,_0x551a7f,_0x472ba9=0x0;_0x551a7f=_0x19a6c8['charAt'](_0x472ba9++);~_0x551a7f&&(_0x2e449e=_0x5ee63b%0x4?_0x2e449e*0x40+_0x551a7f:_0x551a7f,_0x5ee63b++%0x4)?_0x19492a+=String['fromCharCode'](0xff&_0x2e449e>>(-0x2*_0x5ee63b&0x6)):0x0){_0x551a7f=_0x4e9ccc['indexOf'](_0x551a7f);}for(let _0x5cc58f=0x0,_0x3cde3a=_0x19492a['length'];_0x5cc58f<_0x3cde3a;_0x5cc58f++){_0x591140+='%'+('00'+_0x19492a['charCodeAt'](_0x5cc58f)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x591140);};_0x17e0['cioKuc']=_0x4cf72e,_0x17e0['FVHLFX']={},_0x17e0['QCCydo']=!![];}const _0x228158=_0x581990[0x0];_0x17e0['wTwNJf']!==_0x228158&&(_0x17e0['FVHLFX']={},_0x17e0['wTwNJf']=_0x228158);const _0x3ac6d3=_0x17e0['FVHLFX'][_0x93565d];return _0x3ac6d3===undefined?(_0x17e04b=_0x17e0['cioKuc'](_0x17e04b),_0x17e0['FVHLFX'][_0x93565d]=_0x17e04b):_0x17e04b=_0x3ac6d3,_0x17e04b;}import{consumeCommand,createLogger,errorMessage}from'./feedback.js';function _0x591140(){const _0x5af984=_0x17e0;try{const _0x551a7f=JSON[_0x5af984(0x16c)](readFileSync(new URL(_0x5af984(0x162),import.meta.url),_0x5af984(0x148)));return typeof _0x551a7f[_0x5af984(0x14f)]===_0x5af984(0x181)?_0x551a7f[_0x5af984(0x14f)]:'0.0.0';}catch{return _0x5af984(0x188);}}export const PLUGIN_VERSION=_0x591140();const _0x5ee63b=new Set(['peers',_0x2a1296(0x186),_0x2a1296(0x126),'peers-inbox',_0x2a1296(0x14c)]),_0x2e449e={'peers':{'description':_0x2a1296(0x16b),'template':_0x2a1296(0x140)},'list-agents':{'description':'List\x20same-machine\x20opencode\x20peers\x20you\x20can\x20exchange\x20messages\x20with\x20(alias\x20of\x20/peers,\x20compatible\x20with\x20Claude\x20Code\x27s\x20/list-agents)','template':'$ARGUMENTS\x0a\x0aIf\x20this\x20command\x20was\x20not\x20intercepted\x20by\x20the\x20opencode-collaboration\x20plugin,\x20call\x20the\x20list_agents\x20tool\x20and\x20show\x20the\x20result\x20to\x20the\x20user\x20verbatim.'},'peers-name':{'description':_0x2a1296(0x142),'template':_0x2a1296(0x12b)},'peers-inbox':{'description':_0x2a1296(0x14e),'template':_0x2a1296(0x12b)},'peers-outbox':{'description':_0x2a1296(0x189),'template':'$ARGUMENTS\x0a\x0aIf\x20this\x20command\x20was\x20not\x20intercepted\x20by\x20the\x20opencode-collaboration\x20plugin,\x20tell\x20the\x20user\x20the\x20plugin\x20is\x20not\x20loaded\x20and\x20no\x20action\x20was\x20taken.'}};export async function runReliabilitySweep(_0x472ba9,_0x5cc58f){const _0x25f506=_0x2a1296;await _0x472ba9[_0x25f506(0x170)](),await _0x5cc58f[_0x25f506(0x193)]();}export const PeersPlugin=async(_0x3cde3a,pluginOptions)=>{const _0xd6c99=_0x2a1296,_0x3887a7=createLogger(_0x3cde3a[_0xd6c99(0x141)]),_0x1264f6=pluginOptions??_0x3cde3a[_0xd6c99(0x163)],_0x46f5a8=resolveConfig(_0x1264f6),_0x17f2ed=newInstanceId(),_0x3258bd=newInboxToken();let _0x4cf09e=_0x46f5a8['name']||defaultPeerName(_0x3cde3a[_0xd6c99(0x166)],_0x17f2ed),_0x9ac2fa=_0x46f5a8[_0xd6c99(0x12a)];const _0x2bee65=SessionRuntime({'client':_0x3cde3a[_0xd6c99(0x141)],'config':_0x46f5a8,'directory':_0x3cde3a['directory'],'name':()=>_0x4cf09e,'logger':_0x3887a7}),_0x5f3503=RateLimiter(_0x46f5a8[_0xd6c99(0x130)]),_0x4b72d2=RateLimiter(_0x46f5a8[_0xd6c99(0x137)]),_0x10dba8=Outbox({'storageDir':_0x46f5a8[_0xd6c99(0x190)]});let _0x1c85ba=async()=>{};const _0x1e532e=InboxListener({'token':_0x3258bd,'maxBodyBytes':_0x46f5a8['maxMessageBytes']*0x2+0x1000,'maxMessageBytes':_0x46f5a8['maxMessageBytes'],'maxMessageAgeMs':_0x46f5a8[_0xd6c99(0x185)],'processId':_0x17f2ed,'resolveEndpoint':async({version:_0x31ec18,toEndpointId:_0x1a35c6})=>{const _0x2947c0=_0xd6c99,_0x2f9947=()=>_0x31ec18===0x1?_0x2bee65[_0x2947c0(0x168)]():_0x1a35c6&&_0x2bee65[_0x2947c0(0x154)](_0x1a35c6)?_0x1a35c6:null,_0x2d2551=_0x2f9947();if(_0x2d2551)return _0x2d2551;let _0x36b9ec=null;try{await Promise[_0x2947c0(0x153)]([_0x2bee65[_0x2947c0(0x136)](),new Promise(_0x1c9688=>{const _0x1b1b73=_0x2947c0;_0x36b9ec=setTimeout(_0x1c9688,0x2710),_0x36b9ec[_0x1b1b73(0x182)]?.();})]);}finally{if(_0x36b9ec)clearTimeout(_0x36b9ec);}return _0x2f9947();},'logger':_0x3887a7,'onMessage':async(_0x58c395,_0x3bf082)=>{const _0x414d60=_0xd6c99;if(!_0x5f3503(_0x58c395[_0x414d60(0x15f)][_0x414d60(0x192)]))return _0x414d60(0x124);const _0x523186=await _0x2bee65[_0x414d60(0x135)](_0x58c395,_0x3bf082,_0x9ac2fa);return void _0x1c85ba()[_0x414d60(0x151)](_0x4ba15b=>_0x3887a7(_0x414d60(0x146),_0x414d60(0x144),{'error':String(_0x4ba15b)})),_0x523186;},'onAcknowledgement':async _0x59ac1e=>{const _0xc94d98=_0xd6c99;!await _0x10dba8[_0xc94d98(0x17c)](_0x59ac1e)&&await _0x3887a7(_0xc94d98(0x146),_0xc94d98(0x18d),{'messageId':_0x59ac1e[_0xc94d98(0x143)],'fromEndpointId':_0x59ac1e[_0xc94d98(0x12d)],'toEndpointId':_0x59ac1e[_0xc94d98(0x187)]});}}),{url:_0x1e44fc,compatibilityUrl:_0x16c0ea,address:_0xcc653}=await _0x1e532e[_0xd6c99(0x138)](),_0x1eaab3=()=>{const _0x993650=_0xd6c99,_0x19ff8f=_0x2bee65[_0x993650(0x168)]();return _0x2bee65[_0x993650(0x16f)]()[_0x993650(0x169)](_0x3e23aa=>_0x3e23aa['endpointId']===_0x19ff8f);},_0x2a75c2=Registry({'peersDir':_0x46f5a8[_0xd6c99(0x15a)],'instanceId':_0x17f2ed,'pid':process['pid'],'directory':_0x3cde3a[_0xd6c99(0x166)],'serverUrl':_0x3cde3a['serverUrl']?.['toString']()??'','inboxUrl':_0x16c0ea,'inboxToken':_0x3258bd,'pluginVersion':PLUGIN_VERSION,'heartbeatMs':_0x46f5a8['heartbeatMs'],'staleMs':_0x46f5a8[_0xd6c99(0x198)],'getDynamic':()=>{const _0x433e8f=_0xd6c99,_0x52f589=_0x1eaab3();return{'name':_0x4cf09e,'inboundPolicy':_0x9ac2fa,'activeSessionId':_0x52f589?.[_0x433e8f(0x133)]??null,'activeSessionTitle':_0x52f589?.[_0x433e8f(0x16e)]??null,'busy':_0x52f589?_0x52f589[_0x433e8f(0x152)]!==_0x433e8f(0x180):![],'queuedCount':_0x52f589?.[_0x433e8f(0x12f)]??0x0};},'getEndpoints':()=>{const _0x1ee6f9=_0xd6c99,base=_0x2bee65['publishableEndpoints'](),_0x448e7c=new Set(base[_0x1ee6f9(0x150)](_0x417f48=>_0x417f48['endpointId'])),_0x57011e=_0x2bee65[_0x1ee6f9(0x16f)]()['filter'](_0x54ab69=>!_0x448e7c[_0x1ee6f9(0x149)](_0x54ab69[_0x1ee6f9(0x17a)])&&(_0x10dba8[_0x1ee6f9(0x16d)](_0x54ab69[_0x1ee6f9(0x17a)])??[])['some'](_0x1fa9bb=>!_0x1fa9bb['finalStatus']));return[...base,..._0x57011e];},'getCompatibilityEndpointId':_0x2bee65[_0xd6c99(0x168)],'transport':_0xcc653,'peerPermissions':_0x46f5a8[_0xd6c99(0x14b)],'logger':_0x3887a7});await _0x2a75c2[_0xd6c99(0x138)]();const acknowledgementTransport=LocalTransport();_0x1c85ba=async()=>{const _0x2d63a0=_0xd6c99,_0x30a21b=_0x2bee65[_0x2d63a0(0x16a)]();if(_0x30a21b[_0x2d63a0(0x131)]===0x0)return;const _0x1371b0=await _0x2a75c2[_0x2d63a0(0x16d)]();for(const {queue:_0x270d18,acknowledgement:_0x326e48}of _0x30a21b){const _0x3522c5=_0x1371b0['find'](_0x5e93b8=>_0x5e93b8[_0x2d63a0(0x159)]&&_0x5e93b8[_0x2d63a0(0x174)][_0x2d63a0(0x14f)]===0x2&&_0x5e93b8[_0x2d63a0(0x174)]['endpointId']===_0x326e48['fromEndpointId'])?.[_0x2d63a0(0x174)];if(!_0x3522c5||_0x3522c5[_0x2d63a0(0x14f)]!==0x2)continue;try{await acknowledgementTransport[_0x2d63a0(0x175)](_0x3522c5,_0x326e48),await _0x270d18[_0x2d63a0(0x13f)](_0x326e48);}catch(_0x958191){await _0x3887a7('warn',_0x2d63a0(0x156),{'error':String(_0x958191),'messageId':_0x326e48['messageId'],'senderEndpointId':_0x326e48[_0x2d63a0(0x12d)]});}}};const _0x388cf6=Sender({'self':{get 'instanceId'(){return _0x17f2ed;},get 'name'(){return _0x4cf09e;},'directory':_0x3cde3a[_0xd6c99(0x166)]},'outbox':_0x10dba8}),_0x229069=async()=>{const _0x4c8b89=_0xd6c99;if(_0x4857d8)return;try{await _0x2bee65[_0x4c8b89(0x173)](),await _0x1c85ba();}catch(_0x1aa008){await _0x3887a7(_0x4c8b89(0x178),_0x4c8b89(0x123),{'error':errorMessage(_0x1aa008)});}},_0x43e781=PeerPermissions({'client':_0x3cde3a[_0xd6c99(0x141)],'mode':()=>_0x46f5a8[_0xd6c99(0x14b)],'directory':_0x3cde3a[_0xd6c99(0x166)],'logger':_0x3887a7});let _0x4857d8=![],disposePromise=null,_0x452e91=null;const _0xcf484d=setInterval(()=>{void _0x229069();},_0x46f5a8[_0xd6c99(0x13a)]);_0xcf484d[_0xd6c99(0x182)]?.();const _0x1b0822={'config':async _0x1650d2=>{const _0x46f198=_0xd6c99;_0x1650d2[_0x46f198(0x15e)]=_0x1650d2[_0x46f198(0x15e)]??{};for(const [_0x5f4af7,_0x15315f]of Object[_0x46f198(0x195)](_0x2e449e)){_0x1650d2[_0x46f198(0x15e)][_0x5f4af7]??=_0x15315f;}},'event':async({event:_0x63f050})=>{const _0x41028f=_0xd6c99;if(_0x4857d8)return;const _0x4e2ba9=_0x63f050;if(_0x4e2ba9['type']&&_0x4e2ba9[_0x41028f(0x158)]['includes'](_0x41028f(0x147))){const _0x1e43c8=_0x4e2ba9[_0x41028f(0x160)]??{};await _0x3887a7('debug','agent\x20switch\x20event\x20observed',{'type':_0x4e2ba9[_0x41028f(0x158)],'sessionID':typeof _0x1e43c8[_0x41028f(0x165)]===_0x41028f(0x181)?_0x1e43c8['sessionID']:undefined,'agent':typeof _0x1e43c8[_0x41028f(0x15c)]===_0x41028f(0x181)?_0x1e43c8[_0x41028f(0x15c)]:undefined,'messageID':typeof _0x1e43c8[_0x41028f(0x17e)]===_0x41028f(0x181)?_0x1e43c8['messageID']:undefined});}const _0x3a7d5a=await _0x2bee65[_0x41028f(0x191)](_0x4e2ba9);if(_0x3a7d5a&&!_0x4857d8)await _0x2a75c2[_0x41028f(0x18f)]();if(_0x4857d8)return;await _0x43e781[_0x41028f(0x191)](_0x4e2ba9);},'chat.message':async _0x276f90=>{const _0x47b986=_0xd6c99;if(_0x4857d8)return;await _0x2bee65['noteActivity'](_0x276f90[_0x47b986(0x165)]);if(_0x276f90[_0x47b986(0x15c)])await _0x2bee65[_0x47b986(0x12e)](_0x276f90[_0x47b986(0x165)],_0x276f90[_0x47b986(0x15c)]);if(!_0x4857d8)await _0x2a75c2['heartbeat']();},'experimental.chat.messages.transform':async(_0x13cf7b,_0x5d8870)=>{const _0x5aa9b1=_0xd6c99;if(_0x4857d8)return;const _0x14fbc5=_0x5d8870[_0x5aa9b1(0x171)];if(!Array['isArray'](_0x14fbc5)||_0x14fbc5['length']===0x0)return;const _0x4cddf3=sanitizeMessages(_0x14fbc5);_0x4cddf3>0x0&&await _0x3887a7(_0x5aa9b1(0x146),_0x5aa9b1(0x183),{'dropped':_0x4cddf3});},'command.execute.before':async(_0x5ec3cc,_0x18eac7)=>{const _0x22290a=_0xd6c99;if(_0x4857d8)return;if(!_0x5ee63b[_0x22290a(0x149)](_0x5ec3cc[_0x22290a(0x15e)]))return;await _0x2bee65[_0x22290a(0x194)](_0x5ec3cc[_0x22290a(0x165)]);const _0x36ca72=_0x2bee65['queueForSession'](_0x5ec3cc['sessionID']),_0x3f0057=_0x2bee65[_0x22290a(0x134)](_0x5ec3cc[_0x22290a(0x165)]);if(!_0x36ca72||!_0x3f0057)return;let _0x55420f;try{const _0x1c297c=await handlePeersCommand({'registry':_0x2a75c2,'queue':_0x36ca72,'delivery':_0x3f0057,'getName':()=>_0x4cf09e,'setName':async _0x32baa2=>{const _0x32447d=_0x22290a;if(_0x32baa2===_0x4cf09e)return await _0x2a75c2[_0x32447d(0x18f)](),await _0x2bee65[_0x32447d(0x184)](_0x4cf09e),{'name':_0x32baa2,'taken':![]};const _0x59eff4=await _0x2a75c2[_0x32447d(0x16d)](),_0x53c359=_0x59eff4[_0x32447d(0x12c)](_0x257efc=>_0x257efc[_0x32447d(0x159)]&&_0x257efc[_0x32447d(0x174)][_0x32447d(0x132)]===_0x32baa2);if(_0x53c359)return{'name':_0x32baa2,'taken':!![]};return _0x4cf09e=_0x32baa2,await _0x2a75c2['heartbeat'](),await _0x2bee65['retitleRoots'](_0x4cf09e),{'name':_0x32baa2,'taken':![]};},'selfInstanceId':_0x17f2ed,'selfEndpointId':_0x2bee65[_0x22290a(0x14d)](_0x5ec3cc[_0x22290a(0x165)])??_0x17f2ed,'directory':_0x3cde3a[_0x22290a(0x166)],'peerScope':_0x46f5a8[_0x22290a(0x18a)],'outbox':_0x10dba8},_0x5ec3cc[_0x22290a(0x15e)],_0x5ec3cc[_0x22290a(0x13d)]||'');_0x55420f=_0x1c297c[_0x22290a(0x164)]??_0x22290a(0x13b),await _0x1c85ba();}catch(_0x5bd0f5){_0x55420f=_0x22290a(0x17f)+_0x5ec3cc[_0x22290a(0x15e)]+_0x22290a(0x125)+errorMessage(_0x5bd0f5);}consumeCommand(_0x18eac7[_0x22290a(0x127)],_0x55420f),await _0x3887a7(_0x55420f['startsWith']('❌')?_0x22290a(0x178):_0x22290a(0x167),_0x55420f,{'command':_0x5ec3cc[_0x22290a(0x15e)]});}};return _0x1b0822[_0xd6c99(0x172)]=buildPeerTools({'registry':_0x2a75c2,'sender':_0x388cf6,'sendLimit':_0x4b72d2,'maxMessageBytes':_0x46f5a8[_0xd6c99(0x155)],'selfName':()=>_0x4cf09e,'selfInstanceId':_0x17f2ed,'selfDirectory':_0x3cde3a[_0xd6c99(0x166)],'peerScope':_0x46f5a8[_0xd6c99(0x18a)],'endpointForSession':_0x4d33a2=>{const _0x16f2f7=_0xd6c99,_0x1eca4c=_0x2bee65[_0x16f2f7(0x14d)](_0x4d33a2),_0x542073=_0x2bee65[_0x16f2f7(0x16f)]()[_0x16f2f7(0x169)](_0x24caea=>_0x24caea[_0x16f2f7(0x133)]===_0x4d33a2);return _0x1eca4c&&_0x542073?{'endpointId':_0x1eca4c,'name':_0x542073['name'],'directory':_0x542073['directory']}:null;},'outbox':_0x10dba8}),_0x1b0822[_0xd6c99(0x13e)]=()=>{const _0x2798ee=_0xd6c99;if(disposePromise)return disposePromise;_0x4857d8=!![];if(_0x452e91)clearTimeout(_0x452e91);_0x452e91=null,clearInterval(_0xcf484d);const _0x173532=(async()=>{const _0x1e1ceb=_0x17e0;await _0x2bee65[_0x1e1ceb(0x145)](),await Promise[_0x1e1ceb(0x18b)]([_0x2a75c2[_0x1e1ceb(0x17b)](),_0x2bee65[_0x1e1ceb(0x17b)](),_0x1e532e[_0x1e1ceb(0x17b)](),acknowledgementTransport[_0x1e1ceb(0x197)]()]);})()[_0x2798ee(0x151)](()=>undefined);return disposePromise=_0x173532[_0x2798ee(0x17d)](()=>undefined),disposePromise;},await _0x3887a7('info',_0xd6c99(0x177),{'instanceId':_0x17f2ed,'name':_0x4cf09e,'inboxUrl':_0x16c0ea,'transportUrl':_0x1e44fc,'policy':_0x9ac2fa}),_0x452e91=setTimeout(()=>{const _0x481411=_0xd6c99;_0x452e91=null;if(_0x4857d8)return;void _0x2bee65['initialize']()['then'](async()=>{const _0x26ae94=_0x17e0;if(!_0x4857d8)await _0x2bee65[_0x26ae94(0x184)](_0x4cf09e);if(!_0x4857d8)await _0x2a75c2[_0x26ae94(0x18f)]();})['catch'](_0x30bf1a=>_0x3887a7(_0x481411(0x146),_0x481411(0x179),{'error':String(_0x30bf1a)}));},0x0),_0x452e91[_0xd6c99(0x182)]?.(),_0x1b0822;};export const plugin={'id':_0x2a1296(0x15b),'server':PeersPlugin};export default plugin;export{Registry,uniqueName}from'./registry.js';export{MessageQueue,RateLimiter,createProcessMessageQueue,createSessionMessageQueue,hasSpoolRecords,migrateWorkspaceSpool,stableSessionEndpointId,stableSpoolEndpointId}from'./queue.js';function _0x5819(){const _0x1f6de9=['AwrSzq','C3rYAw5N','Dw5Yzwy','C3rYAxbWzwqGzw1WDhKGyxnZAxn0yw50ig1LC3nHz2vZigzYB20GDgHLig91DgDVAw5NigHPC3rVCNK','CMv0AxrSzvjVB3rZ','Bwf4twvZC2fNzufNzu1Z','BgLZDc1Hz2vUDhm','Dg9fBMrWB2LUDeLK','mc4WlJa','u2HVDYb0CMfUC3bVCNqGCMvJzwLWDhmGyw5KigzPBMfSiefdsYbVDxrJB21LCYbMB3iGBwvZC2fNzxmGC2vUDcbIEsb0AgLZihnLC3nPB24','CgvLCLnJB3bL','ywXS','mteZmdbwzgnfr3G','AwDUB3jLzcb1BM1HDgnOzwqGCgvLCIbHy2TUB3DSzwrNzw1LBNq','mZy5ndDVBNj1yvi','AgvHCNrIzwf0','C3rVCMfNzurPCG','AgfUzgXLrxzLBNq','Aw5ZDgfUy2vjza','zMX1C2G','BM90zufJDgL2Axr5','zw50CMLLCW','mtm1odC1odvtBfPRshu','y2XVC2u','C3rHBgvnCW','CMvSAwfIAwXPDhKGC3DLzxaGzMfPBgvK','zNvSBa','igzHAwXLzdOG','CgvLCNmTBMfTzq','CgfYDhm','nZm1nJKZyuTmrKzM','nJK1B09gqKT4','Aw5IB3vUzfbVBgLJEq','jefsr1vnru5uuWOkswyGDgHPCYbJB21Tyw5KihDHCYbUB3qGAw50zxjJzxb0zwqGyNKGDgHLig9Wzw5JB2rLlwnVBgXHyM9YyxrPB24GCgX1z2LUlcb0zwXSihrOzsb1C2vYihrOzsbWBhvNAw4GAxmGBM90igXVywrLzcbHBMqGBM8Gywn0Aw9UihDHCYb0ywTLBI4','C29Tzq','zNjVBuvUzhbVAw50swq','BM90zufNzw50','CxvLDwvKq291BNq','CMvJDLjHDgvqzxjnAw4','BgvUz3rO','BMfTzq','C2vZC2LVBKLK','zgvSAxzLCNLgB3jtzxnZAw9U','CMvJzwL2zq','D2HLBLjLywr5','C2vUzfjHDgvqzxjnAw4','C3rHCNq','mty4ntrUweD6svC','C3DLzxbnCW','4PYfierVBMuU','mJi1thPrsfrz','yxjNDw1LBNrZ','zgLZCg9Zzq','BwfYA0fJA25VD2XLzgDLBwvUDfnLBNq','jefsr1vnru5uuWOkswyGDgHPCYbJB21Tyw5KihDHCYbUB3qGAw50zxjJzxb0zwqGyNKGDgHLig9Wzw5JB2rLlwnVBgXHyM9YyxrPB24GCgX1z2LUlcbJywXSihrOzsbSAxn0x2fNzw50CYb0B29SigfUzcbZAg93ihrOzsbYzxn1BhqGDg8GDgHLihvZzxiGDMvYyMf0Aw0U','y2XPzw50','u2HVDYbVCIbZzxqGDgHPCYbPBNn0yw5JzsDZihbLzxiGBMfTzsaODxnLzcbIEsbVDgHLCIbZzxnZAw9UCYb0BYbHzgrYzxnZihLVDsK','BwvZC2fNzuLK','ywnRBM93BgvKz2vTzw50igrPC3bHDgnOigzHAwXLzdSGD2LSBcbYzxrYEq','y2XLyxjtDwzMAxHLCW','D2fYBG','ywDLBNqUC3DPDgnOzwq','DxrMoa','AgfZ','mtjcqvrOALq','CgvLCLbLCM1PC3nPB25Z','CgvLCNmTB3v0yM94','zw5KCg9PBNrjzezVCLnLC3nPB24','uMv2Awv3igHLBgqGCgvLCIbTzxnZywDLCY4GvxnHz2u6ic9WzwvYCY1PBMjVEcbBywnJzxb0idXUFgfSBd4GFcbKCM9WidXUFgfSBd5D','DMvYC2LVBG','BwfW','y2f0y2G','C3rHDhvZ','CMfJzq','AgfZrw5KCg9PBNq','Bwf4twvZC2fNzuj5DgvZ','zMfPBgvKihrVihjLDhvYBIbWzwvYigfJA25VD2XLzgDLBwvUDdSGD2LSBcbYzxrYEq','nZa5mZe0neDpyKTtDW','DhLWzq','ywXPDMu','CgvLCNneAxi','B3bLBMnVzguTy29SBgfIB3jHDgLVBG','ywDLBNq','mtu5nMHpwKzXEq','y29TBwfUza','zNjVBq','ChjVCgvYDgLLCW','mJqYmZKWr1D2uxnu','lI4VCgfJA2fNzs5QC29U','B3b0Aw9UCW','BwvZC2fNzq','C2vZC2LVBKLe','zgLYzwn0B3j5','Aw5MBW','y29TCgf0AwjPBgL0EuvUzhbVAw50swq','zMLUza','CgvUzgLUz0fJA25VD2XLzgDLBwvUDhm','tgLZDcbZyw1Llw1Hy2HPBMuGB3bLBMnVzguGCgvLCNmGEw91ignHBIbLEgnOyw5NzsbTzxnZywDLCYb3AxrOicHJCM9ZCY1ZzxnZAw9Uig1LC3nHz2LUzYK','CgfYC2u','BgLZDa','DgL0Bgu','CMvNAxn0CNLfBMrWB2LUDhm','zxHWAxjLsgvSza','BwvZC2fNzxm','Dg9VBa','C3DLzxa','zw50CNK','ywnR','mJrhvfvXrNm','B3bLBMnVzguTy29SBgfIB3jHDgLVBIbZDgfYDgvK','zxjYB3i','zgvMzxjYzwqGC2vZC2LVBIbKAxnJB3zLCNKGzMfPBgvK','zw5KCg9PBNrjza','C3rVCa','yxbWBhLby2TUB3DSzwrNzw1LBNq','DgHLBG','BwvZC2fNzuLe','4P2mic8'];_0x5819=function(){return _0x1f6de9;};return _0x5819();}export{SessionTracker}from'./session-tracker.js';export{SessionRuntime}from'./session-runtime.js';export{Delivery,deterministicPeerMessageId,formatMessages}from'./delivery.js';export{Sender,buildMessage,buildMessageV2}from'./sender.js';export{InboxListener}from'./listener.js';export{LocalTransport}from'./transport.js';export{gateMessage}from'./gating.js';export{PeerPermissions,isProtectedPermission}from'./permissions.js';export{Outbox}from'./outbox.js';export{collapseToProcesses,formatSessionList,relativeAge,sortPeers}from'./format.js';export{resolveConfig,validateName}from'./config.js';export*from'./types.js';
|
|
2
|
+
//# sourceMappingURL=.js.map
|