@sleep2agi/agent-network 0.0.33 → 0.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,16 +75,28 @@ anet init profile <id> [options] # 创建启动 profile
75
75
  ```bash
76
76
  anet start <id> # 新建 session
77
77
  anet resume <id> # 恢复上次 session
78
- anet start # 列出所有 profile
78
+ anet start # 列出所有 node 配置
79
79
  anet <id> # 快捷启动
80
80
  ```
81
81
 
82
82
  profile 不存在时自动进入交互式创建。
83
83
 
84
- `anet start` 根据 profile 的 `runtime` 自动选择:
85
- - `claude-code` → spawn claude CLI
84
+ `anet start` 根据 config 的 `runtime` 自动选择:
85
+ - `claude-code` → spawn claude CLI(自动配置 `.mcp.json`)
86
86
  - `agent-sdk` → spawn @sleep2agi/agent-node
87
87
 
88
+ ### 快速接入已有 session
89
+
90
+ 已有 Claude Code session 想接入 anet?一条命令:
91
+
92
+ ```bash
93
+ cd ~/your-project
94
+ anet resume 你的Agent --session <session-id>
95
+ # 自动创建 .anet/nodes/你的Agent/config.json + 配置 .mcp.json + resume
96
+ ```
97
+
98
+ 不需要先 `init profile`,直接 resume 即可。
99
+
88
100
  ### 状态查看
89
101
 
90
102
  ```bash
package/dist/bin/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- var r=Object.defineProperty;var a=(B)=>B;function o(B,Q){this[B]=a.bind(null,Q)}var i=(B,Q)=>{for(var z in Q)r(B,z,{get:Q[z],enumerable:!0,configurable:!0,set:o.bind(Q,z)})};var s=(B,Q)=>()=>(B&&(Q=B(B=0)),Q);var y={};i(y,{default:()=>zz,CommHub:()=>D});import{EventEmitter as e}from"events";import{hostname as b}from"os";var D,zz;var S=s(()=>{D=class D extends e{url;alias;token;agent;resumeId;heartbeatInterval;reconnectDelay;heartbeatTimer;sseAbort;running=!1;constructor(B){super();if(this.url=B.url.replace(/\/$/,""),this.alias=B.alias,this.token=B.token,this.agent=B.agent||"sdk",this.resumeId=`sdk-${B.alias}-${Date.now().toString(36)}`,this.heartbeatInterval=B.heartbeatInterval??180000,this.reconnectDelay=B.reconnectDelay??3000,B.autoConnect!==!1)this.connect()}log(B){console.log(`[${new Date().toTimeString().slice(0,8)}] [commhub:${this.alias}] ${B}`)}async call(B,Q){let z={"Content-Type":"application/json",Accept:"application/json, text/event-stream"};if(this.token)z.Authorization=`Bearer ${this.token}`;let Z=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:z,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:B,arguments:Q}})})).text(),Y=Z.match(/data: (.+)/),$=Y?JSON.parse(Y[1]):JSON.parse(Z),N=$?.result?.content?.[0]?.text;return N?JSON.parse(N):$}async connect(){if(this.running)return;this.running=!0,await this.status("idle"),this.log("registered"),this.heartbeatTimer=setInterval(()=>{this.status("idle").catch((B)=>this.log(`heartbeat failed: ${B.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(B,Q,z="normal"){return this.call("send_task",{alias:B,task:Q,priority:z,from_session:this.alias})}async message(B,Q){return this.call("send_message",{alias:B,message:Q,from_session:this.alias})}async reply(B,Q,z="completed"){return this.call("reply",{task_id:B,text:Q,status:z})}async status(B,Q){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:B,server:b(),hostname:b(),agent:this.agent,project_dir:process.cwd(),...Q})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(B,Q){return this.call("broadcast",{message:B,filter_server:Q?.server,filter_status:Q?.status})}async connectSSE(){let B=encodeURIComponent(this.alias),Q=`${this.url}/events/${B}`,z=this.reconnectDelay;while(this.running){try{this.sseAbort=new AbortController;let W={Accept:"text/event-stream"};if(this.token)W.Authorization=`Bearer ${this.token}`;let Z=await fetch(Q,{headers:W,signal:this.sseAbort.signal});if(!Z.ok||!Z.body){this.log(`SSE failed: ${Z.status}`),await this.sleep(z),z=Math.min(z*1.5,60000);continue}z=this.reconnectDelay;let Y=Z.body.getReader(),$=new TextDecoder,N="";while(this.running){let{done:X,value:K}=await Y.read();if(X)break;N+=$.decode(K,{stream:!0});let R=N.split(`
3
- `);N=R.pop()||"";for(let T of R){if(!T.startsWith("data: "))continue;try{let E=JSON.parse(T.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(W){if(W.name==="AbortError")break;this.emit("error",W),this.log(`SSE error: ${W.message}`)}if(this.running)this.emit("disconnected"),this.log(`SSE reconnecting in ${z/1000}s...`),await this.sleep(z),z=Math.min(z*1.5,60000)}}async processInbox(){try{let Q=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let z of Q)await this.call("ack_inbox",{alias:this.alias,message_id:z.id}),this.log(`← ${z.from_session}: ${z.content.slice(0,60)}`),this.emit("task",z),this.emit("message",z)}catch(B){this.log(`inbox error: ${B.message}`)}}sleep(B){return new Promise((Q)=>setTimeout(Q,B))}};zz=D});import{readFileSync as _,writeFileSync as O,existsSync as H,mkdirSync as I,readdirSync as f}from"fs";import{join as U}from"path";import{spawn as w,execSync as g}from"child_process";import{createInterface as Yz}from"readline";var L=process.argv.slice(2),x=L[0],J=process.env.HOME||process.env.USERPROFILE||"~";function m(){return U(J,".anet","config.json")}function P(){return U(process.cwd(),".anet","nodes")}function G(){let B=m();if(H(B))try{return JSON.parse(_(B,"utf-8"))}catch{}return{}}function Bz(B){let Q=U(J,".anet");I(Q,{recursive:!0}),O(U(Q,"config.json"),JSON.stringify(B,null,2)+`
4
- `)}function A(B){let Q=U(P(),B,"config.json");if(H(Q))try{return JSON.parse(_(Q,"utf-8"))}catch{}return null}function k(B,Q){let z=U(P(),B);I(z,{recursive:!0}),O(U(z,"config.json"),JSON.stringify(Q,null,2)+`
5
- `)}function c(){let B=P();if(!H(B))return[];return f(B).filter((Q)=>H(U(B,Q,"config.json")))}function F(){let B={_channels:[],_envs:[]};for(let Q=0;Q<L.length;Q++){if(L[Q]==="--channel"&&L[Q+1]){B._channels.push(L[++Q]);continue}if(L[Q]==="--env"&&L[Q+1]){B._envs.push(L[++Q]);continue}if(L[Q].startsWith("--")&&L[Q+1]&&!L[Q+1].startsWith("--"))B[L[Q].slice(2)]=L[++Q]}return B}function u(){console.log(`
2
+ var o=Object.defineProperty;var i=(B)=>B;function s(B,Q){this[B]=i.bind(null,Q)}var e=(B,Q)=>{for(var z in Q)o(B,z,{get:Q[z],enumerable:!0,configurable:!0,set:s.bind(Q,z)})};var zz=(B,Q)=>()=>(B&&(Q=B(B=0)),Q);var u={};e(u,{default:()=>Qz,CommHub:()=>w});import{EventEmitter as Bz}from"events";import{hostname as S}from"os";var w,Qz;var h=zz(()=>{w=class w extends Bz{url;alias;token;agent;resumeId;heartbeatInterval;reconnectDelay;heartbeatTimer;sseAbort;running=!1;constructor(B){super();if(this.url=B.url.replace(/\/$/,""),this.alias=B.alias,this.token=B.token,this.agent=B.agent||"sdk",this.resumeId=`sdk-${B.alias}-${Date.now().toString(36)}`,this.heartbeatInterval=B.heartbeatInterval??180000,this.reconnectDelay=B.reconnectDelay??3000,B.autoConnect!==!1)this.connect()}log(B){console.log(`[${new Date().toTimeString().slice(0,8)}] [commhub:${this.alias}] ${B}`)}async call(B,Q){let z={"Content-Type":"application/json",Accept:"application/json, text/event-stream"};if(this.token)z.Authorization=`Bearer ${this.token}`;let N=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:z,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:B,arguments:Q}})})).text(),X=N.match(/data: (.+)/),U=X?JSON.parse(X[1]):JSON.parse(N),Y=U?.result?.content?.[0]?.text;return Y?JSON.parse(Y):U}async connect(){if(this.running)return;this.running=!0,await this.status("idle"),this.log("registered"),this.heartbeatTimer=setInterval(()=>{this.status("idle").catch((B)=>this.log(`heartbeat failed: ${B.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(B,Q,z="normal"){return this.call("send_task",{alias:B,task:Q,priority:z,from_session:this.alias})}async message(B,Q){return this.call("send_message",{alias:B,message:Q,from_session:this.alias})}async reply(B,Q,z="completed"){return this.call("reply",{task_id:B,text:Q,status:z})}async status(B,Q){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:B,server:S(),hostname:S(),agent:this.agent,project_dir:process.cwd(),...Q})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(B,Q){return this.call("broadcast",{message:B,filter_server:Q?.server,filter_status:Q?.status})}async connectSSE(){let B=encodeURIComponent(this.alias),Q=`${this.url}/events/${B}`,z=this.reconnectDelay;while(this.running){try{this.sseAbort=new AbortController;let W={Accept:"text/event-stream"};if(this.token)W.Authorization=`Bearer ${this.token}`;let N=await fetch(Q,{headers:W,signal:this.sseAbort.signal});if(!N.ok||!N.body){this.log(`SSE failed: ${N.status}`),await this.sleep(z),z=Math.min(z*1.5,60000);continue}z=this.reconnectDelay;let X=N.body.getReader(),U=new TextDecoder,Y="";while(this.running){let{done:Z,value:$}=await X.read();if(Z)break;Y+=U.decode($,{stream:!0});let L=Y.split(`
3
+ `);Y=L.pop()||"";for(let E of L){if(!E.startsWith("data: "))continue;try{let R=JSON.parse(E.slice(6));if(R.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(R.type==="new_task"||R.type==="new_message"||R.type==="broadcast")await this.processInbox()}catch{}}}}catch(W){if(W.name==="AbortError")break;this.emit("error",W),this.log(`SSE error: ${W.message}`)}if(this.running)this.emit("disconnected"),this.log(`SSE reconnecting in ${z/1000}s...`),await this.sleep(z),z=Math.min(z*1.5,60000)}}async processInbox(){try{let Q=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let z of Q)await this.call("ack_inbox",{alias:this.alias,message_id:z.id}),this.log(`← ${z.from_session}: ${z.content.slice(0,60)}`),this.emit("task",z),this.emit("message",z)}catch(B){this.log(`inbox error: ${B.message}`)}}sleep(B){return new Promise((Q)=>setTimeout(Q,B))}};Qz=w});import{readFileSync as I,writeFileSync as T,existsSync as q,mkdirSync as J,readdirSync as m}from"fs";import{join as K}from"path";import{spawn as P,execSync as c}from"child_process";import{createInterface as $z}from"readline";var V=process.argv.slice(2),C=V[0],G=process.env.HOME||process.env.USERPROFILE||"~";function p(){return K(G,".anet","config.json")}function v(){return K(process.cwd(),".anet","nodes")}function D(){return M().token||process.env.COMMHUB_TOKEN||O().token||""}function j(B){let Q=B||D();return Q?{Authorization:`Bearer ${Q}`}:{}}function O(){let B=p();if(q(B))try{return JSON.parse(I(B,"utf-8"))}catch{}return{}}function Wz(B){let Q=K(G,".anet");J(Q,{recursive:!0}),T(K(Q,"config.json"),JSON.stringify(B,null,2)+`
4
+ `)}function A(B){let Q=K(v(),B,"config.json");if(q(Q))try{return JSON.parse(I(Q,"utf-8"))}catch{}return null}function b(B,Q){let z=K(v(),B);J(z,{recursive:!0}),T(K(z,"config.json"),JSON.stringify(Q,null,2)+`
5
+ `)}function d(){let B=v();if(!q(B))return[];return m(B).filter((Q)=>q(K(B,Q,"config.json")))}function M(){let B={_channels:[],_envs:[]};for(let Q=0;Q<V.length;Q++){if(V[Q]==="--channel"&&V[Q+1]){B._channels.push(V[++Q]);continue}if(V[Q]==="--env"&&V[Q+1]){B._envs.push(V[++Q]);continue}if(V[Q].startsWith("--")&&V[Q+1]&&!V[Q+1].startsWith("--"))B[V[Q].slice(2)]=V[++Q]}return B}function f(){console.log(`
6
6
  anet — AI Agent Network CLI
7
7
 
8
8
  anet init Configure hub URL (global, once)
@@ -22,11 +22,12 @@ Quick start:
22
22
  anet init --hub http://IP:9200
23
23
  anet start 指挥室 # Claude Code Agent
24
24
  anet start 小明 # MiniMax Agent (runtime: agent-sdk)
25
- `)}async function Qz(){let B=F(),Q=B.hub;if(!Q)Q=await q("CommHub URL (e.g. http://YOUR_IP:9200)"),p();if(!Q)console.error("Error: hub URL required"),process.exit(1);Q=Q.replace(/\/+$/,"");try{let Z=await(await fetch(`${Q}/health`)).json();console.log(`✅ CommHub v${Z.version} — ${Z.sessions} sessions, ${Z.sse_connections} SSE`)}catch(W){console.error(`❌ Cannot reach ${Q}: ${W.message}`),process.exit(1)}let z=G();if(z.hub=Q,B.token)z.token=B.token;Bz(z),console.log(`
26
- Saved to ${m()}`),console.log("Next: anet init project")}async function Wz(){let Q=G().hub;if(!Q)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let z=U(process.cwd(),".anet");I(z,{recursive:!0});let W=U(z,"node-server.ts");if(!H(W)){let K=[U(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),U(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),U(process.argv[1],"..","..","src","node-server.ts")],R=!1;for(let T of K)if(H(T)){O(W,_(T,"utf-8")),console.log(" ✅ .anet/node-server.ts"),R=!0;break}if(!R)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 Z=U(z,"package.json");if(!H(Z)){O(Z,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
27
- `);try{g("bun install",{cwd:z,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let Y=U(z,".env");O(Y,`COMMHUB_URL=${Q}
28
- `),console.log(`CommHub URL: ${Q}`);let $=U(process.cwd(),".mcp.json"),N={};if(H($))try{N=JSON.parse(_($,"utf-8"))}catch{}if(!N.mcpServers?.commhub)N.mcpServers=N.mcpServers||{},N.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},O($,JSON.stringify(N,null,2)+`
29
- `),console.log(".mcp.json: commhub .anet/node-server.ts");else console.log(".mcp.json: commhub already set");let X=U(process.cwd(),"CLAUDE.md");if(!H(X))O(X,`# Agent Network (CommHub)
25
+ `)}async function Xz(){let B=M(),Q=B.hub;if(!Q)Q=await H("CommHub URL (e.g. http://YOUR_IP:9200)"),l();if(!Q)console.error("Error: hub URL required"),process.exit(1);Q=Q.replace(/\/+$/,"");let z=B.token||"";try{let X=await(await fetch(`${Q}/health`,{headers:z?{Authorization:`Bearer ${z}`}:{}})).json();console.log(`✅ CommHub v${X.version} — ${X.sessions} sessions, ${X.sse_connections} SSE`)}catch(N){console.error(`❌ Cannot reach ${Q}: ${N.message}`),process.exit(1)}let W=O();if(W.hub=Q,z)W.token=z;Wz(W),console.log(`
26
+ Saved to ${p()}`),console.log("Next: anet init project")}async function Yz(){let B=O(),Q=B.hub;if(!Q)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let z=K(process.cwd(),".anet");J(z,{recursive:!0});let W=K(z,"node-server.ts");if(!q(W)){let E=[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")],R=!1;for(let _ of E)if(q(_)){T(W,I(_,"utf-8")),console.log(" ✅ .anet/node-server.ts"),R=!0;break}if(!R)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 N=K(z,"package.json");if(!q(N)){T(N,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
27
+ `);try{c("bun install",{cwd:z,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let X=K(z,".env"),U=B.token||"",Y=`COMMHUB_URL=${Q}
28
+ `;if(U)Y+=`COMMHUB_TOKEN=${U}
29
+ `;T(X,Y),console.log(`CommHub URL: ${Q}${U?" (with token)":""}`);let Z=K(process.cwd(),".mcp.json"),$={};if(q(Z))try{$=JSON.parse(I(Z,"utf-8"))}catch{}if(!$.mcpServers?.commhub)$.mcpServers=$.mcpServers||{},$.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},T(Z,JSON.stringify($,null,2)+`
30
+ `),console.log(".mcp.json: commhub → .anet/node-server.ts");else console.log(".mcp.json: commhub already set");let L=K(process.cwd(),"CLAUDE.md");if(!q(L))T(L,`# Agent Network (CommHub)
30
31
 
31
32
  ## 通信方式
32
33
 
@@ -65,28 +66,30 @@ commhub_get_all_status()
65
66
  - 回复指挥室用 commhub_send_task(不是 commhub_reply,reply 不推送)
66
67
  - 不要猜 alias,用 get_all_status 查
67
68
  `),console.log("CLAUDE.md: created");else console.log("CLAUDE.md: already exists");console.log(`
68
- ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function Xz(){let B=L[2];if(!B)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let Q=G(),z=F(),W=z.alias||B,Z=z.hub||Q.hub;if(!Z)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Y={};for(let T of z._envs){let E=T.indexOf("=");if(E>0)Y[T.slice(0,E)]=T.slice(E+1)}let $=z.runtime||"claude-code",N={anet_version:"0.0.24",...z.name?{name:z.name}:{},runtime:$,alias:W,hub:Z,...z.model?{model:z.model}:{},...z.tools?{tools:z.tools.split(",").map((T)=>T.trim())}:{},channels:z._channels.length>0?z._channels:$==="claude-code"?["server:commhub"]:[],env:Y,flags:{dangerouslySkipPermissions:!0,...$==="claude-code"?{teammateMode:z["teammate-mode"]||"in-process"}:{},...z["max-turns"]?{maxTurns:parseInt(z["max-turns"])}:{}},...z.resume?{resume:z.resume}:{},...z["resume-alias"]?{resumeAlias:z["resume-alias"]}:{}},X=U(J,".claude","channels","commhub"),K=process.cwd().replace(/\//g,"-"),R=U(X,K);if(I(R,{recursive:!0}),O(U(R,".env"),`COMMHUB_ALIAS=${W}
69
- `),k(B,N),console.log(`
70
- ✅ Profile "${B}" saved`),console.log(` alias: ${W}`),console.log(` channels: ${N.channels.join(", ")}`),Object.keys(Y).length)console.log(` env: ${Object.keys(Y).join(", ")}`);console.log(`
71
- Start: anet start ${B}`)}var M=null;function Zz(){if(!M)M=Yz({input:process.stdin,output:process.stdout});return M}function p(){if(M)M.close(),M=null}function q(B,Q){let z=Q?` [${Q}]`:"";return new Promise((W)=>{Zz().question(`${B}${z}: `,(Z)=>{W(Z.trim()||Q||"")})})}async function $z(B){let Q=G();console.log(`
69
+ ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function Zz(){let B=V[2];if(!B)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let Q=O(),z=M(),W=z.alias||B,N=z.hub||Q.hub;if(!N)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let X={};for(let E of z._envs){let R=E.indexOf("=");if(R>0)X[E.slice(0,R)]=E.slice(R+1)}let U=z.runtime||"claude-code",Y={anet_version:"0.0.24",...z.name?{name:z.name}:{},runtime:U,alias:W,hub:N,...z.model?{model:z.model}:{},...z.tools?{tools:z.tools.split(",").map((E)=>E.trim())}:{},channels:z._channels.length>0?z._channels:U==="claude-code"?["server:commhub"]:[],env:X,flags:{dangerouslySkipPermissions:!0,...U==="claude-code"?{teammateMode:z["teammate-mode"]||"in-process"}:{},...z["max-turns"]?{maxTurns:parseInt(z["max-turns"])}:{}},...z.resume?{resume:z.resume}:{},...z["resume-alias"]?{resumeAlias:z["resume-alias"]}:{}},Z=K(G,".claude","channels","commhub"),$=process.cwd().replace(/\//g,"-"),L=K(Z,$);if(J(L,{recursive:!0}),T(K(L,".env"),`COMMHUB_ALIAS=${W}
70
+ `),b(B,Y),console.log(`
71
+ ✅ Profile "${B}" saved`),console.log(` alias: ${W}`),console.log(` channels: ${Y.channels.join(", ")}`),Object.keys(X).length)console.log(` env: ${Object.keys(X).join(", ")}`);console.log(`
72
+ Start: anet start ${B}`)}var F=null;function Nz(){if(!F)F=$z({input:process.stdin,output:process.stdout});return F}function l(){if(F)F.close(),F=null}function H(B,Q){let z=Q?` [${Q}]`:"";return new Promise((W)=>{Nz().question(`${B}${z}: `,(N)=>{W(N.trim()||Q||"")})})}async function Uz(B){let Q=O();console.log(`
72
73
  Profile "${B}" not found. Let's create it:
73
- `);let z=await q("Runtime (claude-code / agent-sdk)","claude-code"),W=await q("Alias",B),Z,Y=[],$=[],N="";if(z==="agent-sdk")Z=await q("Model","MiniMax-M2.7"),Y=(await q("Tools (comma-separated)","Read,Bash,Grep")).split(",").map((V)=>V.trim()).filter(Boolean);else $=(await q("Channels (comma-separated)","server:commhub")).split(",").map((V)=>V.trim()).filter(Boolean),N=await q("Teammate mode","in-process");let X=await q("Extra env (K=V, comma-separated, empty to skip)"),K={};if(X)for(let E of X.split(",")){let V=E.trim().indexOf("=");if(V>0)K[E.trim().slice(0,V)]=E.trim().slice(V+1)}let R=Q.hub;if(!R)console.error(`
74
- Run 'anet init' first to configure hub URL`),process.exit(1);let T={anet_version:"0.0.23",alias:W,hub:R,runtime:z,...Z?{model:Z}:{},...Y.length?{tools:Y}:{},channels:$,env:K,flags:{dangerouslySkipPermissions:!0,...N?{teammateMode:N}:{}}};return k(B,T),p(),console.log(`
74
+ `);let z=await H("Runtime (claude-code / agent-sdk)","claude-code"),W=await H("Alias",B),N,X=[],U=[],Y="";if(z==="agent-sdk")N=await H("Model","MiniMax-M2.7"),X=(await H("Tools (comma-separated)","Read,Bash,Grep")).split(",").map((_)=>_.trim()).filter(Boolean);else U=(await H("Channels (comma-separated)","server:commhub")).split(",").map((_)=>_.trim()).filter(Boolean),Y=await H("Teammate mode","in-process");let Z=await H("Extra env (K=V, comma-separated, empty to skip)"),$={};if(Z)for(let R of Z.split(",")){let _=R.trim().indexOf("=");if(_>0)$[R.trim().slice(0,_)]=R.trim().slice(_+1)}let L=Q.hub;if(!L)console.error(`
75
+ Run 'anet init' first to configure hub URL`),process.exit(1);let E={anet_version:"0.0.23",alias:W,hub:L,runtime:z,...N?{model:N}:{},...X.length?{tools:X}:{},channels:U,env:$,flags:{dangerouslySkipPermissions:!0,...Y?{teammateMode:Y}:{}}};return b(B,E),l(),console.log(`
75
76
  ✅ Profile "${B}" saved
76
- `),T}function Nz(B){if((B.runtime||"claude-code")!=="claude-code")return;if(!B.channels?.some(($)=>$.includes("commhub")))return;let Q=U(process.cwd(),".mcp.json"),z={};if(H(Q))try{z=JSON.parse(_(Q,"utf-8"))}catch{}if(z.mcpServers?.commhub)return;let W=U(process.cwd(),".anet"),Z=U(W,"node-server.ts");if(!H(Z)){I(W,{recursive:!0});let $=[U(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),U(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),U(process.argv[1],"..","..","src","node-server.ts")];for(let N of $)if(H(N)){O(Z,_(N,"utf-8")),console.log("[anet] Created .anet/node-server.ts");break}}let Y=U(W,"package.json");if(!H(Y)){I(W,{recursive:!0}),O(Y,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
77
- `);try{g("bun install",{cwd:W,stdio:"pipe"})}catch{}}z.mcpServers=z.mcpServers||{},z.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},O(Q,JSON.stringify(z,null,2)+`
78
- `),console.log("[anet] .mcp.json: added commhub channel server")}async function d(B,Q){let z=A(B);if(!z)z=await $z(B);let W=z.runtime||"claude-code";if(console.log(`[anet] ${Q==="start"?"Starting new":"Resuming"} "${B}" (${z.alias}) [${W}]...
79
- `),Nz(z),W==="agent-sdk"){let Y=["@sleep2agi/agent-node","--alias",z.alias,"--hub",z.hub];if(z.model)Y.push("--model",z.model);if(z.tools?.length)Y.push("--tools",z.tools.join(","));if(z.flags?.maxTurns)Y.push("--max-turns",String(z.flags.maxTurns));let $={...process.env};for(let[X,K]of Object.entries(z.env))$[X]=K.replace(/^~/,J);w("npx",Y,{env:$,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}else{let Y={...process.env,COMMHUB_ALIAS:z.alias};for(let[X,K]of Object.entries(z.env))Y[X]=K.replace(/^~/,J);let $=[];if(z.flags.dangerouslySkipPermissions)$.push("--dangerously-skip-permissions");for(let X of z.channels)if(X.startsWith("server:"))$.push("--dangerously-load-development-channels",X);else $.push("--channels",X);if(z.flags.teammateMode)$.push("--teammate-mode",z.flags.teammateMode);if(Q==="resume"){let X=z.resume||z.resumeAlias||z.name||z.alias;$.push("--resume",X)}$.push("-n",z.name||z.alias),w("claude",$,{env:Y,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}}async function h(){let B=L[1];if(!B){l("start");return}await d(B,"start")}async function Uz(){let B=L[1];if(!B){l("resume");return}let Q=A(B);if(!Q){let z=F(),W=G(),Z=z.hub||W.hub,Y=z.session;if(!Y)console.log(`Profile "${B}" not found.
80
- `),console.log(`Quick setup: anet resume ${B} --session <session-id>`),console.log(`Or create: anet init profile ${B} --alias ${B} --resume <session-id>`),process.exit(1);if(!Z)console.error("Run 'anet init' first"),process.exit(1);Q={runtime:"claude-code",alias:z.alias||B,hub:Z,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:Y},k(B,Q),console.log(`[anet] Created .anet/nodes/${B}/config.json (resume: ${Y.slice(0,8)}...)
81
- `)}await d(B,"resume")}function l(B){let Q=c();if(Q.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
77
+ `),E}function Kz(B){if((B.runtime||"claude-code")!=="claude-code")return;if(!B.channels?.some((L)=>L.includes("commhub")))return;let Q=K(process.cwd(),".mcp.json"),z={};if(q(Q))try{z=JSON.parse(I(Q,"utf-8"))}catch{}if(z.mcpServers?.commhub)return;let W=K(process.cwd(),".anet"),N=K(W,"node-server.ts");if(!q(N)){J(W,{recursive:!0});let L=[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 E of L)if(q(E)){T(N,I(E,"utf-8")),console.log("[anet] Created .anet/node-server.ts");break}}let X=K(W,"package.json");if(!q(X)){J(W,{recursive:!0}),T(X,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
78
+ `);try{c("bun install",{cwd:W,stdio:"pipe"})}catch{}}let U=K(W,".env"),Y=O(),Z=D(),$=`COMMHUB_URL=${B.hub||Y.hub||"http://127.0.0.1:9200"}
79
+ `;if(Z)$+=`COMMHUB_TOKEN=${Z}
80
+ `;T(U,$),z.mcpServers=z.mcpServers||{},z.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},T(Q,JSON.stringify(z,null,2)+`
81
+ `),console.log("[anet] .mcp.json: added commhub channel server")}async function r(B,Q){let z=A(B);if(!z)z=await Uz(B);let W=z.runtime||"claude-code";if(console.log(`[anet] ${Q==="start"?"Starting new":"Resuming"} "${B}" (${z.alias}) [${W}]...
82
+ `),Kz(z),W==="agent-sdk"){let X=["@sleep2agi/agent-node","--alias",z.alias,"--hub",z.hub];if(z.model)X.push("--model",z.model);if(z.tools?.length)X.push("--tools",z.tools.join(","));if(z.flags?.maxTurns)X.push("--max-turns",String(z.flags.maxTurns));let U=D(),Y={...process.env,...U?{COMMHUB_TOKEN:U}:{}};for(let[$,L]of Object.entries(z.env))Y[$]=L.replace(/^~/,G);P("npx",X,{env:Y,stdio:"inherit",shell:!0}).on("exit",($)=>process.exit($||0))}else{let X=D(),U={...process.env,COMMHUB_ALIAS:z.alias,...X?{COMMHUB_TOKEN:X}:{}};for(let[$,L]of Object.entries(z.env))U[$]=L.replace(/^~/,G);let Y=[];if(z.flags.dangerouslySkipPermissions)Y.push("--dangerously-skip-permissions");for(let $ of z.channels)if($.startsWith("server:"))Y.push("--dangerously-load-development-channels",$);else Y.push("--channels",$);if(z.flags.teammateMode)Y.push("--teammate-mode",z.flags.teammateMode);if(Q==="resume"){let $=z.resume||z.resumeAlias||z.name||z.alias;Y.push("--resume",$)}Y.push("-n",z.name||z.alias),P("claude",Y,{env:U,stdio:"inherit",shell:!0}).on("exit",($)=>process.exit($||0))}}async function g(){let B=V[1];if(!B){n("start");return}await r(B,"start")}async function Lz(){let B=V[1];if(!B){n("resume");return}let Q=A(B);if(!Q){let z=M(),W=O(),N=z.hub||W.hub,X=z.session;if(!X)console.log(`Profile "${B}" not found.
83
+ `),console.log(`Quick setup: anet resume ${B} --session <session-id>`),console.log(`Or create: anet init profile ${B} --alias ${B} --resume <session-id>`),process.exit(1);if(!N)console.error("Run 'anet init' first"),process.exit(1);Q={runtime:"claude-code",alias:z.alias||B,hub:N,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:X},b(B,Q),console.log(`[anet] Created .anet/nodes/${B}/config.json (resume: ${X.slice(0,8)}...)
84
+ `)}await r(B,"resume")}function n(B){let Q=d();if(Q.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
82
85
  Profiles:
83
86
  `);for(let z of Q){let W=A(z);console.log(` ${z}${W?.name?` (${W.name})`:""} → ${W?.alias} [${W?.channels.join(", ")}]`)}console.log(`
84
87
  anet ${B} <id>
85
- `)}async function Kz(){let B=c();if(B.length>0){console.log(`
88
+ `)}async function Rz(){let B=d();if(B.length>0){console.log(`
86
89
  Profiles:
87
- `);for(let N of B){let X=A(N);console.log(` ${N}${X?.name?` (${X.name})`:""} → ${X?.alias} [${X?.channels.join(", ")}]`)}console.log()}let Q=process.cwd(),z=U(J,".claude","sessions"),W=[];if(H(z))for(let N of f(z).filter((X)=>X.endsWith(".json")))try{let X=JSON.parse(_(U(z,N),"utf-8"));if(X.cwd===Q)W.push(X)}catch{}if(W.length===0&&B.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
88
- `);return}let Z=G(),Y=[],$={};if(Z.hub)try{let[N,X]=await Promise.all([fetch(`${Z.hub}/api/status`).then((K)=>K.json()),fetch(`${Z.hub}/health`).then((K)=>K.json())]);Y=N.sessions||[],$=X.sse_sessions||{}}catch{}if(W.length>0){console.log(`Sessions (${Q}):
89
- `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let N of W){let X=N.sessionId.slice(0,18),K=!1;try{process.kill(N.pid,0),K=!0}catch{}let R="(not in network)",T=Q.replace(/\//g,"-"),E=U(J,".claude","channels","commhub",T,".env");if(H(E)){let j=_(E,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(j){let C=j[1].trim(),v=Y.find((t)=>t.alias===C),n=$[C]?"●":"○";R=v?`${C} ${v.status} ${n}`:`${C} (not registered)`}}console.log(` ${X} ${(K?`${N.pid}`:`${N.pid}✕`).padEnd(7)} ${R}`)}console.log()}}async function Lz(){let B=G(),Q=F(),z=process.env.COMMHUB_URL||Q.hub||B.hub||"http://127.0.0.1:9200",W=process.env.COMMHUB_ALIAS||Q.alias;if(!W)console.error("Error: --alias required"),process.exit(1);let{CommHub:Z}=await Promise.resolve().then(() => (S(),y)),Y=new Z({url:z,alias:W});Y.on("task",async($)=>{console.log(`[${W}] ← ${$.from_session}: ${$.content.slice(0,100)}`),await Y.send($.from_session,`[${W}] 收到: ${$.content.slice(0,200)}`)}),Y.on("connected",()=>console.log(`[${W}] Connected`)),Y.on("disconnected",()=>console.log(`[${W}] Reconnecting...`)),process.on("SIGINT",()=>Y.disconnect().then(()=>process.exit(0))),console.log(`[${W}] Listening on ${z}`)}async function Tz(){if(L[1]==="start"){let Q=F(),z=Q.port||"9200",W=Q.host||"0.0.0.0",Z=Q.token||"";console.log(`[anet] Starting CommHub Server on ${W}:${z}...`);let Y={...process.env,PORT:z,HOST:W};if(Z)Y.COMMHUB_AUTH_TOKEN=Z;w("npx",["--yes","@sleep2agi/commhub-server"],{env:Y,stdio:"inherit",shell:!0}).on("exit",(N)=>process.exit(N||0))}else console.log(`
90
+ `);for(let Y of B){let Z=A(Y);console.log(` ${Y}${Z?.name?` (${Z.name})`:""} → ${Z?.alias} [${Z?.channels.join(", ")}]`)}console.log()}let Q=process.cwd(),z=K(G,".claude","sessions"),W=[];if(q(z))for(let Y of m(z).filter((Z)=>Z.endsWith(".json")))try{let Z=JSON.parse(I(K(z,Y),"utf-8"));if(Z.cwd===Q)W.push(Z)}catch{}if(W.length===0&&B.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
91
+ `);return}let N=O(),X=[],U={};if(N.hub)try{let[Y,Z]=await Promise.all([fetch(`${N.hub}/api/status`,{headers:j()}).then(($)=>$.json()),fetch(`${N.hub}/health`,{headers:j()}).then(($)=>$.json())]);X=Y.sessions||[],U=Z.sse_sessions||{}}catch{}if(W.length>0){console.log(`Sessions (${Q}):
92
+ `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let Y of W){let Z=Y.sessionId.slice(0,18),$=!1;try{process.kill(Y.pid,0),$=!0}catch{}let L="(not in network)",E=Q.replace(/\//g,"-"),R=K(G,".claude","channels","commhub",E,".env");if(q(R)){let k=I(R,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(k){let x=k[1].trim(),y=X.find((t)=>t.alias===x),a=U[x]?"●":"○";L=y?`${x} ${y.status} ${a}`:`${x} (not registered)`}}console.log(` ${Z} ${($?`${Y.pid}`:`${Y.pid}✕`).padEnd(7)} ${L}`)}console.log()}}async function Ez(){let B=O(),Q=M(),z=process.env.COMMHUB_URL||Q.hub||B.hub||"http://127.0.0.1:9200",W=process.env.COMMHUB_ALIAS||Q.alias;if(!W)console.error("Error: --alias required"),process.exit(1);let{CommHub:N}=await Promise.resolve().then(() => (h(),u)),X=new N({url:z,alias:W});X.on("task",async(U)=>{console.log(`[${W}] ← ${U.from_session}: ${U.content.slice(0,100)}`),await X.send(U.from_session,`[${W}] 收到: ${U.content.slice(0,200)}`)}),X.on("connected",()=>console.log(`[${W}] Connected`)),X.on("disconnected",()=>console.log(`[${W}] Reconnecting...`)),process.on("SIGINT",()=>X.disconnect().then(()=>process.exit(0))),console.log(`[${W}] Listening on ${z}`)}async function Vz(){if(V[1]==="start"){let Q=M(),z=Q.port||"9200",W=Q.host||"0.0.0.0",N=Q.token||"";console.log(`[anet] Starting CommHub Server on ${W}:${z}...`);let X={...process.env,PORT:z,HOST:W};if(N)X.COMMHUB_AUTH_TOKEN=N;P("npx",["--yes","@sleep2agi/commhub-server"],{env:X,stdio:"inherit",shell:!0}).on("exit",(Y)=>process.exit(Y||0))}else console.log(`
90
93
  anet server <command>
91
94
 
92
95
  start [options] Start CommHub Server
@@ -100,6 +103,6 @@ Example:
100
103
  anet server start
101
104
  anet server start --port 9200 --token my-secret
102
105
  anet server start --host 0.0.0.0 --port 9200
103
- `)}async function Ez(){let B=G(),z=F().hub||B.hub;if(!z)console.error("Run 'anet init' first"),process.exit(1);let W=[];try{W=(await(await fetch(`${z}/api/status`)).json()).sessions||[]}catch(X){console.error(`Cannot reach ${z}: ${X.message}`),process.exit(1)}if(W.length===0){console.log("No sessions in CommHub.");return}let Z=W.filter((X)=>X.agent==="claude-code"&&X.project_dir);if(Z.length===0){console.log("No claude-code sessions found.");return}let Y=L[1],$=Y?Z.filter((X)=>X.alias===Y):Z;if($.length===0){console.log(`No session found for "${Y}".`);return}let N=0;for(let X of $){let K=X.project_dir,R=U(K,".anet","nodes",X.alias),T=U(R,"config.json");if(H(T)){console.log(` ⏭ ${X.alias} — already exists (${K})`);continue}if(!H(K)){console.log(` ⚠ ${X.alias} — project_dir not found: ${K}`);continue}let E={runtime:"claude-code",alias:X.alias,hub:z,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:X.resume_id};I(R,{recursive:!0}),O(T,JSON.stringify(E,null,2)+`
104
- `),console.log(` ✅ ${X.alias} → ${K}/.anet/nodes/${X.alias}/config.json`),N++}console.log(`
105
- Imported ${N} session(s). Use: cd <project> && anet resume <alias>`)}switch(x){case"init":if(L[1]==="project")Wz();else if(L[1]==="profile")Xz();else Qz();break;case"server":Tz();break;case"start":h();break;case"resume":Uz();break;case"import":Ez();break;case"ls":case"list":Kz();break;case"run":Lz();break;case"--help":case"-h":case void 0:u();break;default:if(A(x))L.unshift("start"),h();else console.error(`Unknown: ${x}`),u(),process.exit(1)}
106
+ `)}async function qz(){let B=O(),z=M().hub||B.hub;if(!z)console.error("Run 'anet init' first"),process.exit(1);let W=[];try{W=(await(await fetch(`${z}/api/status`,{headers:j()})).json()).sessions||[]}catch(Z){console.error(`Cannot reach ${z}: ${Z.message}`),process.exit(1)}if(W.length===0){console.log("No sessions in CommHub.");return}let N=W.filter((Z)=>Z.agent==="claude-code"&&Z.project_dir);if(N.length===0){console.log("No claude-code sessions found.");return}let X=V[1],U=X?N.filter((Z)=>Z.alias===X):N;if(U.length===0){console.log(`No session found for "${X}".`);return}let Y=0;for(let Z of U){let $=Z.project_dir,L=K($,".anet","nodes",Z.alias),E=K(L,"config.json");if(q(E)){console.log(` ⏭ ${Z.alias} — already exists (${$})`);continue}if(!q($)){console.log(` ⚠ ${Z.alias} — project_dir not found: ${$}`);continue}let R={runtime:"claude-code",alias:Z.alias,hub:z,channels:["server:commhub"],env:{},flags:{dangerouslySkipPermissions:!0,teammateMode:"in-process"},resume:Z.resume_id};J(L,{recursive:!0}),T(E,JSON.stringify(R,null,2)+`
107
+ `),console.log(` ✅ ${Z.alias} → ${$}/.anet/nodes/${Z.alias}/config.json`),Y++}console.log(`
108
+ Imported ${Y} session(s). Use: cd <project> && anet resume <alias>`)}switch(C){case"init":if(V[1]==="project")Yz();else if(V[1]==="profile")Zz();else Xz();break;case"server":Vz();break;case"start":g();break;case"resume":Lz();break;case"import":qz();break;case"ls":case"list":Rz();break;case"run":Ez();break;case"--help":case"-h":case void 0:f();break;default:if(A(C))V.unshift("start"),g();else console.error(`Unknown: ${C}`),f(),process.exit(1)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network",
3
- "version": "0.0.33",
3
+ "version": "0.0.34",
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",