@sleep2agi/agent-network 0.0.52 → 1.0.0

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/bin/cli.js +52 -62
  2. package/package.json +1 -1
package/dist/bin/cli.js CHANGED
@@ -1,16 +1,17 @@
1
1
  #!/usr/bin/env node
2
- var QB=Object.defineProperty;var WB=(Q)=>Q;function XB(Q,W){this[Q]=WB.bind(null,W)}var YB=(Q,W)=>{for(var B in W)QB(Q,B,{get:W[B],enumerable:!0,configurable:!0,set:XB.bind(W,B)})};var ZB=(Q,W)=>()=>(Q&&(W=Q(Q=0)),W);var m={};YB(m,{default:()=>zB,CommHub:()=>b});import{EventEmitter as $B}from"events";import{hostname as f}from"os";var b,zB;var p=ZB(()=>{b=class b extends $B{url;alias;token;agent;resumeId;heartbeatInterval;reconnectDelay;heartbeatTimer;sseAbort;running=!1;constructor(Q){super();if(this.url=Q.url.replace(/\/$/,""),this.alias=Q.alias,this.token=Q.token,this.agent=Q.agent||"sdk",this.resumeId=`sdk-${Q.alias}-${Date.now().toString(36)}`,this.heartbeatInterval=Q.heartbeatInterval??180000,this.reconnectDelay=Q.reconnectDelay??3000,Q.autoConnect!==!1)this.connect()}log(Q){console.log(`[${new Date().toTimeString().slice(0,8)}] [commhub:${this.alias}] ${Q}`)}async call(Q,W){let B={"Content-Type":"application/json",Accept:"application/json, text/event-stream"};if(this.token)B.Authorization=`Bearer ${this.token}`;let $=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:B,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:Q,arguments:W}})})).text(),Z=$.match(/data: (.+)/),z=Z?JSON.parse(Z[1]):JSON.parse($),Y=z?.result?.content?.[0]?.text;return Y?JSON.parse(Y):z}async connect(){if(this.running)return;this.running=!0,await this.status("idle"),this.log("registered"),this.heartbeatTimer=setInterval(()=>{this.status("idle").catch((Q)=>this.log(`heartbeat failed: ${Q.message}`))},this.heartbeatInterval),this.connectSSE()}async disconnect(){if(this.running=!1,this.sseAbort?.abort(),this.heartbeatTimer)clearInterval(this.heartbeatTimer);await this.status("offline").catch(()=>{}),this.log("disconnected")}async send(Q,W,B="normal"){return this.call("send_task",{alias:Q,task:W,priority:B,from_session:this.alias})}async message(Q,W){return this.call("send_message",{alias:Q,message:W,from_session:this.alias})}async reply(Q,W,B="completed"){return this.call("reply",{task_id:Q,text:W,status:B})}async status(Q,W){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:Q,server:f(),hostname:f(),agent:this.agent,project_dir:process.cwd(),...W})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(Q,W){return this.call("broadcast",{message:Q,filter_server:W?.server,filter_status:W?.status})}async connectSSE(){let Q=encodeURIComponent(this.alias),W=`${this.url}/events/${Q}`,B=this.reconnectDelay;while(this.running){try{this.sseAbort=new AbortController;let X={Accept:"text/event-stream"};if(this.token)X.Authorization=`Bearer ${this.token}`;let $=await fetch(W,{headers:X,signal:this.sseAbort.signal});if(!$.ok||!$.body){this.log(`SSE failed: ${$.status}`),await this.sleep(B),B=Math.min(B*1.5,60000);continue}B=this.reconnectDelay;let Z=$.body.getReader(),z=new TextDecoder,Y="";while(this.running){let{done:N,value:U}=await Z.read();if(N)break;Y+=z.decode(U,{stream:!0});let E=Y.split(`
3
- `);Y=E.pop()||"";for(let R of E){if(!R.startsWith("data: "))continue;try{let V=JSON.parse(R.slice(6));if(V.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(V.type==="new_task"||V.type==="new_message"||V.type==="broadcast")await this.processInbox()}catch{}}}}catch(X){if(X.name==="AbortError")break;this.emit("error",X),this.log(`SSE error: ${X.message}`)}if(this.running)this.emit("disconnected"),this.log(`SSE reconnecting in ${B/1000}s...`),await this.sleep(B),B=Math.min(B*1.5,60000)}}async processInbox(){try{let W=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let B of W)await this.call("ack_inbox",{alias:this.alias,message_id:B.id}),this.log(`← ${B.from_session}: ${B.content.slice(0,60)}`),this.emit("task",B),this.emit("message",B)}catch(Q){this.log(`inbox error: ${Q.message}`)}}sleep(Q){return new Promise((W)=>setTimeout(W,Q))}};zB=b});import{readFileSync as T,writeFileSync as K,existsSync as q,mkdirSync as M,readdirSync as w,statSync as D}from"fs";import{join as L}from"path";import{spawn as j,execSync as r}from"child_process";import{createInterface as EB}from"readline";var _=process.argv.slice(2),k=_[0],G=process.env.HOME||process.env.USERPROFILE||"~";function t(){return L(G,".anet","config.json")}function u(){return L(G,".anet","server","config.json")}function F(){return L(process.cwd(),".anet","nodes")}function n(){return I().token||process.env.COMMHUB_TOKEN||J().token||""}function y(Q){let W=Q||n();return W?{Authorization:`Bearer ${W}`}:{}}function J(){let Q=t();if(q(Q))try{return JSON.parse(T(Q,"utf-8"))}catch{}return{}}function i(Q){let W=L(G,".anet");M(W,{recursive:!0}),K(L(W,"config.json"),JSON.stringify(Q,null,2)+`
4
- `)}function c(){let Q=u();if(q(Q))try{return JSON.parse(T(Q,"utf-8"))}catch{}return{}}function d(Q){let W=L(G,".anet","server");M(W,{recursive:!0}),K(L(W,"config.json"),JSON.stringify(Q,null,2)+`
5
- `)}function x(Q){let W=L(F(),Q,"config.json");if(!q(W))return null;try{let B=JSON.parse(T(W,"utf-8")),X=J();return{...B,hub:B.hub||X.hub||"",token:B.token||X.token||"",env:{...B.env},flags:{...B.flags}}}catch{return null}}function P(Q,W){let B=L(F(),Q);M(B,{recursive:!0}),K(L(B,"config.json"),JSON.stringify(W,null,2)+`
6
- `)}function S(){let Q=F();if(!q(Q))return[];return w(Q).filter((W)=>q(L(Q,W,"config.json")))}function I(){let Q={_channels:[],_envs:[]};for(let W=0;W<_.length;W++){if(_[W]==="--channel"&&_[W+1]){Q._channels.push(_[++W]);continue}if(_[W]==="--env"&&_[W+1]){Q._envs.push(_[++W]);continue}if(_[W].startsWith("--")&&_[W+1]&&!_[W+1].startsWith("--"))Q[_[W].slice(2)]=_[++W]}return Q}function l(){console.log(`
2
+ var LB=Object.defineProperty;var VB=(Q)=>Q;function _B(Q,B){this[Q]=VB.bind(null,B)}var qB=(Q,B)=>{for(var W in B)LB(Q,W,{get:B[W],enumerable:!0,configurable:!0,set:_B.bind(B,W)})};var EB=(Q,B)=>()=>(Q&&(B=Q(Q=0)),B);var a={};qB(a,{default:()=>zB,CommHub:()=>j});import{EventEmitter as HB}from"events";import{hostname as l}from"os";var j,zB;var r=EB(()=>{j=class j extends HB{url;alias;token;agent;resumeId;heartbeatInterval;reconnectDelay;heartbeatTimer;sseAbort;running=!1;constructor(Q){super();if(this.url=Q.url.replace(/\/$/,""),this.alias=Q.alias,this.token=Q.token,this.agent=Q.agent||"sdk",this.resumeId=`sdk-${Q.alias}-${Date.now().toString(36)}`,this.heartbeatInterval=Q.heartbeatInterval??180000,this.reconnectDelay=Q.reconnectDelay??3000,Q.autoConnect!==!1)this.connect()}log(Q){console.log(`[${new Date().toTimeString().slice(0,8)}] [commhub:${this.alias}] ${Q}`)}async call(Q,B){let W={"Content-Type":"application/json",Accept:"application/json, text/event-stream"};if(this.token)W.Authorization=`Bearer ${this.token}`;let $=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:W,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:Q,arguments:B}})})).text(),Y=$.match(/data: (.+)/),U=Y?JSON.parse(Y[1]):JSON.parse($),L=U?.result?.content?.[0]?.text;return L?JSON.parse(L):U}async connect(){if(this.running)return;this.running=!0,await this.status("idle"),this.log("registered"),this.heartbeatTimer=setInterval(()=>{this.status("idle").catch((Q)=>this.log(`heartbeat failed: ${Q.message}`))},this.heartbeatInterval),this.connectSSE()}async disconnect(){if(this.running=!1,this.sseAbort?.abort(),this.heartbeatTimer)clearInterval(this.heartbeatTimer);await this.status("offline").catch(()=>{}),this.log("disconnected")}async send(Q,B,W="normal"){return this.call("send_task",{alias:Q,task:B,priority:W,from_session:this.alias})}async message(Q,B){return this.call("send_message",{alias:Q,message:B,from_session:this.alias})}async reply(Q,B,W="completed"){return this.call("reply",{task_id:Q,text:B,status:W})}async status(Q,B){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:Q,server:l(),hostname:l(),agent:this.agent,project_dir:process.cwd(),...B})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(Q,B){return this.call("broadcast",{message:Q,filter_server:B?.server,filter_status:B?.status})}async connectSSE(){let Q=encodeURIComponent(this.alias),B=`${this.url}/events/${Q}`,W=this.reconnectDelay;while(this.running){try{this.sseAbort=new AbortController;let X={Accept:"text/event-stream"};if(this.token)X.Authorization=`Bearer ${this.token}`;let $=await fetch(B,{headers:X,signal:this.sseAbort.signal});if(!$.ok||!$.body){this.log(`SSE failed: ${$.status}`),await this.sleep(W),W=Math.min(W*1.5,60000);continue}W=this.reconnectDelay;let Y=$.body.getReader(),U=new TextDecoder,L="";while(this.running){let{done:Z,value:V}=await Y.read();if(Z)break;L+=U.decode(V,{stream:!0});let _=L.split(`
3
+ `);L=_.pop()||"";for(let z of _){if(!z.startsWith("data: "))continue;try{let E=JSON.parse(z.slice(6));if(E.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(E.type==="new_task"||E.type==="new_message"||E.type==="broadcast")await this.processInbox()}catch{}}}}catch(X){if(X.name==="AbortError")break;this.emit("error",X),this.log(`SSE error: ${X.message}`)}if(this.running)this.emit("disconnected"),this.log(`SSE reconnecting in ${W/1000}s...`),await this.sleep(W),W=Math.min(W*1.5,60000)}}async processInbox(){try{let B=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let W of B)await this.call("ack_inbox",{alias:this.alias,message_id:W.id}),this.log(`← ${W.from_session}: ${W.content.slice(0,60)}`),this.emit("task",W),this.emit("message",W)}catch(Q){this.log(`inbox error: ${Q.message}`)}}sleep(Q){return new Promise((B)=>setTimeout(B,Q))}};zB=j});import{chmodSync as TB,readFileSync as J,writeFileSync as T,existsSync as H,mkdirSync as M,readdirSync as v,statSync as P}from"fs";import{join as K}from"path";import{spawn as h,execSync as f}from"child_process";import{createInterface as FB}from"readline";var q=process.argv.slice(2),y=q[0],G=process.env.HOME||process.env.USERPROFILE||"~";function e(){return K(G,".anet","config.json")}function S(){return K(G,".anet","server","config.json")}function O(){return K(process.cwd(),".anet","nodes")}function BB(){return N().token||process.env.COMMHUB_TOKEN||I().token||""}function u(Q){let B=Q||BB();return B?{Authorization:`Bearer ${B}`}:{}}function I(){let Q=e();if(H(Q))try{return JSON.parse(J(Q,"utf-8"))}catch{}return{}}function QB(Q){let B=K(G,".anet");M(B,{recursive:!0}),T(K(B,"config.json"),JSON.stringify(Q,null,2)+`
4
+ `)}function t(){let Q=S();if(H(Q))try{return JSON.parse(J(Q,"utf-8"))}catch{}return{}}function n(Q){let B=K(G,".anet","server");M(B,{recursive:!0}),T(K(B,"config.json"),JSON.stringify(Q,null,2)+`
5
+ `)}function F(Q){if(typeof Q==="string"){if(Q==="codex"||Q==="codex-sdk")return"codex-sdk";if(Q==="claude"||Q==="claude-sdk"||Q==="claude-agent-sdk")return"claude-agent-sdk";if(Q==="agent-sdk")return"claude-agent-sdk";return"claude-code-cli"}let B=Q;if(!B)return"claude-code-cli";if(B.runtime==="agent-sdk")return B.codexRuntime==="codex"?"codex-sdk":"claude-agent-sdk";return F(B.runtime||"claude-code-cli")}function JB(Q,B){return B?.name||B?.alias||Q}function k(Q){return Q.session||Q.resume||""}function MB(Q){return Q.normalize("NFC")}function m(Q){if(Q!==MB(Q))console.error(`Error: node-name must be Unicode NFC normalized: ${Q}`),process.exit(1);if(!/^[^\s\/\\:*?"<>|.][^\s\/\\:*?"<>|.]*$/.test(Q))console.error(`Error: invalid node-name "${Q}"`),console.error(`Allowed: Chinese/letters/numbers/-/_ ; forbidden: whitespace, '.', / \\ : * ? " < > |`),process.exit(1)}function x(Q){let B=K(O(),Q,"config.json");if(!H(B))return null;try{let W=JSON.parse(J(B,"utf-8")),X=I();return{...W,name:W.name||W.alias||Q,alias:W.alias||W.name||Q,session:W.session||W.resume||"",hub:W.hub||X.hub||"",token:W.token||X.token||"",channels:Array.isArray(W.channels)?W.channels:[],env:{...W.env},flags:{...W.flags}}}catch{return null}}function WB(Q){let B=K(O(),Q,"config.json");if(!H(B))return null;try{let W=JSON.parse(J(B,"utf-8"));return{...W,channels:Array.isArray(W.channels)?W.channels:[],env:{...W.env},flags:{...W.flags}}}catch{return null}}function w(Q,B){let W=K(O(),Q);M(W,{recursive:!0}),T(K(W,"config.json"),JSON.stringify(B,null,2)+`
6
+ `)}function c(){let Q=O();if(!H(Q))return[];return v(Q).filter((B)=>H(K(Q,B,"config.json")))}function N(){let Q={_channels:[],_envs:[]};for(let B=0;B<q.length;B++){if(q[B]==="--channel"&&q[B+1]){Q._channels.push(q[++B]);continue}if(q[B]==="--env"&&q[B+1]){Q._envs.push(q[++B]);continue}if(q[B].startsWith("--")&&q[B+1]&&!q[B+1].startsWith("--"))Q[q[B].slice(2)]=q[++B];else if(q[B].startsWith("--"))Q[q[B].slice(2)]="true"}return Q}function i(Q){try{return f(`command -v ${JSON.stringify(Q)}`,{stdio:"ignore",shell:"/bin/bash"}),!0}catch{return!1}}function XB(){console.log("[anet] claude-code-cli requires:"),console.log(" - Claude Pro / Team / Enterprise subscription"),console.log(' - Run "claude auth login" first'),console.log(" - Uses Anthropic Claude only"),console.log(" - For other models, use --runtime codex-sdk or claude-agent-sdk")}function YB(Q,B){if(Q==="claude-code-cli"){if(!i("claude"))console.warn("[anet] Warning: claude CLI not found in PATH."),console.warn("[anet] Install: npm install -g @anthropic-ai/claude-code");if(B==="start")XB();return}if(!i("npx"))console.warn("[anet] Warning: npx not found in PATH; cannot launch @sleep2agi/agent-node."),console.warn("[anet] Install Node.js/npm first, or install agent-node globally: npm install -g @sleep2agi/agent-node")}function s(){console.log(`
7
7
  anet — AI Agent Network CLI
8
8
 
9
9
  anet init Configure hub URL (global, once)
10
10
  anet init project Setup current project (channel plugin + config)
11
- anet init profile <id> Create a launch profile
12
- anet start <id> New session with profile
13
- anet resume <id> Resume last session with profile
11
+ anet create <node-name> Create a node
12
+ anet start <node-name> Start node (resume config.session when set)
13
+ anet start <node-name> --new-session
14
+ anet resume <node-name> --session <id>
14
15
  anet ls Show profiles + sessions + network
15
16
  anet server start Start CommHub Server
16
17
  anet import Import sessions from CommHub → config.json
@@ -21,14 +22,14 @@ anet — AI Agent Network CLI
21
22
  Quick start:
22
23
  anet server start # 启动 CommHub Server
23
24
  anet init --hub http://IP:9200
24
- anet start 指挥室 # Claude Code Agent
25
- anet start 小明 # MiniMax Agent (runtime: agent-sdk)
26
- `)}async function NB(){let Q=I(),W=Q.hub;if(!W)W=await O("CommHub URL (e.g. http://YOUR_IP:9200)");if(!W)v(),console.error("Error: hub URL required"),process.exit(1);W=W.replace(/\/+$/,"");let B=Q.token||"";if(!B)B=await O("Auth token (empty to skip)");v();try{let Z=await(await fetch(`${W}/health`,{headers:B?{Authorization:`Bearer ${B}`}:{}})).json();console.log(`✅ CommHub v${Z.version} — ${Z.sessions} sessions, ${Z.sse_connections} SSE`)}catch($){console.error(`❌ Cannot reach ${W}: ${$.message}`),process.exit(1)}let X=J();if(X.hub=W,B)X.token=B;else if(!X.token)delete X.token;i(X),console.log(`
27
- Saved to ${t()}`),console.log("Next: anet init project")}async function UB(){let Q=J(),W=Q.hub;if(!W)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let B=L(process.cwd(),".anet");M(B,{recursive:!0});let X=L(B,"node-server.ts");if(!q(X)){let R=[L(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),L(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),L(process.argv[1],"..","..","src","node-server.ts")],V=!1;for(let H of R)if(q(H)){K(X,T(H,"utf-8")),console.log(" ✅ .anet/node-server.ts"),V=!0;break}if(!V)console.log(" ❌ Cannot find node-server.ts"),console.log(" Fix: cp $(npm root -g)/@sleep2agi/agent-network/src/node-server.ts .anet/node-server.ts")}else console.log(" Channel plugin: exists");let $=L(B,"package.json");if(!q($)){K($,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
28
- `);try{r("bun install",{cwd:B,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let Z=L(B,".env"),z=Q.token||"",Y=`COMMHUB_URL=${W}
29
- `;if(z)Y+=`COMMHUB_TOKEN=${z}
30
- `;K(Z,Y),console.log(`CommHub URL: ${W}${z?" (with token)":""}`);let N=L(process.cwd(),".mcp.json"),U={};if(q(N))try{U=JSON.parse(T(N,"utf-8"))}catch{}if(!U.mcpServers?.commhub)U.mcpServers=U.mcpServers||{},U.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},K(N,JSON.stringify(U,null,2)+`
31
- `),console.log(".mcp.json: commhub → .anet/node-server.ts");else console.log(".mcp.json: commhub already set");let E=L(process.cwd(),"CLAUDE.md");if(!q(E))K(E,`# Agent Network (CommHub)
25
+ anet create 指挥室
26
+ anet start 指挥室
27
+ `)}async function GB(){let Q=N(),B=Q.hub;if(!B)B=await C("CommHub URL (e.g. http://YOUR_IP:9200)");if(!B)b(),console.error("Error: hub URL required"),process.exit(1);B=B.replace(/\/+$/,"");let W=Q.token||"";if(!W)W=await C("Auth token (empty to skip)");b();try{let Y=await(await fetch(`${B}/health`,{headers:W?{Authorization:`Bearer ${W}`}:{}})).json();console.log(`✅ CommHub v${Y.version} — ${Y.sessions} sessions, ${Y.sse_connections} SSE`)}catch($){console.error(`❌ Cannot reach ${B}: ${$.message}`),process.exit(1)}let X=I();if(X.hub=B,W)X.token=W;else if(!X.token)delete X.token;QB(X),console.log(`
28
+ Saved to ${e()}`),console.log("Next: anet init project")}async function NB(){let Q=I(),B=Q.hub;if(!B)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let W=K(process.cwd(),".anet");M(W,{recursive:!0});let X=K(W,"node-server.ts");if(!H(X)){let z=[K(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),K(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),K(process.argv[1],"..","..","src","node-server.ts")],E=!1;for(let A of z)if(H(A)){T(X,J(A,"utf-8")),console.log(" ✅ .anet/node-server.ts"),E=!0;break}if(!E)console.log(" ❌ Cannot find node-server.ts"),console.log(" Fix: cp $(npm root -g)/@sleep2agi/agent-network/src/node-server.ts .anet/node-server.ts")}else console.log(" Channel plugin: exists");let $=K(W,"package.json");if(!H($)){T($,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
29
+ `);try{f("bun install",{cwd:W,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let Y=K(W,".env"),U=Q.token||"",L=`COMMHUB_URL=${B}
30
+ `;if(U)L+=`COMMHUB_TOKEN=${U}
31
+ `;T(Y,L),console.log(`CommHub URL: ${B}${U?" (with token)":""}`);let Z=K(process.cwd(),".mcp.json"),V={};if(H(Z))try{V=JSON.parse(J(Z,"utf-8"))}catch{}if(!V.mcpServers?.commhub)V.mcpServers=V.mcpServers||{},V.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},T(Z,JSON.stringify(V,null,2)+`
32
+ `),console.log(".mcp.json: commhub → .anet/node-server.ts");else console.log(".mcp.json: commhub already set");let _=K(process.cwd(),"CLAUDE.md");if(!H(_))T(_,`# Agent Network (CommHub)
32
33
 
33
34
  ## 通信方式
34
35
 
@@ -67,32 +68,28 @@ commhub_get_all_status()
67
68
  - 回复指挥室用 commhub_send_task(不是 commhub_reply,reply 不推送)
68
69
  - 不要猜 alias,用 get_all_status 查
69
70
  `),console.log("CLAUDE.md: created");else console.log("CLAUDE.md: already exists");console.log(`
70
- ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function LB(){let Q=_[2];if(!Q)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let W=J(),B=I(),X=B.alias||Q,$=B.hub||W.hub;if(!$)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Z={};for(let R of B._envs){let V=R.indexOf("=");if(V>0)Z[R.slice(0,V)]=R.slice(V+1)}let z=B.runtime||"claude-code",Y={anet_version:"0.0.24",...B.name?{name:B.name}:{},runtime:z,alias:X,hub:$,...B.model?{model:B.model}:{},...B.tools?{tools:B.tools.split(",").map((R)=>R.trim())}:{},channels:B._channels.length>0?B._channels:z==="claude-code"?["server:commhub"]:[],env:Z,flags:{dangerouslySkipPermissions:!0,...z==="claude-code"?{teammateMode:B["teammate-mode"]||"in-process"}:{},...B["max-turns"]?{maxTurns:parseInt(B["max-turns"])}:{}},...B.resume?{resume:B.resume}:{},...B["resume-alias"]?{resumeAlias:B["resume-alias"]}:{}},N=L(G,".claude","channels","commhub"),U=process.cwd().replace(/\//g,"-"),E=L(N,U);if(M(E,{recursive:!0}),K(L(E,".env"),`COMMHUB_ALIAS=${X}
71
- `),P(Q,Y),console.log(`
72
- ✅ Profile "${Q}" saved`),console.log(` alias: ${X}`),console.log(` channels: ${Y.channels.join(", ")}`),Object.keys(Z).length)console.log(` env: ${Object.keys(Z).join(", ")}`);console.log(`
73
- Start: anet start ${Q}`)}var A=null;function RB(){if(!A)A=EB({input:process.stdin,output:process.stdout});return A}function v(){if(A)A.close(),A=null}function O(Q,W){let B=W?` [${W}]`:"";return new Promise((X)=>{RB().question(`${Q}${B}: `,($)=>{X($.trim()||W||"")})})}async function VB(Q){let W=J();console.log(`
74
- Profile "${Q}" not found. Let's create it:
75
- `);let B=await O("Runtime (claude-code / agent-sdk)","claude-code"),X=await O("Alias",Q),$,Z=[],z=[],Y="";if(B==="agent-sdk")$=await O("Model","MiniMax-M2.7"),Z=(await O("Tools (comma-separated)","Read,Bash,Grep")).split(",").map((H)=>H.trim()).filter(Boolean);else z=(await O("Channels (comma-separated)","server:commhub")).split(",").map((H)=>H.trim()).filter(Boolean),Y=await O("Teammate mode","in-process");let N=await O("Extra env (K=V, comma-separated, empty to skip)"),U={};if(N)for(let V of N.split(",")){let H=V.trim().indexOf("=");if(H>0)U[V.trim().slice(0,H)]=V.trim().slice(H+1)}let E=W.hub;if(!E)console.error(`
76
- Run 'anet init' first to configure hub URL`),process.exit(1);let R={anet_version:"0.0.23",alias:X,hub:E,runtime:B,...$?{model:$}:{},...Z.length?{tools:Z}:{},channels:z,env:U,flags:{dangerouslySkipPermissions:!0,...Y?{teammateMode:Y}:{}}};return P(Q,R),v(),console.log(`
77
- ✅ Profile "${Q}" saved
78
- `),R}function _B(Q){if((Q.runtime||"claude-code")!=="claude-code")return;if(!Q.channels?.some((R)=>R.includes("commhub")))return;let W=L(process.cwd(),".mcp.json"),B={};if(q(W))try{B=JSON.parse(T(W,"utf-8"))}catch{}let X=L(process.cwd(),".anet"),$=L(X,"node-server.ts"),Z=[L(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),L(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),L(process.argv[1],"..","..","src","node-server.ts")];for(let R of Z)if(q(R)){M(X,{recursive:!0});let V=T(R,"utf-8"),H=q($)?T($,"utf-8"):"";if(V!==H)K($,V),console.log("[anet] Updated .anet/node-server.ts");break}let z=L(X,"package.json");if(!q(z)){M(X,{recursive:!0}),K(z,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
79
- `);try{r("bun install",{cwd:X,stdio:"pipe"})}catch{}}if(B.mcpServers=B.mcpServers||{},!Object.keys(B.mcpServers).some((R)=>R.includes("commhub")))B.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},K(W,JSON.stringify(B,null,2)+`
80
- `),console.log("[anet] .mcp.json: added commhub");let N=L(X,".env"),U=Q.token||"",E=`COMMHUB_URL=${Q.hub||"http://127.0.0.1:9200"}
81
- `;if(U)E+=`COMMHUB_TOKEN=${U}
82
- `;K(N,E),B.mcpServers=B.mcpServers||{},B.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},K(W,JSON.stringify(B,null,2)+`
83
- `),console.log("[anet] .mcp.json: added commhub channel server")}async function o(Q,W){let B=x(Q);if(!B)B=await VB(Q);let X=B.runtime||"claude-code";console.log(`[anet] ${W==="start"?"Starting new":"Resuming"} "${Q}" (${B.alias}) [${X}]...
84
- `),_B(B);let Z=B.token||"";if(X==="agent-sdk"){let z=["@sleep2agi/agent-node","--alias",B.alias,"--hub",B.hub];if(B.model)z.push("--model",B.model);if(B.tools?.length)z.push("--tools",B.tools.join(","));if(B.flags?.maxTurns)z.push("--max-turns",String(B.flags.maxTurns));if(B.codexRuntime)z.push("--runtime",B.codexRuntime);if(W==="resume"&&B.resume)z.push("--session",B.resume);let Y=L(F(),Q,"channels");if(q(Y)){for(let E of w(Y))if(q(L(Y,E,".env")))z.push("--channel",`${E}:${L(Y,E)}`)}let N={...process.env,...Z?{COMMHUB_TOKEN:Z}:{}};for(let[E,R]of Object.entries(B.env))N[E]=R.replace(/^~/,G);j("npx",z,{env:N,stdio:"inherit",shell:!0}).on("exit",(E)=>process.exit(E||0))}else{let z={...process.env,COMMHUB_ALIAS:B.alias,...Z?{COMMHUB_TOKEN:Z}:{}};for(let[U,E]of Object.entries(B.env))z[U]=E.replace(/^~/,G);let Y=[];if(B.flags.dangerouslySkipPermissions)Y.push("--dangerously-skip-permissions");for(let U of B.channels)if(U.startsWith("server:"))Y.push("--dangerously-load-development-channels",U);else Y.push("--channels",U);if(B.flags.teammateMode)Y.push("--teammate-mode",B.flags.teammateMode);if(W==="resume"){let U=B.resume||B.resumeAlias||B.name||B.alias;Y.push("--resume",U)}Y.push("-n",B.name||B.alias),j("claude",Y,{env:z,stdio:"inherit",shell:!0}).on("exit",(U)=>process.exit(U||0))}}async function a(){let Q=_[1];if(!Q){s("start");return}await o(Q,"start")}async function qB(){let Q=_[1];if(!Q){s("resume");return}let W=x(Q);if(!W){let B=I(),X=J(),$=B.hub||X.hub,Z=B.session;if(!Z)console.log(`Profile "${Q}" not found.
85
- `),console.log(`Quick setup: anet resume ${Q} --session <session-id>`),console.log(`Or create: anet init profile ${Q} --alias ${Q} --resume <session-id>`),process.exit(1);if(!$)console.error("Run 'anet init' first"),process.exit(1);W={runtime:"claude-code",alias:B.alias||Q,hub:$,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:Z},P(Q,W),console.log(`[anet] Created .anet/nodes/${Q}/config.json (resume: ${Z.slice(0,8)}...)
86
- `)}await o(Q,"resume")}function s(Q){let W=S();if(W.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
87
- Profiles:
88
- `);for(let B of W){let X=x(B);console.log(` ${B}${X?.name?` (${X.name})`:""} → ${X?.alias} [${X?.channels.join(", ")}]`)}console.log(`
89
- anet ${Q} <id>
90
- `)}async function KB(){let Q=S();if(Q.length>0){console.log(`
91
- Profiles:
92
- `);for(let Y of Q){let N=x(Y);console.log(` ${Y}${N?.name?` (${N.name})`:""} → ${N?.alias} [${N?.channels.join(", ")}]`)}console.log()}let W=process.cwd(),B=L(G,".claude","sessions"),X=[];if(q(B))for(let Y of w(B).filter((N)=>N.endsWith(".json")))try{let N=JSON.parse(T(L(B,Y),"utf-8"));if(N.cwd===W)X.push(N)}catch{}if(X.length===0&&Q.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
93
- `);return}let $=J(),Z=[],z={};if($.hub)try{let[Y,N]=await Promise.all([fetch(`${$.hub}/api/status`,{headers:y()}).then((U)=>U.json()),fetch(`${$.hub}/health`,{headers:y()}).then((U)=>U.json())]);Z=Y.sessions||[],z=N.sse_sessions||{}}catch{}if(X.length>0){console.log(`Sessions (${W}):
94
- `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let Y of X){let N=Y.sessionId.slice(0,18),U=!1;try{process.kill(Y.pid,0),U=!0}catch{}let E="(not in network)",R=W.replace(/\//g,"-"),V=L(G,".claude","channels","commhub",R,".env");if(q(V)){let h=T(V,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(h){let C=h[1].trim(),g=Z.find((BB)=>BB.alias===C),e=z[C]?"●":"○";E=g?`${C} ${g.status} ${e}`:`${C} (not registered)`}}console.log(` ${N} ${(U?`${Y.pid}`:`${Y.pid}✕`).padEnd(7)} ${E}`)}console.log()}}async function HB(){let Q=J(),W=I(),B=process.env.COMMHUB_URL||W.hub||Q.hub||"http://127.0.0.1:9200",X=process.env.COMMHUB_ALIAS||W.alias;if(!X)console.error("Error: --alias required"),process.exit(1);let{CommHub:$}=await Promise.resolve().then(() => (p(),m)),Z=new $({url:B,alias:X});Z.on("task",async(z)=>{console.log(`[${X}] ← ${z.from_session}: ${z.content.slice(0,100)}`),await Z.send(z.from_session,`[${X}] 收到: ${z.content.slice(0,200)}`)}),Z.on("connected",()=>console.log(`[${X}] Connected`)),Z.on("disconnected",()=>console.log(`[${X}] Reconnecting...`)),process.on("SIGINT",()=>Z.disconnect().then(()=>process.exit(0))),console.log(`[${X}] Listening on ${B}`)}async function OB(){let Q=_[1];if(Q==="start"){let W=I(),B=c(),X=W.port||B.port||"9200",$=W.host||B.host||"0.0.0.0",Z=W.token||B.token||n();if(!Z)Z=crypto.randomUUID().replace(/-/g,""),console.log(`[anet] Generated auth token: ${Z}`),console.log(`[anet] Save this token — agents need it to connect.
95
- `);d({port:X,host:$,token:Z});let z=J();if(!z.token)z.token=Z,i(z);console.log(`[anet] Starting CommHub Server on ${$}:${X}${Z?" (auth enabled)":""}...`);let Y={...process.env,PORT:X,HOST:$};if(Z)Y.COMMHUB_AUTH_TOKEN=Z;j("bunx",["@sleep2agi/commhub-server"],{env:Y,stdio:"inherit",shell:!0}).on("exit",(U)=>process.exit(U||0))}else if(Q==="config"){let W=I(),B=c();if(W.port)B.port=W.port;if(W.host)B.host=W.host;if(W.token)B.token=W.token;if(W.port||W.host||W.token)d(B),console.log(`Server config saved: ${u()}`);console.log(JSON.stringify(B,null,2))}else console.log(`
71
+ ✅ Project ready. Next: anet create <node-name>`)}function AB(){console.warn("[deprecated] anet init profile is now anet create."),console.warn(` Run: anet create <node-name> [--runtime ...]
72
+ `),$B(q[2])}function ZB(Q,B){let W=I(),X=B.hub||W.hub;if(!X)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let $={};for(let Z of B._envs){let V=Z.indexOf("=");if(V>0)$[Z.slice(0,V)]=Z.slice(V+1)}let Y=F(B.runtime||"claude-code-cli"),U=Y==="codex-sdk"?"gpt-5.4":void 0;return{anet_version:"0.1.0",name:Q,runtime:Y,...B.hub?{hub:X}:{},...B.model||U?{model:B.model||U}:{},...B.tools?{tools:B.tools.split(",").map((Z)=>Z.trim())}:{},channels:B._channels.length>0?B._channels:["server:commhub"],env:$,flags:{dangerouslySkipPermissions:!0,...Y==="claude-code-cli"?{teammateMode:B["teammate-mode"]||"in-process"}:{},...B["max-turns"]?{maxTurns:parseInt(B["max-turns"])}:{}},...B.session?{session:B.session}:{}}}function $B(Q){let B=Q||q[1];if(!B)console.error("Usage: anet create <node-name> [--runtime claude-code-cli|codex-sdk|claude-agent-sdk] [--model ...] [--tools ...]"),process.exit(1);if(m(B),x(B))console.error(`Node "${B}" already exists: .anet/nodes/${B}/config.json`),process.exit(1);let W=N(),X=ZB(B,W),$=K(G,".claude","channels","commhub"),Y=process.cwd().replace(/\//g,"-"),U=K($,Y);if(M(U,{recursive:!0}),T(K(U,".env"),`COMMHUB_ALIAS=${B}
73
+ `),w(B,X),YB(F(X),"create"),console.log(`
74
+ [anet] Created node "${B}" (${F(X)})`),F(X)==="claude-code-cli")XB();console.log("[anet] dangerouslySkipPermissions and teammateMode enabled by default."),console.log(`[anet] To disable: edit .anet/nodes/${B}/config.json flags`),console.log(`
75
+ Start: anet start ${B}`)}var R=null;function IB(){if(!R)R=FB({input:process.stdin,output:process.stdout});return R}function b(){if(R)R.close(),R=null}function C(Q,B){let W=B?` [${B}]`:"";return new Promise((X)=>{IB().question(`${Q}${W}: `,($)=>{X($.trim()||B||"")})})}function OB(Q){if(F(Q)!=="claude-code-cli")return;if(!Q.channels?.some((z)=>z.includes("commhub")))return;let B=K(process.cwd(),".mcp.json"),W={};if(H(B))try{W=JSON.parse(J(B,"utf-8"))}catch{}let X=K(process.cwd(),".anet"),$=K(X,"node-server.ts"),Y=[K(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),K(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),K(process.argv[1],"..","..","src","node-server.ts")];for(let z of Y)if(H(z)){M(X,{recursive:!0});let E=J(z,"utf-8"),A=H($)?J($,"utf-8"):"";if(E!==A)T($,E),console.log("[anet] Updated .anet/node-server.ts");break}let U=K(X,"package.json");if(!H(U)){M(X,{recursive:!0}),T(U,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
76
+ `);try{f("bun install",{cwd:X,stdio:"pipe"})}catch{}}if(W.mcpServers=W.mcpServers||{},!Object.keys(W.mcpServers).some((z)=>z.includes("commhub")))W.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},T(B,JSON.stringify(W,null,2)+`
77
+ `),console.log("[anet] .mcp.json: added commhub");let Z=K(X,".env"),V=Q.token||"",_=`COMMHUB_URL=${Q.hub||"http://127.0.0.1:9200"}
78
+ `;if(V)_+=`COMMHUB_TOKEN=${V}
79
+ `;T(Z,_),W.mcpServers=W.mcpServers||{},W.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},T(B,JSON.stringify(W,null,2)+`
80
+ `),console.log("[anet] .mcp.json: added commhub channel server")}async function g(Q,B=!1){let W=x(Q);if(!W)console.error(`Node "${Q}" not found. Create it first: anet create ${Q}`),process.exit(1);let X=F(W),$=JB(Q,W),Y=k(W),U=!!Y&&!B,L=U?`Resuming session ${Y.slice(0,8)}...`:"Starting new session";console.log(`[anet] ${L} for "${Q}" [${X}]...
81
+ `),YB(X,"start"),OB(W);let Z=W.token||"";if(X==="codex-sdk"||X==="claude-agent-sdk"){let V=["@sleep2agi/agent-node","--config",K(O(),Q,"config.json"),"--alias",$];if(B)V.push("--new-session","true");let _={...process.env,...Z?{COMMHUB_TOKEN:Z}:{}};for(let[E,A]of Object.entries(W.env))_[E]=A.replace(/^~/,G);h("npx",V,{env:_,stdio:"inherit",shell:!0}).on("exit",(E)=>process.exit(E||0))}else{let V={...process.env,COMMHUB_ALIAS:W.alias,...Z?{COMMHUB_TOKEN:Z}:{}};for(let[E,A]of Object.entries(W.env))V[E]=A.replace(/^~/,G);if(W.channels.includes("telegram"))V.TELEGRAM_STATE_DIR=K(O(),Q,"channels","telegram");let _=[];if(W.flags.dangerouslySkipPermissions)_.push("--dangerously-skip-permissions");for(let E of W.channels)if(E.startsWith("server:"))_.push("--dangerously-load-development-channels",E);else if(E==="telegram")_.push("--channels","plugin:telegram@claude-plugins-official");else _.push("--channels",E);if(W.flags.teammateMode)_.push("--teammate-mode",W.flags.teammateMode);if(U)_.push("--resume",Y);_.push("-n",$),h("claude",_,{env:V,stdio:"inherit",shell:!0}).on("exit",(E)=>{if(!U||B){if(console.log(`
82
+ [anet] Tip: bind this Claude Code session with:`),console.log("[anet] anet session ls"),console.log(`[anet] anet resume ${Q} --session <session-id>`),B&&Y)console.log(`[anet] Next "anet start ${Q}" will still resume ${Y.slice(0,8)}... until you rebind.`)}process.exit(E||0)})}}async function o(){let Q=q[1];if(!Q){RB("start");return}await g(Q,!!N()["new-session"])}async function xB(){let Q=q[1];if(!Q){console.error("Usage: anet resume <node-name> --session <session-id>"),console.error("Daily start/resume: anet start <node-name>");return}let B=x(Q),W=N(),X=W.session;if(!X){console.warn("[deprecated] anet resume <node-name> without --session is now anet start <node-name>."),await g(Q,!1);return}if(m(Q),!B){let $={...W,session:X,runtime:W.runtime||"claude-code-cli"};B=ZB(Q,$),w(Q,B),console.log(`[anet] Created node "${Q}"`)}else{let $=k(B);if($&&$!==X&&W.yes!=="true"){let U=await C(`[anet] ${Q} already has session ${$.slice(0,8)}..., overwrite? (y/n)`,"n");if(b(),!/^y(es)?$/i.test(U)){console.log("[anet] Session unchanged.");return}}let Y=WB(Q)||B;Y.session=X,delete Y.resume,delete Y.resumeAlias,w(Q,Y)}console.log(`[anet] Saved session ${X.slice(0,8)}... to .anet/nodes/${Q}/config.json
83
+ `),await g(Q,!1)}function RB(Q){let B=c();if(B.length===0){console.log("No nodes. Run: anet create <node-name>");return}console.log(`
84
+ Nodes:
85
+ `);for(let W of B){let X=x(W);console.log(` ${W} [${F(X||void 0)}] session=${X?k(X).slice(0,8)||"-":"-"} channels=[${X?.channels.join(", ")}]`)}console.log(`
86
+ anet ${Q} <node-name>
87
+ `)}async function CB(){let Q=c();if(Q.length>0){console.log(`
88
+ Nodes:
89
+ `);for(let L of Q){let Z=x(L),V=Z?k(Z).slice(0,8)||"-":"-";console.log(` ${L} [${F(Z||void 0)}] session=${V} channels=[${Z?.channels.join(", ")}]`)}console.log()}let B=process.cwd(),W=K(G,".claude","sessions"),X=[];if(H(W))for(let L of v(W).filter((Z)=>Z.endsWith(".json")))try{let Z=JSON.parse(J(K(W,L),"utf-8"));if(Z.cwd===B)X.push(Z)}catch{}if(X.length===0&&Q.length===0){console.log("No sessions or nodes in this directory."),console.log(`Get started: anet init
90
+ `);return}let $=I(),Y=[],U={};if($.hub)try{let[L,Z]=await Promise.all([fetch(`${$.hub}/api/status`,{headers:u()}).then((V)=>V.json()),fetch(`${$.hub}/health`,{headers:u()}).then((V)=>V.json())]);Y=L.sessions||[],U=Z.sse_sessions||{}}catch{}if(X.length>0){console.log(`Sessions (${B}):
91
+ `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let L of X){let Z=L.sessionId.slice(0,18),V=!1;try{process.kill(L.pid,0),V=!0}catch{}let _="(not in network)",z=B.replace(/\//g,"-"),E=K(G,".claude","channels","commhub",z,".env");if(H(E)){let p=J(E,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(p){let D=p[1].trim(),d=Y.find((KB)=>KB.alias===D),UB=U[D]?"●":"○";_=d?`${D} ${d.status} ${UB}`:`${D} (not registered)`}}console.log(` ${Z} ${(V?`${L.pid}`:`${L.pid}✕`).padEnd(7)} ${_}`)}console.log()}}async function DB(){let Q=I(),B=N(),W=process.env.COMMHUB_URL||B.hub||Q.hub||"http://127.0.0.1:9200",X=process.env.COMMHUB_ALIAS||B.alias;if(!X)console.error("Error: --alias required"),process.exit(1);let{CommHub:$}=await Promise.resolve().then(() => (r(),a)),Y=new $({url:W,alias:X});Y.on("task",async(U)=>{console.log(`[${X}] ← ${U.from_session}: ${U.content.slice(0,100)}`),await Y.send(U.from_session,`[${X}] 收到: ${U.content.slice(0,200)}`)}),Y.on("connected",()=>console.log(`[${X}] Connected`)),Y.on("disconnected",()=>console.log(`[${X}] Reconnecting...`)),process.on("SIGINT",()=>Y.disconnect().then(()=>process.exit(0))),console.log(`[${X}] Listening on ${W}`)}async function PB(){let Q=q[1];if(Q==="start"){let B=N(),W=t(),X=B.port||W.port||"9200",$=B.host||W.host||"0.0.0.0",Y=B.token||W.token||BB();if(!Y)Y=crypto.randomUUID().replace(/-/g,""),console.log(`[anet] Generated auth token: ${Y}`),console.log(`[anet] Save this token — agents need it to connect.
92
+ `);n({port:X,host:$,token:Y});let U=I();if(!U.token)U.token=Y,QB(U);console.log(`[anet] Starting CommHub Server on ${$}:${X}${Y?" (auth enabled)":""}...`);let L={...process.env,PORT:X,HOST:$};if(Y)L.COMMHUB_AUTH_TOKEN=Y;h("bunx",["@sleep2agi/commhub-server"],{env:L,stdio:"inherit",shell:!0}).on("exit",(V)=>process.exit(V||0))}else if(Q==="config"){let B=N(),W=t();if(B.port)W.port=B.port;if(B.host)W.host=B.host;if(B.token)W.token=B.token;if(B.port||B.host||B.token)n(W),console.log(`Server config saved: ${S()}`);console.log(JSON.stringify(W,null,2))}else console.log(`
96
93
  anet server <command>
97
94
 
98
95
  start [options] Start CommHub Server
@@ -103,22 +100,22 @@ Options:
103
100
  --host <host> Bind address (default: 0.0.0.0)
104
101
  --token <token> Auth token
105
102
 
106
- Config: ${u()}
103
+ Config: ${S()}
107
104
  First 'anet server start' saves config, after that just 'anet server start'.
108
105
 
109
106
  Example:
110
107
  anet server start --port 9200 --token my-secret # 首次,保存配置
111
108
  anet server start # 之后直接启动
112
109
  anet server config # 查看配置
113
- `)}async function TB(){let Q=J(),B=I().hub||Q.hub;if(!B)console.error("Run 'anet init' first"),process.exit(1);let X=[];try{X=(await(await fetch(`${B}/api/status`,{headers:y()})).json()).sessions||[]}catch(N){console.error(`Cannot reach ${B}: ${N.message}`),process.exit(1)}if(X.length===0){console.log("No sessions in CommHub.");return}let $=X.filter((N)=>N.agent==="claude-code"&&N.project_dir);if($.length===0){console.log("No claude-code sessions found.");return}let Z=_[1],z=Z?$.filter((N)=>N.alias===Z):$;if(z.length===0){console.log(`No session found for "${Z}".`);return}let Y=0;for(let N of z){let U=N.project_dir,E=L(U,".anet","nodes",N.alias),R=L(E,"config.json");if(q(R)){console.log(` ⏭ ${N.alias} — already exists (${U})`);continue}if(!q(U)){console.log(` ⚠ ${N.alias} — project_dir not found: ${U}`);continue}let V={runtime:"claude-code",alias:N.alias,hub:B,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:N.resume_id};M(E,{recursive:!0}),K(R,JSON.stringify(V,null,2)+`
114
- `),console.log(` ✅ ${N.alias} → ${U}/.anet/nodes/${N.alias}/config.json`),Y++}console.log(`
115
- Imported ${Y} session(s). Use: cd <project> && anet resume <alias>`)}function JB(){let Q=_[1];if(Q==="ls"||Q==="list"||!Q){let W=process.cwd(),B=W.replace(/\//g,"-"),X=L(G,".claude","projects",B);if(!q(X)){console.log(`No sessions for ${W}`);return}let $=w(X).filter((Z)=>Z.endsWith(".jsonl")).sort((Z,z)=>{let Y=D(L(X,Z));return D(L(X,z)).mtimeMs-Y.mtimeMs});if($.length===0){console.log("No sessions.");return}console.log(`
116
- Sessions in ${W} (${$.length} total):
117
- `),console.log(" SESSION ID SIZE MODIFIED"),console.log(" ────────────────────────────────────── ──────── ────────────────");for(let Z of $){let z=Z.replace(".jsonl",""),Y=D(L(X,Z)),N=Y.size<1024?`${Y.size}B`:Y.size<1048576?`${(Y.size/1024).toFixed(0)}KB`:`${(Y.size/1024/1024).toFixed(1)}MB`,U=Y.mtime.toISOString().replace("T"," ").slice(0,16);console.log(` ${z} ${N.padStart(8)} ${U}`)}console.log()}else console.log(`
110
+ `)}async function wB(){let Q=I(),W=N().hub||Q.hub;if(!W)console.error("Run 'anet init' first"),process.exit(1);let X=[];try{X=(await(await fetch(`${W}/api/status`,{headers:u()})).json()).sessions||[]}catch(Z){console.error(`Cannot reach ${W}: ${Z.message}`),process.exit(1)}if(X.length===0){console.log("No sessions in CommHub.");return}let $=X.filter((Z)=>Z.agent==="claude-code"&&Z.project_dir);if($.length===0){console.log("No claude-code sessions found.");return}let Y=q[1],U=Y?$.filter((Z)=>Z.alias===Y):$;if(U.length===0){console.log(`No session found for "${Y}".`);return}let L=0;for(let Z of U){let V=Z.project_dir,_=K(V,".anet","nodes",Z.alias),z=K(_,"config.json");if(H(z)){console.log(` ⏭ ${Z.alias} — already exists (${V})`);continue}if(!H(V)){console.log(` ⚠ ${Z.alias} — project_dir not found: ${V}`);continue}let E={anet_version:"0.1.0",name:Z.alias,runtime:"claude-code-cli",channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},session:Z.resume_id};M(_,{recursive:!0}),T(z,JSON.stringify(E,null,2)+`
111
+ `),console.log(` ✅ ${Z.alias} → ${V}/.anet/nodes/${Z.alias}/config.json`),L++}console.log(`
112
+ Imported ${L} session(s). Use: cd <project> && anet resume <alias>`)}function bB(){let Q=q[1];if(Q==="ls"||Q==="list"||!Q){let B=process.cwd(),W=B.replace(/\//g,"-"),X=K(G,".claude","projects",W);if(!H(X)){console.log(`No sessions for ${B}`);return}let $=v(X).filter((Y)=>Y.endsWith(".jsonl")).sort((Y,U)=>{let L=P(K(X,Y));return P(K(X,U)).mtimeMs-L.mtimeMs});if($.length===0){console.log("No sessions.");return}console.log(`
113
+ Sessions in ${B} (${$.length} total):
114
+ `),console.log(" SESSION ID SIZE MODIFIED"),console.log(" ────────────────────────────────────── ──────── ────────────────");for(let Y of $){let U=Y.replace(".jsonl",""),L=P(K(X,Y)),Z=L.size<1024?`${L.size}B`:L.size<1048576?`${(L.size/1024).toFixed(0)}KB`:`${(L.size/1024/1024).toFixed(1)}MB`,V=L.mtime.toISOString().replace("T"," ").slice(0,16);console.log(` ${U} ${Z.padStart(8)} ${V}`)}console.log()}else console.log(`
118
115
  anet session <command>
119
116
 
120
117
  ls List Claude Code sessions in current project
121
- `)}async function MB(){let Q=_[1],W=I();if(Q==="add"){let B=_[2],X=_[3];if(!B||!X){console.log(`
118
+ `)}async function vB(){let Q=q[1],B=N();if(Q==="add"){let W=q[2],X=q[3];if(!W||!X){console.log(`
122
119
  anet channel add <type> <node-id> [options]
123
120
 
124
121
  Types: telegram
@@ -127,26 +124,19 @@ Options:
127
124
  --bot-token <token> Bot token
128
125
  --allow <user-id> Allow user ID
129
126
 
130
- Options:
131
- --bot-token <token> Bot token
132
- --allow <user-id> Allow user ID
133
- --runtime <rt> claude-code (默认) / codex / claude-sdk(node 不存在时)
134
- --model <model> 模型名(codex 默认 gpt-5.4)
135
-
136
127
  Example:
137
128
  anet channel add telegram 指挥室 --bot-token 123:ABC --allow 7612221352
138
- anet channel add telegram A站牛 --runtime codex --bot-token 123:ABC --allow 7612221352
139
129
  anet channel add telegram 指挥室 # 交互式
140
- `);return}if(B!=="telegram")console.error(`P0 only supports telegram channels. Unsupported type: ${B}`),process.exit(1);let $=x(X);if(!$){let E=J(),R=W.runtime;if(!R)R=await O("Runtime (claude-code/codex/claude-sdk)","claude-code");let V=R!=="claude-code";$={runtime:V?"agent-sdk":"claude-code",...V?{codexRuntime:R==="codex"?"codex":"claude"}:{},alias:X,hub:E.hub||"",channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},...V&&R==="codex"?{model:W.model||"gpt-5.4"}:{}},P(X,$),console.log(`[anet] Created node "${X}" (${R})`)}let Z=W["bot-token"],z=W.allow;if(!Z)Z=await O(`${B} Bot Token`);if(!z)z=await O("Allow User ID (发 @userinfobot 获取数字ID)","7612221352");if(v(),!Z||!z)console.error("Error: bot-token and allow required"),process.exit(1);let Y=L(F(),X,"channels",B);M(Y,{recursive:!0}),M(L(Y,"inbox"),{recursive:!0});let N="TELEGRAM_BOT_TOKEN";K(L(Y,".env"),`${N}=${Z}
141
- `),K(L(Y,"access.json"),JSON.stringify({dmPolicy:"allowlist",allowFrom:[z],groups:{},pending:{}},null,2)+`
142
- `);let U=($.runtime||"claude-code")==="agent-sdk"?`telegram:${Y}`:"plugin:telegram@claude-plugins-official";if(!$.channels.includes(U))$.channels.push(U);$.env.TELEGRAM_STATE_DIR=Y,P(X,$),console.log(`
143
- ✅ ${B} channel added to "${X}"`),console.log(` ${Y}/`),console.log(" config.json updated")}else if(Q==="ls"){let B=_[2],X=B?[B]:S(),$=!1;for(let Z of X){let z=L(F(),Z,"channels");if(!q(z))continue;let Y=w(z).filter((N)=>{try{return D(L(z,N)).isDirectory()}catch{return!1}});if(Y.length===0)continue;if(!$)console.log(`
130
+ `);return}if(W!=="telegram")console.error(`P0 only supports telegram channels. Unsupported type: ${W}`),process.exit(1);m(X);let $=x(X),Y=WB(X);if(!$)console.error(`Node "${X}" not found. Create it first: anet create ${X} --runtime codex-sdk`),process.exit(1);let U=B["bot-token"],L=B.allow;if(!U)U=await C(`${W} Bot Token`);if(!L)L=await C("Allow User ID (发 @userinfobot 获取数字ID)","7612221352");if(b(),!U||!L)console.error("Error: bot-token and allow required"),process.exit(1);let Z=K(O(),X,"channels",W);M(Z,{recursive:!0}),M(K(Z,"inbox"),{recursive:!0});let V="TELEGRAM_BOT_TOKEN",_=K(Z,".env");T(_,`${V}=${U}
131
+ `);try{TB(_,384)}catch{}if(T(K(Z,"access.json"),JSON.stringify({dmPolicy:"allowlist",allowFrom:[L],groups:{},pending:{}},null,2)+`
132
+ `),!Y)console.error(`Node "${X}" not found. Create it first: anet create ${X} --runtime codex-sdk`),process.exit(1);if(Y.channels=Y.channels||[],!Y.channels.includes("telegram"))Y.channels.push("telegram");w(X,Y),console.log(`
133
+ ✅ ${W} channel added to "${X}"`),console.log(` ${Z}/`),console.log(" config.json updated")}else if(Q==="ls"){let W=q[2],X=W?[W]:c(),$=!1;for(let Y of X){let U=K(O(),Y,"channels");if(!H(U))continue;let L=v(U).filter((Z)=>{try{return P(K(U,Z)).isDirectory()}catch{return!1}});if(L.length===0)continue;if(!$)console.log(`
144
134
  Node Channels:
145
- `),$=!0;for(let N of Y){let U=L(z,N,"access.json"),E="";if(q(U))try{E=JSON.parse(T(U,"utf-8")).allowFrom?.join(", ")||""}catch{}console.log(` ${Z.padEnd(20)} ${N.padEnd(12)} allow: ${E||"(none)"}`)}}if(!$)console.log("No channels. Add one: anet channel add telegram <node-id>");console.log()}else console.log(`
135
+ `),$=!0;for(let Z of L){let V=K(U,Z,"access.json"),_="";if(H(V))try{_=JSON.parse(J(V,"utf-8")).allowFrom?.join(", ")||""}catch{}console.log(` ${Y.padEnd(20)} ${Z.padEnd(12)} allow: ${_||"(none)"}`)}}if(!$)console.log("No channels. Add one: anet channel add telegram <node-id>");console.log()}else console.log(`
146
136
  anet channel <command>
147
137
 
148
138
  add <type> <node-id> Add channel to a node
149
139
  ls [node-id] List channels
150
140
 
151
141
  Data: .anet/nodes/<node-id>/channels/<type>/
152
- `)}switch(k){case"init":if(_[1]==="project")UB();else if(_[1]==="profile")LB();else NB();break;case"server":OB();break;case"start":a();break;case"resume":qB();break;case"import":TB();break;case"channel":MB();break;case"session":JB();break;case"ls":case"list":KB();break;case"run":HB();break;case"-v":case"--version":case"version":{let Q=JSON.parse(T(L(new URL(".",import.meta.url).pathname,"..","..","package.json"),"utf-8"));console.log(`anet v${Q.version}`);break}case"--help":case"-h":case void 0:l();break;default:if(x(k))_.unshift("start"),a();else console.error(`Unknown: ${k}`),l(),process.exit(1)}
142
+ `)}switch(y){case"init":if(q[1]==="project")NB();else if(q[1]==="profile")AB();else GB();break;case"create":$B();break;case"server":PB();break;case"start":o();break;case"resume":xB();break;case"import":wB();break;case"channel":vB();break;case"session":bB();break;case"ls":case"list":CB();break;case"run":DB();break;case"-v":case"--version":case"version":{let Q=JSON.parse(J(K(new URL(".",import.meta.url).pathname,"..","..","package.json"),"utf-8"));console.log(`anet v${Q.version}`);break}case"--help":case"-h":case void 0:s();break;default:if(x(y))q.unshift("start"),o();else console.error(`Unknown: ${y}`),s(),process.exit(1)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network",
3
- "version": "0.0.52",
3
+ "version": "1.0.0",
4
4
  "description": "AI Agent Network — Server + Client + Setup in one package. SSE real-time communication for multi-agent orchestration.",
5
5
  "type": "module",
6
6
  "main": "dist/src/client.js",