@sleep2agi/agent-network 0.0.31 → 0.0.33

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
@@ -117,9 +117,9 @@ anet ls # profiles + sessions + 网络状态
117
117
  | `--max-turns` | 每任务最大轮次 |
118
118
  | `--max-budget` | 每任务预算(美元) |
119
119
 
120
- ## Profile 格式
120
+ ## Node 配置
121
121
 
122
- 路径:`.anet/profiles/<id>.json`,anet 和 agent-node 共用。
122
+ 路径:`.anet/nodes/<id>/config.json`,anet 和 agent-node 共用。
123
123
 
124
124
  ```json
125
125
  {
package/dist/bin/cli.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as s}from"node:module";var t=Object.defineProperty;var r=(B)=>B;function o(B,Q){this[B]=r.bind(null,Q)}var a=(B,Q)=>{for(var z in Q)t(B,z,{get:Q[z],enumerable:!0,configurable:!0,set:o.bind(Q,z)})};var i=(B,Q)=>()=>(B&&(Q=B(B=0)),Q);var e=s(import.meta.url);var v={};a(v,{default:()=>Bz,CommHub:()=>x});import{EventEmitter as zz}from"events";import{hostname as b}from"os";var x,Bz;var S=i(()=>{x=class x extends zz{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(),Z=N.match(/data: (.+)/),$=Z?JSON.parse(Z[1]):JSON.parse(N),Y=$?.result?.content?.[0]?.text;return Y?JSON.parse(Y):$}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 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 Z=N.body.getReader(),$=new TextDecoder,Y="";while(this.running){let{done:X,value:T}=await Z.read();if(X)break;Y+=$.decode(T,{stream:!0});let O=Y.split(`
3
- `);Y=O.pop()||"";for(let E of O){if(!E.startsWith("data: "))continue;try{let L=JSON.parse(E.slice(6));if(L.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(L.type==="new_task"||L.type==="new_message"||L.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))}};Bz=x});import{readFileSync as G,writeFileSync as H,existsSync as R,mkdirSync as F,readdirSync as u}from"fs";import{join as U}from"path";import{spawn as w}from"child_process";import{createInterface as Zz}from"readline";var K=process.argv.slice(2),A=K[0],V=process.env.HOME||process.env.USERPROFILE||"~";function f(){return U(V,".anet","config.json")}function P(){return U(process.cwd(),".anet","nodes")}function _(){let B=f();if(R(B))try{return JSON.parse(G(B,"utf-8"))}catch{}return{}}function Qz(B){let Q=U(V,".anet");F(Q,{recursive:!0}),H(U(Q,"config.json"),JSON.stringify(B,null,2)+`
4
- `)}function M(B){let Q=U(P(),B,"config.json");if(R(Q))try{return JSON.parse(G(Q,"utf-8"))}catch{}return null}function g(B,Q){let z=U(P(),B);F(z,{recursive:!0}),H(U(z,"config.json"),JSON.stringify(Q,null,2)+`
5
- `)}function m(){let B=P();if(!R(B))return[];return u(B).filter((Q)=>R(U(B,Q,"config.json")))}function C(){let B={_channels:[],_envs:[]};for(let Q=0;Q<K.length;Q++){if(K[Q]==="--channel"&&K[Q+1]){B._channels.push(K[++Q]);continue}if(K[Q]==="--env"&&K[Q+1]){B._envs.push(K[++Q]);continue}if(K[Q].startsWith("--")&&K[Q+1]&&!K[Q+1].startsWith("--"))B[K[Q].slice(2)]=K[++Q]}return B}function y(){console.log(`
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(`
6
6
  anet — AI Agent Network CLI
7
7
 
8
8
  anet init Configure hub URL (global, once)
@@ -12,6 +12,8 @@ anet — AI Agent Network CLI
12
12
  anet resume <id> Resume last session with profile
13
13
  anet ls Show profiles + sessions + network
14
14
  anet server start Start CommHub Server
15
+ anet import Import sessions from CommHub → config.json
16
+ anet import <alias> Import specific session
15
17
  anet run Run standalone SSE agent
16
18
  anet --help This help
17
19
 
@@ -20,11 +22,11 @@ Quick start:
20
22
  anet init --hub http://IP:9200
21
23
  anet start 指挥室 # Claude Code Agent
22
24
  anet start 小明 # MiniMax Agent (runtime: agent-sdk)
23
- `)}async function Wz(){let B=C(),Q=B.hub;if(!Q)Q=await J("CommHub URL (e.g. http://YOUR_IP:9200)"),c();if(!Q)console.error("Error: hub URL required"),process.exit(1);Q=Q.replace(/\/+$/,"");try{let N=await(await fetch(`${Q}/health`)).json();console.log(`✅ CommHub v${N.version} — ${N.sessions} sessions, ${N.sse_connections} SSE`)}catch(W){console.error(`❌ Cannot reach ${Q}: ${W.message}`),process.exit(1)}let z=_();if(z.hub=Q,B.token)z.token=B.token;Qz(z),console.log(`
24
- Saved to ${f()}`),console.log("Next: anet init project")}async function Xz(){let Q=_().hub;if(!Q)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let z=U(process.cwd(),".anet");F(z,{recursive:!0});let W=U(z,"node-server.ts");if(!R(W)){let T=[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")],O=!1;for(let E of T)if(R(E)){H(W,G(E,"utf-8")),console.log(" ✅ .anet/node-server.ts"),O=!0;break}if(!O)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=U(z,"package.json");if(!R(N)){H(N,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
25
- `);try{let{execSync:T}=await import("child_process");T("bun install",{cwd:z,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let Z=U(z,".env");H(Z,`COMMHUB_URL=${Q}
26
- `),console.log(`CommHub URL: ${Q}`);let $=U(process.cwd(),".mcp.json"),Y={};if(R($))try{Y=JSON.parse(G($,"utf-8"))}catch{}if(!Y.mcpServers?.commhub)Y.mcpServers=Y.mcpServers||{},Y.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},H($,JSON.stringify(Y,null,2)+`
27
- `),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(!R(X))H(X,`# Agent Network (CommHub)
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)
28
30
 
29
31
  ## 通信方式
30
32
 
@@ -63,27 +65,28 @@ commhub_get_all_status()
63
65
  - 回复指挥室用 commhub_send_task(不是 commhub_reply,reply 不推送)
64
66
  - 不要猜 alias,用 get_all_status 查
65
67
  `),console.log("CLAUDE.md: created");else console.log("CLAUDE.md: already exists");console.log(`
66
- ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function Yz(){let B=K[2];if(!B)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let Q=_(),z=C(),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 Z={};for(let E of z._envs){let L=E.indexOf("=");if(L>0)Z[E.slice(0,L)]=E.slice(L+1)}let $=z.runtime||"claude-code",Y={anet_version:"0.0.24",...z.name?{name:z.name}:{},runtime:$,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:$==="claude-code"?["server:commhub"]:[],env:Z,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(V,".claude","channels","commhub"),T=process.cwd().replace(/\//g,"-"),O=U(X,T);if(F(O,{recursive:!0}),H(U(O,".env"),`COMMHUB_ALIAS=${W}
67
- `),g(B,Y),console.log(`
68
- ✅ Profile "${B}" saved`),console.log(` alias: ${W}`),console.log(` channels: ${Y.channels.join(", ")}`),Object.keys(Z).length)console.log(` env: ${Object.keys(Z).join(", ")}`);console.log(`
69
- Start: anet start ${B}`)}var q=null;function $z(){if(!q)q=Zz({input:process.stdin,output:process.stdout});return q}function c(){if(q)q.close(),q=null}function J(B,Q){let z=Q?` [${Q}]`:"";return new Promise((W)=>{$z().question(`${B}${z}: `,(N)=>{W(N.trim()||Q||"")})})}async function Nz(B){let Q=_();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(`
70
72
  Profile "${B}" not found. Let's create it:
71
- `);let z=await J("Runtime (claude-code / agent-sdk)","claude-code"),W=await J("Alias",B),N,Z=[],$=[],Y="";if(z==="agent-sdk")N=await J("Model","MiniMax-M2.7"),Z=(await J("Tools (comma-separated)","Read,Bash,Grep")).split(",").map((I)=>I.trim()).filter(Boolean);else $=(await J("Channels (comma-separated)","server:commhub")).split(",").map((I)=>I.trim()).filter(Boolean),Y=await J("Teammate mode","in-process");let X=await J("Extra env (K=V, comma-separated, empty to skip)"),T={};if(X)for(let L of X.split(",")){let I=L.trim().indexOf("=");if(I>0)T[L.trim().slice(0,I)]=L.trim().slice(I+1)}let O=Q.hub;if(!O)console.error(`
72
- Run 'anet init' first to configure hub URL`),process.exit(1);let E={anet_version:"0.0.23",alias:W,hub:O,runtime:z,...N?{model:N}:{},...Z.length?{tools:Z}:{},channels:$,env:T,flags:{dangerouslySkipPermissions:!0,...Y?{teammateMode:Y}:{}}};return g(B,E),c(),console.log(`
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(`
73
75
  ✅ Profile "${B}" saved
74
- `),E}async function p(B,Q){let z=M(B);if(!z)z=await Nz(B);let W=z.runtime||"claude-code";if(console.log(`[anet] ${Q==="start"?"Starting new":"Resuming"} "${B}" (${z.alias}) [${W}]...
75
- `),W==="agent-sdk"){let Z=["@sleep2agi/agent-node","--alias",z.alias,"--hub",z.hub];if(z.model)Z.push("--model",z.model);if(z.tools?.length)Z.push("--tools",z.tools.join(","));if(z.flags?.maxTurns)Z.push("--max-turns",String(z.flags.maxTurns));let $={...process.env};for(let[X,T]of Object.entries(z.env))$[X]=T.replace(/^~/,V);w("npx",Z,{env:$,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}else{let Z={...process.env,COMMHUB_ALIAS:z.alias};for(let[X,T]of Object.entries(z.env))Z[X]=T.replace(/^~/,V);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:Z,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}}async function h(){let B=K[1];if(!B){d("start");return}await p(B,"start")}async function Uz(){let B=K[1];if(!B){d("resume");return}if(!M(B))console.log(`Profile "${B}" not found. Create one first:
76
-
77
- anet start ${B}
78
- `),process.exit(1);await p(B,"resume")}function d(B){let Q=m();if(Q.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
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(`
79
82
  Profiles:
80
- `);for(let z of Q){let W=M(z);console.log(` ${z}${W?.name?` (${W.name})`:""} → ${W?.alias} [${W?.channels.join(", ")}]`)}console.log(`
83
+ `);for(let z of Q){let W=A(z);console.log(` ${z}${W?.name?` (${W.name})`:""} → ${W?.alias} [${W?.channels.join(", ")}]`)}console.log(`
81
84
  anet ${B} <id>
82
- `)}async function Tz(){let B=m();if(B.length>0){console.log(`
85
+ `)}async function Kz(){let B=c();if(B.length>0){console.log(`
83
86
  Profiles:
84
- `);for(let Y of B){let X=M(Y);console.log(` ${Y}${X?.name?` (${X.name})`:""} → ${X?.alias} [${X?.channels.join(", ")}]`)}console.log()}let Q=process.cwd(),z=U(V,".claude","sessions"),W=[];if(R(z))for(let Y of u(z).filter((X)=>X.endsWith(".json")))try{let X=JSON.parse(G(U(z,Y),"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
85
- `);return}let N=_(),Z=[],$={};if(N.hub)try{let[Y,X]=await Promise.all([fetch(`${N.hub}/api/status`).then((T)=>T.json()),fetch(`${N.hub}/health`).then((T)=>T.json())]);Z=Y.sessions||[],$=X.sse_sessions||{}}catch{}if(W.length>0){console.log(`Sessions (${Q}):
86
- `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let Y of W){let X=Y.sessionId.slice(0,18),T=!1;try{process.kill(Y.pid,0),T=!0}catch{}let O="(not in network)",E=Q.replace(/\//g,"-"),L=U(V,".claude","channels","commhub",E,".env");if(R(L)){let k=G(L,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(k){let D=k[1].trim(),j=Z.find((n)=>n.alias===D),l=$[D]?"●":"○";O=j?`${D} ${j.status} ${l}`:`${D} (not registered)`}}console.log(` ${X} ${(T?`${Y.pid}`:`${Y.pid}✕`).padEnd(7)} ${O}`)}console.log()}}async function Kz(){let B=_(),Q=C(),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(() => (S(),v)),Z=new N({url:z,alias:W});Z.on("task",async($)=>{console.log(`[${W}] ← ${$.from_session}: ${$.content.slice(0,100)}`),await Z.send($.from_session,`[${W}] 收到: ${$.content.slice(0,200)}`)}),Z.on("connected",()=>console.log(`[${W}] Connected`)),Z.on("disconnected",()=>console.log(`[${W}] Reconnecting...`)),process.on("SIGINT",()=>Z.disconnect().then(()=>process.exit(0))),console.log(`[${W}] Listening on ${z}`)}async function Lz(){if(K[1]==="start"){let Q=C(),z=Q.port||"9200",W=Q.host||"0.0.0.0",N=Q.token||"";console.log(`[anet] Starting CommHub Server on ${W}:${z}...`);let Z={...process.env,PORT:z,HOST:W};if(N)Z.COMMHUB_AUTH_TOKEN=N;w("npx",["--yes","@sleep2agi/commhub-server"],{env:Z,stdio:"inherit",shell:!0}).on("exit",(Y)=>process.exit(Y||0))}else console.log(`
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(`
87
90
  anet server <command>
88
91
 
89
92
  start [options] Start CommHub Server
@@ -97,4 +100,6 @@ Example:
97
100
  anet server start
98
101
  anet server start --port 9200 --token my-secret
99
102
  anet server start --host 0.0.0.0 --port 9200
100
- `)}switch(A){case"init":if(K[1]==="project")Xz();else if(K[1]==="profile")Yz();else Wz();break;case"server":Lz();break;case"start":h();break;case"resume":Uz();break;case"ls":case"list":Tz();break;case"run":Kz();break;case"--help":case"-h":case void 0:y();break;default:if(M(A))K.unshift("start"),h();else console.error(`Unknown: ${A}`),y(),process.exit(1)}
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)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
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",