@sleep2agi/agent-network 2.3.0-preview.7 → 2.3.0-preview.9

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
- const a0_0x399040=a0_0x340f;(function(_0x39361b,_0x4180f8){const _0x315c67=a0_0x340f,_0x271cd3=_0x39361b();while(!![]){try{const _0x5a31d2=-parseInt(_0x315c67(0x142))/0x1*(-parseInt(_0x315c67(0x110))/0x2)+-parseInt(_0x315c67(0x149))/0x3+-parseInt(_0x315c67(0x15c))/0x4*(-parseInt(_0x315c67(0x130))/0x5)+-parseInt(_0x315c67(0x155))/0x6+parseInt(_0x315c67(0x118))/0x7*(parseInt(_0x315c67(0x153))/0x8)+parseInt(_0x315c67(0x11a))/0x9+parseInt(_0x315c67(0x12a))/0xa*(-parseInt(_0x315c67(0x147))/0xb);if(_0x5a31d2===_0x4180f8)break;else _0x271cd3['push'](_0x271cd3['shift']());}catch(_0x4b1e5a){_0x271cd3['push'](_0x271cd3['shift']());}}}(a0_0x5a89,0x54140));import{EventEmitter as a0_0x55ec56}from'events';function a0_0x340f(_0x5ea411,_0x424a15){_0x5ea411=_0x5ea411-0x108;const _0x5a89f0=a0_0x5a89();let _0x340f9e=_0x5a89f0[_0x5ea411];return _0x340f9e;}function a0_0x5a89(){const _0x31783e=['get_inbox','send_message','application/json,\x20text/event-stream','pop','min','send','report_status','2AnWlsV','offline','processInbox','heartbeatTimer','message','connect','autoConnect','ack_inbox','128996RRPghX','AbortError','5791725jsDCBh','catch','read','content','now','application/json','sseAbort','/events/','sdk-','task','getAllStatus','resumeId','startsWith','token','cwd','completed','6028210yecmod','heartbeatInterval','status','inbox\x20error:\x20','registered','heartbeat\x20failed:\x20','743455qDgZJb','url','result','replace','type','server','getReader','alias','reply','name','error','messages','POST','call',']\x20[commhub:','SSE\x20connected','disconnected','sdk','683419MzHxpd','abort','connectSSE','Authorization','disconnect','11GkgKBc','emit','2029374jmbGrS','sleep','agent','toTimeString','send_task','text','/mcp','broadcast','toString','body','152kdkLSg','new_task','3889062KUpUJH','log','parse','slice','Bearer\x20','idle','signal','16QlcPHD','split','reconnectDelay','text/event-stream','running'];a0_0x5a89=function(){return _0x31783e;};return a0_0x5a89();}import{hostname as a0_0x236b0c}from'os';class T extends a0_0x55ec56{['url'];['alias'];[a0_0x399040(0x127)];[a0_0x399040(0x14b)];[a0_0x399040(0x125)];[a0_0x399040(0x12b)];[a0_0x399040(0x15e)];[a0_0x399040(0x113)];['sseAbort'];[a0_0x399040(0x108)]=!0x1;constructor(_0x57aedd){const _0x5c20d6=a0_0x399040;super();if(this[_0x5c20d6(0x131)]=_0x57aedd[_0x5c20d6(0x131)][_0x5c20d6(0x133)](/\/$/,''),this['alias']=_0x57aedd[_0x5c20d6(0x137)],this[_0x5c20d6(0x127)]=_0x57aedd[_0x5c20d6(0x127)],this[_0x5c20d6(0x14b)]=_0x57aedd[_0x5c20d6(0x14b)]||_0x5c20d6(0x141),this[_0x5c20d6(0x125)]=_0x5c20d6(0x122)+_0x57aedd['alias']+'-'+Date[_0x5c20d6(0x11e)]()[_0x5c20d6(0x151)](0x24),this[_0x5c20d6(0x12b)]=_0x57aedd[_0x5c20d6(0x12b)]??0x2bf20,this['reconnectDelay']=_0x57aedd['reconnectDelay']??0xbb8,_0x57aedd[_0x5c20d6(0x116)]!==!0x1)this['connect']();}[a0_0x399040(0x156)](_0x2e1f5f){const _0xfaeef9=a0_0x399040;console['log']('['+new Date()[_0xfaeef9(0x14c)]()[_0xfaeef9(0x158)](0x0,0x8)+_0xfaeef9(0x13e)+this['alias']+']\x20'+_0x2e1f5f);}async['call'](_0x32db5e,_0x4993e1){const _0x25c2d5=a0_0x399040;let _0x50ec78={'Content-Type':_0x25c2d5(0x11f),'Accept':_0x25c2d5(0x10b)};if(this[_0x25c2d5(0x127)])_0x50ec78[_0x25c2d5(0x145)]=_0x25c2d5(0x159)+this['token'];let _0x19eff5=await(await fetch(this[_0x25c2d5(0x131)]+_0x25c2d5(0x14f),{'method':_0x25c2d5(0x13c),'headers':_0x50ec78,'body':JSON['stringify']({'jsonrpc':'2.0','id':Date['now'](),'method':'tools/call','params':{'name':_0x32db5e,'arguments':_0x4993e1}})}))[_0x25c2d5(0x14e)](),_0xa1ada5=_0x19eff5['match'](/data: (.+)/),_0x172873=_0xa1ada5?JSON[_0x25c2d5(0x157)](_0xa1ada5[0x1]):JSON['parse'](_0x19eff5),_0x286359=_0x172873?.[_0x25c2d5(0x132)]?.[_0x25c2d5(0x11d)]?.[0x0]?.[_0x25c2d5(0x14e)];return _0x286359?JSON[_0x25c2d5(0x157)](_0x286359):_0x172873;}async[a0_0x399040(0x115)](){const _0x4c706f=a0_0x399040;if(this[_0x4c706f(0x108)])return;this[_0x4c706f(0x108)]=!0x0,await this[_0x4c706f(0x12c)](_0x4c706f(0x15a)),this['log'](_0x4c706f(0x12e)),this[_0x4c706f(0x113)]=setInterval(()=>{const _0x5bddf2=_0x4c706f;this[_0x5bddf2(0x12c)](_0x5bddf2(0x15a))['catch'](_0x9c819b=>this[_0x5bddf2(0x156)](_0x5bddf2(0x12f)+_0x9c819b['message']));},this['heartbeatInterval']),this[_0x4c706f(0x144)]();}async[a0_0x399040(0x146)](){const _0x578f3e=a0_0x399040;if(this['running']=!0x1,this['sseAbort']?.[_0x578f3e(0x143)](),this[_0x578f3e(0x113)])clearInterval(this[_0x578f3e(0x113)]);await this[_0x578f3e(0x12c)](_0x578f3e(0x111))[_0x578f3e(0x11b)](()=>{}),this[_0x578f3e(0x156)](_0x578f3e(0x140));}async[a0_0x399040(0x10e)](_0x30a6e0,_0x587824,_0x3fb8ac='normal'){const _0x4203ac=a0_0x399040;return this['call'](_0x4203ac(0x14d),{'alias':_0x30a6e0,'task':_0x587824,'priority':_0x3fb8ac,'from_session':this['alias']});}async[a0_0x399040(0x114)](_0x5bcff8,_0x3108bf){const _0x4d65d5=a0_0x399040;return this[_0x4d65d5(0x13d)](_0x4d65d5(0x10a),{'alias':_0x5bcff8,'message':_0x3108bf,'from_session':this[_0x4d65d5(0x137)]});}async[a0_0x399040(0x138)](_0x41a286,_0x20add6,_0x1d8e7c=a0_0x399040(0x129)){const _0x36fa1f=a0_0x399040;return this[_0x36fa1f(0x13d)]('send_reply',{'in_reply_to':_0x41a286,'text':_0x20add6,'status':_0x1d8e7c});}async['status'](_0x18ece1,_0x2352f3){const _0x573b42=a0_0x399040;return this[_0x573b42(0x13d)](_0x573b42(0x10f),{'resume_id':this[_0x573b42(0x125)],'alias':this[_0x573b42(0x137)],'status':_0x18ece1,'server':a0_0x236b0c(),'hostname':a0_0x236b0c(),'agent':this[_0x573b42(0x14b)],'project_dir':process[_0x573b42(0x128)](),..._0x2352f3});}async[a0_0x399040(0x124)](){const _0x5825f9=a0_0x399040;return this[_0x5825f9(0x13d)]('get_all_status',{});}async[a0_0x399040(0x150)](_0x16d6d3,_0x41cfe1){const _0x3aa5fe=a0_0x399040;return this[_0x3aa5fe(0x13d)](_0x3aa5fe(0x150),{'message':_0x16d6d3,'filter_server':_0x41cfe1?.[_0x3aa5fe(0x135)],'filter_status':_0x41cfe1?.[_0x3aa5fe(0x12c)]});}async[a0_0x399040(0x144)](){const _0x532a18=a0_0x399040;let _0x114f53=encodeURIComponent(this[_0x532a18(0x137)]),_0x5df645=this[_0x532a18(0x131)]+_0x532a18(0x121)+_0x114f53,_0x10afd0=this[_0x532a18(0x15e)];while(this['running']){try{this[_0x532a18(0x120)]=new AbortController();let _0x1bd2b5={'Accept':_0x532a18(0x15f)};if(this[_0x532a18(0x127)])_0x1bd2b5['Authorization']='Bearer\x20'+this[_0x532a18(0x127)];let _0x195262=await fetch(_0x5df645,{'headers':_0x1bd2b5,'signal':this[_0x532a18(0x120)][_0x532a18(0x15b)]});if(!_0x195262['ok']||!_0x195262[_0x532a18(0x152)]){this[_0x532a18(0x156)]('SSE\x20failed:\x20'+_0x195262[_0x532a18(0x12c)]),await this[_0x532a18(0x14a)](_0x10afd0),_0x10afd0=Math['min'](_0x10afd0*1.5,0xea60);continue;}_0x10afd0=this['reconnectDelay'];let _0x673f17=_0x195262['body'][_0x532a18(0x136)](),_0x526c55=new TextDecoder(),_0x3d58f6='';while(this[_0x532a18(0x108)]){let {done:_0x185423,value:_0x52b3aa}=await _0x673f17[_0x532a18(0x11c)]();if(_0x185423)break;_0x3d58f6+=_0x526c55['decode'](_0x52b3aa,{'stream':!0x0});let _0x113149=_0x3d58f6[_0x532a18(0x15d)]('\x0a');_0x3d58f6=_0x113149[_0x532a18(0x10c)]()||'';for(let _0xda92e9 of _0x113149){if(!_0xda92e9[_0x532a18(0x126)]('data:\x20'))continue;try{let _0x297867=JSON[_0x532a18(0x157)](_0xda92e9['slice'](0x6));if(_0x297867[_0x532a18(0x134)]==='connected'){this[_0x532a18(0x156)](_0x532a18(0x13f)),this[_0x532a18(0x148)]('connected');continue;}if(_0x297867[_0x532a18(0x134)]===_0x532a18(0x154)||_0x297867[_0x532a18(0x134)]==='new_message'||_0x297867['type']===_0x532a18(0x150))await this[_0x532a18(0x112)]();}catch{}}}}catch(_0x4c7cae){if(_0x4c7cae[_0x532a18(0x139)]===_0x532a18(0x119))break;this[_0x532a18(0x148)](_0x532a18(0x13a),_0x4c7cae),this[_0x532a18(0x156)]('SSE\x20error:\x20'+_0x4c7cae[_0x532a18(0x114)]);}if(this[_0x532a18(0x108)])this[_0x532a18(0x148)](_0x532a18(0x140)),this['log']('SSE\x20reconnecting\x20in\x20'+_0x10afd0/0x3e8+'s...'),await this[_0x532a18(0x14a)](_0x10afd0),_0x10afd0=Math[_0x532a18(0x10d)](_0x10afd0*1.5,0xea60);}}async[a0_0x399040(0x112)](){const _0x1bd4ba=a0_0x399040;try{let _0x344cd2=(await this[_0x1bd4ba(0x13d)](_0x1bd4ba(0x109),{'alias':this['alias'],'limit':0xa}))?.[_0x1bd4ba(0x13b)]||[];for(let _0x5244ff of _0x344cd2)await this['call'](_0x1bd4ba(0x117),{'alias':this[_0x1bd4ba(0x137)],'message_id':_0x5244ff['id']}),this[_0x1bd4ba(0x156)]('←\x20'+_0x5244ff['from_session']+':\x20'+_0x5244ff[_0x1bd4ba(0x11d)][_0x1bd4ba(0x158)](0x0,0x3c)),this['emit'](_0x1bd4ba(0x123),_0x5244ff),this[_0x1bd4ba(0x148)](_0x1bd4ba(0x114),_0x5244ff);}catch(_0xe0b16d){this['log'](_0x1bd4ba(0x12d)+_0xe0b16d['message']);}}[a0_0x399040(0x14a)](_0x576196){return new Promise(_0x278a9=>setTimeout(_0x278a9,_0x576196));}}var $=T;export{$ as default,T as CommHub};
1
+ const a0_0x5920d3=a0_0x16ff;(function(_0x2ba291,_0x1e2095){const _0x4ffd6f=a0_0x16ff,_0x24cf74=_0x2ba291();while(!![]){try{const _0x494620=parseInt(_0x4ffd6f(0x210))/0x1*(parseInt(_0x4ffd6f(0x206))/0x2)+-parseInt(_0x4ffd6f(0x22d))/0x3+parseInt(_0x4ffd6f(0x1e6))/0x4*(-parseInt(_0x4ffd6f(0x21e))/0x5)+parseInt(_0x4ffd6f(0x220))/0x6*(parseInt(_0x4ffd6f(0x22c))/0x7)+-parseInt(_0x4ffd6f(0x215))/0x8*(-parseInt(_0x4ffd6f(0x1d8))/0x9)+-parseInt(_0x4ffd6f(0x20f))/0xa*(-parseInt(_0x4ffd6f(0x20b))/0xb)+-parseInt(_0x4ffd6f(0x20e))/0xc;if(_0x494620===_0x1e2095)break;else _0x24cf74['push'](_0x24cf74['shift']());}catch(_0x1fb59b){_0x24cf74['push'](_0x24cf74['shift']());}}}(a0_0x1d84,0x5cc6a));function a0_0x16ff(_0x2bd2c0,_0x1bf401){_0x2bd2c0=_0x2bd2c0-0x1d8;const _0x1d84fe=a0_0x1d84();let _0x16ff51=_0x1d84fe[_0x2bd2c0];return _0x16ff51;}import{EventEmitter as a0_0x302ef1}from'events';function a0_0x1d84(){const _0x4a5a59=['application/json,\x20text/event-stream','alias','705krKHwc','get_all_status','351228KPOtwm','s...','match','token','broadcast','url','call','SSE\x20reconnecting\x20in\x20','POST','tools/call','text/event-stream','signal','28SICtSD','140412SGeGSj','disconnected','send_task','connected','read','531JsuzXG','disconnect','toTimeString','heartbeatInterval','report_status','inbox\x20error:\x20','data:\x20','/mcp','stringify','slice','sdk','processInbox','now','normal','10936cbUyUZ','offline','min','getReader','cwd','parse','catch','Bearer\x20','registered','message','SSE\x20error:\x20','status','toString','resumeId','content','connect','new_task','from_session','log','new_message','send_reply','getAllStatus','messages','AbortError','autoConnect','sseAbort','connectSSE','text','sleep','type','startsWith','/events/','8anUVCl','emit','agent','completed','send_message','11YGRDNc','Authorization','reconnectDelay','8968332JGzJBc','4836790IREQic','184529cLDiAv','split','heartbeatTimer','name','send','14064aPspDd','body','running','2.0','idle','decode','sdk-'];a0_0x1d84=function(){return _0x4a5a59;};return a0_0x1d84();}import{hostname as a0_0x2755ad}from'os';class T extends a0_0x302ef1{['url'];[a0_0x5920d3(0x21d)];['token'];[a0_0x5920d3(0x208)];[a0_0x5920d3(0x1f3)];['heartbeatInterval'];[a0_0x5920d3(0x20d)];[a0_0x5920d3(0x212)];[a0_0x5920d3(0x1ff)];['running']=!0x1;constructor(_0x5f2f64){const _0x12a96f=a0_0x5920d3;super();if(this[_0x12a96f(0x225)]=_0x5f2f64[_0x12a96f(0x225)]['replace'](/\/$/,''),this[_0x12a96f(0x21d)]=_0x5f2f64[_0x12a96f(0x21d)],this[_0x12a96f(0x223)]=_0x5f2f64[_0x12a96f(0x223)],this[_0x12a96f(0x208)]=_0x5f2f64['agent']||_0x12a96f(0x1e2),this[_0x12a96f(0x1f3)]=_0x12a96f(0x21b)+_0x5f2f64[_0x12a96f(0x21d)]+'-'+Date[_0x12a96f(0x1e4)]()[_0x12a96f(0x1f2)](0x24),this[_0x12a96f(0x1db)]=_0x5f2f64['heartbeatInterval']??0x2bf20,this[_0x12a96f(0x20d)]=_0x5f2f64[_0x12a96f(0x20d)]??0xbb8,_0x5f2f64[_0x12a96f(0x1fe)]!==!0x1)this['connect']();}[a0_0x5920d3(0x1f8)](_0x1c820b){const _0x51a463=a0_0x5920d3;console[_0x51a463(0x1f8)]('['+new Date()[_0x51a463(0x1da)]()[_0x51a463(0x1e1)](0x0,0x8)+']\x20[commhub:'+this['alias']+']\x20'+_0x1c820b);}async[a0_0x5920d3(0x226)](_0x510e92,_0x16eb96){const _0xde81c6=a0_0x5920d3;let _0x29b431={'Content-Type':'application/json','Accept':_0xde81c6(0x21c)};if(this[_0xde81c6(0x223)])_0x29b431[_0xde81c6(0x20c)]=_0xde81c6(0x1ed)+this[_0xde81c6(0x223)];let _0x362ba8=await(await fetch(this[_0xde81c6(0x225)]+_0xde81c6(0x1df),{'method':_0xde81c6(0x228),'headers':_0x29b431,'body':JSON[_0xde81c6(0x1e0)]({'jsonrpc':_0xde81c6(0x218),'id':Date[_0xde81c6(0x1e4)](),'method':_0xde81c6(0x229),'params':{'name':_0x510e92,'arguments':_0x16eb96}})}))[_0xde81c6(0x201)](),_0x2e5516=_0x362ba8[_0xde81c6(0x222)](/data: (.+)/),_0x3d67c1=_0x2e5516?JSON[_0xde81c6(0x1eb)](_0x2e5516[0x1]):JSON['parse'](_0x362ba8),_0x2607c=_0x3d67c1?.['result']?.[_0xde81c6(0x1f4)]?.[0x0]?.[_0xde81c6(0x201)];return _0x2607c?JSON[_0xde81c6(0x1eb)](_0x2607c):_0x3d67c1;}async[a0_0x5920d3(0x1f5)](){const _0x3747bf=a0_0x5920d3;if(this[_0x3747bf(0x217)])return;this[_0x3747bf(0x217)]=!0x0,await this['status'](_0x3747bf(0x219)),this[_0x3747bf(0x1f8)](_0x3747bf(0x1ee)),this['heartbeatTimer']=setInterval(()=>{const _0xd4119b=_0x3747bf;this[_0xd4119b(0x1f1)](_0xd4119b(0x219))[_0xd4119b(0x1ec)](_0x19410a=>this[_0xd4119b(0x1f8)]('heartbeat\x20failed:\x20'+_0x19410a[_0xd4119b(0x1ef)]));},this[_0x3747bf(0x1db)]),this['connectSSE']();}async[a0_0x5920d3(0x1d9)](){const _0x3b0abc=a0_0x5920d3;if(this[_0x3b0abc(0x217)]=!0x1,this[_0x3b0abc(0x1ff)]?.['abort'](),this[_0x3b0abc(0x212)])clearInterval(this[_0x3b0abc(0x212)]);await this[_0x3b0abc(0x1f1)](_0x3b0abc(0x1e7))[_0x3b0abc(0x1ec)](()=>{}),this[_0x3b0abc(0x1f8)](_0x3b0abc(0x22e));}async[a0_0x5920d3(0x214)](_0x172e8d,_0x4ee915,_0x520465=a0_0x5920d3(0x1e5)){const _0x496136=a0_0x5920d3;return this[_0x496136(0x226)](_0x496136(0x22f),{'alias':_0x172e8d,'task':_0x4ee915,'priority':_0x520465,'from_session':this[_0x496136(0x21d)]});}async[a0_0x5920d3(0x1ef)](_0x5dd07a,_0x1d1ce3){const _0x5f1bab=a0_0x5920d3;return this[_0x5f1bab(0x226)](_0x5f1bab(0x20a),{'alias':_0x5dd07a,'message':_0x1d1ce3,'from_session':this['alias']});}async['reply'](_0x12a01c,_0x87fda4,_0x466014=a0_0x5920d3(0x209)){const _0x2d5f9a=a0_0x5920d3;return this[_0x2d5f9a(0x226)](_0x2d5f9a(0x1fa),{'in_reply_to':_0x12a01c,'text':_0x87fda4,'status':_0x466014});}async[a0_0x5920d3(0x1f1)](_0x26fef4,_0xd4c06c){const _0x120180=a0_0x5920d3;return this[_0x120180(0x226)](_0x120180(0x1dc),{'resume_id':this[_0x120180(0x1f3)],'alias':this[_0x120180(0x21d)],'status':_0x26fef4,'server':a0_0x2755ad(),'hostname':a0_0x2755ad(),'agent':this[_0x120180(0x208)],'project_dir':process[_0x120180(0x1ea)](),..._0xd4c06c});}async[a0_0x5920d3(0x1fb)](){const _0x1d9c4e=a0_0x5920d3;return this[_0x1d9c4e(0x226)](_0x1d9c4e(0x21f),{});}async[a0_0x5920d3(0x224)](_0x58200f,_0x22c77d){const _0x50a4ec=a0_0x5920d3;return this[_0x50a4ec(0x226)](_0x50a4ec(0x224),{'message':_0x58200f,'filter_server':_0x22c77d?.['server'],'filter_status':_0x22c77d?.[_0x50a4ec(0x1f1)]});}async[a0_0x5920d3(0x200)](){const _0x47cb57=a0_0x5920d3;let _0x560cc2=encodeURIComponent(this['alias']),_0x4841a1=this[_0x47cb57(0x225)]+_0x47cb57(0x205)+_0x560cc2,_0x12cd58=this[_0x47cb57(0x20d)];while(this[_0x47cb57(0x217)]){try{this[_0x47cb57(0x1ff)]=new AbortController();let _0x35d2c6={'Accept':_0x47cb57(0x22a)};if(this[_0x47cb57(0x223)])_0x35d2c6['Authorization']=_0x47cb57(0x1ed)+this[_0x47cb57(0x223)];let _0x34a2cc=await fetch(_0x4841a1,{'headers':_0x35d2c6,'signal':this[_0x47cb57(0x1ff)][_0x47cb57(0x22b)]});if(!_0x34a2cc['ok']||!_0x34a2cc[_0x47cb57(0x216)]){this['log']('SSE\x20failed:\x20'+_0x34a2cc['status']),await this[_0x47cb57(0x202)](_0x12cd58),_0x12cd58=Math['min'](_0x12cd58*1.5,0xea60);continue;}_0x12cd58=this[_0x47cb57(0x20d)];let _0x54d9bc=_0x34a2cc['body'][_0x47cb57(0x1e9)](),_0x44e986=new TextDecoder(),_0x214d83='';while(this[_0x47cb57(0x217)]){let {done:_0x3256bd,value:_0x33943a}=await _0x54d9bc[_0x47cb57(0x231)]();if(_0x3256bd)break;_0x214d83+=_0x44e986[_0x47cb57(0x21a)](_0x33943a,{'stream':!0x0});let _0x5eac3f=_0x214d83[_0x47cb57(0x211)]('\x0a');_0x214d83=_0x5eac3f['pop']()||'';for(let _0x1dc067 of _0x5eac3f){if(!_0x1dc067[_0x47cb57(0x204)](_0x47cb57(0x1de)))continue;try{let _0x8c8d76=JSON[_0x47cb57(0x1eb)](_0x1dc067[_0x47cb57(0x1e1)](0x6));if(_0x8c8d76[_0x47cb57(0x203)]==='connected'){this[_0x47cb57(0x1f8)]('SSE\x20connected'),this[_0x47cb57(0x207)](_0x47cb57(0x230));continue;}if(_0x8c8d76[_0x47cb57(0x203)]===_0x47cb57(0x1f6)||_0x8c8d76[_0x47cb57(0x203)]===_0x47cb57(0x1f9)||_0x8c8d76[_0x47cb57(0x203)]===_0x47cb57(0x224))await this[_0x47cb57(0x1e3)]();}catch{}}}}catch(_0x169a25){if(_0x169a25[_0x47cb57(0x213)]===_0x47cb57(0x1fd))break;this[_0x47cb57(0x207)]('error',_0x169a25),this[_0x47cb57(0x1f8)](_0x47cb57(0x1f0)+_0x169a25[_0x47cb57(0x1ef)]);}if(this[_0x47cb57(0x217)])this[_0x47cb57(0x207)](_0x47cb57(0x22e)),this[_0x47cb57(0x1f8)](_0x47cb57(0x227)+_0x12cd58/0x3e8+_0x47cb57(0x221)),await this['sleep'](_0x12cd58),_0x12cd58=Math[_0x47cb57(0x1e8)](_0x12cd58*1.5,0xea60);}}async['processInbox'](){const _0x60277b=a0_0x5920d3;try{let _0x30d1eb=(await this[_0x60277b(0x226)]('get_inbox',{'alias':this[_0x60277b(0x21d)],'limit':0xa}))?.[_0x60277b(0x1fc)]||[];for(let _0x8a5294 of _0x30d1eb)await this[_0x60277b(0x226)]('ack_inbox',{'alias':this[_0x60277b(0x21d)],'message_id':_0x8a5294['id']}),this[_0x60277b(0x1f8)]('←\x20'+_0x8a5294[_0x60277b(0x1f7)]+':\x20'+_0x8a5294[_0x60277b(0x1f4)][_0x60277b(0x1e1)](0x0,0x3c)),this[_0x60277b(0x207)]('task',_0x8a5294),this[_0x60277b(0x207)](_0x60277b(0x1ef),_0x8a5294);}catch(_0x1597fe){this[_0x60277b(0x1f8)](_0x60277b(0x1dd)+_0x1597fe['message']);}}[a0_0x5920d3(0x202)](_0x11d201){return new Promise(_0x3186f5=>setTimeout(_0x3186f5,_0x11d201));}}var $=T;export{$ as default,T as CommHub};
@@ -4,7 +4,7 @@ export declare class FeishuAdapter implements IMAdapter {
4
4
  readonly platform = "feishu";
5
5
  readonly ingressMode: IMIngressMode;
6
6
  private feishuConfig;
7
- private connectionName;
7
+ private connectionName_;
8
8
  private client;
9
9
  private wsClient;
10
10
  /**
@@ -28,6 +28,12 @@ export declare class FeishuAdapter implements IMAdapter {
28
28
  * the public-channel shape and still needs flood protection.
29
29
  */
30
30
  getAllowFrom(): readonly string[];
31
+ /**
32
+ * Read-only accessor used by bridge to resolve per-connection paths
33
+ * (RFC-020 §15 outbound-marker validation needs the connection name
34
+ * to build the allowed per-conversation directory prefix).
35
+ */
36
+ get connectionName(): string;
31
37
  init(config: IMChannelConfig): Promise<void>;
32
38
  start(onEvent: OnEventHandler): Promise<void>;
33
39
  stop(): Promise<void>;
@@ -57,4 +63,35 @@ export declare class FeishuAdapter implements IMAdapter {
57
63
  * `|` and `**`).
58
64
  */
59
65
  export declare function looksLikeMarkdown(text: string): boolean;
66
+ /**
67
+ * Parse Feishu `message_type: "post"` content into plain text. Post
68
+ * content is a nested structure:
69
+ *
70
+ * { title?: string,
71
+ * content: Array<Array<{ tag: "text"|"img"|"a"|"at"|"emotion", ... }>>
72
+ * }
73
+ *
74
+ * Each top-level array entry is a paragraph; each paragraph is an array
75
+ * of typed segments. We flatten by:
76
+ * - prepending title (if present) as `<title>\n\n`
77
+ * - joining paragraphs with `\n\n`
78
+ * - joining segments within a paragraph in order
79
+ * - tag=text → emit segment.text as-is
80
+ * - tag=a → emit `[label](href)` (markdown link)
81
+ * - tag=at → emit `@user_name` (fallback to `@<user_id>` if no name)
82
+ * - tag=img → emit `[图片]` placeholder (actual download via maybeAttachImages)
83
+ * - tag=emotion → emit `[emoji]`
84
+ * - unknown tag → skip
85
+ *
86
+ * @internal exported for unit tests.
87
+ */
88
+ export declare function parsePostContent(rawJson: string): string;
89
+ /**
90
+ * Walk a Feishu `post` content JSON and collect all `image_key` values
91
+ * from `tag: "img"` segments. Used by `maybeAttachImages` to schedule
92
+ * downloads for every image in a 图文混排 message.
93
+ *
94
+ * @internal exported for unit tests.
95
+ */
96
+ export declare function extractPostImageKeys(rawJson: string): string[];
60
97
  export {};
@@ -0,0 +1,61 @@
1
+ /**
2
+ * RFC-020 §14 — markdown → image rendering for Feishu replies.
3
+ *
4
+ * Vincent 2026-06-29 path: Feishu's `markdown` card element doesn't
5
+ * render ATX headings or GFM tables (preview.7 caught only bold / list
6
+ * / link). Rather than partially support a moving subset of card
7
+ * elements, we render structured markdown to a PNG via headless
8
+ * chromium and send it through Feishu's image API (`im:resource:upload`
9
+ * scope). Pixel-perfect fidelity, zero schema fragility, text-not-
10
+ * copyable accepted as the tradeoff for "actually renders".
11
+ *
12
+ * Hybrid route (decided in adapter.send):
13
+ * - plain text (no markdown markers) → msg_type:"text"
14
+ * - markdown WITHOUT heading / table / long → msg_type:"interactive" (schema 1.0 card with `markdown` element — keeps copy/paste for short bold/list/link replies; preview.7 path)
15
+ * - markdown WITH heading / table / long → THIS PATH (msg_type:"image" with rendered PNG)
16
+ *
17
+ * Renderer choice: `puppeteer-core` (no bundled chromium) + system
18
+ * chromium (apt install in Docker). Rationale:
19
+ * - Pure-JS canvas-layout libraries (node-canvas, @napi-rs/canvas)
20
+ * cost 4-6h of manual paragraph wrapping + table cell measurement
21
+ * + Chinese width metrics; chromium does this natively.
22
+ * - puppeteer-core (5MB) + system chromium (~100MB) is smaller than
23
+ * full puppeteer (170MB) which bundles its own chromium.
24
+ * - Headless screenshot ~500ms after warmup. Bot's heavy turn is 20-
25
+ * 70s; rendering cost is in the noise.
26
+ *
27
+ * Chromium reuse: we keep a single browser instance hot across
28
+ * renderings to avoid the ~2-3s cold-start per call. Auto-close on
29
+ * idle is a follow-up — agent-node worker lifetime is bounded.
30
+ */
31
+ import { Buffer } from "node:buffer";
32
+ /**
33
+ * Close the shared browser. Called from adapter.stop() during graceful
34
+ * worker shutdown. Subsequent render calls re-launch.
35
+ */
36
+ export declare function closeBrowser(): Promise<void>;
37
+ /**
38
+ * Render markdown text to a PNG buffer.
39
+ *
40
+ * Width is fixed at 800px (IM-friendly); height auto-fits content via
41
+ * `fullPage:true`. Returns the raw PNG bytes — caller hands them to
42
+ * `lark.im.image.create({image: Readable.from(buffer)})`.
43
+ *
44
+ * Throws on chromium launch failure or page navigation failure.
45
+ * Caller is responsible for fallback (e.g., send the raw text as a
46
+ * code block in the schema 1.0 card path).
47
+ */
48
+ export declare function renderMarkdownToPng(text: string): Promise<Buffer>;
49
+ /**
50
+ * Decide whether `renderMarkdownToPng` should be invoked for this reply
51
+ * text, vs. falling back to msg_type:"text" / msg_type:"interactive"
52
+ * (schema 1.0 card). Locked by 通信龙 3f70044c — trigger image when:
53
+ * - text contains a markdown table (Feishu card can't render)
54
+ * - text contains an ATX heading (Feishu card can't render)
55
+ * - text length > 2000 chars (image is better than scrollable text wall)
56
+ *
57
+ * Returns false for short prose, single-line plain text, and short
58
+ * markdown lists / bold / link / inline-code which DO render fine in
59
+ * the schema 1.0 `markdown` card element.
60
+ */
61
+ export declare function shouldRenderAsImage(text: string): boolean;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * RFC-020 §15 — agent→bridge outbound file protocol.
3
+ *
4
+ * 2026-06-29 Vincent UAT: agent generated a PDF via reportlab + wrote it
5
+ * to `/work/feishu-attachments/<conv>/x.pdf`, then in text asked Vincent
6
+ * "I'm not sure if the system will auto-attach this — try another way?"
7
+ * The bridge has `adapter.send({files})` since #329, but no protocol
8
+ * told the agent how to signal "dispatch this file to the user".
9
+ *
10
+ * Convention: in its final reply, the agent emits one
11
+ *
12
+ * [[send-file:/abs/path]]
13
+ *
14
+ * marker per file (one per line, end of reply). The bridge:
15
+ *
16
+ * 1. extracts every `[[send-file:...]]` token,
17
+ * 2. strips them from the user-visible text,
18
+ * 3. validates each path against an allowed-outbound-root whitelist
19
+ * (`/work/feishu-attachments/<conn>/<chat>/` — same per-conversation
20
+ * directory the LLM has Write access to under Layer B),
21
+ * 4. checks the file exists, is non-empty, and ≤ 30 MB (Feishu file_v1
22
+ * upper bound),
23
+ * 5. magic-byte sniffs to choose `image_key` vs `file_key` upload route,
24
+ * 6. dispatches each file via `adapter.send({files:[...]})`,
25
+ * 7. emits a friendly fallback if validation fails — never the raw error.
26
+ *
27
+ * Pure module — no I/O, no IM SDK calls. The parser returns the cleaned
28
+ * text + a structured list of file requests; bridge.ts is responsible
29
+ * for filesystem checks and dispatching.
30
+ */
31
+ /**
32
+ * One outbound-file request parsed from an agent reply.
33
+ *
34
+ * - `raw`: the bytes between `[[send-file:` and `]]`, before any
35
+ * normalization. Kept for stderr forensic.
36
+ * - `normalized`: lexical-normalized absolute path (quote-strip, `..`
37
+ * collapse, `//` collapse, `./` resolution against cwd). The
38
+ * `validatedAbsolute` field is set later by the bridge after the
39
+ * realpath / whitelist / exists check.
40
+ */
41
+ export interface OutboundFileRequest {
42
+ raw: string;
43
+ normalized: string;
44
+ }
45
+ export interface MarkerParseResult {
46
+ /** Reply text with all `[[send-file:...]]` markers removed + adjacent
47
+ * whitespace collapsed. May be empty (file-only reply). */
48
+ cleanedText: string;
49
+ /** Files in source order. Caller-side validation happens after. */
50
+ files: OutboundFileRequest[];
51
+ }
52
+ /**
53
+ * Lexically normalize a path token from the marker. NOT a full
54
+ * symlink/realpath resolver — bridge does that after this returns.
55
+ *
56
+ * - Trim leading / trailing whitespace.
57
+ * - Strip one layer of matching quotes (`"/x"` / `'/x'` → `/x`).
58
+ * - `.` and `..` segments collapse via `path.posix.normalize`.
59
+ * - Repeated `/` collapse.
60
+ *
61
+ * Returns an absolute path or the empty string if the input cannot be
62
+ * interpreted as an absolute path token (caller drops empties).
63
+ */
64
+ export declare function normalizeMarkerPath(raw: string): string;
65
+ /**
66
+ * Parse an agent reply into cleaned text + outbound-file requests.
67
+ *
68
+ * Empty / null input returns `{cleanedText: "", files: []}` so callers
69
+ * can safely pipe through without defensive checks.
70
+ *
71
+ * Marker-only reply (no surrounding text) returns `cleanedText: ""` —
72
+ * caller should NOT send an empty text message in that case; they only
73
+ * dispatch the files.
74
+ *
75
+ * Multiple markers on one reply are all captured. Adjacent whitespace
76
+ * around stripped markers is collapsed (no double blank lines).
77
+ */
78
+ export declare function parseOutboundMarkers(reply: string | null | undefined): MarkerParseResult;
79
+ /**
80
+ * The single allowed outbound root for files the agent wants to send.
81
+ * Each conversation gets its own subdirectory under this root; the
82
+ * agent's Write permission on this tree is granted by Layer B (config
83
+ * paths like `access.json` / `config.json` are denied, attachments
84
+ * dir is allowed).
85
+ *
86
+ * `<conv>` is the open_chat_id (group) or open_id (DM). Bridge fills
87
+ * the placeholder per-event when validating.
88
+ */
89
+ export declare const OUTBOUND_ROOT = "/work/feishu-attachments";
90
+ /**
91
+ * Validate a normalized absolute path against the per-conversation
92
+ * whitelist + size + existence checks. Returns null on success or a
93
+ * Chinese user-friendly reason on failure (the same string can be
94
+ * surfaced as a fallback text reply when ALL files fail validation).
95
+ *
96
+ * Filesystem-touching — bridge calls this AFTER `parseOutboundMarkers`.
97
+ *
98
+ * Params:
99
+ * - p: normalized absolute path candidate
100
+ * - convKey: per-conversation directory name (open_chat_id / open_id)
101
+ * - statFn: optional override for tests (defaults to fs.statSync)
102
+ * - realpathFn: optional override for tests (defaults to fs.realpathSync)
103
+ *
104
+ * Note: `convKey` may include characters Feishu accepts but are unusual
105
+ * for file paths (open_id starts with `ou_`, open_chat_id with `oc_`).
106
+ * The whitelist check uses the literal substring + path.posix.dirname
107
+ * walk so symlink redirects don't bypass it — the realpath form must
108
+ * also fall under `OUTBOUND_ROOT/<connection>/<convKey>/`.
109
+ */
110
+ export interface ValidateOpts {
111
+ p: string;
112
+ convKey: string;
113
+ connectionName: string;
114
+ statFn?: (p: string) => {
115
+ size: number;
116
+ };
117
+ realpathFn?: (p: string) => string;
118
+ }
119
+ export declare function validateOutboundPath(opts: ValidateOpts): string | null;
120
+ /**
121
+ * Magic-byte sniffer — picks `image` vs `file` upload route. Reads the
122
+ * first 16 bytes only; safe to call before commitment. Returns:
123
+ *
124
+ * - "image" when the bytes are a PNG / JPG / GIF / WebP / BMP signature
125
+ * (Feishu image_v1 supports these natively, with chat inline render).
126
+ * - "file" otherwise (PDF, TXT, audio, video, archive, …).
127
+ *
128
+ * Caller supplies a Buffer (bridge reads via fs.openSync + readSync).
129
+ */
130
+ export declare function sniffFileKind(buf: Buffer): "image" | "file";
131
+ /**
132
+ * User-facing fallback message when ALL marker validations fail and the
133
+ * stripped text is empty (would leave the user with no reply at all).
134
+ */
135
+ export declare const ALL_FILES_FAILED_FALLBACK = "[\u6587\u4EF6\u9644\u4EF6\u53D1\u9001\u5931\u8D25] \u6211\u51C6\u5907\u597D\u4E86\u6587\u4EF6\u4F46\u5206\u53D1\u65F6\u51FA\u4E86\u95EE\u9898\u2014\u2014\u7A0D\u540E\u518D\u8BD5\u6216\u6362\u79CD\u65B9\u5F0F\u3002";