@sleep2agi/agent-network 2.3.0-preview.88 → 2.3.0-preview.89

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_0x2a09e=a0_0x2438;(function(_0xc1e650,_0x2b23d3){const _0x58b14f=a0_0x2438,_0xd1b4a6=_0xc1e650();while(!![]){try{const _0x2520b0=parseInt(_0x58b14f(0x113))/0x1*(parseInt(_0x58b14f(0x171))/0x2)+-parseInt(_0x58b14f(0x15e))/0x3+parseInt(_0x58b14f(0x118))/0x4+-parseInt(_0x58b14f(0x159))/0x5+-parseInt(_0x58b14f(0x11c))/0x6+parseInt(_0x58b14f(0x158))/0x7+parseInt(_0x58b14f(0x108))/0x8;if(_0x2520b0===_0x2b23d3)break;else _0xd1b4a6['push'](_0xd1b4a6['shift']());}catch(_0x3d83b6){_0xd1b4a6['push'](_0xd1b4a6['shift']());}}}(a0_0x3134,0xa01c6));import{EventEmitter as a0_0x49f04b}from'events';import{hostname as a0_0x25aade}from'os';var K=/(?:atok|ntok|utok|ghp|github_pat)_[A-Za-z0-9_-]+|Bearer\s+\S+/gi,L=(_0x1826c4,_0xc2d14e)=>(_0x1826c4??_0xc2d14e)[a0_0x2a09e(0x147)](/[\r\n\x00-\x1f\x7f]/g,'\x20')[a0_0x2a09e(0x178)](0x0,0xf0);function N(_0x295c82){const _0x479591=a0_0x2a09e;return(_0x295c82 instanceof Error?_0x295c82['message']:String(_0x295c82??_0x479591(0x133)))[_0x479591(0x147)](K,_0x479591(0x102))[_0x479591(0x147)](/[\r\n\x00-\x1f\x7f]/g,'\x20')[_0x479591(0x178)](0x0,0xf0);}function a0_0x3134(){const _0xabb9e5=['to_alias','disconnected','6391512FRzZWi','CommHub\x20response\x20omitted\x20task_id','new_message','reply','not_tracked','task','getReader','token','text/event-stream','lifecycleTracking','decode','3gOpWxg','error_message','agent','/events/','stringify','3751360DpacZa','emit','pop','<unknown>','2267196GImdrk','reconnectDelay','read','get_all_status',']\x20[commhub:','inbox\x20error:\x20','\x20to=','from_session','abort','get_inbox','messages','connected','SSE\x20failed:\x20','\x20transport=','running','status','report_status','\x20task_id=','error','task.send.failed','Authorization','cwd','networkId','unknown\x20error','AbortError','idle','text','SSE\x20reconnecting\x20in\x20','delivered','data:\x20','send_task','fromAlias','application/json','content','body','\x20parent_task_id=','message','send_message','result','parentTaskId','processInbox','connect','getAllStatus','replace','heartbeatTimer','Bearer\x20','call','network_id','sseAbort','startsWith','connectSSE','task.send.delivered','send_reply','\x20from=','url','catch','2.0','resumeId','min','task.started','1737337tlfMwy','6523435LQZlZv','completed','tools/call','send_rejected','autoConnect','356850GYXIoc','failed','split','s...','now','from_alias','heartbeatInterval','sending','/mcp','disconnect','log','type','broadcast','heartbeat\x20failed:\x20','message_id','application/json,\x20text/event-stream','duration_ms','offline','alias','314898pWKdpe','task.ack','[commhub:task]\x20','sleep','CommHub\x20rejected\x20task','<pending>','sdk','slice','error_code','toAlias','task.expired','transport','lifecycle_tracking','task_id','<missing>','[REDACTED]','send_failed','parse','\x20error='];a0_0x3134=function(){return _0xabb9e5;};return a0_0x3134();}function O(_0x4393cf,_0x2348d0=process.env.ANET_TASK_TRACE_FORMAT==='json'){const _0x4d08bb=a0_0x2a09e;if(_0x2348d0)return JSON['stringify'](_0x4393cf);let _0x45f131=L(_0x4393cf['parent_task_id'],_0x4d08bb(0x101)),_0x2eebbb=L(_0x4393cf[_0x4d08bb(0x100)],_0x4d08bb(0x176)),_0xfe5c96=_0x4393cf[_0x4d08bb(0x179)]?_0x4d08bb(0x105)+_0x4393cf[_0x4d08bb(0x179)]+':'+(_0x4393cf[_0x4d08bb(0x114)]??''):'';return _0x4d08bb(0x173)+_0x4393cf[_0x4d08bb(0x12b)]+_0x4d08bb(0x151)+L(_0x4393cf[_0x4d08bb(0x163)],_0x4d08bb(0x11b))+_0x4d08bb(0x122)+L(_0x4393cf[_0x4d08bb(0x106)],_0x4d08bb(0x11b))+_0x4d08bb(0x12d)+_0x2eebbb+_0x4d08bb(0x13f)+_0x45f131+'\x20network_id='+L(_0x4393cf[_0x4d08bb(0x14b)],'<unknown>')+_0x4d08bb(0x129)+_0x4393cf[_0x4d08bb(0xfe)]+'\x20duration_ms='+_0x4393cf[_0x4d08bb(0x16e)]+'\x20lifecycle='+_0x4393cf[_0x4d08bb(0xff)]+_0xfe5c96;}function U(_0x23c669){const _0x202f8c=a0_0x2a09e;return{'event':{'sending':'task.send.start','delivered':_0x202f8c(0x14f),'failed':_0x202f8c(0x12f),'acked':_0x202f8c(0x172),'started':_0x202f8c(0x157),'replied':'task.replied','expired':_0x202f8c(0xfd)}[_0x23c669['status']],..._0x23c669};}function j(_0x142429){const _0x2e8645=a0_0x2a09e;let _0x228759=_0x142429?.[_0x2e8645(0x100)]||_0x142429?.[_0x2e8645(0x16c)]||_0x142429?.['id'];if(_0x228759)return String(_0x228759);let _0x5aaa50=_0x142429?.[_0x2e8645(0x13d)]?.[0x0]?.[_0x2e8645(0x136)];if(typeof _0x5aaa50!=='string')return null;try{let _0x25a2ab=JSON['parse'](_0x5aaa50);return _0x25a2ab?.[_0x2e8645(0x100)]||_0x25a2ab?.['message_id']||_0x25a2ab?.['id']||null;}catch{return null;}}async function X(_0x25a8f4,_0xc81aa6){const _0xf4755d=a0_0x2a09e;let _0x5b7f1e=_0xc81aa6[_0xf4755d(0x162)]??Date[_0xf4755d(0x162)],_0x2dc11b=_0x5b7f1e(),_0x16c18f=(_0x28d207,_0x393273,_0x2cb974,_0x5dbb01)=>{const _0x1ec233=_0xf4755d;_0xc81aa6[_0x1ec233(0x168)](O(U({'from_alias':_0x25a8f4[_0x1ec233(0x13b)],'to_alias':_0x25a8f4[_0x1ec233(0x17a)],'task_id':_0x393273,'parent_task_id':_0x25a8f4[_0x1ec233(0x143)],'network_id':_0x25a8f4[_0x1ec233(0x132)],'transport':_0x25a8f4[_0x1ec233(0xfe)],'status':_0x28d207,'duration_ms':_0x5b7f1e()-_0x2dc11b,'lifecycle_tracking':_0x25a8f4[_0x1ec233(0x111)],..._0x2cb974!==void 0x0?{'error_code':_0x5dbb01||_0x1ec233(0x103),'error_message':N(_0x2cb974)}:{}})));};_0x16c18f(_0xf4755d(0x165),null);try{let _0x41eeff=await _0xc81aa6['send'](),_0x4a3b83=j(_0x41eeff);if(_0x4a3b83)_0x16c18f(_0xf4755d(0x138),_0x4a3b83);else{if(_0x41eeff?.['ok']===!0x1||_0x41eeff?.[_0xf4755d(0x12e)])_0x16c18f(_0xf4755d(0x15f),_0x4a3b83,_0x41eeff?.[_0xf4755d(0x12e)]||_0xf4755d(0x175),_0xf4755d(0x15c));else _0x16c18f(_0xf4755d(0x15f),null,_0xf4755d(0x109),'missing_task_id');}return _0x41eeff;}catch(_0x2db089){throw _0x16c18f(_0xf4755d(0x15f),null,_0x2db089,_0xf4755d(0x103)),_0x2db089;}}function a0_0x2438(_0x59f739,_0x3935b0){_0x59f739=_0x59f739-0xfd;const _0x3134ba=a0_0x3134();let _0x2438c8=_0x3134ba[_0x59f739];return _0x2438c8;}async function Y(_0x513181,_0x2a6fd6){const _0x52cda9=a0_0x2a09e;return X({'fromAlias':_0x513181[_0x52cda9(0x13b)],'toAlias':_0x513181[_0x52cda9(0x170)],'parentTaskId':_0x513181[_0x52cda9(0x143)]||null,'networkId':_0x513181[_0x52cda9(0x132)]||null,'transport':'mcp_http','lifecycleTracking':_0x52cda9(0x10c)},_0x2a6fd6);}class $ extends a0_0x49f04b{[a0_0x2a09e(0x152)];[a0_0x2a09e(0x170)];['token'];['agent'];[a0_0x2a09e(0x155)];['heartbeatInterval'];['reconnectDelay'];[a0_0x2a09e(0x148)];[a0_0x2a09e(0x14c)];[a0_0x2a09e(0x12a)]=!0x1;constructor(_0x1c97ff){const _0x3521ac=a0_0x2a09e;super();if(this[_0x3521ac(0x152)]=_0x1c97ff['url']['replace'](/\/$/,''),this[_0x3521ac(0x170)]=_0x1c97ff['alias'],this[_0x3521ac(0x10f)]=_0x1c97ff[_0x3521ac(0x10f)],this['agent']=_0x1c97ff[_0x3521ac(0x115)]||_0x3521ac(0x177),this[_0x3521ac(0x155)]='sdk-'+_0x1c97ff['alias']+'-'+Date[_0x3521ac(0x162)]()['toString'](0x24),this[_0x3521ac(0x164)]=_0x1c97ff['heartbeatInterval']??0x2bf20,this['reconnectDelay']=_0x1c97ff[_0x3521ac(0x11d)]??0xbb8,_0x1c97ff[_0x3521ac(0x15d)]!==!0x1)this[_0x3521ac(0x145)]();}['log'](_0x5994d1){const _0x1e5b0d=a0_0x2a09e;console[_0x1e5b0d(0x168)]('['+new Date()['toTimeString']()['slice'](0x0,0x8)+_0x1e5b0d(0x120)+this[_0x1e5b0d(0x170)]+']\x20'+_0x5994d1);}async[a0_0x2a09e(0x14a)](_0x491998,_0x14667f){const _0x5f1850=a0_0x2a09e;let _0x57b034={'Content-Type':_0x5f1850(0x13c),'Accept':_0x5f1850(0x16d)};if(this[_0x5f1850(0x10f)])_0x57b034[_0x5f1850(0x130)]=_0x5f1850(0x149)+this[_0x5f1850(0x10f)];let _0x4ec521=await(await fetch(this[_0x5f1850(0x152)]+_0x5f1850(0x166),{'method':'POST','headers':_0x57b034,'body':JSON[_0x5f1850(0x117)]({'jsonrpc':_0x5f1850(0x154),'id':Date[_0x5f1850(0x162)](),'method':_0x5f1850(0x15b),'params':{'name':_0x491998,'arguments':_0x14667f}})}))['text'](),_0x4347e1=_0x4ec521['match'](/data: (.+)/),_0x376b80=_0x4347e1?JSON['parse'](_0x4347e1[0x1]):JSON[_0x5f1850(0x104)](_0x4ec521),_0x16b9e6=_0x376b80?.[_0x5f1850(0x142)]?.[_0x5f1850(0x13d)]?.[0x0]?.['text'];return _0x16b9e6?JSON[_0x5f1850(0x104)](_0x16b9e6):_0x376b80;}async[a0_0x2a09e(0x145)](){const _0x4621e5=a0_0x2a09e;if(this[_0x4621e5(0x12a)])return;this[_0x4621e5(0x12a)]=!0x0,await this[_0x4621e5(0x12b)](_0x4621e5(0x135)),this[_0x4621e5(0x168)]('registered'),this[_0x4621e5(0x148)]=setInterval(()=>{const _0x1af793=_0x4621e5;this[_0x1af793(0x12b)]('idle')[_0x1af793(0x153)](_0x3f286f=>this[_0x1af793(0x168)](_0x1af793(0x16b)+_0x3f286f[_0x1af793(0x140)]));},this[_0x4621e5(0x164)]),this['connectSSE']();}async[a0_0x2a09e(0x167)](){const _0x523f51=a0_0x2a09e;if(this[_0x523f51(0x12a)]=!0x1,this[_0x523f51(0x14c)]?.[_0x523f51(0x124)](),this['heartbeatTimer'])clearInterval(this[_0x523f51(0x148)]);await this[_0x523f51(0x12b)](_0x523f51(0x16f))[_0x523f51(0x153)](()=>{}),this['log'](_0x523f51(0x107));}async['send'](_0x49e5d7,_0x45f45d,_0x28112b='normal'){const _0x3c3596=a0_0x2a09e;return Y({'alias':_0x49e5d7,'fromAlias':this['alias']},{'log':_0x4147e0=>console[_0x3c3596(0x168)](_0x4147e0),'send':()=>this[_0x3c3596(0x14a)](_0x3c3596(0x13a),{'alias':_0x49e5d7,'task':_0x45f45d,'priority':_0x28112b,'from_session':this[_0x3c3596(0x170)]})});}async['message'](_0x4b1ead,_0x225dd2){const _0x4a2eb5=a0_0x2a09e;return this['call'](_0x4a2eb5(0x141),{'alias':_0x4b1ead,'message':_0x225dd2,'from_session':this[_0x4a2eb5(0x170)]});}async[a0_0x2a09e(0x10b)](_0x1102da,_0x4979fc,_0x13d500=a0_0x2a09e(0x15a)){const _0x2795c9=a0_0x2a09e;return this[_0x2795c9(0x14a)](_0x2795c9(0x150),{'in_reply_to':_0x1102da,'text':_0x4979fc,'status':_0x13d500});}async['status'](_0x22165f,_0x1667d4){const _0x2bb8be=a0_0x2a09e;return this[_0x2bb8be(0x14a)](_0x2bb8be(0x12c),{'resume_id':this['resumeId'],'alias':this[_0x2bb8be(0x170)],'status':_0x22165f,'server':a0_0x25aade(),'hostname':a0_0x25aade(),'agent':this[_0x2bb8be(0x115)],'project_dir':process[_0x2bb8be(0x131)](),..._0x1667d4});}async[a0_0x2a09e(0x146)](){const _0x41fa94=a0_0x2a09e;return this[_0x41fa94(0x14a)](_0x41fa94(0x11f),{});}async[a0_0x2a09e(0x16a)](_0x5a8593,_0x6d8be4){const _0x113b56=a0_0x2a09e;return this[_0x113b56(0x14a)](_0x113b56(0x16a),{'message':_0x5a8593,'filter_server':_0x6d8be4?.['server'],'filter_status':_0x6d8be4?.[_0x113b56(0x12b)]});}async[a0_0x2a09e(0x14e)](){const _0x476b96=a0_0x2a09e;let _0xeaeb2d=encodeURIComponent(this[_0x476b96(0x170)]),_0x5bf4d5=this[_0x476b96(0x152)]+_0x476b96(0x116)+_0xeaeb2d,_0x3c082e=this['reconnectDelay'];while(this[_0x476b96(0x12a)]){try{this[_0x476b96(0x14c)]=new AbortController();let _0x4d33d2={'Accept':_0x476b96(0x110)};if(this[_0x476b96(0x10f)])_0x4d33d2[_0x476b96(0x130)]=_0x476b96(0x149)+this[_0x476b96(0x10f)];let _0x389bce=await fetch(_0x5bf4d5,{'headers':_0x4d33d2,'signal':this['sseAbort']['signal']});if(!_0x389bce['ok']||!_0x389bce[_0x476b96(0x13e)]){this['log'](_0x476b96(0x128)+_0x389bce[_0x476b96(0x12b)]),await this[_0x476b96(0x174)](_0x3c082e),_0x3c082e=Math[_0x476b96(0x156)](_0x3c082e*1.5,0xea60);continue;}_0x3c082e=this[_0x476b96(0x11d)];let _0x5bc9de=_0x389bce['body'][_0x476b96(0x10e)](),_0x30000c=new TextDecoder(),_0x49063e='';while(this[_0x476b96(0x12a)]){let {done:_0x50fb0e,value:_0x40747c}=await _0x5bc9de[_0x476b96(0x11e)]();if(_0x50fb0e)break;_0x49063e+=_0x30000c[_0x476b96(0x112)](_0x40747c,{'stream':!0x0});let _0x14d8be=_0x49063e[_0x476b96(0x160)]('\x0a');_0x49063e=_0x14d8be[_0x476b96(0x11a)]()||'';for(let _0x237e4b of _0x14d8be){if(!_0x237e4b[_0x476b96(0x14d)](_0x476b96(0x139)))continue;try{let _0x362388=JSON[_0x476b96(0x104)](_0x237e4b[_0x476b96(0x178)](0x6));if(_0x362388[_0x476b96(0x169)]===_0x476b96(0x127)){this[_0x476b96(0x168)]('SSE\x20connected'),this['emit'](_0x476b96(0x127));continue;}if(_0x362388[_0x476b96(0x169)]==='new_task'||_0x362388['type']===_0x476b96(0x10a)||_0x362388['type']===_0x476b96(0x16a))await this['processInbox']();}catch{}}}}catch(_0x5482d2){if(_0x5482d2['name']===_0x476b96(0x134))break;this[_0x476b96(0x119)](_0x476b96(0x12e),_0x5482d2),this['log']('SSE\x20error:\x20'+_0x5482d2[_0x476b96(0x140)]);}if(this[_0x476b96(0x12a)])this[_0x476b96(0x119)](_0x476b96(0x107)),this[_0x476b96(0x168)](_0x476b96(0x137)+_0x3c082e/0x3e8+_0x476b96(0x161)),await this[_0x476b96(0x174)](_0x3c082e),_0x3c082e=Math['min'](_0x3c082e*1.5,0xea60);}}async[a0_0x2a09e(0x144)](){const _0x320b94=a0_0x2a09e;try{let _0x3d0d9b=(await this[_0x320b94(0x14a)](_0x320b94(0x125),{'alias':this['alias'],'limit':0xa}))?.[_0x320b94(0x126)]||[];for(let _0x21140d of _0x3d0d9b)await this[_0x320b94(0x14a)]('ack_inbox',{'alias':this[_0x320b94(0x170)],'message_id':_0x21140d['id']}),this['log']('←\x20'+_0x21140d[_0x320b94(0x123)]+':\x20'+_0x21140d[_0x320b94(0x13d)][_0x320b94(0x178)](0x0,0x3c)),this[_0x320b94(0x119)](_0x320b94(0x10d),_0x21140d),this[_0x320b94(0x119)](_0x320b94(0x140),_0x21140d);}catch(_0x526f29){this[_0x320b94(0x168)](_0x320b94(0x121)+_0x526f29[_0x320b94(0x140)]);}}[a0_0x2a09e(0x174)](_0x299ca8){return new Promise(_0x5b4bbf=>setTimeout(_0x5b4bbf,_0x299ca8));}}var F=$;export{F as default,$ as CommHub};
1
+ const a0_0x127d7e=a0_0x57e4;function a0_0x4cbd(){const _0x55a735=['<pending>','broadcast','s...','lifecycle_tracking','send_task','network_id','idle','replace','transport','name','send_failed','read','task.replied','get_inbox','message','signal','url','1570oeupyv','to_alias','content','registered','heartbeat\x20failed:\x20','485iepTZt','lifecycleTracking','toString','get_all_status','networkId','task.send.failed','[commhub:task]\x20','Bearer\x20','startsWith','14ATfxTW','CommHub\x20response\x20omitted\x20task_id','tools/call',']\x20[commhub:','agent','toTimeString','task_id','connect','status','call','<unknown>','\x20error=','/events/','sending','4jOVkei','212jLSsUB','task.started','parent_task_id','\x20task_id=','ack_inbox','task.send.delivered','now','/mcp','result','toAlias','split','reply','<missing>','missing_task_id','min','parse','sdk','running','2.0','task','parentTaskId','SSE\x20error:\x20','32352wnEmuP','abort','from_alias','connectSSE','string','CommHub\x20rejected\x20task','heartbeatTimer','resumeId','text/event-stream','error_message','application/json,\x20text/event-stream','text','new_message','new_task','not_tracked','SSE\x20reconnecting\x20in\x20','\x20transport=','[REDACTED]','Authorization','\x20from=','completed','task.send.start','sdk-','catch','send','\x20lifecycle=','task.ack','error_code','8YEiUCk','2163528kHsqWq','POST','unknown\x20error','17919pjkXcc','autoConnect','slice','stringify','offline','cwd','\x20network_id=','\x20duration_ms=','fromAlias','type','\x20parent_task_id=','sseAbort','match','8376ZvhCOo','pop','duration_ms','824100rMsHQl','alias','processInbox','heartbeatInterval','error','send_message','body','getAllStatus','emit','reconnectDelay','connected','524454djkaua','send_rejected','send_reply','sleep','token','disconnected','from_session','application/json','task.expired','message_id','failed','normal','report_status','log'];a0_0x4cbd=function(){return _0x55a735;};return a0_0x4cbd();}(function(_0x15e9e2,_0x3175d2){const _0x5d664c=a0_0x57e4,_0x2ada4a=_0x15e9e2();while(!![]){try{const _0x3167e1=-parseInt(_0x5d664c(0x189))/0x1+-parseInt(_0x5d664c(0x1ff))/0x2*(parseInt(_0x5d664c(0x1c4))/0x3)+parseInt(_0x5d664c(0x200))/0x4*(-parseInt(_0x5d664c(0x1e8))/0x5)+parseInt(_0x5d664c(0x1b6))/0x6*(-parseInt(_0x5d664c(0x1f1))/0x7)+parseInt(_0x5d664c(0x1a5))/0x8*(parseInt(_0x5d664c(0x1a6))/0x9)+-parseInt(_0x5d664c(0x1e3))/0xa*(-parseInt(_0x5d664c(0x1a9))/0xb)+parseInt(_0x5d664c(0x1b9))/0xc;if(_0x3167e1===_0x3175d2)break;else _0x2ada4a['push'](_0x2ada4a['shift']());}catch(_0x22c029){_0x2ada4a['push'](_0x2ada4a['shift']());}}}(a0_0x4cbd,0x2ab33));function a0_0x57e4(_0x469f32,_0x56d5bd){_0x469f32=_0x469f32-0x180;const _0x4cbdb8=a0_0x4cbd();let _0x57e4a7=_0x4cbdb8[_0x469f32];return _0x57e4a7;}import{EventEmitter as a0_0x348bf3}from'events';import{hostname as a0_0x731679}from'os';var K=/(?:atok|ntok|utok|ghp|github_pat)_[A-Za-z0-9_-]+|Bearer\s+\S+/gi,L=(_0x496dac,_0x3df5f4)=>(_0x496dac??_0x3df5f4)['replace'](/[\r\n\x00-\x1f\x7f]/g,'\x20')[a0_0x127d7e(0x1ab)](0x0,0xf0);function N(_0x31bcb9){const _0x3a21c7=a0_0x127d7e;return(_0x31bcb9 instanceof Error?_0x31bcb9['message']:String(_0x31bcb9??_0x3a21c7(0x1a8)))[_0x3a21c7(0x1d9)](K,_0x3a21c7(0x19a))[_0x3a21c7(0x1d9)](/[\r\n\x00-\x1f\x7f]/g,'\x20')[_0x3a21c7(0x1ab)](0x0,0xf0);}function O(_0x58182b,_0x3e62b1=process.env.ANET_TASK_TRACE_FORMAT==='json'){const _0x225045=a0_0x127d7e;if(_0x3e62b1)return JSON[_0x225045(0x1ac)](_0x58182b);let _0x44725f=L(_0x58182b[_0x225045(0x202)],_0x225045(0x20c)),_0x1e6a88=L(_0x58182b[_0x225045(0x1f7)],_0x225045(0x1d2)),_0x14b69d=_0x58182b[_0x225045(0x1a4)]?_0x225045(0x1fc)+_0x58182b['error_code']+':'+(_0x58182b[_0x225045(0x192)]??''):'';return _0x225045(0x1ee)+_0x58182b[_0x225045(0x1f9)]+_0x225045(0x19c)+L(_0x58182b[_0x225045(0x18b)],_0x225045(0x1fb))+'\x20to='+L(_0x58182b[_0x225045(0x1e4)],_0x225045(0x1fb))+_0x225045(0x203)+_0x1e6a88+_0x225045(0x1b3)+_0x44725f+_0x225045(0x1af)+L(_0x58182b[_0x225045(0x1d7)],'<unknown>')+_0x225045(0x199)+_0x58182b[_0x225045(0x1da)]+_0x225045(0x1b0)+_0x58182b[_0x225045(0x1b8)]+_0x225045(0x1a2)+_0x58182b[_0x225045(0x1d5)]+_0x14b69d;}function U(_0x3359e0){const _0x2f230b=a0_0x127d7e;return{'event':{'sending':_0x2f230b(0x19e),'delivered':_0x2f230b(0x205),'failed':_0x2f230b(0x1ed),'acked':_0x2f230b(0x1a3),'started':_0x2f230b(0x201),'replied':_0x2f230b(0x1de),'expired':_0x2f230b(0x1cc)}[_0x3359e0[_0x2f230b(0x1f9)]],..._0x3359e0};}function j(_0x5d55a3){const _0xe5c3f=a0_0x127d7e;let _0x3c4a35=_0x5d55a3?.[_0xe5c3f(0x1f7)]||_0x5d55a3?.[_0xe5c3f(0x1cd)]||_0x5d55a3?.['id'];if(_0x3c4a35)return String(_0x3c4a35);let _0x20643b=_0x5d55a3?.[_0xe5c3f(0x1e5)]?.[0x0]?.['text'];if(typeof _0x20643b!==_0xe5c3f(0x18d))return null;try{let _0x1ed3ab=JSON['parse'](_0x20643b);return _0x1ed3ab?.[_0xe5c3f(0x1f7)]||_0x1ed3ab?.[_0xe5c3f(0x1cd)]||_0x1ed3ab?.['id']||null;}catch{return null;}}async function X(_0x2668b4,_0x36ee96){const _0x2c3aea=a0_0x127d7e;let _0x5e1cf3=_0x36ee96[_0x2c3aea(0x206)]??Date[_0x2c3aea(0x206)],_0x260593=_0x5e1cf3(),_0x53c740=(_0x2211a9,_0x3ba31a,_0x1c07d4,_0x464c80)=>{const _0x40fdc8=_0x2c3aea;_0x36ee96['log'](O(U({'from_alias':_0x2668b4[_0x40fdc8(0x1b1)],'to_alias':_0x2668b4[_0x40fdc8(0x209)],'task_id':_0x3ba31a,'parent_task_id':_0x2668b4[_0x40fdc8(0x187)],'network_id':_0x2668b4[_0x40fdc8(0x1ec)],'transport':_0x2668b4[_0x40fdc8(0x1da)],'status':_0x2211a9,'duration_ms':_0x5e1cf3()-_0x260593,'lifecycle_tracking':_0x2668b4[_0x40fdc8(0x1e9)],..._0x1c07d4!==void 0x0?{'error_code':_0x464c80||_0x40fdc8(0x1dc),'error_message':N(_0x1c07d4)}:{}})));};_0x53c740(_0x2c3aea(0x1fe),null);try{let _0x1d07d5=await _0x36ee96[_0x2c3aea(0x1a1)](),_0x150ae2=j(_0x1d07d5);if(_0x150ae2)_0x53c740('delivered',_0x150ae2);else{if(_0x1d07d5?.['ok']===!0x1||_0x1d07d5?.[_0x2c3aea(0x1bd)])_0x53c740(_0x2c3aea(0x1ce),_0x150ae2,_0x1d07d5?.['error']||_0x2c3aea(0x18e),_0x2c3aea(0x1c5));else _0x53c740(_0x2c3aea(0x1ce),null,_0x2c3aea(0x1f2),_0x2c3aea(0x180));}return _0x1d07d5;}catch(_0x53b6f3){throw _0x53c740(_0x2c3aea(0x1ce),null,_0x53b6f3,_0x2c3aea(0x1dc)),_0x53b6f3;}}async function Y(_0x2ceae0,_0x152d94){const _0x1ef717=a0_0x127d7e;return X({'fromAlias':_0x2ceae0['fromAlias'],'toAlias':_0x2ceae0[_0x1ef717(0x1ba)],'parentTaskId':_0x2ceae0['parentTaskId']||null,'networkId':_0x2ceae0['networkId']||null,'transport':'mcp_http','lifecycleTracking':_0x1ef717(0x197)},_0x152d94);}class $ extends a0_0x348bf3{['url'];[a0_0x127d7e(0x1ba)];[a0_0x127d7e(0x1c8)];[a0_0x127d7e(0x1f5)];[a0_0x127d7e(0x190)];['heartbeatInterval'];[a0_0x127d7e(0x1c2)];[a0_0x127d7e(0x18f)];[a0_0x127d7e(0x1b4)];['running']=!0x1;constructor(_0x29ccd4){const _0x151647=a0_0x127d7e;super();if(this['url']=_0x29ccd4[_0x151647(0x1e2)]['replace'](/\/$/,''),this[_0x151647(0x1ba)]=_0x29ccd4[_0x151647(0x1ba)],this[_0x151647(0x1c8)]=_0x29ccd4['token'],this[_0x151647(0x1f5)]=_0x29ccd4['agent']||_0x151647(0x183),this['resumeId']=_0x151647(0x19f)+_0x29ccd4['alias']+'-'+Date['now']()[_0x151647(0x1ea)](0x24),this[_0x151647(0x1bc)]=_0x29ccd4[_0x151647(0x1bc)]??0x2bf20,this[_0x151647(0x1c2)]=_0x29ccd4[_0x151647(0x1c2)]??0xbb8,_0x29ccd4[_0x151647(0x1aa)]!==!0x1)this[_0x151647(0x1f8)]();}[a0_0x127d7e(0x1d1)](_0x527fd3){const _0x29a46e=a0_0x127d7e;console[_0x29a46e(0x1d1)]('['+new Date()[_0x29a46e(0x1f6)]()[_0x29a46e(0x1ab)](0x0,0x8)+_0x29a46e(0x1f4)+this[_0x29a46e(0x1ba)]+']\x20'+_0x527fd3);}async[a0_0x127d7e(0x1fa)](_0x4fcbc5,_0x59c4cf){const _0x48d975=a0_0x127d7e;let _0x5e6f90={'Content-Type':_0x48d975(0x1cb),'Accept':_0x48d975(0x193)};if(this['token'])_0x5e6f90[_0x48d975(0x19b)]='Bearer\x20'+this['token'];let _0x323935=await(await fetch(this['url']+_0x48d975(0x207),{'method':_0x48d975(0x1a7),'headers':_0x5e6f90,'body':JSON[_0x48d975(0x1ac)]({'jsonrpc':_0x48d975(0x185),'id':Date['now'](),'method':_0x48d975(0x1f3),'params':{'name':_0x4fcbc5,'arguments':_0x59c4cf}})}))[_0x48d975(0x194)](),_0x7feb8a=_0x323935[_0x48d975(0x1b5)](/data: (.+)/),_0x5e66e1=_0x7feb8a?JSON[_0x48d975(0x182)](_0x7feb8a[0x1]):JSON[_0x48d975(0x182)](_0x323935),_0x336a35=_0x5e66e1?.[_0x48d975(0x208)]?.[_0x48d975(0x1e5)]?.[0x0]?.[_0x48d975(0x194)];return _0x336a35?JSON[_0x48d975(0x182)](_0x336a35):_0x5e66e1;}async[a0_0x127d7e(0x1f8)](){const _0x2e83f4=a0_0x127d7e;if(this[_0x2e83f4(0x184)])return;this[_0x2e83f4(0x184)]=!0x0,await this[_0x2e83f4(0x1f9)]('idle'),this[_0x2e83f4(0x1d1)](_0x2e83f4(0x1e6)),this[_0x2e83f4(0x18f)]=setInterval(()=>{const _0x20b90c=_0x2e83f4;this['status'](_0x20b90c(0x1d8))[_0x20b90c(0x1a0)](_0x2f6506=>this[_0x20b90c(0x1d1)](_0x20b90c(0x1e7)+_0x2f6506['message']));},this[_0x2e83f4(0x1bc)]),this['connectSSE']();}async['disconnect'](){const _0x1c3c59=a0_0x127d7e;if(this[_0x1c3c59(0x184)]=!0x1,this['sseAbort']?.[_0x1c3c59(0x18a)](),this['heartbeatTimer'])clearInterval(this['heartbeatTimer']);await this[_0x1c3c59(0x1f9)](_0x1c3c59(0x1ad))[_0x1c3c59(0x1a0)](()=>{}),this['log']('disconnected');}async['send'](_0x6f9dc4,_0x3c1b7c,_0x5b5669=a0_0x127d7e(0x1cf)){const _0x1637aa=a0_0x127d7e;return Y({'alias':_0x6f9dc4,'fromAlias':this[_0x1637aa(0x1ba)]},{'log':_0x2aaae1=>console[_0x1637aa(0x1d1)](_0x2aaae1),'send':()=>this[_0x1637aa(0x1fa)](_0x1637aa(0x1d6),{'alias':_0x6f9dc4,'task':_0x3c1b7c,'priority':_0x5b5669,'from_session':this[_0x1637aa(0x1ba)]})});}async[a0_0x127d7e(0x1e0)](_0x51daca,_0x2abde3){const _0x88a65b=a0_0x127d7e;return this[_0x88a65b(0x1fa)](_0x88a65b(0x1be),{'alias':_0x51daca,'message':_0x2abde3,'from_session':this[_0x88a65b(0x1ba)]});}async[a0_0x127d7e(0x20b)](_0x59625d,_0x2b6573,_0x4f14ee=a0_0x127d7e(0x19d)){const _0xacf631=a0_0x127d7e;return this[_0xacf631(0x1fa)](_0xacf631(0x1c6),{'in_reply_to':_0x59625d,'text':_0x2b6573,'status':_0x4f14ee});}async[a0_0x127d7e(0x1f9)](_0x264481,_0xcfba6b){const _0x99efd0=a0_0x127d7e;return this[_0x99efd0(0x1fa)](_0x99efd0(0x1d0),{'resume_id':this[_0x99efd0(0x190)],'alias':this[_0x99efd0(0x1ba)],'status':_0x264481,'server':a0_0x731679(),'hostname':a0_0x731679(),'agent':this[_0x99efd0(0x1f5)],'project_dir':process[_0x99efd0(0x1ae)](),..._0xcfba6b});}async[a0_0x127d7e(0x1c0)](){const _0x5bcf1b=a0_0x127d7e;return this[_0x5bcf1b(0x1fa)](_0x5bcf1b(0x1eb),{});}async[a0_0x127d7e(0x1d3)](_0x2e02e4,_0x1c8c78){const _0x5c75d2=a0_0x127d7e;return this[_0x5c75d2(0x1fa)]('broadcast',{'message':_0x2e02e4,'filter_server':_0x1c8c78?.['server'],'filter_status':_0x1c8c78?.['status']});}async[a0_0x127d7e(0x18c)](){const _0x1ceb8b=a0_0x127d7e;let _0x2854bf=encodeURIComponent(this[_0x1ceb8b(0x1ba)]),_0x363fa3=this[_0x1ceb8b(0x1e2)]+_0x1ceb8b(0x1fd)+_0x2854bf,_0x584a7e=this[_0x1ceb8b(0x1c2)];while(this[_0x1ceb8b(0x184)]){try{this[_0x1ceb8b(0x1b4)]=new AbortController();let _0x392b3f={'Accept':_0x1ceb8b(0x191)};if(this[_0x1ceb8b(0x1c8)])_0x392b3f[_0x1ceb8b(0x19b)]=_0x1ceb8b(0x1ef)+this[_0x1ceb8b(0x1c8)];let _0x2cb03a=await fetch(_0x363fa3,{'headers':_0x392b3f,'signal':this[_0x1ceb8b(0x1b4)][_0x1ceb8b(0x1e1)]});if(!_0x2cb03a['ok']||!_0x2cb03a[_0x1ceb8b(0x1bf)]){this[_0x1ceb8b(0x1d1)]('SSE\x20failed:\x20'+_0x2cb03a['status']),await this[_0x1ceb8b(0x1c7)](_0x584a7e),_0x584a7e=Math[_0x1ceb8b(0x181)](_0x584a7e*1.5,0xea60);continue;}_0x584a7e=this[_0x1ceb8b(0x1c2)];let _0x41350f=_0x2cb03a[_0x1ceb8b(0x1bf)]['getReader'](),_0x5b0cda=new TextDecoder(),_0x577904='';while(this[_0x1ceb8b(0x184)]){let {done:_0x25da5e,value:_0x1a5e4a}=await _0x41350f[_0x1ceb8b(0x1dd)]();if(_0x25da5e)break;_0x577904+=_0x5b0cda['decode'](_0x1a5e4a,{'stream':!0x0});let _0x1c74f8=_0x577904[_0x1ceb8b(0x20a)]('\x0a');_0x577904=_0x1c74f8[_0x1ceb8b(0x1b7)]()||'';for(let _0x5bdc3c of _0x1c74f8){if(!_0x5bdc3c[_0x1ceb8b(0x1f0)]('data:\x20'))continue;try{let _0x2a7b49=JSON[_0x1ceb8b(0x182)](_0x5bdc3c[_0x1ceb8b(0x1ab)](0x6));if(_0x2a7b49[_0x1ceb8b(0x1b2)]==='connected'){this[_0x1ceb8b(0x1d1)]('SSE\x20connected'),this[_0x1ceb8b(0x1c1)](_0x1ceb8b(0x1c3));continue;}if(_0x2a7b49[_0x1ceb8b(0x1b2)]===_0x1ceb8b(0x196)||_0x2a7b49[_0x1ceb8b(0x1b2)]===_0x1ceb8b(0x195)||_0x2a7b49[_0x1ceb8b(0x1b2)]===_0x1ceb8b(0x1d3))await this[_0x1ceb8b(0x1bb)]();}catch{}}}}catch(_0x1ba4a2){if(_0x1ba4a2[_0x1ceb8b(0x1db)]==='AbortError')break;this[_0x1ceb8b(0x1c1)](_0x1ceb8b(0x1bd),_0x1ba4a2),this[_0x1ceb8b(0x1d1)](_0x1ceb8b(0x188)+_0x1ba4a2[_0x1ceb8b(0x1e0)]);}if(this[_0x1ceb8b(0x184)])this[_0x1ceb8b(0x1c1)](_0x1ceb8b(0x1c9)),this[_0x1ceb8b(0x1d1)](_0x1ceb8b(0x198)+_0x584a7e/0x3e8+_0x1ceb8b(0x1d4)),await this[_0x1ceb8b(0x1c7)](_0x584a7e),_0x584a7e=Math['min'](_0x584a7e*1.5,0xea60);}}async[a0_0x127d7e(0x1bb)](){const _0xb47016=a0_0x127d7e;try{let _0x49eb24=(await this[_0xb47016(0x1fa)](_0xb47016(0x1df),{'alias':this[_0xb47016(0x1ba)],'limit':0xa}))?.['messages']||[];for(let _0x1a2de7 of _0x49eb24)await this[_0xb47016(0x1fa)](_0xb47016(0x204),{'alias':this['alias'],'message_id':_0x1a2de7['id']}),this['log']('←\x20'+_0x1a2de7[_0xb47016(0x1ca)]+':\x20'+_0x1a2de7[_0xb47016(0x1e5)]['slice'](0x0,0x3c)),this[_0xb47016(0x1c1)](_0xb47016(0x186),_0x1a2de7),this[_0xb47016(0x1c1)](_0xb47016(0x1e0),_0x1a2de7);}catch(_0x27314b){this[_0xb47016(0x1d1)]('inbox\x20error:\x20'+_0x27314b[_0xb47016(0x1e0)]);}}[a0_0x127d7e(0x1c7)](_0x5975fd){return new Promise(_0x2e9ee5=>setTimeout(_0x2e9ee5,_0x5975fd));}}var F=$;export{F as default,$ as CommHub};
@@ -0,0 +1,104 @@
1
+ import type { ReceiptCheck } from "./codex-lifecycle-receipt.js";
2
+ import type { RestartOutcome } from "./codex-lifecycle-restart.js";
3
+ export declare const SOURCE_KIND = "codex-login-profile";
4
+ /** `--source` 只接受 `codex-login:<profile-id>`。路径、`env:`、`-`(stdin)、绝对/相对路径都拒绝,错误里说清为什么。 */
5
+ export declare function parseSourceRef(raw: string): {
6
+ kind: typeof SOURCE_KIND;
7
+ profileId: string;
8
+ };
9
+ export declare function shortHash(value: string, length?: number): string;
10
+ /** host_id:machine-id(有则用)+ hostname 的不可逆摘要;registry entry 绑定它,拷到别的机器就不认。 */
11
+ export declare function hostIdOf(machineId: string | null, hostname: string): string;
12
+ export interface ChatgptAuthShape {
13
+ auth_mode?: unknown;
14
+ tokens?: {
15
+ account_id?: unknown;
16
+ } | null;
17
+ OPENAI_API_KEY?: unknown;
18
+ }
19
+ /** 只认 ChatGPT 登录:auth_mode=chatgpt 且 tokens.account_id 是 36 位 uuid;指纹 = sha256(account_id) 前 16 位。 */
20
+ export declare function accountFingerprint(auth: ChatgptAuthShape): string;
21
+ export interface RegistryEntry {
22
+ schema_version: 1;
23
+ profile_id: string;
24
+ provider: "openai-chatgpt";
25
+ host_id: string;
26
+ /** 由 registry 目录解析的相对引用;从不是绝对路径。 */
27
+ credential_ref: string;
28
+ account_fingerprint: string;
29
+ created_at: string;
30
+ last_model_probe_at: string | null;
31
+ last_model_probe_status: ProbeStatus | null;
32
+ revoked: boolean;
33
+ disabled: boolean;
34
+ }
35
+ export interface Registry {
36
+ schema_version: 1;
37
+ host_id: string;
38
+ profiles: Record<string, RegistryEntry>;
39
+ }
40
+ export type ProbeStatus = "ok" | "auth" | "quota" | "model" | "unknown";
41
+ export declare function credentialRefFor(profileId: string): string;
42
+ export declare function credentialPath(registryDir: string, entry: RegistryEntry): string;
43
+ export declare function readRegistry(registryDir: string, hostId: string): Registry;
44
+ export declare function writeRegistry(registryDir: string, reg: Registry): void;
45
+ /** 解析一个 profile:必须存在、未 revoked/disabled、host_id 一致、凭据文件在且 0600。返回凭据路径(只在进程内用,不进 receipt)。 */
46
+ export declare function resolveProfile(registryDir: string, reg: Registry, profileId: string, hostId: string): {
47
+ entry: RegistryEntry;
48
+ credentialFile: string;
49
+ };
50
+ /** 把一次 fresh 模型请求的结果归类;归不进已知类的一律 unknown(unknown 也 STOP,不猜)。 */
51
+ export declare function classifyProbe(exitCode: number | null, stdout: string, stderr: string, expected?: string): ProbeStatus;
52
+ export declare function backupRefFor(receiptId: string): string;
53
+ /** rollback 只认 `receipt:<id>`,且只在该节点的 receipts/ 目录里解析;调用方不能另指文件。 */
54
+ export declare function backupPathFor(nodeDir: string, backupRef: string): string;
55
+ export interface InstallActions {
56
+ /** 目标节点 before 核对:返回 fail 的 key(空 = 可继续)。 */
57
+ preflightBlocks(): Promise<string[]>;
58
+ /** 目标当前 auth 指纹(没有 auth.json → null)。 */
59
+ currentFingerprint(): Promise<string | null>;
60
+ /** 在隔离 staging HOME 里用该 profile 发一次 fresh 模型请求。 */
61
+ probe(): Promise<{
62
+ status: ProbeStatus;
63
+ detail: string;
64
+ }>;
65
+ /** 备份目标 auth.json → backup_ref(0600)。 */
66
+ backup(): Promise<{
67
+ backupRef: string;
68
+ }>;
69
+ /** 把 profile 凭据装进目标 CODEX_HOME(0600,原子)。 */
70
+ install(): Promise<void>;
71
+ /** 完整重启(PR-B 状态机),返回其 outcome。 */
72
+ restart(): Promise<RestartOutcome>;
73
+ /** 从 backup_ref 恢复 auth.json。 */
74
+ restore(backupRef: string): Promise<void>;
75
+ /** 探针在 registry 里的回写(时间 + 状态)。 */
76
+ recordProbe(status: ProbeStatus): Promise<void>;
77
+ }
78
+ export interface InstallInput {
79
+ profileId: string;
80
+ sourceFingerprint: string;
81
+ }
82
+ export interface InstallOutcome {
83
+ checks: ReceiptCheck[];
84
+ stoppedAt: string;
85
+ rolledBack: boolean;
86
+ backupRef: string | null;
87
+ }
88
+ /**
89
+ * account install 状态机:preflight → fresh 探针(401/quota/模型不兼容/unknown 都 STOP,目标一字未动)→ 备份 → 安装 →
90
+ * 完整重启(含 verify)→ 目标指纹 == 源指纹。安装后任一步失败 → 恢复备份 + 再重启一次(回滚),receipt 记两段。
91
+ */
92
+ export declare function runAccountInstall(input: InstallInput, a: InstallActions): Promise<InstallOutcome>;
93
+ export interface RollbackActions {
94
+ /** 读原 install receipt;返回它的 backup_ref 与当时的 target_previous_fingerprint。 */
95
+ readInstallReceipt(): Promise<{
96
+ backupRef: string;
97
+ targetPreviousFingerprint: string | null;
98
+ } | null>;
99
+ backupExists(backupRef: string): Promise<boolean>;
100
+ restore(backupRef: string): Promise<void>;
101
+ restart(): Promise<RestartOutcome>;
102
+ currentFingerprint(): Promise<string | null>;
103
+ }
104
+ export declare function runRollback(a: RollbackActions): Promise<InstallOutcome>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * #1856 PR-E — `anet node codex canary <alias>...`:批量只读体检,**顺序跑、第一个 FAIL 即停**。
3
+ * 批量重启 / 换账号之前先 canary;后面的节点一个都不碰,汇总里明确写"未跑"。纯逻辑,verify 由调用方注入。
4
+ */
5
+ export interface CanaryNodeResult {
6
+ readonly alias: string;
7
+ readonly verdict: "PASS" | "FAIL";
8
+ readonly blocking: readonly string[];
9
+ readonly receiptPath: string | null;
10
+ readonly ms: number;
11
+ }
12
+ export interface CanarySummary {
13
+ readonly verdict: "PASS" | "FAIL";
14
+ readonly ran: readonly CanaryNodeResult[];
15
+ /** 因前面 FAIL 而没跑的节点(顺序保留)。 */
16
+ readonly skipped: readonly string[];
17
+ readonly stoppedAt: string | null;
18
+ }
19
+ export declare function runCanary(aliases: readonly string[], verifyOne: (alias: string) => Promise<Omit<CanaryNodeResult, "alias" | "ms">>, now?: () => number): Promise<CanarySummary>;
20
+ export declare function formatCanarySummary(s: CanarySummary): string;
@@ -0,0 +1,53 @@
1
+ import type { PreflightFacts, ProcessFact, RolloutFact } from "./codex-lifecycle-preflight";
2
+ export interface FactPrimitives {
3
+ /** tmux pane pid of a session, or null when the session is not running. */
4
+ tmuxPanePid(session: string): number | null;
5
+ /** all pids (Linux /proc); [] elsewhere */
6
+ listPids(): number[];
7
+ procStatPpid(pid: number): number | null;
8
+ procCwd(pid: number): string | null;
9
+ procArgv(pid: number): string[] | null;
10
+ procEnviron(pid: number): Record<string, string> | null;
11
+ /** pid listening on a loopback TCP port, or null (free / unknown) */
12
+ listeningPid(port: number): number | null;
13
+ /** hub roster: alias → node_id, or null when unreachable */
14
+ hubNodeIdFor(alias: string): Promise<string | null>;
15
+ }
16
+ export declare function realPrimitives(opts: {
17
+ hub: string;
18
+ token: string;
19
+ networkId?: string;
20
+ }): FactPrimitives;
21
+ export declare function envFileTokenFingerprint(codexHome: string): string | null;
22
+ /** rollout-*-<threadId>.jsonl under CODEX_HOME/sessions/**;精确后缀匹配,不做前缀/最近猜测。 */
23
+ export declare function findRollouts(codexHome: string, threadId: string | null): RolloutFact[];
24
+ /** 从 pane pid 往下找子孙进程(含自身),按 pid 升序。 */
25
+ export declare function descendants(prim: FactPrimitives, rootPid: number): number[];
26
+ export declare function processFact(prim: FactPrimitives, pid: number): ProcessFact;
27
+ export interface GatherInput {
28
+ alias: string;
29
+ nodeId: string | null;
30
+ nodeDir: string;
31
+ codexHome: string;
32
+ configToken: string | null;
33
+ codexProjectDir: string | null;
34
+ codexThreadId: string | null;
35
+ codexAppServerUrl: string | null;
36
+ sessions: {
37
+ appsrv: string;
38
+ bridge: string;
39
+ tui: string;
40
+ };
41
+ recordedPids: {
42
+ appsrv: number | null;
43
+ bridge: number | null;
44
+ tui: number | null;
45
+ };
46
+ markerUuid: string | null;
47
+ }
48
+ /** ⑨ goals.json → 状态摘要 + 内容指纹。没有文件 = none(没派过目标);有文件但 schema 不认识/读不到 = unknown(restart 必须 STOP)。 */
49
+ export declare function goalsFileState(nodeDir: string): {
50
+ state: "active" | "stalled" | "paused" | "achieved" | "none" | "unknown";
51
+ fingerprint: string | null;
52
+ };
53
+ export declare function gatherCodexFacts(prim: FactPrimitives, input: GatherInput): Promise<PreflightFacts>;
@@ -0,0 +1,53 @@
1
+ import type { ReceiptCheck } from "./codex-lifecycle-receipt.js";
2
+ /** Codex 的 thread id 是 UUIDv7(时间有序);fork 出的新 id 也按 v7 生成,便于按文件名/id 排序时落在源之后。 */
3
+ export declare function uuidV7(nowMs: number, rand: Uint8Array): string;
4
+ /** codex 的 rollout 路径:sessions/YYYY/MM/DD/rollout-YYYY-MM-DDTHH-MM-SS-<id>.jsonl(UTC)。 */
5
+ export declare function forkRolloutPath(codexHome: string, now: Date, threadId: string): string;
6
+ /** CODEX_HOME 里哪些文件随 fork 走。显式白名单;env 文件(含源节点 CommHub token)、历史、sqlite、缓存一律不带。 */
7
+ export declare const FORK_HOME_COPY: readonly {
8
+ name: string;
9
+ required: boolean;
10
+ mode: number;
11
+ }[];
12
+ export declare const FORK_HOME_NEVER_COPY: readonly string[];
13
+ export interface RolloutRewriteResult {
14
+ readonly lines: number;
15
+ readonly bytesIn: number;
16
+ readonly bytesOut: number;
17
+ /** 源 thread id 改写次数(定长,不改字节数)。 */
18
+ readonly replacements: number;
19
+ /** `"cwd":"<源目录>"` 改写次数(session_meta + 每个 turn_context 都带;改成新 workdir,字节数按长度差变化)。 */
20
+ readonly cwdReplacements: number;
21
+ /** = bytesIn + cwdReplacements × (新 cwd 编码长度 − 旧 cwd 编码长度);fork_isolation 用它核对复制没有丢字节。 */
22
+ readonly expectedBytesOut: number;
23
+ }
24
+ /**
25
+ * 流式复制 rollout 并把源 thread id 逐处改成新 id(两者定长 36 字符 → 字节数不变,可作 fork_isolation 的证据)。
26
+ * 第一行校验失败时目标文件不存在(先读第一行再开写)。
27
+ */
28
+ export declare function rewriteRollout(src: string, dst: string, oldId: string, newId: string, cwd?: {
29
+ from: string;
30
+ to: string;
31
+ }): Promise<RolloutRewriteResult>;
32
+ export interface ForkSides {
33
+ readonly source: {
34
+ nodeId: string | null;
35
+ homeReal: string | null;
36
+ threadId: string | null;
37
+ alias: string;
38
+ rolloutInode: number | bigint | null;
39
+ rolloutBytes: number | null;
40
+ };
41
+ readonly target: {
42
+ nodeId: string | null;
43
+ homeReal: string | null;
44
+ threadId: string | null;
45
+ alias: string;
46
+ rolloutInode: number | bigint | null;
47
+ rolloutBytes: number | null;
48
+ envFilePresent: boolean;
49
+ };
50
+ readonly rewrite: RolloutRewriteResult | null;
51
+ }
52
+ /** fork_isolation:身份 / HOME / thread / rollout 文件 / tmux 名五处都不同,且 rollout 是等长复制、没带 token 文件。 */
53
+ export declare function checkForkIsolation(s: ForkSides): ReceiptCheck;
@@ -0,0 +1,77 @@
1
+ import type { ReceiptCheck } from "./codex-lifecycle-receipt";
2
+ export interface RolloutFact {
3
+ readonly path: string;
4
+ readonly inode: number | bigint;
5
+ readonly bytes: number;
6
+ readonly mtimeMs: number;
7
+ }
8
+ export interface ProcessFact {
9
+ readonly pid: number;
10
+ readonly cwd: string | null;
11
+ /** 子进程实际环境里的 CODEX_HOME(不是 wrapper 继承的那份 —— wrapper 环境不能作承重证据)。 */
12
+ readonly codexHome: string | null;
13
+ /** 子进程实际环境里 CommHub token 的短指纹;null = 没读到或该进程不该持有。 */
14
+ readonly tokenFingerprint: string | null;
15
+ /** 子进程环境里的 ANET_NODE_MARKER(copresence-identity 的身份 uuid);null = 没有。 */
16
+ readonly markerUuid: string | null;
17
+ readonly argv: readonly string[];
18
+ }
19
+ export interface PreflightFacts {
20
+ readonly alias: string;
21
+ readonly configNodeId: string | null;
22
+ /** hub 名册按 alias 精确查到的 node_id;null = hub 不可达或没这个 alias。 */
23
+ readonly hubNodeId: string | null;
24
+ readonly home: {
25
+ readonly dir: string;
26
+ readonly dirMode: number | null;
27
+ readonly authMode: number | null;
28
+ readonly authBytes: number | null;
29
+ readonly configTokenFingerprint: string | null;
30
+ readonly envFileTokenFingerprint: string | null;
31
+ };
32
+ readonly workdir: {
33
+ readonly configProjectDir: string | null;
34
+ readonly tuiCwd: string | null;
35
+ readonly tuiArgvDir: string | null;
36
+ readonly bridgeProjectDir: string | null;
37
+ readonly statusBarDir: string | null;
38
+ };
39
+ readonly session: {
40
+ readonly threadId: string | null;
41
+ /** CODEX_HOME 里文件名以 <threadId>.jsonl 结尾的 rollout 全集。 */
42
+ readonly rolloutMatches: readonly RolloutFact[];
43
+ };
44
+ readonly port: {
45
+ readonly port: number | null;
46
+ readonly owner: ProcessFact | null;
47
+ };
48
+ readonly topology: {
49
+ /** copresence-identity.json 里的身份 uuid;null = 没有 marker 文件。 */
50
+ readonly markerUuid: string | null;
51
+ /** marker 里记的 pid(采集时的观测提示,**不是**身份来源)与现在 tmux pane 的 pid。 */
52
+ readonly recorded: Readonly<Record<"appsrv" | "bridge" | "tui", number | null>>;
53
+ readonly live: Readonly<Record<"appsrv" | "bridge" | "tui", number | null>>;
54
+ /** 每个 tmux 段下带环境的子进程各自的 ANET_NODE_MARKER。 */
55
+ readonly liveMarkers: Readonly<Record<"appsrv" | "bridge" | "tui", readonly (string | null)[]>>;
56
+ /** 每个 tmux 段下带环境的子进程各自的 CODEX_HOME(realpath)。 */
57
+ readonly liveHomes: Readonly<Record<"appsrv" | "bridge" | "tui", readonly (string | null)[]>>;
58
+ };
59
+ readonly goal: {
60
+ readonly state: "active" | "stalled" | "paused" | "achieved" | "none" | "unknown";
61
+ };
62
+ readonly children: readonly ProcessFact[];
63
+ readonly expectedTokenFingerprint: string | null;
64
+ }
65
+ export declare function checkIdentity(f: PreflightFacts): ReceiptCheck;
66
+ export declare function checkHome(f: PreflightFacts): ReceiptCheck;
67
+ export declare function checkWorkdir(f: PreflightFacts): ReceiptCheck;
68
+ export declare function checkSession(f: PreflightFacts): ReceiptCheck;
69
+ export declare function rolloutSnapshot(f: PreflightFacts): ReceiptCheck;
70
+ export declare function compareRollout(before: RolloutFact, after: RolloutFact | null): ReceiptCheck;
71
+ export declare function checkPortOwner(f: PreflightFacts): ReceiptCheck;
72
+ export declare function checkChildEnv(f: PreflightFacts): ReceiptCheck;
73
+ export declare function checkGoalState(f: PreflightFacts): ReceiptCheck;
74
+ export declare function checkTopology(f: PreflightFacts): ReceiptCheck;
75
+ export declare function evaluateCodexPreflight(f: PreflightFacts): ReceiptCheck[];
76
+ /** verify = preflight + 子进程环境 + 跨节点身份验收(identity_attested 由调用方注入;PR-A 里没有探针时给 unknown)。 */
77
+ export declare function evaluateCodexVerify(f: PreflightFacts, identityAttested: ReceiptCheck): ReceiptCheck[];
@@ -0,0 +1,44 @@
1
+ export type CheckStatus = "pass" | "fail" | "unknown";
2
+ export interface ReceiptCheck {
3
+ readonly key: string;
4
+ readonly status: CheckStatus;
5
+ /** 一句人话:pass 说核到了什么,fail 说差在哪,unknown 说为什么量不到。 */
6
+ readonly detail: string;
7
+ /** 可复核的证据(路径、inode、字节数、短指纹……);不得含凭据。 */
8
+ readonly evidence?: Readonly<Record<string, unknown>>;
9
+ }
10
+ export type LifecycleVerb = "preflight" | "verify" | "start" | "restart" | "resume" | "fork" | "account-install" | "rollback";
11
+ export interface LifecycleReceipt {
12
+ readonly format: "anet-codex-lifecycle-receipt/1";
13
+ readonly id: string;
14
+ readonly verb: LifecycleVerb;
15
+ readonly alias: string;
16
+ readonly nodeId: string | null;
17
+ readonly startedAt: string;
18
+ readonly finishedAt: string;
19
+ readonly verdict: "PASS" | "FAIL";
20
+ /** FAIL 时阻塞的 check key(fail 与 unknown 都算)。 */
21
+ readonly blocking: readonly string[];
22
+ readonly checks: readonly ReceiptCheck[];
23
+ }
24
+ /** 每个动词要求哪些 check 必须 pass。preflight 只读,不要求 identity_attested(那是 verify 的活)。 */
25
+ export declare const REQUIRED_CHECKS: Readonly<Record<LifecycleVerb, readonly string[]>>;
26
+ export declare function shortFingerprint(value: string | undefined | null, length?: number): string | null;
27
+ export declare function redactReceipt<T>(value: T, key?: string): T;
28
+ export declare const INFORMATIONAL_PREFIXES: readonly string[];
29
+ export declare function receiptVerdict(verb: LifecycleVerb, checks: readonly ReceiptCheck[]): {
30
+ verdict: "PASS" | "FAIL";
31
+ blocking: string[];
32
+ };
33
+ export declare function buildReceipt(opts: {
34
+ verb: LifecycleVerb;
35
+ alias: string;
36
+ nodeId: string | null;
37
+ startedAt: Date;
38
+ finishedAt?: Date;
39
+ checks: readonly ReceiptCheck[];
40
+ }): LifecycleReceipt;
41
+ /** receipts 落在节点目录下 receipts/<id>.json,0600,先写临时文件再 rename(原子)。返回绝对路径。 */
42
+ export declare function writeReceipt(nodeDir: string, receipt: LifecycleReceipt): string;
43
+ /** 终端摘要:一行一 check,PASS/FAIL 在最后;不打印 evidence 里的长值。 */
44
+ export declare function formatReceiptSummary(receipt: LifecycleReceipt): string;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * #1856 PR-B — `anet node codex start|restart|resume` 的确定性状态机。
3
+ *
4
+ * 零 LLM:每一步是「读事实 → 判 → 动作 → 写 receipt check」,顺序固定;所有副作用都经 `RestartActions`
5
+ * 注入,所以这个文件可以在纯单测里跑完整个流程(含失败与回滚分支)。
6
+ *
7
+ * 停:Bridge → TUI → App Server(反向于依赖:先断任务入口,再让 TUI 把 rollout 刷完,最后放掉端口)。
8
+ * 起:交给 `anet node start <alias> --copresence --tui-first`(App Server → 端口就绪 → exact-session
9
+ * TUI 完全恢复 → Bridge),再用 preflight/verify 复核 —— 起的顺序由启动器保证,这里只验证结果。
10
+ * 任一步 fail → 不再往下;若已停掉进程则尝试一次「回滚」= 按原配置再起一次;仍失败就留在已停状态,
11
+ * receipt 记录到哪一步、为什么,exit 2。绝不猜、绝不 fallback 到别的线程。
12
+ */
13
+ import type { ReceiptCheck } from "./codex-lifecycle-receipt.js";
14
+ import type { RolloutFact } from "./codex-lifecycle-preflight.js";
15
+ export type RestartVerb = "start" | "restart" | "resume";
16
+ export type GoalState = "active" | "paused" | "stalled" | "achieved" | "none" | "unknown";
17
+ export type CopresenceRole = "bridge" | "tui" | "appsrv";
18
+ export interface GateResult {
19
+ /** 该阶段所有 check(preflight 或 verify 的输出)。 */
20
+ readonly checks: readonly ReceiptCheck[];
21
+ /** 该阶段 rollout 快照(session_exact 通过时才有)。 */
22
+ readonly rollout: RolloutFact | null;
23
+ /** 端口占用者(null = 空闲)。 */
24
+ readonly port: {
25
+ readonly port: number | null;
26
+ readonly ownerPid: number | null;
27
+ readonly ownerIsOurs: boolean | null;
28
+ };
29
+ }
30
+ export interface RestartActions {
31
+ /** 只读核对(PR-A 的 preflight;`after` 阶段可带 identity_attested 变 verify)。 */
32
+ gate(phase: "before" | "after"): Promise<GateResult>;
33
+ /** goals.json 的状态摘要 + 内容指纹(unknown = 读不到/不认识的 schema)。 */
34
+ goalState(): Promise<{
35
+ state: GoalState;
36
+ fingerprint: string | null;
37
+ }>;
38
+ /** 三个 tmux 会话谁还活着。 */
39
+ liveSessions(): Promise<Readonly<Record<CopresenceRole, boolean>>>;
40
+ /** 杀掉一个角色的 tmux 会话并等它消失;ok=false 时 detail 说为什么。 */
41
+ stopSession(role: CopresenceRole): Promise<{
42
+ ok: boolean;
43
+ detail: string;
44
+ }>;
45
+ /** 等 rollout 文件字节数稳定(TUI 退出后大 rollout 还在刷盘);返回最终快照。 */
46
+ waitRolloutSettled(before: RolloutFact | null): Promise<RolloutFact | null>;
47
+ /** 等端口空闲;超时仍被占用时给出占用者 pid 与「是不是我们自己的 app-server」。 */
48
+ waitPortFree(): Promise<{
49
+ free: boolean;
50
+ ownerPid: number | null;
51
+ ownerIsOurs: boolean | null;
52
+ }>;
53
+ /** 对已核实属于本节点的残留 pid 发 TERM(定向,绝不 pkill -f)。 */
54
+ termOwnedPid(pid: number): Promise<{
55
+ ok: boolean;
56
+ detail: string;
57
+ }>;
58
+ /** 跑启动器(`anet node start --copresence --tui-first`);ok=false 时 detail 是它的尾部输出。 */
59
+ start(): Promise<{
60
+ ok: boolean;
61
+ detail: string;
62
+ }>;
63
+ /** hub 上该 node_id 是否在超时内回到 online/idle。 */
64
+ waitHubOnline(): Promise<{
65
+ ok: boolean;
66
+ detail: string;
67
+ }>;
68
+ /** 跨节点 nonce 探针;未配置时返回 undefined(check 记 unknown)。 */
69
+ nonceProbe?: () => Promise<{
70
+ ok: boolean;
71
+ detail: string;
72
+ evidence?: Record<string, unknown>;
73
+ }>;
74
+ }
75
+ export interface RestartOutcome {
76
+ readonly verb: RestartVerb;
77
+ readonly checks: readonly ReceiptCheck[];
78
+ /** 走到哪一步停下(PASS 时 = "done")。 */
79
+ readonly stoppedAt: string;
80
+ readonly rolledBack: boolean;
81
+ }
82
+ /** before 阶段的门:required 里不许有 fail;unknown 允许(要重启的节点常常就是缺了一截进程)。 */
83
+ export declare function beforeGateBlocks(checks: readonly ReceiptCheck[]): string[];
84
+ /** 三个角色按依赖反向停;返回 stop_order check(顺序本身就是证据)。 */
85
+ export declare function orderedStop(actions: RestartActions, live: Readonly<Record<CopresenceRole, boolean>>): Promise<ReceiptCheck>;
86
+ export declare function runCodexRestart(verb: RestartVerb, actions: RestartActions): Promise<RestartOutcome>;