@sleep2agi/agent-network 2.3.0-preview.15 → 2.3.0-preview.17

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_0x57f1ff=a0_0x101e;function a0_0x101e(_0x54fed8,_0x2dad15){_0x54fed8=_0x54fed8-0x1f2;const _0x748cb4=a0_0x748c();let _0x101e72=_0x748cb4[_0x54fed8];return _0x101e72;}(function(_0x3d6ecb,_0x4654e8){const _0x2f9768=a0_0x101e,_0x565f3a=_0x3d6ecb();while(!![]){try{const _0x5d10f4=-parseInt(_0x2f9768(0x236))/0x1+parseInt(_0x2f9768(0x212))/0x2+-parseInt(_0x2f9768(0x221))/0x3+parseInt(_0x2f9768(0x1f8))/0x4+parseInt(_0x2f9768(0x203))/0x5+parseInt(_0x2f9768(0x219))/0x6+parseInt(_0x2f9768(0x237))/0x7;if(_0x5d10f4===_0x4654e8)break;else _0x565f3a['push'](_0x565f3a['shift']());}catch(_0x17c87d){_0x565f3a['push'](_0x565f3a['shift']());}}}(a0_0x748c,0xe5fe4));import{EventEmitter as a0_0x364783}from'events';import{hostname as a0_0x257b58}from'os';class T extends a0_0x364783{[a0_0x57f1ff(0x22e)];[a0_0x57f1ff(0x201)];[a0_0x57f1ff(0x20d)];['agent'];[a0_0x57f1ff(0x21b)];[a0_0x57f1ff(0x213)];[a0_0x57f1ff(0x231)];[a0_0x57f1ff(0x1f9)];[a0_0x57f1ff(0x1fa)];[a0_0x57f1ff(0x20b)]=!0x1;constructor(_0x7e9fc6){const _0xd27749=a0_0x57f1ff;super();if(this['url']=_0x7e9fc6['url'][_0xd27749(0x244)](/\/$/,''),this[_0xd27749(0x201)]=_0x7e9fc6[_0xd27749(0x201)],this[_0xd27749(0x20d)]=_0x7e9fc6['token'],this['agent']=_0x7e9fc6[_0xd27749(0x21d)]||_0xd27749(0x248),this[_0xd27749(0x21b)]=_0xd27749(0x1fc)+_0x7e9fc6[_0xd27749(0x201)]+'-'+Date['now']()[_0xd27749(0x218)](0x24),this['heartbeatInterval']=_0x7e9fc6[_0xd27749(0x213)]??0x2bf20,this[_0xd27749(0x231)]=_0x7e9fc6[_0xd27749(0x231)]??0xbb8,_0x7e9fc6[_0xd27749(0x23b)]!==!0x1)this['connect']();}['log'](_0x4b3a02){const _0x82dcbb=a0_0x57f1ff;console[_0x82dcbb(0x22f)]('['+new Date()[_0x82dcbb(0x20f)]()[_0x82dcbb(0x1f6)](0x0,0x8)+']\x20[commhub:'+this['alias']+']\x20'+_0x4b3a02);}async['call'](_0x317f8b,_0x4ea8d6){const _0x3d188e=a0_0x57f1ff;let _0x5a1afd={'Content-Type':'application/json','Accept':'application/json,\x20text/event-stream'};if(this['token'])_0x5a1afd['Authorization']='Bearer\x20'+this[_0x3d188e(0x20d)];let _0x153bee=await(await fetch(this[_0x3d188e(0x22e)]+_0x3d188e(0x1f5),{'method':_0x3d188e(0x228),'headers':_0x5a1afd,'body':JSON[_0x3d188e(0x22b)]({'jsonrpc':_0x3d188e(0x210),'id':Date[_0x3d188e(0x245)](),'method':'tools/call','params':{'name':_0x317f8b,'arguments':_0x4ea8d6}})}))[_0x3d188e(0x239)](),_0x30b6ca=_0x153bee[_0x3d188e(0x247)](/data: (.+)/),_0xf47e6f=_0x30b6ca?JSON['parse'](_0x30b6ca[0x1]):JSON[_0x3d188e(0x214)](_0x153bee),_0x362790=_0xf47e6f?.[_0x3d188e(0x21a)]?.[_0x3d188e(0x216)]?.[0x0]?.[_0x3d188e(0x239)];return _0x362790?JSON[_0x3d188e(0x214)](_0x362790):_0xf47e6f;}async[a0_0x57f1ff(0x232)](){const _0x2b9a59=a0_0x57f1ff;if(this[_0x2b9a59(0x20b)])return;this['running']=!0x0,await this['status'](_0x2b9a59(0x21f)),this['log'](_0x2b9a59(0x22a)),this[_0x2b9a59(0x1f9)]=setInterval(()=>{const _0x3fdc0b=_0x2b9a59;this[_0x3fdc0b(0x23c)](_0x3fdc0b(0x21f))[_0x3fdc0b(0x211)](_0x399825=>this[_0x3fdc0b(0x22f)]('heartbeat\x20failed:\x20'+_0x399825[_0x3fdc0b(0x200)]));},this['heartbeatInterval']),this[_0x2b9a59(0x1fd)]();}async['disconnect'](){const _0x44a6d0=a0_0x57f1ff;if(this[_0x44a6d0(0x20b)]=!0x1,this[_0x44a6d0(0x1fa)]?.[_0x44a6d0(0x204)](),this[_0x44a6d0(0x1f9)])clearInterval(this[_0x44a6d0(0x1f9)]);await this[_0x44a6d0(0x23c)](_0x44a6d0(0x1f7))['catch'](()=>{}),this[_0x44a6d0(0x22f)](_0x44a6d0(0x206));}async[a0_0x57f1ff(0x22d)](_0x3858c9,_0x4ed4d8,_0x294b99=a0_0x57f1ff(0x233)){const _0x589252=a0_0x57f1ff;return this[_0x589252(0x23f)]('send_task',{'alias':_0x3858c9,'task':_0x4ed4d8,'priority':_0x294b99,'from_session':this[_0x589252(0x201)]});}async[a0_0x57f1ff(0x200)](_0x539fd7,_0x176a28){const _0x88635=a0_0x57f1ff;return this[_0x88635(0x23f)](_0x88635(0x20e),{'alias':_0x539fd7,'message':_0x176a28,'from_session':this[_0x88635(0x201)]});}async[a0_0x57f1ff(0x217)](_0x2d9386,_0x415560,_0x425cd6=a0_0x57f1ff(0x220)){const _0x3132ee=a0_0x57f1ff;return this[_0x3132ee(0x23f)](_0x3132ee(0x1ff),{'in_reply_to':_0x2d9386,'text':_0x415560,'status':_0x425cd6});}async[a0_0x57f1ff(0x23c)](_0x28243d,_0x7e6cf2){const _0x443c45=a0_0x57f1ff;return this[_0x443c45(0x23f)](_0x443c45(0x240),{'resume_id':this['resumeId'],'alias':this['alias'],'status':_0x28243d,'server':a0_0x257b58(),'hostname':a0_0x257b58(),'agent':this[_0x443c45(0x21d)],'project_dir':process['cwd'](),..._0x7e6cf2});}async['getAllStatus'](){const _0x20a559=a0_0x57f1ff;return this[_0x20a559(0x23f)]('get_all_status',{});}async[a0_0x57f1ff(0x225)](_0x307972,_0x21c6ce){const _0x3f35ec=a0_0x57f1ff;return this[_0x3f35ec(0x23f)](_0x3f35ec(0x225),{'message':_0x307972,'filter_server':_0x21c6ce?.[_0x3f35ec(0x208)],'filter_status':_0x21c6ce?.[_0x3f35ec(0x23c)]});}async[a0_0x57f1ff(0x1fd)](){const _0x2536bc=a0_0x57f1ff;let _0x2901c9=encodeURIComponent(this[_0x2536bc(0x201)]),_0x1cad20=this[_0x2536bc(0x22e)]+'/events/'+_0x2901c9,_0x3c4ca0=this[_0x2536bc(0x231)];while(this['running']){try{this[_0x2536bc(0x1fa)]=new AbortController();let _0x5f0c75={'Accept':_0x2536bc(0x23e)};if(this[_0x2536bc(0x20d)])_0x5f0c75['Authorization']=_0x2536bc(0x202)+this['token'];let _0xa6ae1f=await fetch(_0x1cad20,{'headers':_0x5f0c75,'signal':this[_0x2536bc(0x1fa)][_0x2536bc(0x241)]});if(!_0xa6ae1f['ok']||!_0xa6ae1f[_0x2536bc(0x227)]){this[_0x2536bc(0x22f)](_0x2536bc(0x1fb)+_0xa6ae1f[_0x2536bc(0x23c)]),await this['sleep'](_0x3c4ca0),_0x3c4ca0=Math[_0x2536bc(0x23a)](_0x3c4ca0*1.5,0xea60);continue;}_0x3c4ca0=this[_0x2536bc(0x231)];let _0x15d782=_0xa6ae1f['body'][_0x2536bc(0x205)](),_0x3b2994=new TextDecoder(),_0x5719cd='';while(this[_0x2536bc(0x20b)]){let {done:_0x61e56a,value:_0x46bff0}=await _0x15d782['read']();if(_0x61e56a)break;_0x5719cd+=_0x3b2994[_0x2536bc(0x230)](_0x46bff0,{'stream':!0x0});let _0xef2cec=_0x5719cd[_0x2536bc(0x226)]('\x0a');_0x5719cd=_0xef2cec[_0x2536bc(0x1fe)]()||'';for(let _0x3b7359 of _0xef2cec){if(!_0x3b7359[_0x2536bc(0x224)](_0x2536bc(0x222)))continue;try{let _0x165e54=JSON[_0x2536bc(0x214)](_0x3b7359[_0x2536bc(0x1f6)](0x6));if(_0x165e54[_0x2536bc(0x234)]===_0x2536bc(0x22c)){this[_0x2536bc(0x22f)](_0x2536bc(0x1f3)),this[_0x2536bc(0x1f4)]('connected');continue;}if(_0x165e54['type']===_0x2536bc(0x235)||_0x165e54[_0x2536bc(0x234)]===_0x2536bc(0x20c)||_0x165e54[_0x2536bc(0x234)]===_0x2536bc(0x225))await this[_0x2536bc(0x207)]();}catch{}}}}catch(_0x269680){if(_0x269680[_0x2536bc(0x229)]===_0x2536bc(0x215))break;this[_0x2536bc(0x1f4)](_0x2536bc(0x23d),_0x269680),this[_0x2536bc(0x22f)](_0x2536bc(0x238)+_0x269680[_0x2536bc(0x200)]);}if(this[_0x2536bc(0x20b)])this['emit'](_0x2536bc(0x206)),this['log'](_0x2536bc(0x21c)+_0x3c4ca0/0x3e8+_0x2536bc(0x209)),await this['sleep'](_0x3c4ca0),_0x3c4ca0=Math[_0x2536bc(0x23a)](_0x3c4ca0*1.5,0xea60);}}async[a0_0x57f1ff(0x207)](){const _0x248cc7=a0_0x57f1ff;try{let _0x12827d=(await this['call'](_0x248cc7(0x20a),{'alias':this[_0x248cc7(0x201)],'limit':0xa}))?.[_0x248cc7(0x242)]||[];for(let _0x2cc4c9 of _0x12827d)await this[_0x248cc7(0x23f)](_0x248cc7(0x243),{'alias':this[_0x248cc7(0x201)],'message_id':_0x2cc4c9['id']}),this[_0x248cc7(0x22f)]('←\x20'+_0x2cc4c9[_0x248cc7(0x1f2)]+':\x20'+_0x2cc4c9[_0x248cc7(0x216)][_0x248cc7(0x1f6)](0x0,0x3c)),this[_0x248cc7(0x1f4)](_0x248cc7(0x21e),_0x2cc4c9),this[_0x248cc7(0x1f4)](_0x248cc7(0x200),_0x2cc4c9);}catch(_0x2d0577){this[_0x248cc7(0x22f)](_0x248cc7(0x246)+_0x2d0577['message']);}}[a0_0x57f1ff(0x223)](_0x1f3f87){return new Promise(_0xf1fa84=>setTimeout(_0xf1fa84,_0x1f3f87));}}var $=T;function a0_0x748c(){const _0xe4972d=['autoConnect','status','error','text/event-stream','call','report_status','signal','messages','ack_inbox','replace','now','inbox\x20error:\x20','match','sdk','from_session','SSE\x20connected','emit','/mcp','slice','offline','5667020RNCYmH','heartbeatTimer','sseAbort','SSE\x20failed:\x20','sdk-','connectSSE','pop','send_reply','message','alias','Bearer\x20','1455210fYJmFf','abort','getReader','disconnected','processInbox','server','s...','get_inbox','running','new_message','token','send_message','toTimeString','2.0','catch','749774OjJRIK','heartbeatInterval','parse','AbortError','content','reply','toString','1412286bwWKGN','result','resumeId','SSE\x20reconnecting\x20in\x20','agent','task','idle','completed','4672041vjJjbT','data:\x20','sleep','startsWith','broadcast','split','body','POST','name','registered','stringify','connected','send','url','log','decode','reconnectDelay','connect','normal','type','new_task','358874HzVAkD','3781456xzcCLB','SSE\x20error:\x20','text','min'];a0_0x748c=function(){return _0xe4972d;};return a0_0x748c();}export{$ as default,T as CommHub};
1
+ const a0_0x1e05e3=a0_0x17ad;(function(_0xa84030,_0x2b6ba6){const _0x5cd28f=a0_0x17ad,_0x840ed=_0xa84030();while(!![]){try{const _0x399355=parseInt(_0x5cd28f(0x107))/0x1*(parseInt(_0x5cd28f(0x10d))/0x2)+parseInt(_0x5cd28f(0x106))/0x3+-parseInt(_0x5cd28f(0xe1))/0x4*(parseInt(_0x5cd28f(0xc9))/0x5)+-parseInt(_0x5cd28f(0xf7))/0x6+parseInt(_0x5cd28f(0xda))/0x7*(-parseInt(_0x5cd28f(0x114))/0x8)+parseInt(_0x5cd28f(0xd0))/0x9+parseInt(_0x5cd28f(0xd9))/0xa;if(_0x399355===_0x2b6ba6)break;else _0x840ed['push'](_0x840ed['shift']());}catch(_0x1c6911){_0x840ed['push'](_0x840ed['shift']());}}}(a0_0x541d,0xbb255));import{EventEmitter as a0_0x1d4b36}from'events';import{hostname as a0_0xf8f996}from'os';function a0_0x541d(){const _0x49f1b9=['/mcp','read','slice','url','connectSSE','2XFLsBC','task','abort','emit','min','decode','reply','6128rDFjMG','autoConnect','connected','reconnectDelay','application/json,\x20text/event-stream','getReader','application/json','normal','send_reply','SSE\x20connected','getAllStatus','processInbox','get_all_status','match','registered','error','sdk','split','call','Bearer\x20','POST','5xgKcNn','parse','inbox\x20error:\x20','result','tools/call','heartbeat\x20failed:\x20','2.0','1512963cGWYxM','pop','content','catch','name','alias','get_inbox','send','server','28635950Dmpesl','12831gaSKzJ','message','completed','sseAbort','toTimeString','offline','SSE\x20reconnecting\x20in\x20','4304392pETzQv','disconnected','send_task','cwd','running','replace','now','body','new_message','type','broadcast','SSE\x20error:\x20','startsWith','status','resumeId','sleep','AbortError','data:\x20','new_task','heartbeatTimer','send_message','/events/','6423750fECuck','toString','heartbeatInterval','ack_inbox','agent','Authorization','disconnect','idle','text','log','s...',']\x20[commhub:','messages','token','connect','2353107GhfMyv','501279iIIyeE'];a0_0x541d=function(){return _0x49f1b9;};return a0_0x541d();}class T extends a0_0x1d4b36{[a0_0x1e05e3(0x10b)];['alias'];[a0_0x1e05e3(0x104)];[a0_0x1e05e3(0xfb)];['resumeId'];[a0_0x1e05e3(0xf9)];[a0_0x1e05e3(0x117)];[a0_0x1e05e3(0xf4)];[a0_0x1e05e3(0xdd)];[a0_0x1e05e3(0xe5)]=!0x1;constructor(_0x3aef50){const _0x34362b=a0_0x1e05e3;super();if(this[_0x34362b(0x10b)]=_0x3aef50[_0x34362b(0x10b)][_0x34362b(0xe6)](/\/$/,''),this[_0x34362b(0xd5)]=_0x3aef50[_0x34362b(0xd5)],this[_0x34362b(0x104)]=_0x3aef50[_0x34362b(0x104)],this[_0x34362b(0xfb)]=_0x3aef50[_0x34362b(0xfb)]||_0x34362b(0xc4),this[_0x34362b(0xef)]='sdk-'+_0x3aef50[_0x34362b(0xd5)]+'-'+Date[_0x34362b(0xe7)]()[_0x34362b(0xf8)](0x24),this[_0x34362b(0xf9)]=_0x3aef50['heartbeatInterval']??0x2bf20,this[_0x34362b(0x117)]=_0x3aef50['reconnectDelay']??0xbb8,_0x3aef50[_0x34362b(0x115)]!==!0x1)this[_0x34362b(0x105)]();}[a0_0x1e05e3(0x100)](_0x3e191e){const _0x51ed56=a0_0x1e05e3;console['log']('['+new Date()[_0x51ed56(0xde)]()['slice'](0x0,0x8)+_0x51ed56(0x102)+this[_0x51ed56(0xd5)]+']\x20'+_0x3e191e);}async[a0_0x1e05e3(0xc6)](_0x35a2b9,_0x2e56b8){const _0x43a918=a0_0x1e05e3;let _0x5a4ee8={'Content-Type':_0x43a918(0x11a),'Accept':_0x43a918(0x118)};if(this['token'])_0x5a4ee8[_0x43a918(0xfc)]=_0x43a918(0xc7)+this[_0x43a918(0x104)];let _0x44a97b=await(await fetch(this[_0x43a918(0x10b)]+_0x43a918(0x108),{'method':_0x43a918(0xc8),'headers':_0x5a4ee8,'body':JSON['stringify']({'jsonrpc':_0x43a918(0xcf),'id':Date['now'](),'method':_0x43a918(0xcd),'params':{'name':_0x35a2b9,'arguments':_0x2e56b8}})}))[_0x43a918(0xff)](),_0x5c1b65=_0x44a97b[_0x43a918(0xc1)](/data: (.+)/),_0x380f67=_0x5c1b65?JSON[_0x43a918(0xca)](_0x5c1b65[0x1]):JSON['parse'](_0x44a97b),_0x451864=_0x380f67?.[_0x43a918(0xcc)]?.[_0x43a918(0xd2)]?.[0x0]?.[_0x43a918(0xff)];return _0x451864?JSON[_0x43a918(0xca)](_0x451864):_0x380f67;}async[a0_0x1e05e3(0x105)](){const _0x4c9801=a0_0x1e05e3;if(this[_0x4c9801(0xe5)])return;this[_0x4c9801(0xe5)]=!0x0,await this[_0x4c9801(0xee)](_0x4c9801(0xfe)),this[_0x4c9801(0x100)](_0x4c9801(0xc2)),this['heartbeatTimer']=setInterval(()=>{const _0x21aee8=_0x4c9801;this[_0x21aee8(0xee)]('idle')[_0x21aee8(0xd3)](_0x4e0cf7=>this[_0x21aee8(0x100)](_0x21aee8(0xce)+_0x4e0cf7[_0x21aee8(0xdb)]));},this['heartbeatInterval']),this['connectSSE']();}async[a0_0x1e05e3(0xfd)](){const _0x167c9d=a0_0x1e05e3;if(this[_0x167c9d(0xe5)]=!0x1,this[_0x167c9d(0xdd)]?.[_0x167c9d(0x10f)](),this[_0x167c9d(0xf4)])clearInterval(this[_0x167c9d(0xf4)]);await this[_0x167c9d(0xee)](_0x167c9d(0xdf))[_0x167c9d(0xd3)](()=>{}),this[_0x167c9d(0x100)](_0x167c9d(0xe2));}async[a0_0x1e05e3(0xd7)](_0x15d03e,_0x15b127,_0x42f0c1=a0_0x1e05e3(0x11b)){const _0x1f08e3=a0_0x1e05e3;return this[_0x1f08e3(0xc6)](_0x1f08e3(0xe3),{'alias':_0x15d03e,'task':_0x15b127,'priority':_0x42f0c1,'from_session':this[_0x1f08e3(0xd5)]});}async['message'](_0xa58786,_0x11c51b){const _0x520aca=a0_0x1e05e3;return this[_0x520aca(0xc6)](_0x520aca(0xf5),{'alias':_0xa58786,'message':_0x11c51b,'from_session':this[_0x520aca(0xd5)]});}async[a0_0x1e05e3(0x113)](_0x56f239,_0x51fd09,_0x1b9089=a0_0x1e05e3(0xdc)){const _0x1eb37c=a0_0x1e05e3;return this[_0x1eb37c(0xc6)](_0x1eb37c(0x11c),{'in_reply_to':_0x56f239,'text':_0x51fd09,'status':_0x1b9089});}async['status'](_0x4236a4,_0x4c36a0){const _0x3adb22=a0_0x1e05e3;return this[_0x3adb22(0xc6)]('report_status',{'resume_id':this[_0x3adb22(0xef)],'alias':this['alias'],'status':_0x4236a4,'server':a0_0xf8f996(),'hostname':a0_0xf8f996(),'agent':this[_0x3adb22(0xfb)],'project_dir':process[_0x3adb22(0xe4)](),..._0x4c36a0});}async[a0_0x1e05e3(0x11e)](){const _0x30e151=a0_0x1e05e3;return this['call'](_0x30e151(0xc0),{});}async[a0_0x1e05e3(0xeb)](_0x52446b,_0x16a9e1){const _0x222bb2=a0_0x1e05e3;return this[_0x222bb2(0xc6)](_0x222bb2(0xeb),{'message':_0x52446b,'filter_server':_0x16a9e1?.[_0x222bb2(0xd8)],'filter_status':_0x16a9e1?.[_0x222bb2(0xee)]});}async[a0_0x1e05e3(0x10c)](){const _0x39735f=a0_0x1e05e3;let _0x5aead5=encodeURIComponent(this['alias']),_0x5a8154=this[_0x39735f(0x10b)]+_0x39735f(0xf6)+_0x5aead5,_0x6a387e=this['reconnectDelay'];while(this[_0x39735f(0xe5)]){try{this['sseAbort']=new AbortController();let _0x396add={'Accept':'text/event-stream'};if(this[_0x39735f(0x104)])_0x396add[_0x39735f(0xfc)]=_0x39735f(0xc7)+this[_0x39735f(0x104)];let _0x36f07e=await fetch(_0x5a8154,{'headers':_0x396add,'signal':this[_0x39735f(0xdd)]['signal']});if(!_0x36f07e['ok']||!_0x36f07e['body']){this['log']('SSE\x20failed:\x20'+_0x36f07e[_0x39735f(0xee)]),await this[_0x39735f(0xf0)](_0x6a387e),_0x6a387e=Math[_0x39735f(0x111)](_0x6a387e*1.5,0xea60);continue;}_0x6a387e=this[_0x39735f(0x117)];let _0x2ec3e6=_0x36f07e[_0x39735f(0xe8)][_0x39735f(0x119)](),_0xb5aff4=new TextDecoder(),_0x21a1bf='';while(this[_0x39735f(0xe5)]){let {done:_0x30a148,value:_0x362c60}=await _0x2ec3e6[_0x39735f(0x109)]();if(_0x30a148)break;_0x21a1bf+=_0xb5aff4[_0x39735f(0x112)](_0x362c60,{'stream':!0x0});let _0x45e493=_0x21a1bf[_0x39735f(0xc5)]('\x0a');_0x21a1bf=_0x45e493[_0x39735f(0xd1)]()||'';for(let _0xca0a28 of _0x45e493){if(!_0xca0a28[_0x39735f(0xed)](_0x39735f(0xf2)))continue;try{let _0x115ee0=JSON['parse'](_0xca0a28['slice'](0x6));if(_0x115ee0[_0x39735f(0xea)]===_0x39735f(0x116)){this[_0x39735f(0x100)](_0x39735f(0x11d)),this[_0x39735f(0x110)]('connected');continue;}if(_0x115ee0[_0x39735f(0xea)]===_0x39735f(0xf3)||_0x115ee0[_0x39735f(0xea)]===_0x39735f(0xe9)||_0x115ee0[_0x39735f(0xea)]===_0x39735f(0xeb))await this[_0x39735f(0x11f)]();}catch{}}}}catch(_0x2a4069){if(_0x2a4069[_0x39735f(0xd4)]===_0x39735f(0xf1))break;this['emit'](_0x39735f(0xc3),_0x2a4069),this[_0x39735f(0x100)](_0x39735f(0xec)+_0x2a4069[_0x39735f(0xdb)]);}if(this[_0x39735f(0xe5)])this[_0x39735f(0x110)](_0x39735f(0xe2)),this['log'](_0x39735f(0xe0)+_0x6a387e/0x3e8+_0x39735f(0x101)),await this[_0x39735f(0xf0)](_0x6a387e),_0x6a387e=Math[_0x39735f(0x111)](_0x6a387e*1.5,0xea60);}}async[a0_0x1e05e3(0x11f)](){const _0xc072a7=a0_0x1e05e3;try{let _0x48fa6c=(await this[_0xc072a7(0xc6)](_0xc072a7(0xd6),{'alias':this[_0xc072a7(0xd5)],'limit':0xa}))?.[_0xc072a7(0x103)]||[];for(let _0x570824 of _0x48fa6c)await this[_0xc072a7(0xc6)](_0xc072a7(0xfa),{'alias':this[_0xc072a7(0xd5)],'message_id':_0x570824['id']}),this[_0xc072a7(0x100)]('←\x20'+_0x570824['from_session']+':\x20'+_0x570824[_0xc072a7(0xd2)][_0xc072a7(0x10a)](0x0,0x3c)),this['emit'](_0xc072a7(0x10e),_0x570824),this[_0xc072a7(0x110)](_0xc072a7(0xdb),_0x570824);}catch(_0x3795da){this['log'](_0xc072a7(0xcb)+_0x3795da['message']);}}[a0_0x1e05e3(0xf0)](_0x11b3c0){return new Promise(_0x274f3e=>setTimeout(_0x274f3e,_0x11b3c0));}}var $=T;function a0_0x17ad(_0x3fa784,_0x4b9841){_0x3fa784=_0x3fa784-0xc0;const _0x541dd4=a0_0x541d();let _0x17ada9=_0x541dd4[_0x3fa784];return _0x17ada9;}export{$ as default,T as CommHub};
@@ -94,6 +94,17 @@ export declare function parsePostContent(rawJson: string): string;
94
94
  * @internal exported for unit tests.
95
95
  */
96
96
  export declare function extractPostImageKeys(rawJson: string): string[];
97
+ /**
98
+ * Sanitize a Feishu-supplied `file_name` so it's safe to append to a
99
+ * filesystem path. Strips `/`, `\`, `..`, control characters, and NUL
100
+ * bytes. Empty / all-stripped input falls back to a placeholder that
101
+ * uses the message id, so a hostile client can never write outside the
102
+ * conversation's `<mediaDir>/<convKey>/` directory.
103
+ *
104
+ * NOT a full display-safety pass — the LLM still sees the sanitized
105
+ * bytes and shouldn't render them as HTML/etc. That's a Layer above.
106
+ */
107
+ export declare function sanitizeFileName(raw: string, fallback: string): string;
97
108
  /**
98
109
  * Feishu text-message practical chunk threshold (RFC-020 §16).
99
110
  *
@@ -0,0 +1,88 @@
1
+ /**
2
+ * RFC-020 §17 — feishu inbound bridge → hub `/api/upload` integration.
3
+ *
4
+ * Vincent 2026-06-30: cross-machine agents (e.g. TM门户运维@toodadev2)
5
+ * delegated by the feishu-local bot can't read inbound attachments
6
+ * because the only thing they get is a host-local path that doesn't
7
+ * exist on the receiver's filesystem. #351 already wired agent-node's
8
+ * receiver to prefer `file_id` and pull via `GET /api/files/<id>` when
9
+ * present. This module is the SENDER half: the feishu bridge uploads
10
+ * each downloaded inbound file to the hub via `POST /api/upload`,
11
+ * gets back a `file_id`, and propagates it alongside the local path.
12
+ *
13
+ * Failure mode (load-bearing): every failure path returns `null` and
14
+ * the caller falls back to path-only. The bridge MUST NOT crash because
15
+ * the hub is down / overloaded / refused a 12 MiB cap. Single-host
16
+ * `agent-node` Read still works on the local path; only cross-host
17
+ * delegation degrades, no regression vs the pre-fix baseline.
18
+ *
19
+ * Concurrency cap: a single feishu message can carry many images; bursts
20
+ * to /api/upload would hammer the hub rate limit (60/hour per token).
21
+ * `uploadFilesToHubConcurrent` caps in-flight requests at `concurrency`
22
+ * (default 4) so a 20-image message takes 5 sequential rounds instead
23
+ * of 20 simultaneous open sockets + a likely rate-limit denial.
24
+ */
25
+ /**
26
+ * Hub upload limit, mirrors `server/src/uploads.ts:MAX_UPLOAD_BYTES`.
27
+ * Anything bigger is skipped at the bridge — the hub would 413 anyway.
28
+ */
29
+ export declare const HUB_UPLOAD_LIMIT_BYTES: number;
30
+ /** Default in-flight cap for `uploadFilesToHubConcurrent`. */
31
+ export declare const DEFAULT_UPLOAD_CONCURRENCY = 4;
32
+ /**
33
+ * One file uploaded to the hub. `mime` and `size` are from the local
34
+ * filesystem read; `file_id` and `path` come from the hub's response.
35
+ *
36
+ * `file_id` is the canonical cross-machine handle — receiving agent
37
+ * resolves to bytes via `GET /api/files/<file_id>`. `path` is the
38
+ * hub-machine-local absolute path the hub stored to; on the sender
39
+ * side it's purely informational (we already have the source file).
40
+ */
41
+ export interface HubUploadResult {
42
+ file_id: string;
43
+ path?: string;
44
+ mime?: string;
45
+ size?: number;
46
+ name?: string;
47
+ }
48
+ export interface HubUploadOpts {
49
+ /** Hub base URL, no trailing slash. Defaults to env. */
50
+ hubUrl: string;
51
+ /** Bearer token (ntok_ / utok_ / atok_). Defaults to env. */
52
+ authToken: string;
53
+ /** Optional MIME hint; sniffed by filename ext otherwise. */
54
+ mime?: string;
55
+ /** Optional override filename (defaults to basename(path)). */
56
+ name?: string;
57
+ /** Injectable for tests. Defaults to global fetch. */
58
+ fetch?: typeof fetch;
59
+ }
60
+ /**
61
+ * Upload one local file to `${hubUrl}/api/upload`. Returns the file
62
+ * descriptor on success, or `null` on any failure (caller falls back
63
+ * to path-only).
64
+ *
65
+ * - File must exist + be ≤ 12 MiB. Larger → skipped silently with
66
+ * a stderr warn; caller gets `null` and ships path-only.
67
+ * - Auth via `Authorization: Bearer <token>`.
68
+ * - `Content-Length` header is set by `fetch` when given a Blob body;
69
+ * the hub validates it before consuming bytes.
70
+ * - Multipart body with a single `file` field. The hub server
71
+ * reads `form.get("file")` and stores under a new file_id.
72
+ * - Any network error / non-2xx / malformed JSON response → null.
73
+ */
74
+ export declare function uploadToHub(filePath: string, opts: HubUploadOpts): Promise<HubUploadResult | null>;
75
+ /**
76
+ * Upload many files to the hub with a bounded concurrency window.
77
+ * Returns one result per input path, preserving order. A failed
78
+ * upload appears as `null` at that slot — caller composes path-only
79
+ * descriptors for those.
80
+ *
81
+ * Why this matters: one feishu post can carry an arbitrary number of
82
+ * images. Naive `Promise.all(paths.map(uploadToHub))` would open N
83
+ * simultaneous HTTPS sockets to the hub AND blow past the 60/hour
84
+ * per-token rate limit on a single message with >60 images. A
85
+ * concurrency cap of 4 means N/4 sequential rounds, predictable
86
+ * load, no head-of-line blocking on the agent's reply.
87
+ */
88
+ export declare function uploadFilesToHubConcurrent(filePaths: string[], opts: HubUploadOpts, concurrency?: number): Promise<(HubUploadResult | null)[]>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * RFC-020 §16.1 — feishu outbound route decision (pure helper).
3
+ *
4
+ * Single source of truth for the `adapter.send` decision tree that
5
+ * picks among text / interactive card / image (rendered PNG) / file /
6
+ * imagePath outputs. Extracted into a pure module so the production
7
+ * call site AND the unit tests can bind the same function — previously
8
+ * the test mirrored the decision tree in a sibling `pickRoute` helper,
9
+ * which would drift silently if the production tree changed.
10
+ *
11
+ * Inputs are the minimal data the decision needs:
12
+ *
13
+ * - `text` / `imagePath` / `files` — payload from `NormalizedIMMessage`
14
+ * - `forceTextOnly` — caption-mode hint (RFC-020 §15.2)
15
+ * - `mode` — channel-config `outboundRender` (`"plain"` / `"card"` /
16
+ * `"auto"`, RFC-020 §16)
17
+ *
18
+ * Outputs the chosen `route` plus a short `reason` string for log /
19
+ * debug. The CALLER (adapter.send) actually performs the upload /
20
+ * render side-effects keyed on the route — this function does no I/O.
21
+ *
22
+ * Behavior contract (mirrors adapter.send line-for-line, locked by
23
+ * `feishu-outbound-render-mode.test.ts`):
24
+ *
25
+ * 1. `imagePath` set → `image_upload`
26
+ * 2. `files[0].path` set → `file_upload`
27
+ * 3. `forceTextOnly` true → `text`
28
+ * 4. mode "plain" → `text` (always)
29
+ * 5. mode "card" → `card_short_md` iff `looksLikeMarkdown(text)` AND
30
+ * NOT `shouldRenderAsImage(text)`; else `text`
31
+ * 6. mode "auto" → `image_render` iff `shouldRenderAsImage(text)`;
32
+ * else `card_short_md` iff `looksLikeMarkdown(text)`; else `text`
33
+ * 7. unknown mode (defensive default-default) → `text`
34
+ *
35
+ * The production switch in adapter.send may add the actual upload /
36
+ * render / lark API calls keyed on the route, but the route itself
37
+ * is decided HERE. To change the decision, change this file.
38
+ */
39
+ export type OutboundRoute = "image_upload" | "file_upload" | "text" | "card_short_md" | "image_render";
40
+ export interface RouteInput {
41
+ text?: string;
42
+ imagePath?: string;
43
+ files?: {
44
+ name: string;
45
+ path?: string;
46
+ }[];
47
+ forceTextOnly?: boolean;
48
+ /** `outboundRender` from the channel config. Defaults to "plain" when
49
+ * absent so a caller that doesn't read the config still gets the
50
+ * "Vincent default" behavior. */
51
+ mode?: "plain" | "card" | "auto";
52
+ }
53
+ export interface RouteDecision {
54
+ route: OutboundRoute;
55
+ reason: string;
56
+ }
57
+ /**
58
+ * Decide the outbound route for a `NormalizedIMMessage` (or a subset
59
+ * of its fields). Pure — no I/O, no SDK calls; safe to call from tests
60
+ * directly.
61
+ */
62
+ export declare function resolveOutboundRoute(input: RouteInput): RouteDecision;