@sleep2agi/agent-node 2.5.0-preview.109 → 2.5.0-preview.110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -240,7 +240,7 @@ ${A}`}function k_(A,Q,B,C,I){let{interactiveDashboardTask:E,messageType:g}=B,U=G
|
|
|
240
240
|
`,"config.json",Q?.stat),{config:I,source:"prev",primaryError:B}}function hO(A){return JSON.parse(x0(A,"config.json").body)}function mO(A,Q){let B=x0(A,"config.json");tG(A,JSON.stringify(Q,null,2)+`
|
|
241
241
|
`,"config.json",B.stat)}function uO(A){let Q=x0(A,"config.json");return tG(`${A}.prev`,Q.body,"config.json.prev"),{backedUp:!0}}function cO(A,Q){let B=x0(A,"config.json"),C=JSON.parse(B.body);if(C.session===Q)return!1;return C.session=Q,tG(A,JSON.stringify(C,null,2)+`
|
|
242
242
|
`,"config.json",B.stat),!0}MF();$F();async function QT(A,Q){let B=!1,C;for(let I of A)try{await Q(I)}catch(E){if(!B)C=E;B=!0}if(B)throw C}function _Z(A,Q){let B=Promise.resolve(),C=new Map,I=async(E)=>{let g=Q?.initialDelayMs??0;while(!0)try{await E();return}catch(U){if(A(U),!Q)return;await new Promise((D)=>{setTimeout(D,g).unref?.()}),g=Math.min(g*2,Q.maxDelayMs)}};return{schedule(E){let g=C.get(E);if(g){g.dirty=!0;return}let U={dirty:!1};C.set(E,U);let D=async()=>{try{do U.dirty=!1,await I(E);while(U.dirty)}finally{C.delete(E)}};B=B.then(D,D)},idle(){return B}}}var aQA=new Set(["replied","failed","cancelled","expired"]);function sQA(A){return typeof A==="string"&&aQA.has(A)}async function BT(A,Q){if(!Q)return{skip:!1,status:null,reason:"no-task-id"};let B;try{B=await A(Q)}catch{return{skip:!1,status:null,reason:"lookup-failed"}}if(!B||B.ok===!1||!B.task)return{skip:!1,status:null,reason:"not-found"};let C=typeof B.task.status==="string"?B.task.status:null;return sQA(C)?{skip:!0,status:C,reason:"terminal"}:{skip:!1,status:C,reason:"open"}}function IT(A){if(A.meta&&typeof A.meta==="object"&&!Array.isArray(A.meta))return A.meta;if(typeof A.meta_json!=="string"||A.meta_json.length===0)return null;try{let Q=JSON.parse(A.meta_json);return Q&&typeof Q==="object"&&!Array.isArray(Q)?Q:null}catch{return null}}function qZ(A){let Q=A.type??"task";if(Q!=="task"&&Q!=="broadcast")return!1;let B=IT(A);if(!B||B.source!=="dashboard-chat")return!1;if(typeof B.client_request_id!=="string"||!/^dreq_[a-f0-9]{32}$/.test(B.client_request_id))return!1;return B.auth_origin==="user"}function CT(A){if(!qZ(A))return null;let Q=IT(A)?.client_request_id;return typeof Q==="string"?Q:null}async function ET(A,Q){for(let B of A)await Q(B)}function gT(A){if(!Number.isInteger(A.maxConcurrent)||A.maxConcurrent<1)throw Error("maxConcurrent must be a positive integer");let Q=new Set,B=new Set,C=[],I=()=>{while(Q.size<A.maxConcurrent&&C.length>0){let E=C.shift(),g=A.key(E.message);B.delete(g),Q.add(g);let U;try{U=E.handler(E.message)}catch(D){U=Promise.reject(D)}U.catch(A.onError).finally(()=>{Q.delete(g);try{A.onSettled?.()}catch(D){A.onError(D)}finally{I()}})}};return{submit(E,g){let U=0,D=0;for(let F of E){let Y=A.key(F);if(Q.has(Y)||B.has(Y)){D++;continue}B.add(Y),C.push({message:F,handler:g}),U++}return I(),{active:Q.size,queued:C.length,accepted:U,deduplicated:D}},stats(){return{active:Q.size,queued:C.length}}}}function UT(A,Q){return A!=="codex-app-server"||Q===0}var tQA={self:"sender alias equals node alias; reply-loop guard","own-prefix":"message carries this node's own reply prefix; reply-loop guard",cooldown:"sender cooldown is active","low-value-inbound":"non-task message matched the low-value filter"};function DT(A){let Q=tQA[A.reason]||"inbound filter rejected the message";return`skipped inbound ${A.messageType} ${A.taskId} from ${A.sender}: ${A.reason} (${Q}); acknowledged without model delivery`}function FT(A){let Q=A||"task";return Q==="task"||Q==="broadcast"}function YT(A){let{alias:Q,from:B,content:C,msgType:I}=A;if(B===Q&&!A.imBridge)return"self";if(C.startsWith(`[${Q}]`))return"own-prefix";let E=I==="task"||I==="broadcast"||I==="reply";if(!E&&B!=="hub"&&B!=="api"){if(A.lastReplyAt&&A.now-A.lastReplyAt<A.cooldownMs)return"cooldown"}if(!E&&A.isLowValue(C))return"low-value-inbound";return null}var eQA="skipped by agent-node: self-sent task (sender is this node; reply-loop guard), no turn ran. To wake a node later, use a Hub scheduled task or /aloop instead of send_task to yourself. (#519)",ABA="skipped by agent-node: task text starts with this node's own reply prefix (echo of its own reply; reply-loop guard), no turn ran. (#519)";function QBA(A){if(A==="self")return eQA;if(A==="own-prefix")return ABA;return null}async function JT(A,Q){let B=QBA(Q.reason);if(!B)return{kind:"not-applicable",detail:`reason ${Q.reason} does not close a task`};if(!FT(Q.msgType))return{kind:"not-applicable",detail:`type ${Q.msgType} carries no task`};if(!Q.taskId)return{kind:"not-applicable",detail:"no task id"};try{let C=await A("cancel_task",{task_id:Q.taskId,reason:B});if(C&&typeof C==="object"&&C.ok===!0)return{kind:"closed",tool:"cancel_task"};return{kind:"not-closed",tool:"cancel_task",detail:JSON.stringify(C??null).slice(0,200)}}catch(C){return{kind:"error",tool:"cancel_task",detail:String(C?.message??C).slice(0,200)}}}async function NT(A,Q){if(!FT(Q.msgType))return{kind:"not-applicable",detail:`type ${Q.msgType} carries no task`};if(!Q.taskId)return{kind:"not-applicable",detail:"no task id"};let C=`${Q.result.trim()||"(empty reply)"} [low-value reply withheld from sender by agent-node (#519)]`.slice(0,4000);try{return await A("report_completion",{alias:Q.alias,task:Q.taskId,result:C}),{kind:"closed",tool:"report_completion"}}catch(I){return{kind:"error",tool:"report_completion",detail:String(I?.message??I).slice(0,200)}}}function VF(A,Q){switch(Q.kind){case"closed":return`closed task ${A} via ${Q.tool} (#519)`;case"not-closed":return`task ${A} not closed by ${Q.tool} (already terminal?): ${Q.detail}`;case"not-applicable":return`task ${A} left as-is: ${Q.detail}`;case"error":return`failed to close task ${A} via ${Q.tool}: ${Q.detail}`}}function E$(){let A=null;return{run(Q){if(A)return A;let B=Promise.resolve().then(Q);return A=B,B.finally(()=>{if(A===B)A=null}).catch(()=>{}),B},pending(){return A}}}function GT(){let A=null,Q=E$();return{async getOrOpen(B){if(A?.isRunning)return A;return Q.run(async()=>{if(A?.isRunning)return A;A=null;let C=await B();if(!C.isRunning)throw Error("codex app-server session stopped while opening");return A=C,C})},invalidate(B){if(!B||A===B)A=null},current(){return A},pending(){return Q.pending()}}}WF();import{closeSync as LF,constants as BC,existsSync as UBA,fchmodSync as U$,fstatSync as MT,fsyncSync as DBA,ftruncateSync as FBA,lstatSync as YBA,mkdirSync as JBA,openSync as xZ,readdirSync as NBA,readFileSync as GBA,realpathSync as PZ,writeSync as $BA}from"node:fs";import{join as VT,resolve as kZ}from"node:path";function WT(){return process.platform==="linux"&&UBA("/proc/self/fd")}function LT(A,Q){return WT()?`/proc/self/fd/${A}`:Q}function XT(A,Q){let B=MT(A),C=process.getuid?.();if(!B.isFile()||B.nlink!==1||C!==void 0&&B.uid!==C)throw Error(`private log is not a single owner-controlled file: ${Q}`);U$(A,384)}function ZT(A){let Q=kZ(A);if(PZ(Q)!==Q)throw Error(`private log directory is not canonical: ${Q}`);let B=xZ(Q,BC.O_RDONLY|(BC.O_DIRECTORY||0)|(BC.O_NOFOLLOW||0));try{let C=MT(B),I=process.getuid?.();if(!C.isDirectory()||I!==void 0&&C.uid!==I)throw Error(`private log directory is not owner-controlled: ${Q}`);if(WT()&&PZ(`/proc/self/fd/${B}`)!==Q)throw Error(`private log directory changed during validation: ${Q}`);if(process.platform!=="win32")U$(B,448);return B}catch(C){throw LF(B),C}}function wT(A,Q,B){let C=0;while(C<Q.length){let I=$BA(A,Q,C,Q.length-C,B===null?null:B+C);if(I<=0)throw Error("private log write made no progress");C+=I}}function MBA(A,Q){let B=xZ(A,BC.O_RDWR|(BC.O_NOFOLLOW||0));try{XT(B,A);let C=Buffer.from(Q.redactText(GBA(B,"utf8")).text,"utf8");if(FBA(B,0),C.length>0)wT(B,C,0);DBA(B),U$(B,384)}finally{LF(B)}}function KT(A,Q){let B=kZ(A);JBA(B,{recursive:!0,mode:448});let C=YBA(B),I=process.getuid?.();if(C.isSymbolicLink()||!C.isDirectory()||PZ(B)!==B||I!==void 0&&C.uid!==I)throw Error(`private log directory is not owner-controlled: ${B}`);let E=ZT(B);try{let g=LT(E,B);for(let U of NBA(g)){if(!U.endsWith(".log"))continue;MBA(VT(g,U),Q)}}finally{LF(E)}return B}function zT(A,Q,B,C){if(!/^\d{4}-\d{2}-\d{2}\.log$/.test(Q))throw Error("private log filename is not a canonical daily log name");let I=ZT(A),E=VT(LT(I,kZ(A)),Q),g;try{g=xZ(E,BC.O_WRONLY|BC.O_CREAT|BC.O_APPEND|(BC.O_NOFOLLOW||0),384),XT(g,E);let U=Buffer.from(C.redactText(B).text,"utf8");if(U.length>0)wT(g,U,null);U$(g,384)}finally{if(g!==void 0)LF(g);LF(I)}}function vZ(A){return JSON.stringify(A)}function HT(A){let Q=A.configNodeId||"",B=A.envNodeId||"";if(Q){if(B&&B!==Q)A.warn?.(`COMMHUB_NODE_ID mismatch: env=${vZ(B)} config=${vZ(Q)} config_path=${vZ(A.configPath||"config.json")}; ignoring env COMMHUB_NODE_ID, using config node_id`);return{value:Q,source:"config"}}if(B)return{value:B,source:"env"};return{value:"",source:"none"}}function VBA(A){let Q=A?.task_id||A?.message_id||A?.id;if(Q)return String(Q);let B=A?.content?.[0]?.text;if(typeof B!=="string")return null;try{let C=JSON.parse(B);return C?.task_id||C?.message_id||C?.id||null}catch{return null}}function b0(A,Q,B,C={}){let I=wG({from_alias:A.fromAlias,to_alias:A.toAlias,task_id:B,parent_task_id:A.parentTaskId,network_id:A.networkId,transport:"mcp_http",status:Q,duration_ms:Date.now()-A.startedAt,lifecycle_tracking:"tracked",...C.errorCode?{error_code:C.errorCode}:{},...C.errorMessage?{error_message:XG(C.errorMessage)}:{}});if(C.event)I.event=C.event;A.log(ZG(I))}async function RT(A,Q,B){let C=B.now??Date.now,I=B.sleep??((M)=>new Promise((V)=>setTimeout(V,M))),E=B.timeoutMs??120000,g=B.pollIntervalMs??2000,U=B.stale30Ms??30000,D=B.stale60Ms??60000,F=B.emit,Y=C()+E,J=null,N=new Set,G=!1,$=!1;while(C()<Y){J=await B.getTask(A);let M=J?.task||J,V=M?.status;if((V==="acked"||V==="running"||V==="processing")&&!N.has(V))N.add(V),F(V==="acked"?"acked":"started",A);if(V==="replied"||V==="failed"||V==="cancelled")return F(V==="replied"?"replied":"failed",A,{...V==="replied"?{}:{errorCode:`task_${V}`,event:"task.failed"}}),{kind:"terminal",status:V,latest:J,row:M};let W=C()-Q;if(!G&&W>=U&&V==="delivered")G=!0,F("delivered",A,{event:"task.warning.delivered_stale_30s"});if(!$&&W>=D&&V==="delivered")$=!0,F("delivered",A,{event:"task.warning.delivered_stale_60s"});await I(g)}return F("expired",A,{errorCode:"lifecycle_timeout"}),{kind:"expired",latest:J}}async function jT(A,Q,B){b0(Q,"sending",null);try{let C=await B({alias:A.alias,task:A.task,priority:A.priority||"normal",from_session:Q.fromAlias,parent_task_id:Q.parentTaskId||void 0}),I=VBA(C);if(!I)b0(Q,"failed",null,{errorCode:"missing_task_id",errorMessage:"CommHub response omitted task_id"});else b0(Q,"delivered",I);return C}catch(C){throw b0(Q,"failed",null,{errorCode:"send_failed",errorMessage:C}),C}}function _T(A){let Q=A||"task";if(Q==="task"||Q==="broadcast")return{deliverToRuntime:!0,replyExpected:!0};if(Q==="reply")return{deliverToRuntime:!0,replyExpected:!1};return{deliverToRuntime:!1,replyExpected:!1}}async function qT(A,Q,B){let C=await B.deliverToRuntime(A);if(Q)return{kind:"request",result:C};return await B.acknowledge(A.id),{kind:"terminal_peer_reply",result:C}}function OT(A,Q){if(A.type!=="new_reply")return!1;return Q(),!0}function bZ(){return{hubSupportsTool:null}}function WBA(A){if(!(A instanceof dB))return!1;if(A.code===-32601)return!0;let Q=String(A.message||"");return A.code===-32602&&/(?:unknown|not found|does not exist).{0,80}send_peer_reply|send_peer_reply.{0,80}(?:unknown|not found|does not exist)/i.test(Q)}function LBA(A){if(!(A instanceof dB))return!1;return A.code==="peer_reply_unsupported"||A.code==="peer_reply_origin_not_node"||A.code==="reply_task_not_owned"||A.code==="peer_reply_node_token_required"||WBA(A)}async function TT(A,Q,B=bZ()){try{let C=await Q.sendAtomic(A);return B.hubSupportsTool=!0,{route:"atomic",payload:C}}catch(C){if(!LBA(C))throw C;return{route:"legacy-reply",payload:await Q.sendLegacyReply(A)}}}import{chmodSync as ST,closeSync as yZ,existsSync as XBA,fchmodSync as ZBA,fsyncSync as wBA,openSync as PT,readFileSync as KBA,renameSync as zBA,unlinkSync as xT,writeFileSync as HBA}from"node:fs";import{randomBytes as RBA}from"node:crypto";var kT=15000,jBA=2500,yT=300000,XF=2000,_BA=new Set(["replied","failed","cancelled","expired"]);function hZ(A){if(A===void 0||A===null||String(A).trim()==="")return kT;let Q=Number(A);if(!Number.isSafeInteger(Q))return kT;return Math.min(yT,Math.max(jBA,Q))}function fZ(){return{version:3,consumed_task_ids:[],consumed_client_request_ids:[],surfaced_outbound_terminal_ids:[],outbound_deliveries:[],outbound_terminal_watermark:0,inbound_lifecycle:[],last_success_at:null}}function pC(A){if(!Array.isArray(A))return[];return[...new Set(A.filter((Q)=>typeof Q==="string"&&Q.length>0&&Q.length<=512))].slice(-XF)}function qBA(A){if(!A||typeof A!=="object")return fZ();let Q=A;return{version:3,consumed_task_ids:pC(Q.consumed_task_ids),consumed_client_request_ids:pC(Q.consumed_client_request_ids),surfaced_outbound_terminal_ids:pC(Q.surfaced_outbound_terminal_ids),outbound_deliveries:Array.isArray(Q.outbound_deliveries)?Q.outbound_deliveries.filter((B)=>!!B&&typeof B.task_id==="string"&&typeof B.idempotency_key==="string"&&["pending","delivering","delivered"].includes(B.state)).slice(-XF):pC(Q.surfaced_outbound_terminal_ids).map((B)=>({task_id:B,idempotency_key:`commhub-terminal:${B}`,state:"delivered"})),outbound_terminal_watermark:Number.isSafeInteger(Q.outbound_terminal_watermark)&&Number(Q.outbound_terminal_watermark)>=0?Number(Q.outbound_terminal_watermark):0,inbound_lifecycle:Array.isArray(Q.inbound_lifecycle)?Q.inbound_lifecycle.filter((B)=>!!B&&typeof B.task_id==="string"&&["delivered","submitted","consumed","completed"].includes(B.state)).slice(-XF):pC(Q.consumed_task_ids).map((B)=>({task_id:B,state:"consumed"})),last_success_at:typeof Q.last_success_at==="string"?Q.last_success_at:null}}function vT(A){return CT(A)}function bT(A){return typeof A.task_id==="string"&&A.task_id?A.task_id:A.id}function OBA(A){let Q=A,B=String(Q?.message??A??"");return Q?.code===-32601||Q?.code===-32602||/unknown tool|tool .+ not found|method not found|-3260[12]/i.test(B)}var TBA=new Set(["from_node_id_identity_mismatch","node_token_required"]);function SBA(A){let Q=A;return Q?.appLevel===!0&&typeof Q.code==="string"&&TBA.has(Q.code)}class fT{path;state;constructor(A){this.path=A;this.state=this.read()}snapshot(){return this.state=this.read(),this.state}update(A){this.withLock(()=>{let Q=this.read();A(Q),Q.consumed_task_ids=pC(Q.consumed_task_ids),Q.consumed_client_request_ids=pC(Q.consumed_client_request_ids),Q.surfaced_outbound_terminal_ids=pC(Q.surfaced_outbound_terminal_ids),Q.outbound_deliveries=Q.outbound_deliveries.filter((B)=>B.state!=="delivered").slice(-XF),Q.inbound_lifecycle=Q.inbound_lifecycle.slice(-XF),this.write(Q),this.state=Q})}claimOutbound(A,Q,B,C){return this.withLock(()=>{let I=this.read(),E=I.outbound_deliveries.find((g)=>g.task_id===A);if(E?.state==="delivered"||E?.state==="delivering"&&(E.lease_until??0)>B)return!1;if(E)E.state="delivering",E.lease_until=B+C;else I.outbound_deliveries.push({task_id:A,idempotency_key:Q,state:"delivering",lease_until:B+C});return this.write(I),this.state=I,!0},!1)}withLock(A,Q){let B=`${this.path}.lock`,C;try{C=PT(B,"wx",384)}catch{if(arguments.length>1)return Q;throw Error("compensation cursor is locked")}try{return A()}finally{yZ(C);try{xT(B)}catch{}}}read(){if(!XBA(this.path))return fZ();try{let A=qBA(JSON.parse(KBA(this.path,"utf8")));return ST(this.path,384),A}catch{return fZ()}}write(A){let Q=`${this.path}.tmp-${process.pid}-${RBA(6).toString("hex")}`,B=null;try{B=PT(Q,"wx",384),ZBA(B,384),HBA(B,`${JSON.stringify(A)}
|
|
243
|
-
`,"utf8"),wBA(B),yZ(B),B=null,zBA(Q,this.path),ST(this.path,384)}finally{if(B!==null)yZ(B);try{xT(Q)}catch{}}}}function hT(A){let Q=hZ(A.intervalMs),B=A.adapters,C=new fT(A.cursorPath),I="probing",E=null,g=!1,U=!1,D=null,F=0,Y=!1,J=!1,N=B.now??Date.now,G=Math.max(30000,Q*2),$=B.setTimer??((P,c)=>{let S=setTimeout(P,c);return S.unref?.(),S}),M=B.clearTimer??((P)=>clearTimeout(P)),V=(P)=>{let c=C.snapshot(),S=bT(P),x=vT(P);return c.consumed_task_ids.includes(S)||!!x&&c.consumed_client_request_ids.includes(x)},W=(P)=>{let c=bT(P),S=vT(P);C.update((x)=>{if(x.consumed_task_ids.push(c),S)x.consumed_client_request_ids.push(S);let p=x.inbound_lifecycle.find((q)=>q.task_id===c);if(p)p.state="completed";else x.inbound_lifecycle.push({task_id:c,state:"completed"})})},L={delivered:0,submitted:1,consumed:2,completed:3},X=(P,c)=>{if(!P)return;C.update((S)=>{let x=S.inbound_lifecycle.find((p)=>p.task_id===P);if(!x)S.inbound_lifecycle.push({task_id:P,state:c});else if(L[c]>L[x.state])x.state=c;if(L[c]>=L.consumed)S.consumed_task_ids.push(P)})},Z=(P)=>{if(U||I==="realtime-only")return;if(D!==null)M(D);D=$(()=>{D=null,T("timer")},P)},z=async(P)=>{try{let c=C.snapshot().outbound_terminal_watermark,[S,x]=await Promise.all([B.getInbox(),J?Promise.resolve({tasks:[],hasMore:!1}):B.listOutbound(c).catch((q)=>{if(!SBA(q))throw q;return J=!0,B.warn(`[commhub-compensation] outbound reconciliation disabled: this node's token is not bound to its node_id (${q.code}); inbox compensation continues. Re-issue a node-bound token to restore lost-reply reconciliation.`),{tasks:[],hasMore:!1}})]),p=x.tasks;if(I==="probing")I="active",B.log(`[commhub-compensation] active (${Q}ms; SSE remains primary)`);if(S.some((q)=>!V(q)))B.scheduleInboxDrain();for(let q of p){if(!q?.task_id||!_BA.has(q.status))continue;if(!Number.isSafeInteger(q.terminal_seq)||Number(q.terminal_seq)<=0)throw Object.assign(Error("Hub terminal sequence missing"),{code:-32602});let r=Number(q.terminal_seq),$Q=C.snapshot();if(r<=$Q.outbound_terminal_watermark)continue;let KA=C.snapshot().outbound_deliveries.find((gA)=>gA.task_id===q.task_id);if(KA?.state==="delivered"){C.update((gA)=>{gA.outbound_terminal_watermark=Math.max(gA.outbound_terminal_watermark,r)});continue}let yA=KA?.idempotency_key??`commhub-terminal:${q.task_id}`;if(!C.claimOutbound(q.task_id,yA,N(),G))break;try{await B.onOutboundTerminal(q,yA)}catch(gA){throw C.update((UA)=>{let DA=UA.outbound_deliveries.find((qA)=>qA.task_id===q.task_id);if(DA)DA.state="pending",DA.lease_until=0}),gA}C.update((gA)=>{let UA=gA.outbound_deliveries.find((DA)=>DA.task_id===q.task_id);if(UA)UA.state="delivered",UA.lease_until=0;gA.outbound_terminal_watermark=Math.max(gA.outbound_terminal_watermark,r)})}if(C.update((q)=>{q.last_success_at=new Date(N()).toISOString()}),x.hasMore)g=!0;F=0,B.log(`[commhub-compensation] ${P} poll ok; inbox=${S.length} outbound=${p.length}`),Z(Q)}catch(c){if(OBA(c)){if(I="realtime-only",!Y)Y=!0,B.warn("[commhub-compensation] Hub lacks durable inbox/outbox polling capability; realtime-only mode (SSE/turn-steer only)");return}F++;let S=Math.min(yT,Q*2**Math.min(F,5));B.warn(`[commhub-compensation] poll failed; retry in ${S}ms: ${c instanceof Error?c.message:String(c)}`),Z(S)}},T=(P)=>{if(U||I==="realtime-only")return;if(E){g=!0;return}E=(async()=>{let c=P;do g=!1,await z(c),c="idle";while(g&&!U&&I!=="realtime-only")})().finally(()=>{E=null})};return{get mode(){return I},get outboundDisabled(){return J},trigger:T,recordConsumed:W,recordLifecycle:X,wasConsumed:V,async idle(){await E},stop(){if(U=!0,D!==null)M(D);D=null}}}import{appendFileSync as gn,mkdirSync as jM,statSync as aXA}from"fs";var mT={name:"@sleep2agi/agent-node",version:"2.5.0-preview.109",description:"AI Agent runtime for CommHub networks. Supports Claude Code CLI, Claude Agent SDK, Codex SDK, Codex app-server, Grok Build ACP, and OpenCode CLI.",bin:{"agent-node":"dist/cli.js"},type:"module",files:["dist","README.md"],scripts:{build:"bun build src/cli.ts --outdir dist --entry-naming cli.js --target node --minify --external @anthropic-ai/claude-agent-sdk --external '@anthropic-ai/claude-agent-sdk-*' --external @openai/codex-sdk --external node-pty && bun build src/upload-file-mcp-stdio.ts --outdir dist --entry-naming upload-file-mcp-stdio.js --target node --minify",prepublishOnly:"npm run build"},keywords:["agent","ai","commhub","claude","claude-code","codex","gpt5","grok","xai","grok-build-cli","copresence","acp","sdk","minimax","mimo","runtime","node","anthropic"],author:"sleep2agi",license:"Apache-2.0",homepage:"https://anet.sh",repository:{type:"git",url:"git+https://github.com/sleep2agi/agent-network.git",directory:"agent-node"},publishConfig:{access:"public",tag:"preview"},bugs:{url:"https://github.com/sleep2agi/agent-network/issues"},engines:{node:">=18.17.0"},dependencies:{"@anthropic-ai/claude-agent-sdk":"0.3.289",undici:"^6.27.0",zod:"^4.4.3"},optionalDependencies:{"@openai/codex":"^0.133.0","@openai/codex-sdk":"^0.133.0","node-pty":"^1.1.0"}};Y$();J$();import{readFileSync as sBA}from"node:fs";var tBA=[/refresh[_ ]token[^\n]{0,40}\b(revoked|already (been )?used|invalidated|reused)\b/i,/\btoken[^\n]{0,20}\b(has been|was) revoked\b/i,/\brefresh_token_reused\b/i,/\binvalid_grant\b/i],eBA=[/\b(access[_ ])?token[^\n]{0,30}\bexpired\b/i,/\btoken_expired\b/i,/\b401\b[^\n]{0,40}\bunauthori[sz]ed\b/i,/\bunauthori[sz]ed\b[^\n]{0,40}\b401\b/i,/\bstatus(?: code)?[:= ]+401\b/i,/\bHTTP\/?\d?(?:\.\d)? 401\b/i];function uZ(A){if(!A)return null;if(tBA.some((Q)=>Q.test(A)))return"revoked";if(eBA.some((Q)=>Q.test(A)))return"expired";return null}class cZ{now;state="unknown";failedAtMs=null;constructor(A=()=>Date.now()){this.now=A}get(){return this.state}noteSuccess(){this.state="ok",this.failedAtMs=null}noteError(A){let Q=uZ(A);if(Q)this.state=Q,this.failedAtMs=this.now()}reconsiderAfterLogin(A){if(!oT(this.state)||this.failedAtMs===null||A===null)return!1;if(A<=this.failedAtMs)return!1;return this.state="unknown",this.failedAtMs=null,!0}}function oT(A){return A==="revoked"||A==="expired"}function lZ(A,Q){let B=Q?`this node's CODEX_HOME (${Q})`:"this node's CODEX_HOME",C=Q?` — log in again there: CODEX_HOME=${Q} codex login`:" — log in again for this node";return`model login ${A}: ${B} needs a fresh login${C}. Not taking work until then (do not copy another node's auth.json).`}function rT(A,Q,B,C){if(A==="idle"&&oT(B))return{status:"error",task:lZ(B,C)};return{status:A,task:Q}}function AIA(A){try{let Q=new URL(A);return(Q.protocol==="ws:"||Q.protocol==="wss:")&&["127.0.0.1","localhost","[::1]","::1"].includes(Q.hostname)}catch{return!1}}async function aT(A,Q){let B=Q.now??(()=>Date.now());if(!AIA(A))return{ok:!1,rtt_ms:null,last_error:"not a loopback ws url"};let C=Q.timeoutMs??5000,I=B();return await new Promise((E)=>{let g=!1,U,D=(Y)=>{if(g)return;g=!0,clearTimeout(F);try{U?.close()}catch{}E(Y)},F=setTimeout(()=>D({ok:!1,rtt_ms:null,last_error:`no ws handshake within ${C}ms`}),C);try{U=new Q.wsCtor(A)}catch(Y){D({ok:!1,rtt_ms:null,last_error:String(Y?.message??Y).slice(0,200)});return}U.onopen=()=>D({ok:!0,rtt_ms:Math.max(0,B()-I),last_error:null}),U.onerror=(Y)=>D({ok:!1,rtt_ms:null,last_error:String(Y?.message??Y?.error?.message??"ws error (connection refused?)").slice(0,200)}),U.onclose=(Y)=>D({ok:!1,rtt_ms:null,last_error:`closed before open (code=${Y?.code??"?"})`})})}var iZ=N$(["list-panes","-a"],["#{session_name}","#{pane_pid}","#{pane_dead}","#{pane_current_command}"]);function iE(A){let Q=[];for(let[B,C,I,E]of G$(A,4))Q.push({session:B,pid:Number(C),dead:I==="1",command:E});return Q}var QIA=/^(?:\S*\/)?sleep(?:\0|$)/;function dT(A,Q,B){if(A===null)return{ok:!1,reason:"tmux-unavailable"};let C=A.filter((g)=>g.session===Q);if(C.length===0)return{ok:!1,reason:"session-missing"};let I=C.filter((g)=>!g.dead);if(I.length===0)return{ok:!1,reason:"pane-dead"};let E=(g)=>g.command==="sleep"||QIA.test(B(g.pid)??"");if(I.every(E))return{ok:!1,reason:"sleep-placeholder"};return{ok:!0,reason:"running"}}function BIA(A){let Q;try{Q=nC(iZ,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return dT([],A,()=>null)}return dT(iE(Q),A,(B)=>{try{return sBA(`/proc/${B}/cmdline`,"latin1")}catch{return null}})}function sT(A){let Q=Number(A.ANET_CODEX_HEALTH_INTERVAL_MS);return Number.isInteger(Q)&&Q>=1000?Q:30000}function IIA(A){let Q=A?.last_error??"";if(/^restarting app-server\b/.test(Q))return"restarting";if(/auto-restart gave up/.test(Q))return"gave_up";if(/alive but not answering/.test(Q))return"hung";if(/; not restarting: /.test(Q))return"blocked";return"-"}function nT(A){return[A.app_server?.ok??"-",IIA(A.app_server),A.tui?.ok??"-",A.tui?.reason??"-",A.model_auth].join("|")}function tT(A){let Q,B,C=null,I=!1,E=null,g=()=>({bridge:"ok",...Q?{app_server:Q}:{},...B?{tui:B}:{},model_auth:A.modelAuth.get()}),U=async()=>{if(I)return g();I=!0;try{let J=A.appServerUrl();if(Q=J?await A.probeAppServer(J):void 0,Q&&A.onAppServerProbe)Q=A.onAppServerProbe(Q);if(A.tuiSession)B=(A.probeTui??BIA)(A.tuiSession);if(A.authFileMtimeMs)A.modelAuth.reconsiderAfterLogin(A.authFileMtimeMs())}catch(J){Q={ok:!1,rtt_ms:null,last_error:String(J?.message??J).slice(0,200)}}finally{I=!1}let D=g(),F=nT(D);if(E===null&&D.app_server?.ok===!1&&A.appServerWasUp?.()===!0||E!==null&&F!==E)A.onChange?.(D);return E=F,D};return{snapshot:g,tick:U,noteModelAuthMaybeChanged(){let D=g(),F=nT(D);if(E!==null&&F!==E)A.onChange?.(D);E=F},start(){if(C)return;U(),C=setInterval(()=>{U()},A.intervalMs??30000),C.unref?.()},stop(){if(C)clearInterval(C);C=null}}}var eT=(A)=>`${Math.round(A/60000)} min`;function AS(A){let Q=Math.max(1,A.maxRestarts??3),B=Math.max(1000,A.windowMs??600000),C=Math.max(1,A.failuresBeforeRestart??2),I=Math.max(1,A.hungProbesBeforeKill??4),E=A.now??(()=>Date.now()),g=A.log??(()=>{}),U=A.warn??(()=>{}),D="watching",F=[],Y=0,J=!1,N="",G=null,$=null,M=()=>F.length,V=(L,X)=>({ok:!1,rtt_ms:null,last_error:X.slice(0,200)||L.last_error}),W=(L,X=!1)=>{F.push(E()),D="restarting",N=L,g(`[app-server-watchdog] restarting app-server (attempt ${M()}/${Q} in ${eT(B)}): ${L}`),Promise.resolve().then(()=>A.restart(L,{killHung:X})).then(()=>{G=null,g(`[app-server-watchdog] app-server restarted (attempt ${M()}/${Q}); waiting for the probe to confirm`)}).catch((Z)=>{G=String(Z?.message??Z).slice(0,160),U(`[app-server-watchdog] restart attempt ${M()}/${Q} failed: ${G}`)}).finally(()=>{D="watching",Y=0,J=!1,A.onSettled?.()})};return{observe(L){if(L.ok){if(D==="gave_up")g("[app-server-watchdog] app-server is answering again (fixed by hand?) — watching again");if(D!=="restarting")D="watching";return Y=0,J=!1,$=null,L}let X=L.last_error??"unreachable";if(D==="restarting")return V(L,`restarting app-server (attempt ${M()}/${Q}): ${N}`);if(D==="gave_up")return V(L,$??X);if(Y+=1,!J&&Y<C)return L;let Z=A.canRestart?.()??null,z=!1;if(Z&&A.appServerAlive?.()){if(Y<I)return V(L,`${X}; app-server is alive but not answering (${Y}/${I} failed probes before restarting it)`);let P=A.canKillHung?A.canKillHung():"hung app-server recovery is not available here";if(P)return V(L,`${X}; app-server is alive but not answering; not killing it: ${P}`);Z=null,z=!0}if(Z)return V(L,`${X}; not restarting: ${Z}`);let T=E();if(F=F.filter((P)=>T-P<B),F.length>=Q)return D="gave_up",$=`app-server auto-restart gave up: ${F.length} restarts in ${eT(B)}${G?` (last: ${G})`:""} — restart the node by hand (anet node restart)`,U(`[app-server-watchdog] ${$}; staying degraded`),V(L,$);return W(z?`hung (alive, ${Y} failed probes); ${X}`:J?`process exited; ${X}`:X,z),V(L,`restarting app-server (attempt ${M()}/${Q}): ${N}`)},noteExit(){J=!0},state(){return{phase:D,restarts:[...F],consecutiveFailures:Y,lastRestartError:G,gaveUpReason:$}}}}function QS(A){let Q=(B,C,I)=>{let E=Number(B);return Number.isInteger(E)&&E>=C?E:I};return{maxRestarts:Q(A.ANET_CODEX_APPSERVER_RESTART_MAX,1,3),windowMs:Q(A.ANET_CODEX_APPSERVER_RESTART_WINDOW_MS,1000,600000),hungProbesBeforeKill:Q(A.ANET_CODEX_APPSERVER_HUNG_PROBES,1,4)}}function BS(A){let Q=Number(A.ANET_CODEX_APPSERVER_KILL_GRACE_MS);return A.ANET_CODEX_APPSERVER_KILL_GRACE_MS!==void 0&&Number.isInteger(Q)&&Q>=0?Q:1e4}J$();Y$();import{chmodSync as CIA,existsSync as EIA,readFileSync as $$,readlinkSync as gIA,unlinkSync as pZ,writeFileSync as UIA}from"node:fs";import{createConnection as DIA}from"node:net";import{join as FIA}from"node:path";var pE={cmdline:(A)=>{try{return $$(`/proc/${A}/cmdline`,"latin1")}catch{return null}},cwd:(A)=>{try{return gIA(`/proc/${A}/cwd`)}catch{return null}},environ:(A)=>{try{return $$(`/proc/${A}/environ`,"latin1")}catch{return null}},alive:(A)=>{try{return process.kill(A,0),!0}catch(Q){return Q?.code==="EPERM"}}};function IS(A){return`${A}-appsrv`}function y0(){try{return nC(iZ,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return null}}function wF(A){let Q;try{Q=nC(YIA,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return null}return JIA(Q,A)}var YIA=N$(["list-sessions"],["#{session_id}","#{session_name}"]);function JIA(A,Q){for(let[B,C]of G$(A,2))if(B&&C===Q)return B;return null}function dZ(A){if(A.panes===null)return{ok:!1,reason:"tmux unavailable"};let Q=iE(A.panes).filter((B)=>B.session===A.session&&!B.dead);if(Q.length===0)return{ok:!1,reason:`tmux session ${A.session} has no live pane`};for(let B of Q){let C=A.proc.cmdline(B.pid);if(!C)continue;let I=C.split("\x00").filter((D,F,Y)=>D!==""||F<Y.length-1),E=I.indexOf("--listen");if(!I.includes("app-server")||E<0||I[E+1]!==A.url)continue;let g=dC(A.proc.environ(B.pid),"ANET_NODE_MARKER");if(A.marker&&g!==A.marker)return{ok:!1,reason:`pane pid ${B.pid} carries another identity marker`};let U=A.proc.cwd(B.pid);if(!U)return{ok:!1,reason:`cannot read cwd of pid ${B.pid}`};return{ok:!0,snapshot:{session:A.session,url:A.url,argv:I,cwd:U,pid:B.pid,...A.sessionId?{sessionId:A.sessionId}:{}}}}return{ok:!1,reason:`no pane in ${A.session} runs \`app-server --listen ${A.url}\``}}function ZF(A){return`'${A.replace(/'/g,"'\\''")}'`}function NIA(A,Q,B){return[`export CODEX_HOME=${ZF(Q)}`,`. ${ZF(B)}`,`rm -f ${ZF(B)}`,`exec ${A.argv.map(ZF).join(" ")}`].join(" ; ")}function GIA(A,Q){let B=FIA(A,".anet-copresence.env");try{pZ(B)}catch(C){if(C?.code!=="ENOENT")throw C}UIA(B,`export ANET_CODEX_COMMHUB_TOKEN=${ZF(Q)}
|
|
243
|
+
`,"utf8"),wBA(B),yZ(B),B=null,zBA(Q,this.path),ST(this.path,384)}finally{if(B!==null)yZ(B);try{xT(Q)}catch{}}}}function hT(A){let Q=hZ(A.intervalMs),B=A.adapters,C=new fT(A.cursorPath),I="probing",E=null,g=!1,U=!1,D=null,F=0,Y=!1,J=!1,N=B.now??Date.now,G=Math.max(30000,Q*2),$=B.setTimer??((P,c)=>{let S=setTimeout(P,c);return S.unref?.(),S}),M=B.clearTimer??((P)=>clearTimeout(P)),V=(P)=>{let c=C.snapshot(),S=bT(P),x=vT(P);return c.consumed_task_ids.includes(S)||!!x&&c.consumed_client_request_ids.includes(x)},W=(P)=>{let c=bT(P),S=vT(P);C.update((x)=>{if(x.consumed_task_ids.push(c),S)x.consumed_client_request_ids.push(S);let p=x.inbound_lifecycle.find((q)=>q.task_id===c);if(p)p.state="completed";else x.inbound_lifecycle.push({task_id:c,state:"completed"})})},L={delivered:0,submitted:1,consumed:2,completed:3},X=(P,c)=>{if(!P)return;C.update((S)=>{let x=S.inbound_lifecycle.find((p)=>p.task_id===P);if(!x)S.inbound_lifecycle.push({task_id:P,state:c});else if(L[c]>L[x.state])x.state=c;if(L[c]>=L.consumed)S.consumed_task_ids.push(P)})},Z=(P)=>{if(U||I==="realtime-only")return;if(D!==null)M(D);D=$(()=>{D=null,T("timer")},P)},z=async(P)=>{try{let c=C.snapshot().outbound_terminal_watermark,[S,x]=await Promise.all([B.getInbox(),J?Promise.resolve({tasks:[],hasMore:!1}):B.listOutbound(c).catch((q)=>{if(!SBA(q))throw q;return J=!0,B.warn(`[commhub-compensation] outbound reconciliation disabled: this node's token is not bound to its node_id (${q.code}); inbox compensation continues. Re-issue a node-bound token to restore lost-reply reconciliation.`),{tasks:[],hasMore:!1}})]),p=x.tasks;if(I==="probing")I="active",B.log(`[commhub-compensation] active (${Q}ms; SSE remains primary)`);if(S.some((q)=>!V(q)))B.scheduleInboxDrain();for(let q of p){if(!q?.task_id||!_BA.has(q.status))continue;if(!Number.isSafeInteger(q.terminal_seq)||Number(q.terminal_seq)<=0)throw Object.assign(Error("Hub terminal sequence missing"),{code:-32602});let r=Number(q.terminal_seq),$Q=C.snapshot();if(r<=$Q.outbound_terminal_watermark)continue;let KA=C.snapshot().outbound_deliveries.find((gA)=>gA.task_id===q.task_id);if(KA?.state==="delivered"){C.update((gA)=>{gA.outbound_terminal_watermark=Math.max(gA.outbound_terminal_watermark,r)});continue}let yA=KA?.idempotency_key??`commhub-terminal:${q.task_id}`;if(!C.claimOutbound(q.task_id,yA,N(),G))break;try{await B.onOutboundTerminal(q,yA)}catch(gA){throw C.update((UA)=>{let DA=UA.outbound_deliveries.find((qA)=>qA.task_id===q.task_id);if(DA)DA.state="pending",DA.lease_until=0}),gA}C.update((gA)=>{let UA=gA.outbound_deliveries.find((DA)=>DA.task_id===q.task_id);if(UA)UA.state="delivered",UA.lease_until=0;gA.outbound_terminal_watermark=Math.max(gA.outbound_terminal_watermark,r)})}if(C.update((q)=>{q.last_success_at=new Date(N()).toISOString()}),x.hasMore)g=!0;F=0,B.log(`[commhub-compensation] ${P} poll ok; inbox=${S.length} outbound=${p.length}`),Z(Q)}catch(c){if(OBA(c)){if(I="realtime-only",!Y)Y=!0,B.warn("[commhub-compensation] Hub lacks durable inbox/outbox polling capability; realtime-only mode (SSE/turn-steer only)");return}F++;let S=Math.min(yT,Q*2**Math.min(F,5));B.warn(`[commhub-compensation] poll failed; retry in ${S}ms: ${c instanceof Error?c.message:String(c)}`),Z(S)}},T=(P)=>{if(U||I==="realtime-only")return;if(E){g=!0;return}E=(async()=>{let c=P;do g=!1,await z(c),c="idle";while(g&&!U&&I!=="realtime-only")})().finally(()=>{E=null})};return{get mode(){return I},get outboundDisabled(){return J},trigger:T,recordConsumed:W,recordLifecycle:X,wasConsumed:V,async idle(){await E},stop(){if(U=!0,D!==null)M(D);D=null}}}import{appendFileSync as gn,mkdirSync as jM,statSync as aXA}from"fs";var mT={name:"@sleep2agi/agent-node",version:"2.5.0-preview.110",description:"AI Agent runtime for CommHub networks. Supports Claude Code CLI, Claude Agent SDK, Codex SDK, Codex app-server, Grok Build ACP, and OpenCode CLI.",bin:{"agent-node":"dist/cli.js"},type:"module",files:["dist","README.md"],scripts:{build:"bun build src/cli.ts --outdir dist --entry-naming cli.js --target node --minify --external @anthropic-ai/claude-agent-sdk --external '@anthropic-ai/claude-agent-sdk-*' --external @openai/codex-sdk --external node-pty && bun build src/upload-file-mcp-stdio.ts --outdir dist --entry-naming upload-file-mcp-stdio.js --target node --minify",prepublishOnly:"npm run build"},keywords:["agent","ai","commhub","claude","claude-code","codex","gpt5","grok","xai","grok-build-cli","copresence","acp","sdk","minimax","mimo","runtime","node","anthropic"],author:"sleep2agi",license:"Apache-2.0",homepage:"https://anet.sh",repository:{type:"git",url:"git+https://github.com/sleep2agi/agent-network.git",directory:"agent-node"},publishConfig:{access:"public",tag:"preview"},bugs:{url:"https://github.com/sleep2agi/agent-network/issues"},engines:{node:">=18.17.0"},dependencies:{"@anthropic-ai/claude-agent-sdk":"0.3.289",undici:"^6.27.0",zod:"^4.4.3"},optionalDependencies:{"@openai/codex":"^0.133.0","@openai/codex-sdk":"^0.133.0","node-pty":"^1.1.0"}};Y$();J$();import{readFileSync as sBA}from"node:fs";var tBA=[/refresh[_ ]token[^\n]{0,40}\b(revoked|already (been )?used|invalidated|reused)\b/i,/\btoken[^\n]{0,20}\b(has been|was) revoked\b/i,/\brefresh_token_reused\b/i,/\binvalid_grant\b/i],eBA=[/\b(access[_ ])?token[^\n]{0,30}\bexpired\b/i,/\btoken_expired\b/i,/\b401\b[^\n]{0,40}\bunauthori[sz]ed\b/i,/\bunauthori[sz]ed\b[^\n]{0,40}\b401\b/i,/\bstatus(?: code)?[:= ]+401\b/i,/\bHTTP\/?\d?(?:\.\d)? 401\b/i];function uZ(A){if(!A)return null;if(tBA.some((Q)=>Q.test(A)))return"revoked";if(eBA.some((Q)=>Q.test(A)))return"expired";return null}class cZ{now;state="unknown";failedAtMs=null;constructor(A=()=>Date.now()){this.now=A}get(){return this.state}noteSuccess(){this.state="ok",this.failedAtMs=null}noteError(A){let Q=uZ(A);if(Q)this.state=Q,this.failedAtMs=this.now()}reconsiderAfterLogin(A){if(!oT(this.state)||this.failedAtMs===null||A===null)return!1;if(A<=this.failedAtMs)return!1;return this.state="unknown",this.failedAtMs=null,!0}}function oT(A){return A==="revoked"||A==="expired"}function lZ(A,Q){let B=Q?`this node's CODEX_HOME (${Q})`:"this node's CODEX_HOME",C=Q?` — log in again there: CODEX_HOME=${Q} codex login`:" — log in again for this node";return`model login ${A}: ${B} needs a fresh login${C}. Not taking work until then (do not copy another node's auth.json).`}function rT(A,Q,B,C){if(A==="idle"&&oT(B))return{status:"error",task:lZ(B,C)};return{status:A,task:Q}}function AIA(A){try{let Q=new URL(A);return(Q.protocol==="ws:"||Q.protocol==="wss:")&&["127.0.0.1","localhost","[::1]","::1"].includes(Q.hostname)}catch{return!1}}async function aT(A,Q){let B=Q.now??(()=>Date.now());if(!AIA(A))return{ok:!1,rtt_ms:null,last_error:"not a loopback ws url"};let C=Q.timeoutMs??5000,I=B();return await new Promise((E)=>{let g=!1,U,D=(Y)=>{if(g)return;g=!0,clearTimeout(F);try{U?.close()}catch{}E(Y)},F=setTimeout(()=>D({ok:!1,rtt_ms:null,last_error:`no ws handshake within ${C}ms`}),C);try{U=new Q.wsCtor(A)}catch(Y){D({ok:!1,rtt_ms:null,last_error:String(Y?.message??Y).slice(0,200)});return}U.onopen=()=>D({ok:!0,rtt_ms:Math.max(0,B()-I),last_error:null}),U.onerror=(Y)=>D({ok:!1,rtt_ms:null,last_error:String(Y?.message??Y?.error?.message??"ws error (connection refused?)").slice(0,200)}),U.onclose=(Y)=>D({ok:!1,rtt_ms:null,last_error:`closed before open (code=${Y?.code??"?"})`})})}var iZ=N$(["list-panes","-a"],["#{session_name}","#{pane_pid}","#{pane_dead}","#{pane_current_command}"]);function iE(A){let Q=[];for(let[B,C,I,E]of G$(A,4))Q.push({session:B,pid:Number(C),dead:I==="1",command:E});return Q}var QIA=/^(?:\S*\/)?sleep(?:\0|$)/;function dT(A,Q,B){if(A===null)return{ok:!1,reason:"tmux-unavailable"};let C=A.filter((g)=>g.session===Q);if(C.length===0)return{ok:!1,reason:"session-missing"};let I=C.filter((g)=>!g.dead);if(I.length===0)return{ok:!1,reason:"pane-dead"};let E=(g)=>g.command==="sleep"||QIA.test(B(g.pid)??"");if(I.every(E))return{ok:!1,reason:"sleep-placeholder"};return{ok:!0,reason:"running"}}function BIA(A){let Q;try{Q=nC(iZ,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return dT([],A,()=>null)}return dT(iE(Q),A,(B)=>{try{return sBA(`/proc/${B}/cmdline`,"latin1")}catch{return null}})}function sT(A){let Q=Number(A.ANET_CODEX_HEALTH_INTERVAL_MS);return Number.isInteger(Q)&&Q>=1000?Q:30000}function IIA(A){let Q=A?.last_error??"";if(/^restarting app-server\b/.test(Q))return"restarting";if(/auto-restart gave up/.test(Q))return"gave_up";if(/alive but not answering/.test(Q))return"hung";if(/; not restarting: /.test(Q))return"blocked";return"-"}function nT(A){return[A.app_server?.ok??"-",IIA(A.app_server),A.tui?.ok??"-",A.tui?.reason??"-",A.model_auth].join("|")}function tT(A){let Q,B,C=null,I=!1,E=null,g=()=>({bridge:"ok",...Q?{app_server:Q}:{},...B?{tui:B}:{},model_auth:A.modelAuth.get()}),U=async()=>{if(I)return g();I=!0;try{let J=A.appServerUrl();if(Q=J?await A.probeAppServer(J):void 0,Q&&A.onAppServerProbe)Q=A.onAppServerProbe(Q);if(A.tuiSession)B=(A.probeTui??BIA)(A.tuiSession);if(A.authFileMtimeMs)A.modelAuth.reconsiderAfterLogin(A.authFileMtimeMs())}catch(J){Q={ok:!1,rtt_ms:null,last_error:String(J?.message??J).slice(0,200)}}finally{I=!1}let D=g(),F=nT(D);if(E===null&&D.app_server?.ok===!1&&A.appServerWasUp?.()===!0||E!==null&&F!==E)A.onChange?.(D);return E=F,D};return{snapshot:g,tick:U,noteModelAuthMaybeChanged(){let D=g(),F=nT(D);if(E!==null&&F!==E)A.onChange?.(D);E=F},start(){if(C)return;U(),C=setInterval(()=>{U()},A.intervalMs??30000),C.unref?.()},stop(){if(C)clearInterval(C);C=null}}}var eT=(A)=>`${Math.round(A/60000)} min`;function AS(A){let Q=Math.max(1,A.maxRestarts??3),B=Math.max(1000,A.windowMs??600000),C=Math.max(1,A.failuresBeforeRestart??2),I=Math.max(1,A.hungProbesBeforeKill??4),E=A.now??(()=>Date.now()),g=A.log??(()=>{}),U=A.warn??(()=>{}),D="watching",F=[],Y=0,J=!1,N="",G=null,$=null,M=()=>F.length,V=(L,X)=>({ok:!1,rtt_ms:null,last_error:X.slice(0,200)||L.last_error}),W=(L,X=!1)=>{F.push(E()),D="restarting",N=L,g(`[app-server-watchdog] restarting app-server (attempt ${M()}/${Q} in ${eT(B)}): ${L}`),Promise.resolve().then(()=>A.restart(L,{killHung:X})).then(()=>{G=null,g(`[app-server-watchdog] app-server restarted (attempt ${M()}/${Q}); waiting for the probe to confirm`)}).catch((Z)=>{G=String(Z?.message??Z).slice(0,160),U(`[app-server-watchdog] restart attempt ${M()}/${Q} failed: ${G}`)}).finally(()=>{D="watching",Y=0,J=!1,A.onSettled?.()})};return{observe(L){if(L.ok){if(D==="gave_up")g("[app-server-watchdog] app-server is answering again (fixed by hand?) — watching again");if(D!=="restarting")D="watching";return Y=0,J=!1,$=null,L}let X=L.last_error??"unreachable";if(D==="restarting")return V(L,`restarting app-server (attempt ${M()}/${Q}): ${N}`);if(D==="gave_up")return V(L,$??X);if(Y+=1,!J&&Y<C)return L;let Z=A.canRestart?.()??null,z=!1;if(Z&&A.appServerAlive?.()){if(Y<I)return V(L,`${X}; app-server is alive but not answering (${Y}/${I} failed probes before restarting it)`);let P=A.canKillHung?A.canKillHung():"hung app-server recovery is not available here";if(P)return V(L,`${X}; app-server is alive but not answering; not killing it: ${P}`);Z=null,z=!0}if(Z)return V(L,`${X}; not restarting: ${Z}`);let T=E();if(F=F.filter((P)=>T-P<B),F.length>=Q)return D="gave_up",$=`app-server auto-restart gave up: ${F.length} restarts in ${eT(B)}${G?` (last: ${G})`:""} — restart the node by hand (anet node restart)`,U(`[app-server-watchdog] ${$}; staying degraded`),V(L,$);return W(z?`hung (alive, ${Y} failed probes); ${X}`:J?`process exited; ${X}`:X,z),V(L,`restarting app-server (attempt ${M()}/${Q}): ${N}`)},noteExit(){J=!0},state(){return{phase:D,restarts:[...F],consecutiveFailures:Y,lastRestartError:G,gaveUpReason:$}}}}function QS(A){let Q=(B,C,I)=>{let E=Number(B);return Number.isInteger(E)&&E>=C?E:I};return{maxRestarts:Q(A.ANET_CODEX_APPSERVER_RESTART_MAX,1,3),windowMs:Q(A.ANET_CODEX_APPSERVER_RESTART_WINDOW_MS,1000,600000),hungProbesBeforeKill:Q(A.ANET_CODEX_APPSERVER_HUNG_PROBES,1,4)}}function BS(A){let Q=Number(A.ANET_CODEX_APPSERVER_KILL_GRACE_MS);return A.ANET_CODEX_APPSERVER_KILL_GRACE_MS!==void 0&&Number.isInteger(Q)&&Q>=0?Q:1e4}J$();Y$();import{chmodSync as CIA,existsSync as EIA,readFileSync as $$,readlinkSync as gIA,unlinkSync as pZ,writeFileSync as UIA}from"node:fs";import{createConnection as DIA}from"node:net";import{join as FIA}from"node:path";var pE={cmdline:(A)=>{try{return $$(`/proc/${A}/cmdline`,"latin1")}catch{return null}},cwd:(A)=>{try{return gIA(`/proc/${A}/cwd`)}catch{return null}},environ:(A)=>{try{return $$(`/proc/${A}/environ`,"latin1")}catch{return null}},alive:(A)=>{try{return process.kill(A,0),!0}catch(Q){return Q?.code==="EPERM"}}};function IS(A){return`${A}-appsrv`}function y0(){try{return nC(iZ,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return null}}function wF(A){let Q;try{Q=nC(YIA,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5000})}catch{return null}return JIA(Q,A)}var YIA=N$(["list-sessions"],["#{session_id}","#{session_name}"]);function JIA(A,Q){for(let[B,C]of G$(A,2))if(B&&C===Q)return B;return null}function dZ(A){if(A.panes===null)return{ok:!1,reason:"tmux unavailable"};let Q=iE(A.panes).filter((B)=>B.session===A.session&&!B.dead);if(Q.length===0)return{ok:!1,reason:`tmux session ${A.session} has no live pane`};for(let B of Q){let C=A.proc.cmdline(B.pid);if(!C)continue;let I=C.split("\x00").filter((D,F,Y)=>D!==""||F<Y.length-1),E=I.indexOf("--listen");if(!I.includes("app-server")||E<0||I[E+1]!==A.url)continue;let g=dC(A.proc.environ(B.pid),"ANET_NODE_MARKER");if(A.marker&&g!==A.marker)return{ok:!1,reason:`pane pid ${B.pid} carries another identity marker`};let U=A.proc.cwd(B.pid);if(!U)return{ok:!1,reason:`cannot read cwd of pid ${B.pid}`};return{ok:!0,snapshot:{session:A.session,url:A.url,argv:I,cwd:U,pid:B.pid,...A.sessionId?{sessionId:A.sessionId}:{}}}}return{ok:!1,reason:`no pane in ${A.session} runs \`app-server --listen ${A.url}\``}}function ZF(A){return`'${A.replace(/'/g,"'\\''")}'`}function NIA(A,Q,B){return[`export CODEX_HOME=${ZF(Q)}`,`. ${ZF(B)}`,`rm -f ${ZF(B)}`,`exec ${A.argv.map(ZF).join(" ")}`].join(" ; ")}function GIA(A,Q){let B=FIA(A,".anet-copresence.env");try{pZ(B)}catch(C){if(C?.code!=="ENOENT")throw C}UIA(B,`export ANET_CODEX_COMMHUB_TOKEN=${ZF(Q)}
|
|
244
244
|
`,{mode:384,flag:"wx"});try{CIA(B,384)}catch{}return B}async function $IA(A,Q){let B=new URL(A),C=Date.now()+Q;while(Date.now()<C){if(await new Promise((E)=>{let g=DIA({host:B.hostname.replace(/^\[|\]$/g,""),port:Number(B.port)});g.once("connect",()=>{g.destroy(),E(!0)}),g.once("error",()=>E(!1)),setTimeout(()=>{g.destroy(),E(!1)},1000).unref?.()}))return!0;await new Promise((E)=>setTimeout(E,200))}return!1}function nZ(A,Q){if(!A)return"no launch snapshot (this bridge never saw the app-server alive)";if(!Q.token.startsWith("ntok_"))return"node token is not an ntok_; cannot hand the app-server its CommHub MCP token";if(oZ(A,Q))return`app-server process ${A.pid} is still alive but not answering; not killing a live process`;let B=Q.panes();if(B!==null&&iE(B).some((C)=>C.session===A.session&&!C.dead))return`tmux session ${A.session} still has a live pane; not replacing it`;return null}function oZ(A,Q){if(!Q.proc.alive(A.pid))return!1;let B=dC(Q.proc.environ(A.pid),"ANET_NODE_MARKER");return!Q.marker||B===Q.marker}var MIA=(A,Q)=>A.replace(/\/+$/,"")===Q.replace(/\/+$/,"");function rZ(A,Q){if(!A)return"no launch snapshot";if(!Q.marker)return"this node has no identity marker (ANET_NODE_MARKER); cannot prove the process is ours";if(!A.sessionId)return"launch snapshot has no tmux session id";let B=Q.sessionId(A.session);if(B!==A.sessionId)return`tmux session ${A.session} is not the one this node started (id ${B??"none"}, expected ${A.sessionId})`;let C=Q.panes();if(C===null)return"tmux unavailable";if(!iE(C).some((F)=>F.session===A.session&&!F.dead&&F.pid===A.pid))return`pid ${A.pid} is no longer the live pane of ${A.session}`;let I=Q.proc.cmdline(A.pid),E=I?I.split("\x00"):[],g=E.indexOf("--listen");if(!E.includes("app-server")||g<0||E[g+1]!==A.url)return`pid ${A.pid} is not \`app-server --listen ${A.url}\``;let U=Q.proc.environ(A.pid);if(U===null)return`cannot read the environment of pid ${A.pid}`;if(dC(U,"ANET_NODE_MARKER")!==Q.marker)return`pid ${A.pid} carries another identity marker`;let D=dC(U,"CODEX_HOME");if(!D||!MIA(D,Q.codexHome))return`pid ${A.pid} runs with another CODEX_HOME`;return null}async function CS(A,Q){let B=rZ(A,Q);if(B)throw Error(`not killing the hung app-server: ${B}`);let C=Q.log??(()=>{}),I=A.pid,E=Q.pgid(I)===I?-I:I,g=()=>{try{return Q.signal(E,0),!1}catch{return!0}};C(`[app-server-watchdog] app-server pid ${I} is alive but not answering; SIGTERM ${E<0?`process group ${I}`:`pid ${I}`} (grace ${Math.round(Q.graceMs/1000)}s)`),Q.signal(E,"SIGTERM");let U="SIGTERM";for(let D=0;!g()&&D<Q.graceMs;D+=200)await Q.sleep(200);if(!g()){if(Q.proc.alive(I)&&dC(Q.proc.environ(I),"ANET_NODE_MARKER")!==Q.marker)throw Error(`pid ${I} changed identity during the grace period; not sending SIGKILL`);C(`[app-server-watchdog] app-server pid ${I} still alive after ${Math.round(Q.graceMs/1000)}s; SIGKILL`),Q.signal(E,"SIGKILL"),U="SIGKILL";for(let D=0;!g()&&D<5000;D+=200)await Q.sleep(200);if(!g())throw Error(`hung app-server pid ${I} survived SIGKILL`)}for(let D=0;D<5000;D+=200){let F=Q.panes();if(F===null||!iE(F).some((Y)=>Y.session===A.session&&!Y.dead))break;await Q.sleep(200)}return U}function VIA(A){try{let Q=$$(`/proc/${A}/stat`,"latin1"),B=Q.slice(Q.lastIndexOf(")")+2).split(" "),C=Number(B[2]);return Number.isInteger(C)&&C>0?C:null}catch{return null}}function ES(A){return{marker:A.marker,codexHome:A.codexHome,panes:y0,proc:pE,sessionId:wF,pgid:VIA,signal:(Q,B)=>{process.kill(Q,B)},sleep:(Q)=>new Promise((B)=>setTimeout(B,Q)),graceMs:A.graceMs,log:A.log}}async function gS(A,Q){let B=Q.log??(()=>{}),C=nZ(A,Q);if(C)throw Error(C);let I=Q.panes();if(I!==null&&iE(I).some((Y)=>Y.session===A.session)){let Y=Q.sessionId(A.session);if(Y)try{Q.tmux(["kill-session","-t",Y])}catch{}}let E=Q.writeTokenFile(Q.codexHome,Q.token),g=NIA(A,Q.codexHome,E);try{Q.tmux(["new-session","-d","-s",A.session,"-c",A.cwd,...Q.marker?["-e",`ANET_NODE_MARKER=${Q.marker}`]:[],"-e",`CODEX_HOME=${Q.codexHome}`,"bash","-lc",g])}catch(Y){try{pZ(E)}catch{}throw Error(`tmux new-session ${A.session} failed: ${String(Y?.message??Y).slice(0,120)}`)}B(`[app-server-watchdog] relaunched tmux=${A.session} listening ${A.url}`);let U=await Q.waitPort(A.url,Q.bindTimeoutMs??25000);if(EIA(E))try{pZ(E)}catch{}if(!U)throw Error(`relaunched app-server did not bind ${A.url} within ${Math.round((Q.bindTimeoutMs??25000)/1000)}s`);let D=dZ({session:A.session,url:A.url,marker:Q.marker,panes:Q.panes(),proc:Q.proc,sessionId:Q.sessionId(A.session)});if(!D.ok)throw Error(`relaunched app-server not found: ${D.reason}`);let F=Q.verifyHome(D.snapshot.pid,Q.codexHome);if(!F.ok){let Y=Q.sessionId(A.session);if(Y)try{Q.tmux(["kill-session","-t",Y])}catch{}throw Error(`refusing the relaunched app-server: ${F.message} (#448 fail-closed)`)}if(F.skipped)B(`[app-server-watchdog] CODEX_HOME check skipped: ${F.skipped}`);return D.snapshot}function US(A){return{codexHome:A.codexHome,marker:A.marker,token:A.token,panes:y0,proc:pE,tmux:(Q)=>{nC(Q,{stdio:"pipe",timeout:1e4})},sessionId:wF,waitPort:$IA,writeTokenFile:GIA,verifyHome:(Q,B)=>F$({rootPid:Q,expected:B,label:"relaunched app-server",reader:A.procReader}),log:A.log}}function DS(A,Q){if(!Q)return!0;try{return JSON.parse($$(A,"utf8"))?.marker===Q}catch{return!1}}var __dirname="/home/runner/work/agent-network/agent-network/agent-node/src";function nd(){let A=IV(import.meta.url,process.argv[1]);return A?A.replace(/\/+$/,"")+"/dist":__dirname}var PXA={};function xXA(){let A=GO({role:j?.role,probe:()=>(jF(),cM(Z$)).probeAnetBinReadiness(),now:()=>Date.now(),log:w,logState:PXA});if(!A)return A;return{...A,defaultWorkdirRoot:zO(j,{home:ZO()})}}var pQ=wH(),kXA=bZ(),od=process.env.ANET_OPENCODE_BIN,pI=process.env.ANET_OPENCODE_VERSION,rd=process.env.PATH||"",Xd=process.env.ANET_OPENCODE_SAFE_BASE,EB=process.argv.slice(2),wA={},ad=[];if(EB.length===1&&EB[0]==="--print-entrypoint")console.log(TXA(process.argv[1])),process.exit(0);var sd="2.1.0";try{let A=new URL(".",import.meta.url).pathname;for(let Q of["../package.json","../../package.json"])try{let B=JSON.parse(eB(IA(A,Q),"utf-8"));if(B.version){sd=B.version;break}}catch{}}catch{}for(let A=0;A<EB.length;A++){if(EB[A]==="--version"||EB[A]==="-v")console.log(`agent-node v${sd}`),process.exit(0);if(EB[A]==="-h"||EB[A]==="--help")console.log(`
|
|
245
245
|
@sleep2agi/agent-node — AI Agent 节点,一行命令加入 CommHub 网络
|
|
246
246
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleep2agi/agent-node",
|
|
3
|
-
"version": "2.5.0-preview.
|
|
3
|
+
"version": "2.5.0-preview.110",
|
|
4
4
|
"description": "AI Agent runtime for CommHub networks. Supports Claude Code CLI, Claude Agent SDK, Codex SDK, Codex app-server, Grok Build ACP, and OpenCode CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-node": "dist/cli.js"
|