@sleep2agi/agent-network 2.3.0-preview.34 → 2.3.0-preview.36

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.
@@ -1 +1 @@
1
- function a0_0x9418(){const _0x454798=['sdk-','completed','ack_inbox','processInbox','connect','heartbeatInterval','reconnectDelay','split','token','1102851pkALrK','/mcp','log','send_task','offline','agent','startsWith','call','Bearer\x20','sleep','heartbeat\x20failed:\x20','18GUttkd','POST','send_reply','sseAbort','parse','catch','send','messages','reply','url','tools/call','application/json,\x20text/event-stream','abort','slice','type','task','connected','error','read','getReader','Authorization','resumeId','SSE\x20connected','disconnected','809568YMGlFg','send_message','disconnect','1366000cyTevn','status','emit','2.0',']\x20[commhub:','getAllStatus','content','message','connectSSE','heartbeatTimer','now','5KuWHWF','184404Gpvqqb','body','5157060mOPyCN','application/json','/events/','inbox\x20error:\x20','849175IXKUxY','get_all_status','server','5056992FStvGn','broadcast','running','s...','SSE\x20failed:\x20','text/event-stream','name','SSE\x20error:\x20','alias','idle','35fvCLtW'];a0_0x9418=function(){return _0x454798;};return a0_0x9418();}const a0_0x5a1909=a0_0x4e34;(function(_0x2865f9,_0x3761fc){const _0x5ebf3d=a0_0x4e34,_0x15d8d9=_0x2865f9();while(!![]){try{const _0x3d8dfe=parseInt(_0x5ebf3d(0x106))/0x1*(-parseInt(_0x5ebf3d(0x107))/0x2)+parseInt(_0x5ebf3d(0xd5))/0x3+parseInt(_0x5ebf3d(0xfb))/0x4+-parseInt(_0x5ebf3d(0xbe))/0x5*(parseInt(_0x5ebf3d(0xe0))/0x6)+-parseInt(_0x5ebf3d(0xcb))/0x7*(-parseInt(_0x5ebf3d(0xf8))/0x8)+parseInt(_0x5ebf3d(0xc1))/0x9+-parseInt(_0x5ebf3d(0x109))/0xa;if(_0x3d8dfe===_0x3761fc)break;else _0x15d8d9['push'](_0x15d8d9['shift']());}catch(_0x3b4465){_0x15d8d9['push'](_0x15d8d9['shift']());}}}(a0_0x9418,0x46fcc));function a0_0x4e34(_0x3b0a03,_0x34118d){_0x3b0a03=_0x3b0a03-0xbb;const _0x94180e=a0_0x9418();let _0x4e3437=_0x94180e[_0x3b0a03];return _0x4e3437;}import{EventEmitter as a0_0x536da2}from'events';import{hostname as a0_0x1ffcb0}from'os';class T extends a0_0x536da2{['url'];[a0_0x5a1909(0xc9)];[a0_0x5a1909(0xd4)];[a0_0x5a1909(0xda)];[a0_0x5a1909(0xf5)];[a0_0x5a1909(0xd1)];[a0_0x5a1909(0xd2)];['heartbeatTimer'];[a0_0x5a1909(0xe3)];[a0_0x5a1909(0xc3)]=!0x1;constructor(_0x36c4fe){const _0x1bfaff=a0_0x5a1909;super();if(this['url']=_0x36c4fe[_0x1bfaff(0xe9)]['replace'](/\/$/,''),this[_0x1bfaff(0xc9)]=_0x36c4fe[_0x1bfaff(0xc9)],this[_0x1bfaff(0xd4)]=_0x36c4fe['token'],this[_0x1bfaff(0xda)]=_0x36c4fe[_0x1bfaff(0xda)]||'sdk',this[_0x1bfaff(0xf5)]=_0x1bfaff(0xcc)+_0x36c4fe[_0x1bfaff(0xc9)]+'-'+Date[_0x1bfaff(0x105)]()['toString'](0x24),this[_0x1bfaff(0xd1)]=_0x36c4fe['heartbeatInterval']??0x2bf20,this[_0x1bfaff(0xd2)]=_0x36c4fe[_0x1bfaff(0xd2)]??0xbb8,_0x36c4fe['autoConnect']!==!0x1)this[_0x1bfaff(0xd0)]();}[a0_0x5a1909(0xd7)](_0xac0e7e){const _0x1e7171=a0_0x5a1909;console['log']('['+new Date()['toTimeString']()[_0x1e7171(0xed)](0x0,0x8)+_0x1e7171(0xff)+this[_0x1e7171(0xc9)]+']\x20'+_0xac0e7e);}async[a0_0x5a1909(0xdc)](_0x94ed95,_0x215f21){const _0x5dfb3f=a0_0x5a1909;let _0x3d96f9={'Content-Type':_0x5dfb3f(0xbb),'Accept':_0x5dfb3f(0xeb)};if(this[_0x5dfb3f(0xd4)])_0x3d96f9[_0x5dfb3f(0xf4)]=_0x5dfb3f(0xdd)+this[_0x5dfb3f(0xd4)];let _0x4f4ade=await(await fetch(this[_0x5dfb3f(0xe9)]+_0x5dfb3f(0xd6),{'method':_0x5dfb3f(0xe1),'headers':_0x3d96f9,'body':JSON['stringify']({'jsonrpc':_0x5dfb3f(0xfe),'id':Date['now'](),'method':_0x5dfb3f(0xea),'params':{'name':_0x94ed95,'arguments':_0x215f21}})}))['text'](),_0x57a7a1=_0x4f4ade['match'](/data: (.+)/),_0x284fcf=_0x57a7a1?JSON[_0x5dfb3f(0xe4)](_0x57a7a1[0x1]):JSON[_0x5dfb3f(0xe4)](_0x4f4ade),_0x5b6cc3=_0x284fcf?.['result']?.[_0x5dfb3f(0x101)]?.[0x0]?.['text'];return _0x5b6cc3?JSON[_0x5dfb3f(0xe4)](_0x5b6cc3):_0x284fcf;}async[a0_0x5a1909(0xd0)](){const _0x5d92e4=a0_0x5a1909;if(this['running'])return;this['running']=!0x0,await this[_0x5d92e4(0xfc)](_0x5d92e4(0xca)),this['log']('registered'),this[_0x5d92e4(0x104)]=setInterval(()=>{const _0x13bb35=_0x5d92e4;this[_0x13bb35(0xfc)]('idle')['catch'](_0x43940e=>this[_0x13bb35(0xd7)](_0x13bb35(0xdf)+_0x43940e[_0x13bb35(0x102)]));},this[_0x5d92e4(0xd1)]),this['connectSSE']();}async[a0_0x5a1909(0xfa)](){const _0x5e789a=a0_0x5a1909;if(this[_0x5e789a(0xc3)]=!0x1,this[_0x5e789a(0xe3)]?.[_0x5e789a(0xec)](),this['heartbeatTimer'])clearInterval(this[_0x5e789a(0x104)]);await this[_0x5e789a(0xfc)](_0x5e789a(0xd9))[_0x5e789a(0xe5)](()=>{}),this[_0x5e789a(0xd7)](_0x5e789a(0xf7));}async[a0_0x5a1909(0xe6)](_0x11c606,_0x2ba2d3,_0x2b6299='normal'){const _0x573381=a0_0x5a1909;return this[_0x573381(0xdc)](_0x573381(0xd8),{'alias':_0x11c606,'task':_0x2ba2d3,'priority':_0x2b6299,'from_session':this[_0x573381(0xc9)]});}async['message'](_0x4d2249,_0x5c2fc4){const _0xfaf92f=a0_0x5a1909;return this[_0xfaf92f(0xdc)](_0xfaf92f(0xf9),{'alias':_0x4d2249,'message':_0x5c2fc4,'from_session':this[_0xfaf92f(0xc9)]});}async[a0_0x5a1909(0xe8)](_0x1e4478,_0x3c89bf,_0x403566=a0_0x5a1909(0xcd)){const _0x361e4f=a0_0x5a1909;return this[_0x361e4f(0xdc)](_0x361e4f(0xe2),{'in_reply_to':_0x1e4478,'text':_0x3c89bf,'status':_0x403566});}async[a0_0x5a1909(0xfc)](_0x3bcca2,_0xd343fa){const _0x59c013=a0_0x5a1909;return this[_0x59c013(0xdc)]('report_status',{'resume_id':this[_0x59c013(0xf5)],'alias':this[_0x59c013(0xc9)],'status':_0x3bcca2,'server':a0_0x1ffcb0(),'hostname':a0_0x1ffcb0(),'agent':this[_0x59c013(0xda)],'project_dir':process['cwd'](),..._0xd343fa});}async[a0_0x5a1909(0x100)](){const _0x1ea804=a0_0x5a1909;return this[_0x1ea804(0xdc)](_0x1ea804(0xbf),{});}async['broadcast'](_0x1b15e3,_0x13f9e1){const _0x376bad=a0_0x5a1909;return this[_0x376bad(0xdc)](_0x376bad(0xc2),{'message':_0x1b15e3,'filter_server':_0x13f9e1?.[_0x376bad(0xc0)],'filter_status':_0x13f9e1?.[_0x376bad(0xfc)]});}async[a0_0x5a1909(0x103)](){const _0x30be42=a0_0x5a1909;let _0xd3dc6d=encodeURIComponent(this['alias']),_0x1634ca=this[_0x30be42(0xe9)]+_0x30be42(0xbc)+_0xd3dc6d,_0x10ce93=this['reconnectDelay'];while(this[_0x30be42(0xc3)]){try{this[_0x30be42(0xe3)]=new AbortController();let _0x27184b={'Accept':_0x30be42(0xc6)};if(this[_0x30be42(0xd4)])_0x27184b[_0x30be42(0xf4)]='Bearer\x20'+this[_0x30be42(0xd4)];let _0x66c85b=await fetch(_0x1634ca,{'headers':_0x27184b,'signal':this[_0x30be42(0xe3)]['signal']});if(!_0x66c85b['ok']||!_0x66c85b[_0x30be42(0x108)]){this[_0x30be42(0xd7)](_0x30be42(0xc5)+_0x66c85b[_0x30be42(0xfc)]),await this[_0x30be42(0xde)](_0x10ce93),_0x10ce93=Math['min'](_0x10ce93*1.5,0xea60);continue;}_0x10ce93=this['reconnectDelay'];let _0x2a9a54=_0x66c85b['body'][_0x30be42(0xf3)](),_0x362655=new TextDecoder(),_0xb7259e='';while(this['running']){let {done:_0x589725,value:_0x4dc8ba}=await _0x2a9a54[_0x30be42(0xf2)]();if(_0x589725)break;_0xb7259e+=_0x362655['decode'](_0x4dc8ba,{'stream':!0x0});let _0x2105a0=_0xb7259e[_0x30be42(0xd3)]('\x0a');_0xb7259e=_0x2105a0['pop']()||'';for(let _0x30924a of _0x2105a0){if(!_0x30924a[_0x30be42(0xdb)]('data:\x20'))continue;try{let _0x5ef844=JSON[_0x30be42(0xe4)](_0x30924a[_0x30be42(0xed)](0x6));if(_0x5ef844[_0x30be42(0xee)]===_0x30be42(0xf0)){this['log'](_0x30be42(0xf6)),this['emit'](_0x30be42(0xf0));continue;}if(_0x5ef844['type']==='new_task'||_0x5ef844[_0x30be42(0xee)]==='new_message'||_0x5ef844[_0x30be42(0xee)]===_0x30be42(0xc2))await this[_0x30be42(0xcf)]();}catch{}}}}catch(_0x574727){if(_0x574727[_0x30be42(0xc7)]==='AbortError')break;this[_0x30be42(0xfd)](_0x30be42(0xf1),_0x574727),this['log'](_0x30be42(0xc8)+_0x574727[_0x30be42(0x102)]);}if(this['running'])this[_0x30be42(0xfd)]('disconnected'),this[_0x30be42(0xd7)]('SSE\x20reconnecting\x20in\x20'+_0x10ce93/0x3e8+_0x30be42(0xc4)),await this['sleep'](_0x10ce93),_0x10ce93=Math['min'](_0x10ce93*1.5,0xea60);}}async[a0_0x5a1909(0xcf)](){const _0x8c91ed=a0_0x5a1909;try{let _0x46203c=(await this['call']('get_inbox',{'alias':this[_0x8c91ed(0xc9)],'limit':0xa}))?.[_0x8c91ed(0xe7)]||[];for(let _0x3c15ce of _0x46203c)await this[_0x8c91ed(0xdc)](_0x8c91ed(0xce),{'alias':this['alias'],'message_id':_0x3c15ce['id']}),this[_0x8c91ed(0xd7)]('←\x20'+_0x3c15ce['from_session']+':\x20'+_0x3c15ce[_0x8c91ed(0x101)]['slice'](0x0,0x3c)),this[_0x8c91ed(0xfd)](_0x8c91ed(0xef),_0x3c15ce),this[_0x8c91ed(0xfd)](_0x8c91ed(0x102),_0x3c15ce);}catch(_0x167d4f){this[_0x8c91ed(0xd7)](_0x8c91ed(0xbd)+_0x167d4f[_0x8c91ed(0x102)]);}}[a0_0x5a1909(0xde)](_0x28f9a4){return new Promise(_0x1df5c7=>setTimeout(_0x1df5c7,_0x28f9a4));}}var $=T;export{$ as default,T as CommHub};
1
+ function a0_0x855f(_0x39248a,_0x4f8b92){_0x39248a=_0x39248a-0x17e;const _0x1fdedc=a0_0x1fde();let _0x855f3a=_0x1fdedc[_0x39248a];return _0x855f3a;}const a0_0x4d231b=a0_0x855f;function a0_0x1fde(){const _0x6156d4=['1284230tDpjGQ','send','4054gZjmun','new_message','token','12sHOfGT','replace','application/json,\x20text/event-stream','name','content','510fdmlNL','completed','signal','startsWith','send_task','sdk-','url','decode','connected','alias','cwd','idle','SSE\x20failed:\x20','SSE\x20error:\x20','reconnectDelay','tools/call','report_status','203291GZjLqV','1420065tZtERR','body','POST','s...','292812gmjImy','sseAbort','emit','connect',']\x20[commhub:','Bearer\x20','180AKOQIx','Authorization','parse','normal','error','327072wpmrft','reply','sleep','status','text','toString','text/event-stream','heartbeatTimer','min','ack_inbox','/events/','387qyGICo','autoConnect','log','message','read','send_message','disconnect','pop','broadcast','agent','catch','abort','running','18GuMYSJ','type','connectSSE','getReader','data:\x20','server','get_inbox','registered','offline','slice','new_task','455xtKROn','call','disconnected','heartbeatInterval','split','messages','sdk','task','match','resumeId','processInbox','1860873HDbrtt','/mcp'];a0_0x1fde=function(){return _0x6156d4;};return a0_0x1fde();}(function(_0x69f157,_0x34d6a8){const _0x16a939=a0_0x855f,_0x43f872=_0x69f157();while(!![]){try{const _0x163c93=parseInt(_0x16a939(0x18e))/0x1*(parseInt(_0x16a939(0x1b5))/0x2)+parseInt(_0x16a939(0x1cf))/0x3+parseInt(_0x16a939(0x1b8))/0x4*(parseInt(_0x16a939(0x1b3))/0x5)+-parseInt(_0x16a939(0x19b))/0x6*(parseInt(_0x16a939(0x1b1))/0x7)+parseInt(_0x16a939(0x183))/0x8*(-parseInt(_0x16a939(0x17e))/0x9)+parseInt(_0x16a939(0x1bd))/0xa*(parseInt(_0x16a939(0x1ce))/0xb)+-parseInt(_0x16a939(0x1d3))/0xc*(parseInt(_0x16a939(0x1a6))/0xd);if(_0x163c93===_0x34d6a8)break;else _0x43f872['push'](_0x43f872['shift']());}catch(_0xff4c24){_0x43f872['push'](_0x43f872['shift']());}}}(a0_0x1fde,0x7a789));import{EventEmitter as a0_0x124210}from'events';import{hostname as a0_0x4fa072}from'os';class T extends a0_0x124210{[a0_0x4d231b(0x1c3)];[a0_0x4d231b(0x1c6)];[a0_0x4d231b(0x1b7)];[a0_0x4d231b(0x197)];[a0_0x4d231b(0x1af)];[a0_0x4d231b(0x1a9)];[a0_0x4d231b(0x1cb)];[a0_0x4d231b(0x18a)];[a0_0x4d231b(0x1d4)];[a0_0x4d231b(0x19a)]=!0x1;constructor(_0x378de7){const _0x3e0180=a0_0x4d231b;super();if(this[_0x3e0180(0x1c3)]=_0x378de7[_0x3e0180(0x1c3)][_0x3e0180(0x1b9)](/\/$/,''),this[_0x3e0180(0x1c6)]=_0x378de7[_0x3e0180(0x1c6)],this[_0x3e0180(0x1b7)]=_0x378de7[_0x3e0180(0x1b7)],this['agent']=_0x378de7[_0x3e0180(0x197)]||_0x3e0180(0x1ac),this[_0x3e0180(0x1af)]=_0x3e0180(0x1c2)+_0x378de7[_0x3e0180(0x1c6)]+'-'+Date['now']()[_0x3e0180(0x188)](0x24),this[_0x3e0180(0x1a9)]=_0x378de7[_0x3e0180(0x1a9)]??0x2bf20,this[_0x3e0180(0x1cb)]=_0x378de7['reconnectDelay']??0xbb8,_0x378de7[_0x3e0180(0x18f)]!==!0x1)this[_0x3e0180(0x1d6)]();}[a0_0x4d231b(0x190)](_0x1bcd5e){const _0x1c84f5=a0_0x4d231b;console['log']('['+new Date()['toTimeString']()[_0x1c84f5(0x1a4)](0x0,0x8)+_0x1c84f5(0x1d7)+this['alias']+']\x20'+_0x1bcd5e);}async['call'](_0x2c471f,_0x1d8c39){const _0x3f9e56=a0_0x4d231b;let _0x11ef76={'Content-Type':'application/json','Accept':_0x3f9e56(0x1ba)};if(this['token'])_0x11ef76[_0x3f9e56(0x17f)]=_0x3f9e56(0x1d8)+this[_0x3f9e56(0x1b7)];let _0x32392e=await(await fetch(this[_0x3f9e56(0x1c3)]+_0x3f9e56(0x1b2),{'method':_0x3f9e56(0x1d1),'headers':_0x11ef76,'body':JSON['stringify']({'jsonrpc':'2.0','id':Date['now'](),'method':_0x3f9e56(0x1cc),'params':{'name':_0x2c471f,'arguments':_0x1d8c39}})}))['text'](),_0x4a9b2d=_0x32392e[_0x3f9e56(0x1ae)](/data: (.+)/),_0x29381a=_0x4a9b2d?JSON['parse'](_0x4a9b2d[0x1]):JSON[_0x3f9e56(0x180)](_0x32392e),_0x40fe30=_0x29381a?.['result']?.['content']?.[0x0]?.[_0x3f9e56(0x187)];return _0x40fe30?JSON[_0x3f9e56(0x180)](_0x40fe30):_0x29381a;}async[a0_0x4d231b(0x1d6)](){const _0x490e88=a0_0x4d231b;if(this[_0x490e88(0x19a)])return;this[_0x490e88(0x19a)]=!0x0,await this[_0x490e88(0x186)](_0x490e88(0x1c8)),this[_0x490e88(0x190)](_0x490e88(0x1a2)),this['heartbeatTimer']=setInterval(()=>{const _0x323a3d=_0x490e88;this[_0x323a3d(0x186)](_0x323a3d(0x1c8))[_0x323a3d(0x198)](_0x2688bf=>this['log']('heartbeat\x20failed:\x20'+_0x2688bf[_0x323a3d(0x191)]));},this[_0x490e88(0x1a9)]),this[_0x490e88(0x19d)]();}async[a0_0x4d231b(0x194)](){const _0x48dfe2=a0_0x4d231b;if(this[_0x48dfe2(0x19a)]=!0x1,this['sseAbort']?.[_0x48dfe2(0x199)](),this['heartbeatTimer'])clearInterval(this[_0x48dfe2(0x18a)]);await this['status'](_0x48dfe2(0x1a3))['catch'](()=>{}),this[_0x48dfe2(0x190)](_0x48dfe2(0x1a8));}async[a0_0x4d231b(0x1b4)](_0x3e0fac,_0x58ed5e,_0x2a11e7=a0_0x4d231b(0x181)){const _0x32dbcc=a0_0x4d231b;return this[_0x32dbcc(0x1a7)](_0x32dbcc(0x1c1),{'alias':_0x3e0fac,'task':_0x58ed5e,'priority':_0x2a11e7,'from_session':this['alias']});}async[a0_0x4d231b(0x191)](_0x78ee4d,_0x4cd5f2){const _0x42f76f=a0_0x4d231b;return this[_0x42f76f(0x1a7)](_0x42f76f(0x193),{'alias':_0x78ee4d,'message':_0x4cd5f2,'from_session':this[_0x42f76f(0x1c6)]});}async[a0_0x4d231b(0x184)](_0x4ac7fd,_0x4eaf65,_0x4d2158=a0_0x4d231b(0x1be)){const _0x9807bc=a0_0x4d231b;return this[_0x9807bc(0x1a7)]('send_reply',{'in_reply_to':_0x4ac7fd,'text':_0x4eaf65,'status':_0x4d2158});}async[a0_0x4d231b(0x186)](_0x2a2d4a,_0x33278e){const _0x9d60a7=a0_0x4d231b;return this[_0x9d60a7(0x1a7)](_0x9d60a7(0x1cd),{'resume_id':this[_0x9d60a7(0x1af)],'alias':this[_0x9d60a7(0x1c6)],'status':_0x2a2d4a,'server':a0_0x4fa072(),'hostname':a0_0x4fa072(),'agent':this[_0x9d60a7(0x197)],'project_dir':process[_0x9d60a7(0x1c7)](),..._0x33278e});}async['getAllStatus'](){const _0x4a2eae=a0_0x4d231b;return this[_0x4a2eae(0x1a7)]('get_all_status',{});}async[a0_0x4d231b(0x196)](_0x2c4132,_0x1b73f1){const _0x1d63a4=a0_0x4d231b;return this['call'](_0x1d63a4(0x196),{'message':_0x2c4132,'filter_server':_0x1b73f1?.[_0x1d63a4(0x1a0)],'filter_status':_0x1b73f1?.[_0x1d63a4(0x186)]});}async['connectSSE'](){const _0x1cc7a5=a0_0x4d231b;let _0x4667ef=encodeURIComponent(this[_0x1cc7a5(0x1c6)]),_0x493abb=this['url']+_0x1cc7a5(0x18d)+_0x4667ef,_0xcdf218=this[_0x1cc7a5(0x1cb)];while(this[_0x1cc7a5(0x19a)]){try{this[_0x1cc7a5(0x1d4)]=new AbortController();let _0x11a55a={'Accept':_0x1cc7a5(0x189)};if(this[_0x1cc7a5(0x1b7)])_0x11a55a['Authorization']=_0x1cc7a5(0x1d8)+this['token'];let _0x21e48a=await fetch(_0x493abb,{'headers':_0x11a55a,'signal':this['sseAbort'][_0x1cc7a5(0x1bf)]});if(!_0x21e48a['ok']||!_0x21e48a['body']){this[_0x1cc7a5(0x190)](_0x1cc7a5(0x1c9)+_0x21e48a['status']),await this[_0x1cc7a5(0x185)](_0xcdf218),_0xcdf218=Math[_0x1cc7a5(0x18b)](_0xcdf218*1.5,0xea60);continue;}_0xcdf218=this['reconnectDelay'];let _0x1aa8d2=_0x21e48a[_0x1cc7a5(0x1d0)][_0x1cc7a5(0x19e)](),_0x5c90d3=new TextDecoder(),_0x3ad1a8='';while(this[_0x1cc7a5(0x19a)]){let {done:_0x21a8a7,value:_0x2f9942}=await _0x1aa8d2[_0x1cc7a5(0x192)]();if(_0x21a8a7)break;_0x3ad1a8+=_0x5c90d3[_0x1cc7a5(0x1c4)](_0x2f9942,{'stream':!0x0});let _0x564e1a=_0x3ad1a8[_0x1cc7a5(0x1aa)]('\x0a');_0x3ad1a8=_0x564e1a[_0x1cc7a5(0x195)]()||'';for(let _0x527343 of _0x564e1a){if(!_0x527343[_0x1cc7a5(0x1c0)](_0x1cc7a5(0x19f)))continue;try{let _0x15a837=JSON['parse'](_0x527343[_0x1cc7a5(0x1a4)](0x6));if(_0x15a837['type']===_0x1cc7a5(0x1c5)){this['log']('SSE\x20connected'),this[_0x1cc7a5(0x1d5)]('connected');continue;}if(_0x15a837[_0x1cc7a5(0x19c)]===_0x1cc7a5(0x1a5)||_0x15a837[_0x1cc7a5(0x19c)]===_0x1cc7a5(0x1b6)||_0x15a837[_0x1cc7a5(0x19c)]===_0x1cc7a5(0x196))await this['processInbox']();}catch{}}}}catch(_0x511634){if(_0x511634[_0x1cc7a5(0x1bb)]==='AbortError')break;this[_0x1cc7a5(0x1d5)](_0x1cc7a5(0x182),_0x511634),this['log'](_0x1cc7a5(0x1ca)+_0x511634['message']);}if(this[_0x1cc7a5(0x19a)])this[_0x1cc7a5(0x1d5)]('disconnected'),this['log']('SSE\x20reconnecting\x20in\x20'+_0xcdf218/0x3e8+_0x1cc7a5(0x1d2)),await this[_0x1cc7a5(0x185)](_0xcdf218),_0xcdf218=Math[_0x1cc7a5(0x18b)](_0xcdf218*1.5,0xea60);}}async[a0_0x4d231b(0x1b0)](){const _0x3f29f2=a0_0x4d231b;try{let _0x203ada=(await this[_0x3f29f2(0x1a7)](_0x3f29f2(0x1a1),{'alias':this[_0x3f29f2(0x1c6)],'limit':0xa}))?.[_0x3f29f2(0x1ab)]||[];for(let _0x12737f of _0x203ada)await this['call'](_0x3f29f2(0x18c),{'alias':this[_0x3f29f2(0x1c6)],'message_id':_0x12737f['id']}),this['log']('←\x20'+_0x12737f['from_session']+':\x20'+_0x12737f[_0x3f29f2(0x1bc)]['slice'](0x0,0x3c)),this['emit'](_0x3f29f2(0x1ad),_0x12737f),this[_0x3f29f2(0x1d5)](_0x3f29f2(0x191),_0x12737f);}catch(_0x2e2065){this[_0x3f29f2(0x190)]('inbox\x20error:\x20'+_0x2e2065['message']);}}[a0_0x4d231b(0x185)](_0x1b81ae){return new Promise(_0x12eb0d=>setTimeout(_0x12eb0d,_0x1b81ae));}}var $=T;export{$ as default,T as CommHub};
@@ -0,0 +1,339 @@
1
+ export interface SessionInfo {
2
+ tmux: string;
3
+ pid: number;
4
+ pgid: number;
5
+ starttime_jiffies: number;
6
+ }
7
+ export interface CopresenceMarker {
8
+ marker: string;
9
+ boot_id: string;
10
+ started_at_epoch_ms: number;
11
+ owner_uid: number;
12
+ sessions: {
13
+ appsrv?: SessionInfo;
14
+ bridge?: SessionInfo;
15
+ tui?: SessionInfo;
16
+ };
17
+ }
18
+ export type RefuseCause = "MISSING" | "SYMLINK" | "NOT_REGULAR" | "WRONG_MODE" | "OWNER_MISMATCH" | "PARSE_ERROR" | "SCHEMA_INVALID" | "STALE_BOOT_ID" | "PLATFORM_UNSUPPORTED";
19
+ export type ReadMarkerResult = {
20
+ kind: "ok";
21
+ marker: CopresenceMarker;
22
+ } | {
23
+ kind: "refuse";
24
+ cause: RefuseCause;
25
+ detail: string;
26
+ };
27
+ export interface ProcStat {
28
+ pgid: number;
29
+ starttime_jiffies: number;
30
+ ppid: number;
31
+ }
32
+ /**
33
+ * Injectable primitive for /proc access. Real impl reads the filesystem;
34
+ * unit tests inject a mock so /proc-based logic is deterministically testable.
35
+ *
36
+ * Contract:
37
+ * - listAllPids: read /proc directory and return numeric-name entries.
38
+ * Throws on unrecoverable errors (permission denied on /proc itself).
39
+ * - readEnviron: read /proc/<pid>/environ as a raw string. Returns null
40
+ * if the pid has vanished (ENOENT) — that's a normal race, not a failure.
41
+ * Throws for permission errors etc.
42
+ * - readStat: read /proc/<pid>/stat and extract (pgid, starttime, ppid).
43
+ * Returns null on ENOENT (pid gone). Throws on other errors.
44
+ */
45
+ export interface ProcessEnumerator {
46
+ listAllPids(): number[];
47
+ readEnviron(pid: number): string | null;
48
+ readStat(pid: number): ProcStat | null;
49
+ /**
50
+ * REAL uid of the process itself (`Uid:` line of /proc/<pid>/status,
51
+ * field 0). Used by the environ-EACCES discriminator to tell
52
+ * "other-user process (expected EACCES)" from "our own process we could
53
+ * not inspect (must be accounted for)".
54
+ *
55
+ * MUST NOT be implemented as `statSync('/proc/<pid>/environ').uid`.
56
+ * A process that called prctl(PR_SET_DUMPABLE, 0) keeps its real uid but
57
+ * its /proc/<pid>/{environ,mem,...} nodes flip to root:root 0400 (see
58
+ * proc(5) / kernel `task_dump_owner`). Deriving ownership from the
59
+ * environ inode therefore reports uid 0 for our OWN non-dumpable
60
+ * children, which made them invisible to the scan: not in `hits`, not in
61
+ * the unreadable list, so teardown reported success and deleted the
62
+ * marker while the orphan lived on (Defect A).
63
+ *
64
+ * Returns null if the pid is gone (ENOENT) or if even /proc/<pid>/status
65
+ * is blocked (hidepid / LSM) — in that case the process cannot be ours
66
+ * to reason about and is skipped.
67
+ */
68
+ readOwnerUid(pid: number): number | null;
69
+ /**
70
+ * Single-character process state from /proc/<pid>/status (R/S/D/Z/T/...).
71
+ * `Z` means zombie — mm freed, environ returns EACCES even to owner, but
72
+ * the pid is going away shortly. Skip zombies during environ scan.
73
+ * Returns null if the pid is gone (ENOENT).
74
+ */
75
+ readState(pid: number): string | null;
76
+ }
77
+ /**
78
+ * Injectable primitive for sending signals. Real impl uses process.kill;
79
+ * tests inject a mock.
80
+ */
81
+ export interface KillPrimitive {
82
+ killPgroup(pgid: number, signal: "TERM" | "KILL"): void;
83
+ /** Returns true if ANY process in the pgroup is still alive. */
84
+ pgroupAlive(pgid: number): boolean;
85
+ }
86
+ export declare function markerFilePath(nodesDir: string, nodeId: string): string;
87
+ export declare function readBootId(): string;
88
+ /**
89
+ * Write the marker file atomically.
90
+ *
91
+ * IMPORTANT (Blocker 1 fix): the uuid parameter is the SINGLE SOURCE OF
92
+ * TRUTH. Caller is expected to inject this same uuid into every tmux
93
+ * session's ANET_NODE_MARKER env var. writeMarker does NOT generate its
94
+ * own uuid — that was the exact bug in 9f2ec282.
95
+ */
96
+ export declare function writeMarker(nodesDir: string, nodeId: string, uuid: string, sessions: CopresenceMarker["sessions"]): CopresenceMarker;
97
+ /**
98
+ * Read the marker file with structured fail-closed refuses.
99
+ *
100
+ * Never throws for expected refuse causes. Only throws if the OS itself
101
+ * is broken (e.g. EIO). Malformed JSON, wrong types, null bodies etc.
102
+ * all return { kind: "refuse", cause, detail }.
103
+ */
104
+ export declare function readMarker(nodesDir: string, nodeId: string): ReadMarkerResult;
105
+ export declare function removeMarker(nodesDir: string, nodeId: string): void;
106
+ export declare function realEnumerator(): ProcessEnumerator;
107
+ export declare function realKiller(): KillPrimitive;
108
+ /**
109
+ * Scan /proc for all pids whose environ contains ANET_NODE_MARKER=<uuid>.
110
+ * This is the authoritative identity source — NOT the marker file's stored
111
+ * pids, which may be stale (main died, workers survived under new pgids).
112
+ *
113
+ * Bytes format of /proc/PID/environ: NUL-separated key=value pairs.
114
+ *
115
+ * Blocker 1 fix (independent audit 92d53c8f, 2026-07-29): /proc/<pid>/environ
116
+ * is 0400 owner-only. Blindly reading it will hit EACCES on every other-user
117
+ * process (pid 1 is systemd/root → guaranteed EACCES). The naive fix — wrap
118
+ * in try/catch and continue — would silently miss marker-carrying processes
119
+ * whose environ we can't read for some other reason, recreating Defect A
120
+ * ("nothing killed but report success"). Right fix:
121
+ *
122
+ * 1. Try readEnviron.
123
+ * 2. On EACCES, discriminate via readOwnerUid + readState:
124
+ * - Owner uid != ours → EXPECTED skip (can't be one of our procs).
125
+ * - Own uid, state = Z → EXPECTED skip (zombie, mm freed).
126
+ * - Own uid, not zombie → FAIL-CLOSED (unexplained EACCES on our own
127
+ * live process is a real problem, must throw).
128
+ */
129
+ export interface ScanResult {
130
+ /** Pids whose environ we successfully read and matched the marker uuid. */
131
+ hits: number[];
132
+ /**
133
+ * Own-uid, live, environ-unreadable pids that are PLAUSIBLY PART OF THE
134
+ * COPRESENCE TREE (invariant 11 scope test). These might be marker-
135
+ * carrying without us being able to prove it, so the reap flow REFUSES
136
+ * marker removal while this list is non-empty — defense against Defect A
137
+ * (silently missing a marker-carrying process, then deleting the marker
138
+ * as if teardown had succeeded).
139
+ */
140
+ unreadableOwnUid: number[];
141
+ /**
142
+ * Own-uid, live, environ-unreadable pids that failed the scope test:
143
+ * their pgid belongs to no marker-carrying group and their ppid chain
144
+ * reaches no marker carrier / validated marker-file session pid.
145
+ *
146
+ * INFORMATIONAL ONLY — never fail-closed. A machine routinely has such
147
+ * processes (a same-uid process whose primary GID differs from ours fails
148
+ * the kernel's __ptrace_may_access gid check and EACCESes on environ even
149
+ * though its real uid matches). v2 lumped these into unreadableOwnUid,
150
+ * which made reapMarkerGroups structurally unable to return success on
151
+ * any such host.
152
+ *
153
+ * KNOWN RESIDUAL GAP (stated rather than papered over): a marker-carrying
154
+ * process that is BOTH non-dumpable (environ unreadable) AND fully
155
+ * detached (setsid'd into its own pgroup with ppid=1, no live recorded
156
+ * session pid above it) lands here and is therefore not reaped and does
157
+ * not block marker removal. Nothing in /proc exposes the environment of a
158
+ * non-dumpable task to a non-root reader, so no scope widening can
159
+ * recover it — only running teardown as root could. Widening scope to
160
+ * "every same-uid unreadable process" is NOT an acceptable trade: that is
161
+ * exactly the v2 behaviour that made teardown never succeed. The
162
+ * realistic copresence shape (child of a recorded pane pid, or sharing a
163
+ * marker carrier's pgroup) IS covered — see the real-/proc test.
164
+ */
165
+ unreadableOutOfScope: number[];
166
+ }
167
+ /**
168
+ * Marker-file session records used to anchor the invariant-11 scope test.
169
+ * Each entry must be re-validated (pid alive AND same starttime) before it
170
+ * is trusted — see validateAnchors.
171
+ */
172
+ export interface ScanAnchors {
173
+ sessions?: Array<{
174
+ pid: number;
175
+ starttime_jiffies: number;
176
+ }>;
177
+ }
178
+ export declare function anchorsFromMarker(marker: CopresenceMarker): ScanAnchors;
179
+ /**
180
+ * Invariant 11 scope test: is `pid` plausibly part of the copresence tree?
181
+ *
182
+ * True when the pid IS an anchor, when its pgid belongs to a marker-carrying
183
+ * group (or a validated anchor's group), or when walking its ppid chain
184
+ * reaches an anchor / marker carrier / a pid inside a relevant pgroup.
185
+ *
186
+ * Everything else is out of scope and must not participate in a fail-closed
187
+ * decision, no matter how unreadable it is.
188
+ */
189
+ export declare function isInCopresenceScope(enumer: ProcessEnumerator, pid: number, relevantPids: Set<number>, relevantPgids: Set<number>): boolean;
190
+ export declare function scanEnvironForMarker(enumer: ProcessEnumerator, markerUuid: string): number[];
191
+ export declare function scanEnvironForMarkerFull(enumer: ProcessEnumerator, markerUuid: string, anchors?: ScanAnchors): ScanResult;
192
+ export declare function groupPidsByPgid(enumer: ProcessEnumerator, pids: number[]): Map<number, number[]>;
193
+ export type HomogeneityResult = {
194
+ ok: true;
195
+ members: number[];
196
+ } | {
197
+ ok: false;
198
+ cause: "FOREIGN_MEMBER" | "ENUM_ERROR" | "EMPTY_GROUP";
199
+ foreignPids: number[];
200
+ unreadablePids: number[];
201
+ detail: string;
202
+ };
203
+ /**
204
+ * Verify that EVERY live member of `pgid` carries the marker.
205
+ *
206
+ * Blocker 2 fix: enumeration errors surface as ENUM_ERROR (fail-closed),
207
+ * never as an empty-list judged "safe". Any unreadable member also
208
+ * fails-closed. Empty group (no live members at all) also refuses — killing
209
+ * an empty pgroup can't be right and empty-list judged "ok" recreates the
210
+ * exact defect shape (independent audit 92d53c8f finding #6).
211
+ *
212
+ * Blocker 2 second half (zombie): a zombie same-uid process's environ
213
+ * returns EACCES even to owner (mm freed), but stat still exists with
214
+ * original pgid. Without discrimination, the zombie would be treated as
215
+ * "unreadable member" → ENUM_ERROR → entire group SKIPPED. Since re-verify
216
+ * happens post-SIGTERM (when zombies are most numerous), teardown would
217
+ * never escalate. Fix: apply the same owner-uid + state=Z discriminator as
218
+ * scanEnvironForMarker.
219
+ *
220
+ * Algorithm:
221
+ * 1. Enumerate all pids on the system.
222
+ * 2. Filter to pids whose /proc/PID/stat pgid == target pgid.
223
+ * 3. For each such pid, check its environ with EACCES discrimination:
224
+ * - Other-user EACCES → skip (can't be ours anyway).
225
+ * - Own-uid zombie → skip (expected, dying).
226
+ * - Own-uid live EACCES → truly unreadable → fail-closed.
227
+ * - Missing marker → foreign member → fail-closed.
228
+ */
229
+ export declare function verifyGroupHomogeneity(enumer: ProcessEnumerator, pgid: number, markerUuid: string): HomogeneityResult;
230
+ /**
231
+ * Walk the caller's ancestry (self → PPID → grandparent → ...) and check
232
+ * whether any ancestor carries the target marker. If yes → caller is
233
+ * running inside the copresence tree we're about to kill, and would take
234
+ * itself down.
235
+ */
236
+ export declare function callerCarriesMarker(enumer: ProcessEnumerator, markerUuid: string): {
237
+ self: boolean;
238
+ ancestorPid?: number;
239
+ };
240
+ export type ReapResult = {
241
+ kind: "success";
242
+ killedPgids: number[];
243
+ residualPids: number[];
244
+ unreadableOwnUid?: number[];
245
+ } | {
246
+ kind: "failed";
247
+ killedPgids: number[];
248
+ residualPids: number[];
249
+ skippedGroups: Array<{
250
+ pgid: number;
251
+ reason: string;
252
+ }>;
253
+ detail: string;
254
+ unreadableOwnUid?: number[];
255
+ };
256
+ export interface ReapOptions {
257
+ graceMs: number;
258
+ logger: (msg: string) => void;
259
+ /**
260
+ * Sleep primitive (grace period). Real code uses setTimeout; tests inject
261
+ * a fast/deterministic sleep so grace paths are actually covered. Prior
262
+ * impl was a busy-wait `while (Date.now() < end) {}` — audit 92d53c8f
263
+ * finding #3 flagged that as pinning one CPU core for graceMs and blocking
264
+ * the event loop; test coverage missed it because tests passed graceMs=0.
265
+ */
266
+ sleep?: (ms: number) => Promise<void>;
267
+ /**
268
+ * Invariant-11 scope anchors, normally `anchorsFromMarker(marker)`.
269
+ *
270
+ * Without them the only anchors are the marker carriers the scan itself
271
+ * found, so a marker-carrying process we cannot READ (non-dumpable) but
272
+ * whose parent IS a recorded session pid would be judged out of scope and
273
+ * silently dropped. Passing the marker's recorded session pids closes that
274
+ * hole; each one is re-validated (alive + same starttime) before it can
275
+ * widen scope, so a stale/recycled pid cannot.
276
+ */
277
+ anchors?: ScanAnchors;
278
+ }
279
+ /**
280
+ * Full reap flow with TOCTOU re-verification.
281
+ *
282
+ * Sequence:
283
+ * 1. Environ scan for marker → get all live pids carrying it.
284
+ * 2. Group by current PGID.
285
+ * 3. For each group: verify homogeneity. Skip on foreign/unreadable.
286
+ * 4. For each verified group: send SIGTERM to pgroup.
287
+ * 5. Wait grace.
288
+ * 6. Re-verify each group (marker still there, no new foreign) before SIGKILL.
289
+ * 7. Send SIGKILL to any group still alive.
290
+ * 8. Post-rescan: if any marker-carrying pid alive → preserve marker.
291
+ */
292
+ export declare function reapMarkerGroups(enumer: ProcessEnumerator, killer: KillPrimitive, markerUuid: string, opts: ReapOptions): Promise<ReapResult>;
293
+ export interface PrepareStartDeps {
294
+ /** Usually () => readMarker(nodesDir, nodeId). */
295
+ readMarker(): ReadMarkerResult;
296
+ /** Usually (uuid, anchors) => reapMarkerGroups(realEnumerator(), realKiller(), uuid, {...anchors}). */
297
+ reap(uuid: string, anchors: ScanAnchors): Promise<ReapResult>;
298
+ /** Usually () => removeMarker(nodesDir, nodeId). */
299
+ removeMarker(): void;
300
+ /** Usually (uuid, sessions) => writeMarker(nodesDir, nodeId, uuid, sessions). */
301
+ writeMarker(uuid: string, sessions: CopresenceMarker["sessions"]): void;
302
+ logger(msg: string): void;
303
+ }
304
+ export type PrepareStartResult = {
305
+ kind: "ok";
306
+ reclaimedUuid?: string;
307
+ } | {
308
+ kind: "blocked";
309
+ cause: "STALE_TREE_ALIVE" | "UNUSABLE_MARKER";
310
+ detail: string;
311
+ remedy: string;
312
+ };
313
+ /**
314
+ * Everything that must happen BEFORE the first `tmux new-session` of a
315
+ * copresence start. Extracted out of cli.ts so both blockers below are
316
+ * actually reachable by tests — the audit's point that the two fatal
317
+ * defects of the previous rounds both lived in an untested cli.ts seam.
318
+ *
319
+ * Blocker 5 — marker-before-tmux ordering.
320
+ * v2 wrote the marker only after the app-server had bound its port, i.e.
321
+ * after a 25s wait and after several `process.exit(1)` paths. A start that
322
+ * died in that window left a live, marker-carrying tmux session behind
323
+ * with NO marker file on disk: the exact unreclaimable-ghost this feature
324
+ * exists to prevent. The marker is now written here, before any session is
325
+ * created, with an empty `sessions` object — reap identity has always been
326
+ * the environ uuid, never the recorded pids, so an empty sessions object
327
+ * loses nothing but observability hints (which the start path fills in
328
+ * later, best-effort).
329
+ *
330
+ * Blocker 6 — never overwrite a preserved marker.
331
+ * A failed stop deliberately PRESERVES the marker so the next stop can
332
+ * retry idempotently. v2's start then overwrote it with a fresh uuid while
333
+ * only killing tmux sessions BY NAME, so the still-running subprocesses of
334
+ * the previous instance became permanently unreclaimable: their uuid was
335
+ * gone from disk forever. Now the old identity is reaped FIRST; if that
336
+ * reap does not fully succeed we refuse to start rather than destroy the
337
+ * only handle on those processes.
338
+ */
339
+ export declare function prepareIdentityForStart(newUuid: string, deps: PrepareStartDeps): Promise<PrepareStartResult>;