@sleep2agi/agent-node 2.4.11-preview.0 → 2.4.11

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.
Files changed (2) hide show
  1. package/dist/cli.js +10 -10
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -76,7 +76,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
76
76
  `),L1(v,this.filePath)}}function oU(r){let i=new Date;return{goal_id:uU(),text:r.text,status:"active",interval_ms:r.interval_ms,next_wake_at:new Date(i.getTime()+r.interval_ms).toISOString(),parent_task_id:r.parent_task_id,report_to:r.report_to,runtime:r.runtime,created_at:i.toISOString(),updated_at:i.toISOString(),progress_log:[]}}var A1=new Set(["你","我","他","她","它","对方","大家","我们","你们","他们"]);function E1(r){return r.trim().replace(/^[@@]+/,"").replace(/^[「『“"'【\[]+|[」』”"'】\]]+$/g,"").replace(/[::,,。.!?!?]+$/g,"").trim()}function bU(r){let i=r.trim();if(!i)return null;if(!/\b(?:mcp_commhub__send_task|commhub_send_task|send_task)\b|发任务|派任务|派给|转给|交给|发给|沟通一下|让|请|麻烦|和|你去给|给\s+\S+\s+(?:发|说|沟通|打)/.test(i))return null;let v=[/\b(?:mcp_commhub__send_task|commhub_send_task|send_task)\s*\(\s*alias\s*=\s*["']([^"']+)["']\s*,\s*task\s*=\s*["']([\s\S]+?)["']\s*\)/i,/\b(?:mcp_commhub__send_task|commhub_send_task|send_task)\s*\(\s*["']([^"']+)["']\s*,\s*["']([\s\S]+?)["']\s*\)/i,/^send_task\s+(\S+)\s+([\s\S]+)$/i,/给\s+(.+?)\s*(?:发任务|派任务|send_task)(?:\s*[::]\s*([\s\S]+))?$/i,/给\s+[「『"'’“@@]?(\S+?)[」』"'’“]?\s+(?:发(?:个?消息|个)?|说(?:一下)?|沟通(?:一下)?|打(?:个?招呼)?)\s+([\s\S]+)$/i,/(?:派给|转给|交给|发给)\s+(.+?)\s*[::,,]\s*([\s\S]+)$/i,/你去给\s+[「『"'’“@@]?(\S+?)[」』"'’“]?\s+([\s\S]+)$/i,/(?:你\s*)?和\s*(@?[^\s,,::。.!?!?]+)\s*(?:沟通一下|send_task(?:\s*一下)?)(?:\s*(?:[,,::]\s*)?([\s\S]+))?$/i,/(?:你\s*)?和\s*(@?[\s\S]+?)\s*沟通一下\s*[,,]\s*([\s\S]+)$/i,/(?:让|请|麻烦)\s+(@?[^\s,,::。.!?!?]+)\s+([\s\S]+)$/i],u="",n="";for(let $ of v){let t=i.match($);if(!t?.[1])continue;u=E1(t[1]),n=t[2]?.trim()||"";break}if(!u||A1.has(u))return null;if(!n){let $=i.match(/(?:发任务|派任务|send_task)\s*[::]\s*([\s\S]+)$/i);if($?.[1])n=$[1].trim();else n=i.match(/(?:让|请)\s*(?:他|她|它|对方|该节点)?\s*([\s\S]+?)(?:。|$)/)?.[1]?.trim()||i}if(n=n.replace(/必须.*?(?:总结回|回复)\s*(?:admin|我).*$/i,"").replace(/并?用\s*commhub_get_task[\s\S]*$/i,"").replace(/^[::,,\s]+/,"").trim(),!n)n=i;return{alias:u,childTask:n}}import{existsSync as M1,readFileSync as Z1,writeFileSync as x1}from"fs";class Xr extends Error{code;payload;appLevel;constructor(r,i={}){super(r);this.name="CommHubError",this.code=i.code,this.payload=i.payload,this.appLevel=i.appLevel??!1}}function gU(r){if(r?.error){let u=`${r.error.code??"?"}: ${r.error.message??"no message"}`;return{kind:"retryable",error:new Xr(`JSON-RPC error: ${u}`,{code:r.error.code,payload:r.error})}}if(r?.result?.isError===!0){let u=r?.result?.content?.[0]?.text||"tool returned isError";return{kind:"retryable",error:new Xr(`tool isError: ${u.slice(0,200)}`,{payload:r.result})}}let i=r?.result?.content?.[0]?.text,v;if(typeof i==="string")try{v=JSON.parse(i)}catch{return{kind:"ok",payload:i}}else v=r;if(v&&typeof v==="object"&&v.ok===!1){let u=v.error||v.message||"no detail";return{kind:"appLevel",error:new Xr(`app-level rejection: ${u}`,{code:v.error,payload:v,appLevel:!0})}}return{kind:"ok",payload:v}}function UU(r){let i=1083885398,v=-537806866;for(let u=0;u<r.length;u++){let n=r.charCodeAt(u);i=Math.imul(i^n,2654435761),v=Math.imul(v^n,1597334677)}return i=Math.imul(i^i>>>16,2246822507)^Math.imul(v^v>>>13,3266489909),v=Math.imul(v^v>>>16,2246822507)^Math.imul(i^i>>>13,3266489909),(4294967296*(2097151&v)+(i>>>0)).toString(16).padStart(16,"0").repeat(2).slice(0,32)}class Kb{filePath;constructor(r){this.filePath=r}load(){try{if(!M1(this.filePath))return[];let r=Z1(this.filePath,"utf8"),i=JSON.parse(r);return Array.isArray(i)?i:[]}catch{return[]}}save(r){x1(this.filePath,JSON.stringify(r,null,2))}persist(r){let i=this.load(),v=this.findIndex(i,r.to,r.taskId,r.text);if(v>=0)i[v]={...i[v],...r,attempts:i[v].attempts};else i.push({...r,attempts:0});this.save(i)}clear(r,i){if(!i)return;let v=this.load(),u=`${r}|task:${i}`,n=v.filter(($)=>cU($)!==u);if(n.length!==v.length)this.save(n)}async drain(r){let i=this.load(),v=0,u=0,n=[];for(let $ of i)try{await r($),v++}catch(t){if(t instanceof Xr&&t.appLevel){u++;continue}n.push({...$,attempts:$.attempts+1,lastTryAt:Date.now(),lastError:t?.message??String(t)})}if(i.length>0)this.save(n);return{delivered:v,dropped:u,requeued:n.length}}findIndex(r,i,v,u){let n=v?`${i}|task:${v}`:`${i}|sha:${UU(u??"")}`;return r.findIndex(($)=>cU($)===n)}}function cU(r){return r.taskId?`${r.to}|task:${r.taskId}`:`${r.to}|sha:${UU(r.text)}`}function k$(r){let i=IU(r.envValue);if(i!==null)return{valueMs:i,source:"env",rawValue:String(r.envValue)};let v=IU(r.flagValue);if(v!==null)return{valueMs:v,source:"flags",rawValue:String(r.flagValue)};return{valueMs:r.defaultMs,source:"default"}}function IU(r){if(r===void 0||r===null)return null;if(typeof r==="number")return Number.isFinite(r)&&r>0?r:null;if(typeof r==="string"){if(r.trim()==="")return null;let i=Number(r);return Number.isFinite(i)&&i>0?i:null}return null}import{dirname as T1}from"path";var Hn="@openai/codex-sdk",DU="@openai/codex",w$="^0.133.0";async function kU(r,i){try{return{module:await r.importCodexSdk(),source:"already-installed"}}catch(v){r.log?.(`[codex] ${Hn} not resolved — auto-installing to ${i} ...`);try{await r.npmInstall(i,[`${Hn}@${w$}`,`${DU}@${w$}`])}catch(u){throw _U({agentNodeDir:i,initialReason:z$(v),installReason:z$(u)})}try{let u=await r.importCodexSdk();return r.log?.(`[codex] ${Hn} installed and loaded`),{module:u,source:"auto-installed"}}catch(u){throw _U({agentNodeDir:i,initialReason:z$(v),installReason:`install succeeded but ${Hn} still does not resolve: ${z$(u)}`})}}}function zU(r){return T1(r)}function _U(r){let i=[`${Hn} not available and the auto-install attempt failed.`,"","Recovery — install both packages into agent-node's own node_modules:","",` npm install --prefix ${wU(r.agentNodeDir)} \\`,` ${Hn}@${w$} \\`,` ${DU}@${w$}`,"","Then restart this node.","","Underlying reasons:",` - initial import: ${r.initialReason}`,` - auto-install: ${r.installReason}`],v=Error(i.join(`
77
77
  `));return v.name="CodexSdkUnavailable",v}function z$(r){if(!r)return"unknown";if(r instanceof Error)return r.message||r.name||"unknown Error";if(typeof r==="string")return r;try{return JSON.stringify(r).slice(0,240)}catch{return String(r)}}function wU(r){return/[^A-Za-z0-9_\-./@~]/.test(r)?`'${r.replace(/'/g,"'\\''")}'`:r}function jU(r){return async(i,v)=>{let u=`npm install --no-save --prefix ${wU(i)} ${v.join(" ")}`;r(u,{stdio:"pipe",timeout:90000})}}async function JU(r,i,v={}){let u=Math.max(1,Math.min(100,v.limit??100)),n=Math.max(1,Math.min(50,v.topN??10));try{let t=v.serverSupportsFromNodeId===!0&&!!r.nodeId?{from_node_id:r.nodeId,limit:u}:{from_name:r.alias,limit:u},o=await i(t),c=Array.isArray(o?.tasks)?o.tasks:[],b=(g)=>{let I=typeof g.from_node_id==="string"?g.from_node_id:"",_=typeof g.from_name==="string"?g.from_name:"";if(I&&r.nodeId)return I===r.nodeId;if(_)return _===r.alias;return!1};return c.filter((g)=>!!g&&typeof g.task_id==="string"&&typeof g.to_name==="string"&&(g.status==="delivered"||g.status==="started")).filter(b).slice(0,n)}catch{return[]}}function NU(r){if(!r.length)return null;return["【⚠ 节点 resume 提醒 — 你停机前已派出但仍在等回复的任务】","",r.map((v,u)=>{let n=String(v.task_id||"?").slice(0,8),$=String(v.to_name||"?"),t=v.created_at?`, sent ${v.created_at}`:"",o=R1(v.content);return` ${u+1}. → ${$} [task ${n}${t}]: ${o}`}).join(`
78
78
  `),"","重要约束 (do NOT re-dispatch):","- 上面这些任务 **已经发出去过**, 对方尚未回复。**不要再次** 用 commhub_send_task 发同样内容。",'- 如果需要跟进进度, 用 commhub_send_message(alias=对方, message="任务 <task_id> 进度?") 发一条**轻问询**, **不是** send_task。',"- server 端有自动去重护栏会拒绝重复 send_task, 但请不要靠它兜底 — 直接按上面规则处理。",'- 如果用户现在派的新任务跟上面某条**实质相同**, 直接告诉用户 "task <id> 已派给 <对方>, 仍在等回复, 不重新派", 不要 send_task。'].join(`
79
- `)}function R1(r){let i=String(r??"").replace(/```/g,"ʼʼʼ").replace(/\s+/g," ").trim(),v=120;return i.length>120?i.slice(0,117)+"...":i||"(empty content)"}class Bb{opts;cachedAlias;cachedAt;fetchInFlight=null;cacheTtlMs;constructor(r){this.opts=r;this.cachedAlias=r.initialAlias,this.cachedAt=0,this.cacheTtlMs=r.cacheTtlMs??30000}current(){return this.cachedAlias}async refresh(r=Date.now()){if(!this.opts.nodeId)return this.cachedAlias;if(this.cacheTtlMs>0&&this.cachedAt>0&&r-this.cachedAt<this.cacheTtlMs)return this.cachedAlias;if(this.fetchInFlight)return this.fetchInFlight;let i=(async()=>{try{let v=await this.opts.fetchCanonicalAlias(this.opts.nodeId);if(v&&v.length>0&&v!==this.cachedAlias)this.opts.onDrift?.(this.cachedAlias,v,"fetch"),this.cachedAlias=v}catch(v){this.opts.warn?.(`currentAlias: fetch failed (${v?.message??v}); keeping cached value "${this.cachedAlias}"`)}finally{this.cachedAt=r,this.fetchInFlight=null}return this.cachedAlias})();return this.fetchInFlight=i,i}set(r,i=Date.now()){if(!r)return;if(r!==this.cachedAlias)this.opts.onDrift?.(this.cachedAlias,r,"snapshot"),this.cachedAlias=r;this.cachedAt=i}get nodeId(){return this.opts.nodeId}ageMs(r=Date.now()){return this.cachedAt===0?Number.POSITIVE_INFINITY:r-this.cachedAt}isFresh(r=Date.now()){return this.cachedAt!==0&&r-this.cachedAt<this.cacheTtlMs}}function WU(r,i,v){if(!Array.isArray(r))return{exists:!1,reason:"no_sessions_field"};if(r.length===0)return{exists:!1,reason:"empty_sessions"};let u=(i??"").trim(),n=(v??"").trim();if(!u)return{exists:!1,reason:"not_in_sessions"};let $=!1;for(let t of r){let o=typeof t?.alias==="string"?t.alias.trim():"";if(!o)continue;if(o===u){if(o===n){$=!0;continue}return{exists:!0,source:"session"}}}return{exists:!1,reason:$?"self_only":"not_in_sessions"}}import{mkdirSync as $I,appendFileSync as Lk}from"fs";var __dirname="/tmp/p20-2411/agent-node/src";var pU=zk(),cr=process.argv.slice(2),A={},aU=[],sU="2.1.0";try{let r=new URL(".",import.meta.url).pathname;for(let i of["../package.json","../../package.json"])try{let v=JSON.parse(rn(f(r,i),"utf-8"));if(v.version){sU=v.version;break}}catch{}}catch{}for(let r=0;r<cr.length;r++){if(cr[r]==="--version"||cr[r]==="-v")console.log(`agent-node v${sU}`),process.exit(0);if(cr[r]==="-h"||cr[r]==="--help")console.log(`
79
+ `)}function R1(r){let i=String(r??"").replace(/```/g,"ʼʼʼ").replace(/\s+/g," ").trim(),v=120;return i.length>120?i.slice(0,117)+"...":i||"(empty content)"}class Bb{opts;cachedAlias;cachedAt;fetchInFlight=null;cacheTtlMs;constructor(r){this.opts=r;this.cachedAlias=r.initialAlias,this.cachedAt=0,this.cacheTtlMs=r.cacheTtlMs??30000}current(){return this.cachedAlias}async refresh(r=Date.now()){if(!this.opts.nodeId)return this.cachedAlias;if(this.cacheTtlMs>0&&this.cachedAt>0&&r-this.cachedAt<this.cacheTtlMs)return this.cachedAlias;if(this.fetchInFlight)return this.fetchInFlight;let i=(async()=>{try{let v=await this.opts.fetchCanonicalAlias(this.opts.nodeId);if(v&&v.length>0&&v!==this.cachedAlias)this.opts.onDrift?.(this.cachedAlias,v,"fetch"),this.cachedAlias=v}catch(v){this.opts.warn?.(`currentAlias: fetch failed (${v?.message??v}); keeping cached value "${this.cachedAlias}"`)}finally{this.cachedAt=r,this.fetchInFlight=null}return this.cachedAlias})();return this.fetchInFlight=i,i}set(r,i=Date.now()){if(!r)return;if(r!==this.cachedAlias)this.opts.onDrift?.(this.cachedAlias,r,"snapshot"),this.cachedAlias=r;this.cachedAt=i}get nodeId(){return this.opts.nodeId}ageMs(r=Date.now()){return this.cachedAt===0?Number.POSITIVE_INFINITY:r-this.cachedAt}isFresh(r=Date.now()){return this.cachedAt!==0&&r-this.cachedAt<this.cacheTtlMs}}function WU(r,i,v){if(!Array.isArray(r))return{exists:!1,reason:"no_sessions_field"};if(r.length===0)return{exists:!1,reason:"empty_sessions"};let u=(i??"").trim(),n=(v??"").trim();if(!u)return{exists:!1,reason:"not_in_sessions"};let $=!1;for(let t of r){let o=typeof t?.alias==="string"?t.alias.trim():"";if(!o)continue;if(o===u){if(o===n){$=!0;continue}return{exists:!0,source:"session"}}}return{exists:!1,reason:$?"self_only":"not_in_sessions"}}import{mkdirSync as $I,appendFileSync as Lk}from"fs";var __dirname="/tmp/p35-promote/agent-node/src";var pU=zk(),cr=process.argv.slice(2),A={},aU=[],sU="2.1.0";try{let r=new URL(".",import.meta.url).pathname;for(let i of["../package.json","../../package.json"])try{let v=JSON.parse(rn(f(r,i),"utf-8"));if(v.version){sU=v.version;break}}catch{}}catch{}for(let r=0;r<cr.length;r++){if(cr[r]==="--version"||cr[r]==="-v")console.log(`agent-node v${sU}`),process.exit(0);if(cr[r]==="-h"||cr[r]==="--help")console.log(`
80
80
  @sleep2agi/agent-node — AI Agent 节点,一行命令加入 CommHub 网络
81
81
 
82
82
  用法:
@@ -129,18 +129,18 @@ ${o}
129
129
  ${r}`:c,g=process.env.COMMHUB_URL||Nr,I=process.env.COMMHUB_TOKEN||ur,_={};if(g)try{_.commhub=await sg(g,I,nn)}catch(l){V(`[claude] ⚠ commhub SDK MCP server init failed (${l?.message||l}); falling back to type:"http" (known-broken, see #102 smoke).`),_.commhub={type:"http",url:`${g}/mcp`,headers:I?{Authorization:`Bearer ${I}`}:void 0}}let k=(()=>{try{let{execSync:l}=h("child_process"),gr=h("fs");try{let nr=h.resolve("@anthropic-ai/claude-agent-sdk-linux-x64/claude");if(gr.existsSync(nr))return l(`${nr} --version`,{stdio:"pipe"}),V(`[claude] using glibc binary: ${nr}`),nr}catch{}try{let nr=l("which claude",{encoding:"utf-8"}).trim();if(nr)return V(`[claude] using global binary: ${nr}`),nr}catch{}V("[claude] no binary resolved, falling back to SDK default");return}catch{return}})(),N={model:Yr||void 0,tools:pr,maxTurns:Wk,permissionMode:"bypassPermissions",allowDangerouslySkipPermissions:!0,settingSources:[],mcpServers:Object.keys(_).length?_:void 0,pathToClaudeCodeExecutable:k,env:process.env,cwd:process.cwd(),stderr:(l)=>{if(l.trim())V(`[stderr] ${l.trim().slice(0,300)}`)},hooks:{PreToolUse:[{hooks:[async(l)=>{return V(`[tool] ${l.tool_name}(${JSON.stringify(l.tool_input).slice(0,80)})`),{continue:!0}}]}]}};if(MU>0)N.maxBudgetUsd=MU;let T=(/intern-ai\.org\.cn|chat\.intern-ai/i.test(process.env.ANTHROPIC_BASE_URL||"")?`When a tool is available and applicable to the user request, you MUST respond by emitting a tool_use content block, not by writing text that describes the tool call. Do not show a verbose thinking process. Do not embed tool-call JSON inside text. Use the tool_use content channel directly. If no tool fits, respond normally with text.
130
130
 
131
131
  `:"")+(N$||"");if(T)N.systemPrompt=T;if(W$)N.resume=W$;let R="",e=Date.now();V(`[claude] claudePath=${k||"SDK default"}, mcpServers=${Object.keys(_).join(",")||"none"}`);let E=(l)=>{if(!l)return!1;return/(401|403)\b|invalid[_\s]?api[_\s]?key|authentication[_\s]?error|expired[_\s]?token|unauthor(iz|is)ed|A02\d{2}|user[_\s]?token[_\s]?expired/i.test(l)},C=(l)=>{let gr=(process.env.ANTHROPIC_BASE_URL||"").toLowerCase();if(gr.includes("intern-ai.org.cn"))return"→ Refresh INTERN_S1_API_KEY at https://chat.intern-ai.org.cn and re-export it";if(gr.includes("minimax"))return"→ Refresh MiniMax API key at https://platform.minimaxi.com";if(gr.includes("anthropic"))return"→ Refresh ANTHROPIC_AUTH_TOKEN at https://console.anthropic.com/settings/keys";return"→ Refresh your vendor API key and re-export the ENV var"},Qr="",Zn=!1;for(let l=0;l<=Fn;l++){let gr=!1,nr,eb=new AbortController;if(N.abortController=eb,Fb>0)nr=setTimeout(()=>{gr=!0,eb.abort()},Fb);let wI=Date.now();try{R="";for await(let Li of n({prompt:b,options:N})){let Z=Li;if(Z.type==="system"&&Z.subtype==="init")W$=Z.session_id,V(`[claude] session=${Z.session_id?.slice(0,8)} model=${Yr||"default"} attempt=${l+1}`),mb(Z.session_id);if(Z.type==="result"){let Q$=Date.now()-e,xn=Z.usage||{};V(`[claude] ${Z.subtype} | ${Q$}ms | $${Z.total_cost_usd?.toFixed(4)||"?"} | in=${xn.input_tokens||0} out=${xn.output_tokens||0} | turns=${Z.num_turns}${l>0?` | attempt=${l+1}`:""}`),R=Z.subtype==="success"?Z.result||"任务完成":`执行出错: ${Z.error||Z.result||"未知错误"}`}}if(nr)clearTimeout(nr);return R}catch(Li){if(nr)clearTimeout(nr);let Z=String(Li?.message||Li).slice(0,300),Q$=Date.now()-wI;if(E(Z))return V(`[claude] ✗ FATAL: vendor API auth failed (${Z.slice(0,150)})`),V(`[anet] FATAL: Vendor API auth failed — ${Z.slice(0,100)}`),V(`[anet] ${C(Z)}`),`执行出错: vendor API auth failed (${Z.slice(0,80)}) — refresh API key and re-export ENV var; see agent-node log for vendor-specific URL`;Qr=Z,Zn=gr;let xn=gr?`timed out after ${Q$}ms`:`errored: ${Z.slice(0,100)}`;if(l<Fn){let yb=4000*Math.pow(2,l)+Math.floor(Math.random()*1000);V(`[claude] attempt ${l+1}/${Fn+1} ${xn}; retry in ${yb}ms`),await new Promise((jI)=>setTimeout(jI,yb));continue}V(`[claude] ✗ all ${Fn+1} attempts failed; last: ${xn}`)}}if(Zn)return`执行出错: claude-agent-sdk 调用超时 (${Math.round(Fb/1000)}s × ${Fn+1} attempts) — vendor 长时间未响应, 检查 ANTHROPIC_BASE_URL endpoint 或 vendor 负载`;return`执行出错: ${Qr.slice(0,200)} (after ${Fn+1} attempts)`}var Or=null,fk=N$||[`你是 ${K},一个 AI Agent 节点,工作目录:${process.cwd()}。`,"你通过通信网络(CommHub)接收任务并和其他 agent 协作。","","【可用通信工具】","- mcp_commhub__send_task(alias, task):派任务给指定 agent,等其 LLM 处理完返回 reply(同步语义)。","- mcp_commhub__send_message(alias, message):发聊天消息(不要求对方回复)。","- mcp_commhub__get_task(task_id):查询某任务的当前状态/reply。","- mcp_commhub__get_all_status():查看网络上所有在线 agent。","","【协作模式】","当你的任务需要其他 agent 的能力时:","1. 先 get_all_status 看哪些 agent 在线。","2. 用 send_task(alias, task, parent_task_id=<env CURRENT_TASK_ID>) 派给合适的 agent。"," ⚠ 必须把 parent_task_id 设成你当前任务的 ID(环境变量 CURRENT_TASK_ID 里),系统会自动把子任务最终结果串回给你的上游。",'3. 用 get_task 轮询子任务直到 status=replied/failed。允许中途汇报"还在等",但要继续轮询。',"4. 拿到 reply 后整合进你给上游的最终汇报。"," 即使你的 session 中途断开,只要 parent_task_id 设了,结果也会被系统自动 chain 回上游,不必焦虑。","","【禁止】",'- 不要回复"收到""好的""ok""在线""待命"等无内容确认。',"- 不要给自己发任务(会死循环)。","- 收到的若是 reply 类型,不要再 send_task 给原方(会乒乓回复)。","- 没有新任务时保持沉默,不主动发消息。","","你的最终回复会被系统自动 send_reply 给任务发起者。"].join(`
132
- `),CU={model_auto_compact_token_limit:200000,developer_instructions:fk};async function ek(r,i,v){try{let{execSync:c}=await import("child_process"),b=c("which codex 2>/dev/null",{encoding:"utf-8"}).trim();if(b){let g=b.replace(/\/codex$/,"");if(!process.env.PATH?.includes(g))process.env.PATH=`${g}:${process.env.PATH}`}}catch{}let u;{let{execSync:c}=await import("child_process"),{module:b}=await kU({importCodexSdk:()=>import("@openai/codex-sdk"),npmInstall:jU(c),log:V,warn:G},zU(__dirname));u=b.Codex}if(!Or){let c=new u({config:CU}),b=Yr||"gpt-5.5",g=P?.flags||{},I={skipGitRepoCheck:g.skipGitRepoCheck===!1?!1:!0,approvalPolicy:typeof g.approvalPolicy==="string"?g.approvalPolicy:"never",model:b,sandboxMode:typeof g.sandboxMode==="string"?g.sandboxMode:"danger-full-access",modelReasoningEffort:"low"};if(Ir)Or=c.resumeThread(Ir,I),V(`codex resumed thread: ${Ir}`);else Or=c.startThread(I)}V(`[codex] model=${Yr||"gpt-5.5"} thread=${Or?.id||"new"}`);let $=r,t=v?.length?[{type:"text",text:$},...v.map((c)=>({type:"local_image",path:c}))]:$,o=Date.now();try{let{events:c}=await Or.runStreamed(t),b="",g=null,I=0;for await(let N of c)if(N.type==="item.started"){let X=N.item;H(`[codex] ${X.type}${X.command?`: ${X.command.slice(0,60)}`:X.tool?`: ${X.server}/${X.tool}`:""}`)}else if(N.type==="item.completed"){I++;let X=N.item;if(X.type==="agent_message")b=X.text||"";if(X.type==="command_execution")H(`[codex] cmd exit=${X.exit_code} | ${X.aggregated_output?.slice(0,80)}`);if(X.type==="reasoning")H(`[codex] thinking: ${X.text?.slice(0,80)}`);if(X.type==="mcp_tool_call")H(`[codex] mcp: ${X.server}/${X.tool} → ${X.status}`)}else if(N.type==="turn.completed")g=N.usage;let _=Date.now()-o,k=g?.input_tokens||0;if(V(`[codex] done | ${_}ms | in=${k} out=${g?.output_tokens||0} | items=${I}`),Or?.id)mb(Or.id);return b||"(无回复)"}catch(c){V(`codex thread error: ${c.message}, 重建`),Or=new u({config:CU}).startThread({skipGitRepoCheck:!0,approvalPolicy:"never",model:Yr||"gpt-5.5",sandboxMode:"danger-full-access",modelReasoningEffort:"low"});let g=await Or.run(t),I=Date.now()-o;return V(`[codex] retry done | ${I}ms`),g.finalResponse||"(无回复)"}}var j$=null,dr=null;async function yk(){if(j$)return j$;let{CodexStdioClient:r}=await Promise.resolve().then(() => (XU(),PU)),i=new r;return i.on("stderr",(v)=>H(`[codex-stderr] ${v.trim()}`)),i.on("exit",(v)=>{V(`[codex-stdio] app-server exited (code=${v.code} signal=${v.signal})`),j$=null,dr=null}),i.on("error",(v)=>V(`[codex-stdio] subprocess error: ${v.message}`)),i.start({cwd:process.cwd()}),await i.request("initialize",{clientInfo:{name:"anet/agent-node",version:"2.3.10"}}),j$=i,i}async function hk(r,i,v){let u=await yk();if(!dr){let c={model:Yr||"gpt-5.5",approvalPolicy:"on-request",sandboxPolicy:{type:"dangerFullAccess"}};if(Ir)c.threadId=Ir;if(dr=(await u.request("thread/start",c)).thread.id,V(`[codex-stdio] thread/start → ${dr}`),dr)mb(dr)}let n=[{type:"text",text:r}];if(v?.length)for(let c of v)n.push({type:"localImage",path:c});let $="",t=0,o=await new Promise(async(c,b)=>{let g=null,I=(k)=>{let N=k?.item;if(!N)return;if(t++,N.type==="agentMessage"&&typeof N.text==="string")$=N.text},_=(k)=>{let N=k?.turn?.id??k?.turnId??null;if(g&&N&&N!==g)return;u.off("item/completed",I),u.off("turn/completed",_),c(N||g||"")};u.on("item/completed",I),u.on("turn/completed",_);try{let k=Date.now(),N=await u.request("turn/start",{threadId:dr,input:n});g=(N?.turn?.id??N?.turnId)||null,V(`[codex-stdio] turn/start → ${g??"(no id)"} ${Date.now()-k}ms`)}catch(k){u.off("item/completed",I),u.off("turn/completed",_),b(k)}});return V(`[codex-stdio] turn done | items=${t} | turn_id=${o.slice(0,8)}`),$||"(无回复)"}function dk(r,i){let v=process.env.CURRENT_TASK_ID||"(unknown)";return[`你是 ${K},CommHub 网络中的 AI 节点。`,"","【Agent Network 接入边界】",`- agent-node 已负责从 CommHub 收取任务、上报状态,并把你的最终文本回复给 ${i}。`,"- 你当前通过 Grok Build ACP 推理,不要声称 MCP servers 正在连接,也不要要求用户等待 MCP 工具就绪。","- 如果任务只是要求回答、总结、分析或生成文本,请直接完成任务。",'- 如果任务要求给某个 alias 发任务、派任务、交给、沟通或调用 send_task:agent-node 会优先在进入 Grok 前用 CommHub wrapper 自动处理;若 wrapper 没拦住、你直接看到原始指令,请主动调用 `commhub_send_task(alias="<目标>", task="<子任务内容>")` 工具完成派发,**不要回复 "无法执行" 或要求用户重新格式化**。','- 派发指令的常见形式包括 `send_task X Y`、`给 X 发/说/沟通/打 ...`、`你去给 X ...`、`让/请 X ...`、`派给/转给/交给 X ...`。这些都已在 wrapper 里覆盖;若你仍看到原文,说明属于 wrapper 漏拦边缘 case,你拥有 `commhub_send_task` 工具权限,请直接调用完成任务,不需要用户提供更多 "精确格式"。',`- 当前任务 ID 是 ${v},只在用户要求你引用任务上下文时提及。`,"",`收到来自 ${i} 的任务:`,r].join(`
133
- `)}function pk(r){let i=r.split(/\r?\n/),v=[],u=0;for(let $ of i){let t=$.trim();if(/CommHub\s+MCP\s+状态说明/i.test(t)||/根据当前系统提示.*MCP\s*服务器/i.test(t)||/Do not attempt to use tools from these servers yet/i.test(t)||/commhub_(get_all_status|send_task|get_task|reply|report_status)/i.test(t)||/无法(调用|执行).*CommHub/i.test(t)||/MCP\s*服务器仍?在连接中/i.test(t)){u++;continue}v.push($)}let n=v.join(`
132
+ `);function ek(r){let i=f(r,".anet","node-server.js");return{model_auto_compact_token_limit:200000,developer_instructions:fk,mcp_servers:{commhub:{command:"bun",args:[i]}}}}var CU=ek(process.cwd());async function yk(r,i,v){try{let{execSync:c}=await import("child_process"),b=c("which codex 2>/dev/null",{encoding:"utf-8"}).trim();if(b){let g=b.replace(/\/codex$/,"");if(!process.env.PATH?.includes(g))process.env.PATH=`${g}:${process.env.PATH}`}}catch{}let u;{let{execSync:c}=await import("child_process"),{module:b}=await kU({importCodexSdk:()=>import("@openai/codex-sdk"),npmInstall:jU(c),log:V,warn:G},zU(__dirname));u=b.Codex}if(!Or){let c=new u({config:CU}),b=Yr||"gpt-5.5",g=P?.flags||{},I={skipGitRepoCheck:g.skipGitRepoCheck===!1?!1:!0,approvalPolicy:typeof g.approvalPolicy==="string"?g.approvalPolicy:"never",model:b,sandboxMode:typeof g.sandboxMode==="string"?g.sandboxMode:"danger-full-access",modelReasoningEffort:"low"};if(Ir)Or=c.resumeThread(Ir,I),V(`codex resumed thread: ${Ir}`);else Or=c.startThread(I)}V(`[codex] model=${Yr||"gpt-5.5"} thread=${Or?.id||"new"}`);let $=r,t=v?.length?[{type:"text",text:$},...v.map((c)=>({type:"local_image",path:c}))]:$,o=Date.now();try{let{events:c}=await Or.runStreamed(t),b="",g=null,I=0;for await(let N of c)if(N.type==="item.started"){let X=N.item;H(`[codex] ${X.type}${X.command?`: ${X.command.slice(0,60)}`:X.tool?`: ${X.server}/${X.tool}`:""}`)}else if(N.type==="item.completed"){I++;let X=N.item;if(X.type==="agent_message")b=X.text||"";if(X.type==="command_execution")H(`[codex] cmd exit=${X.exit_code} | ${X.aggregated_output?.slice(0,80)}`);if(X.type==="reasoning")H(`[codex] thinking: ${X.text?.slice(0,80)}`);if(X.type==="mcp_tool_call")H(`[codex] mcp: ${X.server}/${X.tool} → ${X.status}`)}else if(N.type==="turn.completed")g=N.usage;let _=Date.now()-o,k=g?.input_tokens||0;if(V(`[codex] done | ${_}ms | in=${k} out=${g?.output_tokens||0} | items=${I}`),Or?.id)mb(Or.id);return b||"(无回复)"}catch(c){V(`codex thread error: ${c.message}, 重建`),Or=new u({config:CU}).startThread({skipGitRepoCheck:!0,approvalPolicy:"never",model:Yr||"gpt-5.5",sandboxMode:"danger-full-access",modelReasoningEffort:"low"});let g=await Or.run(t),I=Date.now()-o;return V(`[codex] retry done | ${I}ms`),g.finalResponse||"(无回复)"}}var j$=null,dr=null;async function hk(){if(j$)return j$;let{CodexStdioClient:r}=await Promise.resolve().then(() => (XU(),PU)),i=new r;return i.on("stderr",(v)=>H(`[codex-stderr] ${v.trim()}`)),i.on("exit",(v)=>{V(`[codex-stdio] app-server exited (code=${v.code} signal=${v.signal})`),j$=null,dr=null}),i.on("error",(v)=>V(`[codex-stdio] subprocess error: ${v.message}`)),i.start({cwd:process.cwd()}),await i.request("initialize",{clientInfo:{name:"anet/agent-node",version:"2.3.10"}}),j$=i,i}async function dk(r,i,v){let u=await hk();if(!dr){let c={model:Yr||"gpt-5.5",approvalPolicy:"on-request",sandboxPolicy:{type:"dangerFullAccess"}};if(Ir)c.threadId=Ir;if(dr=(await u.request("thread/start",c)).thread.id,V(`[codex-stdio] thread/start → ${dr}`),dr)mb(dr)}let n=[{type:"text",text:r}];if(v?.length)for(let c of v)n.push({type:"localImage",path:c});let $="",t=0,o=await new Promise(async(c,b)=>{let g=null,I=(k)=>{let N=k?.item;if(!N)return;if(t++,N.type==="agentMessage"&&typeof N.text==="string")$=N.text},_=(k)=>{let N=k?.turn?.id??k?.turnId??null;if(g&&N&&N!==g)return;u.off("item/completed",I),u.off("turn/completed",_),c(N||g||"")};u.on("item/completed",I),u.on("turn/completed",_);try{let k=Date.now(),N=await u.request("turn/start",{threadId:dr,input:n});g=(N?.turn?.id??N?.turnId)||null,V(`[codex-stdio] turn/start → ${g??"(no id)"} ${Date.now()-k}ms`)}catch(k){u.off("item/completed",I),u.off("turn/completed",_),b(k)}});return V(`[codex-stdio] turn done | items=${t} | turn_id=${o.slice(0,8)}`),$||"(无回复)"}function pk(r,i){let v=process.env.CURRENT_TASK_ID||"(unknown)";return[`你是 ${K},CommHub 网络中的 AI 节点。`,"","【Agent Network 接入边界】",`- agent-node 已负责从 CommHub 收取任务、上报状态,并把你的最终文本回复给 ${i}。`,"- 你当前通过 Grok Build ACP 推理,不要声称 MCP servers 正在连接,也不要要求用户等待 MCP 工具就绪。","- 如果任务只是要求回答、总结、分析或生成文本,请直接完成任务。",'- 如果任务要求给某个 alias 发任务、派任务、交给、沟通或调用 send_task:agent-node 会优先在进入 Grok 前用 CommHub wrapper 自动处理;若 wrapper 没拦住、你直接看到原始指令,请主动调用 `commhub_send_task(alias="<目标>", task="<子任务内容>")` 工具完成派发,**不要回复 "无法执行" 或要求用户重新格式化**。','- 派发指令的常见形式包括 `send_task X Y`、`给 X 发/说/沟通/打 ...`、`你去给 X ...`、`让/请 X ...`、`派给/转给/交给 X ...`。这些都已在 wrapper 里覆盖;若你仍看到原文,说明属于 wrapper 漏拦边缘 case,你拥有 `commhub_send_task` 工具权限,请直接调用完成任务,不需要用户提供更多 "精确格式"。',`- 当前任务 ID 是 ${v},只在用户要求你引用任务上下文时提及。`,"",`收到来自 ${i} 的任务:`,r].join(`
133
+ `)}function ak(r){let i=r.split(/\r?\n/),v=[],u=0;for(let $ of i){let t=$.trim();if(/CommHub\s+MCP\s+状态说明/i.test(t)||/根据当前系统提示.*MCP\s*服务器/i.test(t)||/Do not attempt to use tools from these servers yet/i.test(t)||/commhub_(get_all_status|send_task|get_task|reply|report_status)/i.test(t)||/无法(调用|执行).*CommHub/i.test(t)||/MCP\s*服务器仍?在连接中/i.test(t)){u++;continue}v.push($)}let n=v.join(`
134
134
  `).replace(/\n{3,}/g,`
135
135
 
136
- `).trim();if(u>0)G(`[grok] stripped ${u} leaked CommHub/MCP status line(s) from reply`);if(!n&&u>0)return"Grok 输出包含 CommHub/MCP 状态泄漏,已过滤。请用明确 alias 和子任务内容重试。";return n||r.trim()||"(无回复)"}async function ak(r,i,v){if(v?.length)G("[grok] image attachments received but Grok ACP fixture reports promptCapabilities.image=false; sending text-only prompt");try{let{execFileSync:_}=await import("child_process"),k=_("grok",["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"]}).trim();H(`[grok] ${k}`)}catch{throw Error("grok CLI not found. Install Grok Build CLI and run `grok --version` before starting this node.")}let{runGrokAcpTurn:u}=await Promise.resolve().then(() => (KU(),GU)),n=[];if(ur)n.push({name:"Authorization",value:`Bearer ${ur}`});if(n.push({name:"X-Commhub-MCP-Transport",value:"acp-http"}),K)n.push({name:"X-Commhub-Alias-Hint",value:K});let $=[{type:"http",name:"commhub",url:`${Nr}/mcp`,headers:n}],{prepareGrokIsolatedCwd:t}=await Promise.resolve().then(() => (LU(),BU)),o=t({userCwd:process.cwd(),nodeId:Mr,alias:K,onWarn:(_)=>G(`[grok] ${_}`)});if(o.isolated)V(`[grok] #204 isolated cwd: ${o.cwd} (symlinked=${o.symlinked}, skipped=${o.skipped})`);else G(`[grok] #204 isolated cwd failed: ${o.error} — falling back to process.cwd(), may re-read project .mcp.json`);let c=o.cwd,b="";if(Ck&&!RU){RU=!0;try{let _=async(Q)=>{return await Promise.race([qr("list_tasks",Q,0),new Promise((T,R)=>setTimeout(()=>R(Error("list_tasks timeout 3s")),3000))])},k=await Hk(),N=await JU({nodeId:Mr||null,alias:tI()},_,{topN:10,serverSupportsFromNodeId:k}),X=NU(N);if(X)V(`[grok] resume hint: ${N.length} un-closed-loop outbound task(s) prepended to first prompt`),b=X+`
136
+ `).trim();if(u>0)G(`[grok] stripped ${u} leaked CommHub/MCP status line(s) from reply`);if(!n&&u>0)return"Grok 输出包含 CommHub/MCP 状态泄漏,已过滤。请用明确 alias 和子任务内容重试。";return n||r.trim()||"(无回复)"}async function sk(r,i,v){if(v?.length)G("[grok] image attachments received but Grok ACP fixture reports promptCapabilities.image=false; sending text-only prompt");try{let{execFileSync:_}=await import("child_process"),k=_("grok",["--version"],{encoding:"utf-8",stdio:["ignore","pipe","pipe"]}).trim();H(`[grok] ${k}`)}catch{throw Error("grok CLI not found. Install Grok Build CLI and run `grok --version` before starting this node.")}let{runGrokAcpTurn:u}=await Promise.resolve().then(() => (KU(),GU)),n=[];if(ur)n.push({name:"Authorization",value:`Bearer ${ur}`});if(n.push({name:"X-Commhub-MCP-Transport",value:"acp-http"}),K)n.push({name:"X-Commhub-Alias-Hint",value:K});let $=[{type:"http",name:"commhub",url:`${Nr}/mcp`,headers:n}],{prepareGrokIsolatedCwd:t}=await Promise.resolve().then(() => (LU(),BU)),o=t({userCwd:process.cwd(),nodeId:Mr,alias:K,onWarn:(_)=>G(`[grok] ${_}`)});if(o.isolated)V(`[grok] #204 isolated cwd: ${o.cwd} (symlinked=${o.symlinked}, skipped=${o.skipped})`);else G(`[grok] #204 isolated cwd failed: ${o.error} — falling back to process.cwd(), may re-read project .mcp.json`);let c=o.cwd,b="";if(Ck&&!RU){RU=!0;try{let _=async(Q)=>{return await Promise.race([qr("list_tasks",Q,0),new Promise((T,R)=>setTimeout(()=>R(Error("list_tasks timeout 3s")),3000))])},k=await Hk(),N=await JU({nodeId:Mr||null,alias:tI()},_,{topN:10,serverSupportsFromNodeId:k}),X=NU(N);if(X)V(`[grok] resume hint: ${N.length} un-closed-loop outbound task(s) prepended to first prompt`),b=X+`
137
137
 
138
- `;else H("[grok] resume hint: no un-closed-loop outbound tasks — nothing to prepend")}catch(_){G(`[grok] resume hint skipped (non-fatal): ${_?.message??_}`)}}let g=async(_,k="primary")=>{let N=Date.now(),X=await u({prompt:b+dk(r,i),cwd:c,sessionId:_,mcpServers:$,timeoutMs:k$({envValue:process.env.GROK_ACP_TIMEOUT_MS,flagValue:P.flags?.grokAcpTimeoutMs,defaultMs:300000}).valueMs,drainMs:k$({envValue:process.env.GROK_ACP_DRAIN_MS,flagValue:P.flags?.grokAcpDrainMs,defaultMs:15000}).valueMs,onSession:(R)=>Qk(R),onEvent:(R,e)=>{if(e.skippedReplay>0&&e.skippedReplay%50===0)H(`[grok] skipped replay chunks=${e.skippedReplay}`)},onStderr:(R)=>{if(/error|fail|cannot|denied|enoent|not found/i.test(R))G(`[grok-stderr] ${R}`);else H(`[grok-stderr] ${R}`)}}),Q=Date.now()-N;V(`[grok] done ${k} | ${Q}ms | session=${X.sessionId.slice(0,8)} | chunks=${X.state.chunks} replay_skipped=${X.state.skippedReplay}`);let T=pk(X.replyText.trim()||"(无回复)");try{let{listGrokVideoArtifacts:R,formatVideoTrailer:e}=await Promise.resolve().then(() => (FU(),HU)),{homedir:E}=await import("os"),C=X.sessionId?E()+"/.grok/sessions/"+encodeURIComponent(c)+"/"+X.sessionId:void 0,Qr=e(R(C),T);if(Qr)V("[grok] #205 surfacing video path(s) to reply"),T=T+`
139
- `+Qr}catch(R){G(`[grok] #205 path surface skipped: ${R?.message||R}`)}return T},I=q$||Ir||void 0;try{return await g(I,"primary")}catch(_){let k=String(_?.message||_);if(I&&/ACP error -32603|Internal error/i.test(k))return G(`[grok] ${k}; retrying once with a fresh session`),lk("-32603 internal error"),await g(void 0,"fresh-retry");throw _}}function Mb(r){let i=r?.content?.[0]?.text;if(typeof i==="string")try{return JSON.parse(i)}catch{return i}return r}function sk(r){if(!r||typeof r!=="object")return;return r.task_id||r.message_id||r.id}async function rz(r,i,v){let u=bU(r);if(!u||!v)return null;let $=Mb(await qr("get_all_status",{}))?.sessions??null,t=WU($,u.alias,tI());if(!t.exists){let _=t.reason==="self_only"?"self-only match (parsed alias equals our own)":t.reason==="empty_sessions"?"commhub status returned empty sessions":t.reason==="no_sessions_field"?"commhub status missing sessions field":"not online";return H(`[explicit-delegation] precheck miss for "${u.alias}" (${_}); falling through to LLM`),null}let o=await nn(),c;try{c=Mb(await qr("send_task",{alias:u.alias,task:u.childTask,priority:"normal",from_session:o,parent_task_id:v}))}catch(_){if(_?.name==="CommHubError"&&_?.appLevel===!0)return H(`[explicit-delegation] send_task rejected server-side (${_.message}); falling through to LLM`),null;throw _}let b=sk(c);if(!b)return`已尝试给 ${u.alias} 派任务,但 CommHub 未返回 task_id:${JSON.stringify(c).slice(0,1000)}`;let g=Date.now()+120000,I=null;while(Date.now()<g){I=Mb(await qr("get_task",{task_id:b}));let _=I?.task||I,k=_?.status;if(k==="replied"||k==="failed"||k==="cancelled"){let N=_?.result||I?.result||JSON.stringify(I);return[`已通过 CommHub 给 ${u.alias} 派发子任务并等到结果。`,`子任务:${b}`,`状态:${k}`,"",String(N).slice(0,1600)].join(`
140
- `)}await new Promise((N)=>setTimeout(N,2000))}return`已给 ${u.alias} 派发子任务 ${b},但 120 秒内未等到 replied/failed。最新状态:${JSON.stringify(I).slice(0,1000)}`}var mU=Promise.resolve();function gI(r,i,v,u){let n=async()=>{let t=process.env.CURRENT_TASK_ID;if(v)process.env.CURRENT_TASK_ID=v;else delete process.env.CURRENT_TASK_ID;nU();try{if(_r==="codex"){if(process.env.ANET_CODEX_STDIO_DIRECT==="1")return await hk(r,i,u);return await ek(r,i,u)}if(_r==="grok")return await ak(r,i,u);return await mk(r,i)}finally{if(t!==void 0)process.env.CURRENT_TASK_ID=t;else delete process.env.CURRENT_TASK_ID;iU()}},$=mU.then(n,n);return mU=$.then(()=>{},()=>{}),$}function nz(r){let i=r?.meta||(()=>{try{return r?.meta_json?JSON.parse(r.meta_json):null}catch{return null}})();return(Array.isArray(i?.attachments)?i.attachments:[]).filter((u)=>u&&(u.type==="image"||String(u.mime||"").startsWith("image/"))&&typeof u.path==="string"&&u.path).map((u)=>u.path)}async function UI(r,i,v=null,u){V(`→ processing [${_r}]${u?.length?` +${u.length} image(s)`:""}: ${r.slice(0,80)}`),await P$("working",r.slice(0,200)).catch(()=>{});let n,$=!1;try{n=await rz(r,i,v)||await gI(r,i,v,u)}catch(t){n=`${_r} 错误: ${t.message}`,$=!0,Er(`✗ ${t.message}`)}finally{await P$("idle").catch(()=>{})}if(!$&&/(API 错误|API error|需要设置.*KEY|missing.*key|issue with the selected model|may not have access|may not exist|model.+not.+(found|available))/i.test(n))$=!0;return{text:n,failed:$}}var xb={},iz=5000,vz=new Set(["收到","好的","ok","嗯","是的","了解","明白","确认","done","ack","roger","yes","no","在线","待命","正常","保持在线","通信正常","已收到","收到了","好","行","noted","copy","received","understood","等待任务","等待中","等待指令","无新任务","idle","waiting"]);function II(r,i=!1){if(!r)return!0;let u=r.trim().replace(/^[\[【].+?[\]】]\s*/,"").trim().toLowerCase().replace(/[\s。!?.!?✅❌👀⏳,,]+$/g,"").trim();if(vz.has(u))return!0;if(/^[\p{Emoji}\s]+$/u.test(r.trim())&&!/[0-9a-zA-Z#*]/.test(r))return!0;return!1}function $z(r,i,v){if(r===K)return"self";if(i.startsWith(`[${K}]`))return"own-prefix";if(v!=="task"&&v!=="broadcast"&&r!=="hub"&&r!=="api"){let u=Date.now();if(xb[r]&&u-xb[r]<iz)return"cooldown"}if(v!=="task"&&v!=="broadcast"&&II(i))return"low-value-inbound";return null}async function _I(){await Zk();let r=await Ek();if(!r.length)return;for(let i of r){if(Ab.has(i.id)){H(`skip inflight message ${i.id.slice(0,8)}`);continue}Ab.add(i.id);try{let v=i.from_session||"hub",u=i.content,n=i.type||"task",$=nz(i);if(V(`← [${v}] (${n}/${i.priority||"normal"})${$.length?` +${$.length} image(s)`:""} ${u.slice(0,100)}`),n!=="task"&&n!=="broadcast"){H(`skip non-task message: type=${n}`),await Gi(i.id).catch((g)=>G(`ack failed for non-task ${i.id.slice(0,8)}: ${g.message}`));continue}let t=$z(v,u,n);if(t){H(`skip message from ${v}: ${t}`),await Gi(i.id).catch((g)=>G(`ack failed for skipped ${i.id.slice(0,8)}: ${g.message}`));continue}if(xk(u)){let g,I=!1;try{let _=await Tk(u,v,i.id);g=`[${K}] ${_}`}catch(_){g=`[${K}] /loop 创建失败:${_.message}`,I=!0}await fU(v,g,i.id,I),await Gi(i.id).catch((_)=>G(`ack failed for goal ${i.id.slice(0,8)}: ${_.message}`));continue}let{text:o,failed:c}=await UI(u,v,i.id,$);if(V(`processTask returned: "${o.slice(0,80)}" (${o.length} chars, failed=${c})`),!c&&II(o,!0)){V(`skip reply: low-value (${o.slice(0,30)})`),await Gi(i.id).catch((g)=>G(`ack failed for low-value ${i.id.slice(0,8)}: ${g.message}`));continue}let b=`[${K}] ${o.slice(0,2000)}`;await fU(v,b,i.id,c),await Gi(i.id).catch((g)=>G(`ack failed for ${i.id.slice(0,8)}: ${g.message}`))}finally{Ab.delete(i.id)}}}async function fU(r,i,v,u){Mk({to:r,text:i,taskId:v,failed:u,queuedAt:Date.now()}),V(`sending reply to ${r} (task ${v.slice(0,8)}, status=${u?"failed":"replied"})...`);try{await fb(r,i,v,u),TU(r,v),xb[r]=Date.now(),V(`→ [${r}] ${i.slice(0,100)}`)}catch(n){if(n instanceof Xr&&n.appLevel){G(`reply rejected by server for ${r} (task ${v.slice(0,8)}): ${n.message}`),TU(r,v);return}G(`reply failed for ${r} (task ${v.slice(0,8)}): ${n.message} — queued for retry`)}}function DI(r){return String(r.from?.id||r.chat?.id||"")}function kI(r){return r.from?.username||r.from?.first_name||DI(r)||"telegram"}function uz(r,i){if(r.allowFrom.length===0)return!0;let v=DI(i),u=i.from?.username?String(i.from.username):"";return r.allowFrom.includes(v)||!!u&&r.allowFrom.includes(u)}async function X$(r,i,v){let u=await fetch(`${r.apiBase}/${i}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(v)}),n=await u.json();if(!n.ok)throw Error(`telegram ${i} failed: ${n.description||u.statusText}`);return n.result}async function eU(r,i,v,u){let n=v.match(/[\s\S]{1,4096}/g)||["(无回复)"];for(let $=0;$<n.length;$++)await X$(r,"sendMessage",{chat_id:i,text:n[$],...u&&$===0?{reply_to_message_id:u}:{}})}async function yU(r,i,v){let u=await X$(r,"getFile",{file_id:i}),n=String(u.file_path||""),$=await fetch(`${r.fileBase}/${n}`);if(!$.ok)throw Error(`telegram file download failed: ${$.status} ${$.statusText}`);let t=n.split(".").pop(),o=(v||n.split("/").pop()||i).replace(/[^a-zA-Z0-9._-]/g,"_"),c=o.includes(".")||!t?o:`${o}.${t}`,b=f(r.channel.inboxDir,`${Date.now()}_${c}`);return Bi(b,Buffer.from(await $.arrayBuffer())),b}async function tz(r,i){let v=i.text||i.caption||"",u=[];if(Array.isArray(i.photo)&&i.photo.length>0){let $=i.photo[i.photo.length-1],t=await yU(r,$.file_id,`photo_${i.message_id}.jpg`);u.push(t)}let n=String(i.document?.mime_type||"");if(i.document&&n.startsWith("image/")){let $=await yU(r,i.document.file_id,i.document.file_name||`image_${i.message_id}`);u.push($)}if(u.length)v+=`
138
+ `;else H("[grok] resume hint: no un-closed-loop outbound tasks — nothing to prepend")}catch(_){G(`[grok] resume hint skipped (non-fatal): ${_?.message??_}`)}}let g=async(_,k="primary")=>{let N=Date.now(),X=await u({prompt:b+pk(r,i),cwd:c,sessionId:_,mcpServers:$,timeoutMs:k$({envValue:process.env.GROK_ACP_TIMEOUT_MS,flagValue:P.flags?.grokAcpTimeoutMs,defaultMs:300000}).valueMs,drainMs:k$({envValue:process.env.GROK_ACP_DRAIN_MS,flagValue:P.flags?.grokAcpDrainMs,defaultMs:15000}).valueMs,onSession:(R)=>Qk(R),onEvent:(R,e)=>{if(e.skippedReplay>0&&e.skippedReplay%50===0)H(`[grok] skipped replay chunks=${e.skippedReplay}`)},onStderr:(R)=>{if(/error|fail|cannot|denied|enoent|not found/i.test(R))G(`[grok-stderr] ${R}`);else H(`[grok-stderr] ${R}`)}}),Q=Date.now()-N;V(`[grok] done ${k} | ${Q}ms | session=${X.sessionId.slice(0,8)} | chunks=${X.state.chunks} replay_skipped=${X.state.skippedReplay}`);let T=ak(X.replyText.trim()||"(无回复)");try{let{listGrokVideoArtifacts:R,formatVideoTrailer:e}=await Promise.resolve().then(() => (FU(),HU)),{homedir:E}=await import("os"),C=X.sessionId?E()+"/.grok/sessions/"+encodeURIComponent(c)+"/"+X.sessionId:void 0,Qr=e(R(C),T);if(Qr)V("[grok] #205 surfacing video path(s) to reply"),T=T+`
139
+ `+Qr}catch(R){G(`[grok] #205 path surface skipped: ${R?.message||R}`)}return T},I=q$||Ir||void 0;try{return await g(I,"primary")}catch(_){let k=String(_?.message||_);if(I&&/ACP error -32603|Internal error/i.test(k))return G(`[grok] ${k}; retrying once with a fresh session`),lk("-32603 internal error"),await g(void 0,"fresh-retry");throw _}}function Mb(r){let i=r?.content?.[0]?.text;if(typeof i==="string")try{return JSON.parse(i)}catch{return i}return r}function rz(r){if(!r||typeof r!=="object")return;return r.task_id||r.message_id||r.id}async function nz(r,i,v){let u=bU(r);if(!u||!v)return null;let $=Mb(await qr("get_all_status",{}))?.sessions??null,t=WU($,u.alias,tI());if(!t.exists){let _=t.reason==="self_only"?"self-only match (parsed alias equals our own)":t.reason==="empty_sessions"?"commhub status returned empty sessions":t.reason==="no_sessions_field"?"commhub status missing sessions field":"not online";return H(`[explicit-delegation] precheck miss for "${u.alias}" (${_}); falling through to LLM`),null}let o=await nn(),c;try{c=Mb(await qr("send_task",{alias:u.alias,task:u.childTask,priority:"normal",from_session:o,parent_task_id:v}))}catch(_){if(_?.name==="CommHubError"&&_?.appLevel===!0)return H(`[explicit-delegation] send_task rejected server-side (${_.message}); falling through to LLM`),null;throw _}let b=rz(c);if(!b)return`已尝试给 ${u.alias} 派任务,但 CommHub 未返回 task_id:${JSON.stringify(c).slice(0,1000)}`;let g=Date.now()+120000,I=null;while(Date.now()<g){I=Mb(await qr("get_task",{task_id:b}));let _=I?.task||I,k=_?.status;if(k==="replied"||k==="failed"||k==="cancelled"){let N=_?.result||I?.result||JSON.stringify(I);return[`已通过 CommHub 给 ${u.alias} 派发子任务并等到结果。`,`子任务:${b}`,`状态:${k}`,"",String(N).slice(0,1600)].join(`
140
+ `)}await new Promise((N)=>setTimeout(N,2000))}return`已给 ${u.alias} 派发子任务 ${b},但 120 秒内未等到 replied/failed。最新状态:${JSON.stringify(I).slice(0,1000)}`}var mU=Promise.resolve();function gI(r,i,v,u){let n=async()=>{let t=process.env.CURRENT_TASK_ID;if(v)process.env.CURRENT_TASK_ID=v;else delete process.env.CURRENT_TASK_ID;nU();try{if(_r==="codex"){if(process.env.ANET_CODEX_STDIO_DIRECT==="1")return await dk(r,i,u);return await yk(r,i,u)}if(_r==="grok")return await sk(r,i,u);return await mk(r,i)}finally{if(t!==void 0)process.env.CURRENT_TASK_ID=t;else delete process.env.CURRENT_TASK_ID;iU()}},$=mU.then(n,n);return mU=$.then(()=>{},()=>{}),$}function iz(r){let i=r?.meta||(()=>{try{return r?.meta_json?JSON.parse(r.meta_json):null}catch{return null}})();return(Array.isArray(i?.attachments)?i.attachments:[]).filter((u)=>u&&(u.type==="image"||String(u.mime||"").startsWith("image/"))&&typeof u.path==="string"&&u.path).map((u)=>u.path)}async function UI(r,i,v=null,u){V(`→ processing [${_r}]${u?.length?` +${u.length} image(s)`:""}: ${r.slice(0,80)}`),await P$("working",r.slice(0,200)).catch(()=>{});let n,$=!1;try{n=await nz(r,i,v)||await gI(r,i,v,u)}catch(t){n=`${_r} 错误: ${t.message}`,$=!0,Er(`✗ ${t.message}`)}finally{await P$("idle").catch(()=>{})}if(!$&&/(API 错误|API error|需要设置.*KEY|missing.*key|issue with the selected model|may not have access|may not exist|model.+not.+(found|available))/i.test(n))$=!0;return{text:n,failed:$}}var xb={},vz=5000,$z=new Set(["收到","好的","ok","嗯","是的","了解","明白","确认","done","ack","roger","yes","no","在线","待命","正常","保持在线","通信正常","已收到","收到了","好","行","noted","copy","received","understood","等待任务","等待中","等待指令","无新任务","idle","waiting"]);function II(r,i=!1){if(!r)return!0;let u=r.trim().replace(/^[\[【].+?[\]】]\s*/,"").trim().toLowerCase().replace(/[\s。!?.!?✅❌👀⏳,,]+$/g,"").trim();if($z.has(u))return!0;if(/^[\p{Emoji}\s]+$/u.test(r.trim())&&!/[0-9a-zA-Z#*]/.test(r))return!0;return!1}function uz(r,i,v){if(r===K)return"self";if(i.startsWith(`[${K}]`))return"own-prefix";if(v!=="task"&&v!=="broadcast"&&r!=="hub"&&r!=="api"){let u=Date.now();if(xb[r]&&u-xb[r]<vz)return"cooldown"}if(v!=="task"&&v!=="broadcast"&&II(i))return"low-value-inbound";return null}async function _I(){await Zk();let r=await Ek();if(!r.length)return;for(let i of r){if(Ab.has(i.id)){H(`skip inflight message ${i.id.slice(0,8)}`);continue}Ab.add(i.id);try{let v=i.from_session||"hub",u=i.content,n=i.type||"task",$=iz(i);if(V(`← [${v}] (${n}/${i.priority||"normal"})${$.length?` +${$.length} image(s)`:""} ${u.slice(0,100)}`),n!=="task"&&n!=="broadcast"){H(`skip non-task message: type=${n}`),await Gi(i.id).catch((g)=>G(`ack failed for non-task ${i.id.slice(0,8)}: ${g.message}`));continue}let t=uz(v,u,n);if(t){H(`skip message from ${v}: ${t}`),await Gi(i.id).catch((g)=>G(`ack failed for skipped ${i.id.slice(0,8)}: ${g.message}`));continue}if(xk(u)){let g,I=!1;try{let _=await Tk(u,v,i.id);g=`[${K}] ${_}`}catch(_){g=`[${K}] /loop 创建失败:${_.message}`,I=!0}await fU(v,g,i.id,I),await Gi(i.id).catch((_)=>G(`ack failed for goal ${i.id.slice(0,8)}: ${_.message}`));continue}let{text:o,failed:c}=await UI(u,v,i.id,$);if(V(`processTask returned: "${o.slice(0,80)}" (${o.length} chars, failed=${c})`),!c&&II(o,!0)){V(`skip reply: low-value (${o.slice(0,30)})`),await Gi(i.id).catch((g)=>G(`ack failed for low-value ${i.id.slice(0,8)}: ${g.message}`));continue}let b=`[${K}] ${o.slice(0,2000)}`;await fU(v,b,i.id,c),await Gi(i.id).catch((g)=>G(`ack failed for ${i.id.slice(0,8)}: ${g.message}`))}finally{Ab.delete(i.id)}}}async function fU(r,i,v,u){Mk({to:r,text:i,taskId:v,failed:u,queuedAt:Date.now()}),V(`sending reply to ${r} (task ${v.slice(0,8)}, status=${u?"failed":"replied"})...`);try{await fb(r,i,v,u),TU(r,v),xb[r]=Date.now(),V(`→ [${r}] ${i.slice(0,100)}`)}catch(n){if(n instanceof Xr&&n.appLevel){G(`reply rejected by server for ${r} (task ${v.slice(0,8)}): ${n.message}`),TU(r,v);return}G(`reply failed for ${r} (task ${v.slice(0,8)}): ${n.message} — queued for retry`)}}function DI(r){return String(r.from?.id||r.chat?.id||"")}function kI(r){return r.from?.username||r.from?.first_name||DI(r)||"telegram"}function tz(r,i){if(r.allowFrom.length===0)return!0;let v=DI(i),u=i.from?.username?String(i.from.username):"";return r.allowFrom.includes(v)||!!u&&r.allowFrom.includes(u)}async function X$(r,i,v){let u=await fetch(`${r.apiBase}/${i}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(v)}),n=await u.json();if(!n.ok)throw Error(`telegram ${i} failed: ${n.description||u.statusText}`);return n.result}async function eU(r,i,v,u){let n=v.match(/[\s\S]{1,4096}/g)||["(无回复)"];for(let $=0;$<n.length;$++)await X$(r,"sendMessage",{chat_id:i,text:n[$],...u&&$===0?{reply_to_message_id:u}:{}})}async function yU(r,i,v){let u=await X$(r,"getFile",{file_id:i}),n=String(u.file_path||""),$=await fetch(`${r.fileBase}/${n}`);if(!$.ok)throw Error(`telegram file download failed: ${$.status} ${$.statusText}`);let t=n.split(".").pop(),o=(v||n.split("/").pop()||i).replace(/[^a-zA-Z0-9._-]/g,"_"),c=o.includes(".")||!t?o:`${o}.${t}`,b=f(r.channel.inboxDir,`${Date.now()}_${c}`);return Bi(b,Buffer.from(await $.arrayBuffer())),b}async function oz(r,i){let v=i.text||i.caption||"",u=[];if(Array.isArray(i.photo)&&i.photo.length>0){let $=i.photo[i.photo.length-1],t=await yU(r,$.file_id,`photo_${i.message_id}.jpg`);u.push(t)}let n=String(i.document?.mime_type||"");if(i.document&&n.startsWith("image/")){let $=await yU(r,i.document.file_id,i.document.file_name||`image_${i.message_id}`);u.push($)}if(u.length)v+=`
141
141
 
142
142
  [Telegram 附件已下载]
143
143
  ${u.map(($)=>`- 图片: ${$}`).join(`
144
- `)}`;return{text:v.trim(),images:u}}async function oz(r,i){if(!uz(r.channel,i))return;let v=i.chat?.id,u=i.message_id,n=`telegram:${kI(i)}`,{text:$,images:t}=await tz(r,i);if(!v||!u||!$)return;H(`[TG] processing: ${$.slice(0,80)}`);try{let o=await gI($,n,null,t);await eU(r,v,o,u),V(`→ [${n}] ${o.slice(0,100)}`)}catch(o){Er(`telegram task failed: ${o.message}`),await eU(r,v,`处理出错: ${o.message}`,u).catch(()=>{})}}async function bz(r){let i={channel:r,apiBase:`https://api.telegram.org/bot${r.token}`,fileBase:`https://api.telegram.org/file/bot${r.token}`,offset:0};try{let o=await X$(i,"getMe",{});V(`Telegram bot: @${o.username} (${o.first_name})`)}catch(o){Er(`Telegram token 无效: ${o.message}`),process.exit(1)}let v=f(r.dir,"state.json");try{let o=JSON.parse(rn(v,"utf-8"));if(o.offset)i.offset=o.offset,H(`Telegram offset restored: ${i.offset}`)}catch{}let u=()=>{try{Bi(v,JSON.stringify({offset:i.offset})+`
145
- `)}catch{}},n=!1,$=[];async function t(){if(n)return;n=!0;while($.length){let{msg:o,updateId:c}=$.shift();try{await oz(i,o),i.offset=c+1,u()}catch(b){Er(`TG handle: ${b.message}`)}}n=!1}V(`Telegram polling: ${r.dir}`);while(!0)try{let c=await(await fetch(`${i.apiBase}/getUpdates?offset=${i.offset}&timeout=30`)).json();if(!c.ok)throw Error(c.description||"getUpdates failed");for(let b of c.result||[])if(i.offset=b.update_id+1,b.message){let g=b.message,I=kI(g),_=g.text||g.caption||"";if(V(`← TG [${I}] ${_.slice(0,80)}${g.photo?" +img":""}${g.document?" +file":""}`),g.chat?.id&&g.message_id)X$(i,"setMessageReaction",{chat_id:g.chat.id,message_id:g.message_id,reaction:[{type:"emoji",emoji:$.length>0?"⏳":"\uD83D\uDC40"}]}).catch(()=>{});$.push({msg:g,updateId:b.update_id}),t()}}catch(o){G(`Telegram polling error: ${o.message}`),await new Promise((c)=>setTimeout(c,3000))}}async function cz(){let r=`${Nr}/events/${encodeURIComponent(K)}`,i=1000,v=30000,u=3600000,n=1000,$=!0,t=null;while(!0){H(`SSE connecting: ${r}`);try{let o={Accept:"text/event-stream","Cache-Control":"no-cache"};if(ur)o.Authorization=`Bearer ${ur}`;let c=await fetch(r,{headers:o});if(!c.ok||!c.body){if(c.status===401){if(Pk()){G(`SSE 401: ntok_ 已刷新,正在用 .anet/nodes/${K}/config.json 里的新 token 重试`),await new Promise((_)=>setTimeout(_,500));continue}Er("SSE 401: ntok_ 已失效(hub DB 可能被重置或 token 被撤销)。试 `anet doctor --fix`")}else G(`SSE failed: ${c.status}`);if(t=t??Date.now(),Date.now()-t>3600000){Er(`SSE 连续 >1h 连不上 hub (${Nr}) — 放弃自动重连。运行 \`anet node start ${K}\` 手动恢复。`);return}await new Promise((_)=>setTimeout(_,n)),n=Math.min(n*2,30000);continue}n=1000;let b=c.body.getReader(),g=new TextDecoder,I="";while(!0){let{done:_,value:k}=await b.read();if(_)break;I+=g.decode(k,{stream:!0});let N=I.split(`
146
- `);I=N.pop()||"";for(let X of N){if(!X.startsWith("data: "))continue;try{let Q=JSON.parse(X.slice(6));if(Q.type==="connected"){if(V("SSE connected"),t=null,!$)V("re-registering after SSE reconnect"),oI().catch((T)=>G(`re-register failed: ${T?.message||T}`));$=!1;continue}if(["new_task","broadcast"].includes(Q.type))V(`← SSE ${Q.type}`),await _I();if(Q.type==="new_reply")V(`← SSE reply from ${Q.from||"?"}${Q.in_reply_to?` (task ${Q.in_reply_to.slice(0,8)})`:""}`)}catch{}}}}catch(o){G(`SSE error: ${o.message}`)}if(t=t??Date.now(),Date.now()-t>3600000){Er(`SSE 连续 >1h 连不上 hub (${Nr}) — 放弃自动重连。运行 \`anet node start ${K}\` 手动恢复。`);return}H(`SSE reconnecting (${n/1000}s)...`),await new Promise((o)=>setTimeout(o,n)),n=Math.min(n*2,30000)}}V("启动");V(` alias: ${K||"(none!)"} [from: ${Jk}]`);V(` runtime: ${iI}`);V(` model: ${Yr||(_r==="codex"?"gpt-5.5":_r==="grok"?"grok-build":"claude-sonnet-4-6")} ${Yr?"":"(default)"}`);V(` hub: ${Nr}${ur?" (auth)":" (no auth!)"}`);if(_r==="grok"){let r=k$({envValue:process.env.GROK_ACP_TIMEOUT_MS,flagValue:P.flags?.grokAcpTimeoutMs,defaultMs:300000}),i=r.source==="flags"?"flags.grokAcpTimeoutMs":r.source==="env"?"env GROK_ACP_TIMEOUT_MS":"default";V(` [grok] session/prompt idle timeout = ${r.valueMs}ms (source: ${i})`)}if(ur)try{let r=await fetch(`${Nr}/api/auth/me`,{headers:{Authorization:`Bearer ${ur}`}}).then((i)=>i.json()).catch(()=>null);if(r?.ok&&r.user)if(V(` user: ${r.user.username} (${r.user.role})`),r.current_network){let i=r.networks?.find((v)=>v.network_id===r.current_network)?.network_name;V(` network: ${i||r.current_network}`)}else V(` network: ${ar||"(global)"}`);else if(r?.ok===!1)V(` network: ${ar||"(global)"}`);else G(" token 验证失败 — 检查 token 是否有效。运行: anet login")}catch{V(` network: ${ar||"(global)"}`)}else G(" 未配置 token — agent 数据不隔离。运行: anet login");V(` tools: ${Array.isArray(pr)?pr.length?`[${pr.join(",")}]`:"(none)":"all (Claude Code preset — built-in: WebFetch/WebSearch/Bash/Read/Write/Edit/Glob/Grep/Task/...)"}`);V(` channels:${V$.length?` telegram(${V$.map((r)=>r.dir).join(",")})`:" (none)"}`);V(` session: ${Ir||"(new)"}`);V(` log-dir: ${Rb}`);V(` goals: ${Cb}`);var J$=await An.load();if(!J$.ok)G(` goals load recovered: ${J$.error||"unknown"}${J$.recovered?` (${J$.recovered})`:""}`);var hU=(await An.list()).filter((r)=>r.status==="active");if(hU.length)V(` goals active: ${hU.length}`);await oI();V("已注册到 CommHub");_I().catch((r)=>G(`initial inbox scan failed: ${r.message}`));setInterval(()=>P$("idle").catch(()=>{}),180000);setInterval(()=>cI().catch(()=>{}),Ok);cI().catch(()=>{});var zI=async()=>{V("shutting down..."),await P$("offline").catch(()=>{}),process.exit(0)};process.on("SIGINT",zI);process.on("SIGTERM",zI);for(let r of V$)bz(r);cz();
144
+ `)}`;return{text:v.trim(),images:u}}async function bz(r,i){if(!tz(r.channel,i))return;let v=i.chat?.id,u=i.message_id,n=`telegram:${kI(i)}`,{text:$,images:t}=await oz(r,i);if(!v||!u||!$)return;H(`[TG] processing: ${$.slice(0,80)}`);try{let o=await gI($,n,null,t);await eU(r,v,o,u),V(`→ [${n}] ${o.slice(0,100)}`)}catch(o){Er(`telegram task failed: ${o.message}`),await eU(r,v,`处理出错: ${o.message}`,u).catch(()=>{})}}async function cz(r){let i={channel:r,apiBase:`https://api.telegram.org/bot${r.token}`,fileBase:`https://api.telegram.org/file/bot${r.token}`,offset:0};try{let o=await X$(i,"getMe",{});V(`Telegram bot: @${o.username} (${o.first_name})`)}catch(o){Er(`Telegram token 无效: ${o.message}`),process.exit(1)}let v=f(r.dir,"state.json");try{let o=JSON.parse(rn(v,"utf-8"));if(o.offset)i.offset=o.offset,H(`Telegram offset restored: ${i.offset}`)}catch{}let u=()=>{try{Bi(v,JSON.stringify({offset:i.offset})+`
145
+ `)}catch{}},n=!1,$=[];async function t(){if(n)return;n=!0;while($.length){let{msg:o,updateId:c}=$.shift();try{await bz(i,o),i.offset=c+1,u()}catch(b){Er(`TG handle: ${b.message}`)}}n=!1}V(`Telegram polling: ${r.dir}`);while(!0)try{let c=await(await fetch(`${i.apiBase}/getUpdates?offset=${i.offset}&timeout=30`)).json();if(!c.ok)throw Error(c.description||"getUpdates failed");for(let b of c.result||[])if(i.offset=b.update_id+1,b.message){let g=b.message,I=kI(g),_=g.text||g.caption||"";if(V(`← TG [${I}] ${_.slice(0,80)}${g.photo?" +img":""}${g.document?" +file":""}`),g.chat?.id&&g.message_id)X$(i,"setMessageReaction",{chat_id:g.chat.id,message_id:g.message_id,reaction:[{type:"emoji",emoji:$.length>0?"⏳":"\uD83D\uDC40"}]}).catch(()=>{});$.push({msg:g,updateId:b.update_id}),t()}}catch(o){G(`Telegram polling error: ${o.message}`),await new Promise((c)=>setTimeout(c,3000))}}async function gz(){let r=`${Nr}/events/${encodeURIComponent(K)}`,i=1000,v=30000,u=3600000,n=1000,$=!0,t=null;while(!0){H(`SSE connecting: ${r}`);try{let o={Accept:"text/event-stream","Cache-Control":"no-cache"};if(ur)o.Authorization=`Bearer ${ur}`;let c=await fetch(r,{headers:o});if(!c.ok||!c.body){if(c.status===401){if(Pk()){G(`SSE 401: ntok_ 已刷新,正在用 .anet/nodes/${K}/config.json 里的新 token 重试`),await new Promise((_)=>setTimeout(_,500));continue}Er("SSE 401: ntok_ 已失效(hub DB 可能被重置或 token 被撤销)。试 `anet doctor --fix`")}else G(`SSE failed: ${c.status}`);if(t=t??Date.now(),Date.now()-t>3600000){Er(`SSE 连续 >1h 连不上 hub (${Nr}) — 放弃自动重连。运行 \`anet node start ${K}\` 手动恢复。`);return}await new Promise((_)=>setTimeout(_,n)),n=Math.min(n*2,30000);continue}n=1000;let b=c.body.getReader(),g=new TextDecoder,I="";while(!0){let{done:_,value:k}=await b.read();if(_)break;I+=g.decode(k,{stream:!0});let N=I.split(`
146
+ `);I=N.pop()||"";for(let X of N){if(!X.startsWith("data: "))continue;try{let Q=JSON.parse(X.slice(6));if(Q.type==="connected"){if(V("SSE connected"),t=null,!$)V("re-registering after SSE reconnect"),oI().catch((T)=>G(`re-register failed: ${T?.message||T}`));$=!1;continue}if(["new_task","broadcast"].includes(Q.type))V(`← SSE ${Q.type}`),await _I();if(Q.type==="new_reply")V(`← SSE reply from ${Q.from||"?"}${Q.in_reply_to?` (task ${Q.in_reply_to.slice(0,8)})`:""}`)}catch{}}}}catch(o){G(`SSE error: ${o.message}`)}if(t=t??Date.now(),Date.now()-t>3600000){Er(`SSE 连续 >1h 连不上 hub (${Nr}) — 放弃自动重连。运行 \`anet node start ${K}\` 手动恢复。`);return}H(`SSE reconnecting (${n/1000}s)...`),await new Promise((o)=>setTimeout(o,n)),n=Math.min(n*2,30000)}}V("启动");V(` alias: ${K||"(none!)"} [from: ${Jk}]`);V(` runtime: ${iI}`);V(` model: ${Yr||(_r==="codex"?"gpt-5.5":_r==="grok"?"grok-build":"claude-sonnet-4-6")} ${Yr?"":"(default)"}`);V(` hub: ${Nr}${ur?" (auth)":" (no auth!)"}`);if(_r==="grok"){let r=k$({envValue:process.env.GROK_ACP_TIMEOUT_MS,flagValue:P.flags?.grokAcpTimeoutMs,defaultMs:300000}),i=r.source==="flags"?"flags.grokAcpTimeoutMs":r.source==="env"?"env GROK_ACP_TIMEOUT_MS":"default";V(` [grok] session/prompt idle timeout = ${r.valueMs}ms (source: ${i})`)}if(ur)try{let r=await fetch(`${Nr}/api/auth/me`,{headers:{Authorization:`Bearer ${ur}`}}).then((i)=>i.json()).catch(()=>null);if(r?.ok&&r.user)if(V(` user: ${r.user.username} (${r.user.role})`),r.current_network){let i=r.networks?.find((v)=>v.network_id===r.current_network)?.network_name;V(` network: ${i||r.current_network}`)}else V(` network: ${ar||"(global)"}`);else if(r?.ok===!1)V(` network: ${ar||"(global)"}`);else G(" token 验证失败 — 检查 token 是否有效。运行: anet login")}catch{V(` network: ${ar||"(global)"}`)}else G(" 未配置 token — agent 数据不隔离。运行: anet login");V(` tools: ${Array.isArray(pr)?pr.length?`[${pr.join(",")}]`:"(none)":"all (Claude Code preset — built-in: WebFetch/WebSearch/Bash/Read/Write/Edit/Glob/Grep/Task/...)"}`);V(` channels:${V$.length?` telegram(${V$.map((r)=>r.dir).join(",")})`:" (none)"}`);V(` session: ${Ir||"(new)"}`);V(` log-dir: ${Rb}`);V(` goals: ${Cb}`);var J$=await An.load();if(!J$.ok)G(` goals load recovered: ${J$.error||"unknown"}${J$.recovered?` (${J$.recovered})`:""}`);var hU=(await An.list()).filter((r)=>r.status==="active");if(hU.length)V(` goals active: ${hU.length}`);await oI();V("已注册到 CommHub");_I().catch((r)=>G(`initial inbox scan failed: ${r.message}`));setInterval(()=>P$("idle").catch(()=>{}),180000);setInterval(()=>cI().catch(()=>{}),Ok);cI().catch(()=>{});var zI=async()=>{V("shutting down..."),await P$("offline").catch(()=>{}),process.exit(0)};process.on("SIGINT",zI);process.on("SIGTERM",zI);for(let r of V$)cz(r);gz();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-node",
3
- "version": "2.4.11-preview.0",
3
+ "version": "2.4.11",
4
4
  "description": "AI Agent runtime for CommHub networks. Supports 4 runtimes: Claude Code CLI, Claude Agent SDK, Codex SDK, and Grok Build ACP.",
5
5
  "bin": {
6
6
  "agent-node": "dist/cli.js"