@sleep2agi/agent-network 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cli.js +13 -10
- package/package.json +1 -1
package/dist/bin/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createRequire as a}from"node:module";var n=Object.defineProperty;var l=(z)=>z;function t(z,B){this[z]=l.bind(null,B)}var r=(z,B)=>{for(var Q in B)n(z,Q,{get:B[Q],enumerable:!0,configurable:!0,set:t.bind(B,Q)})};var o=(z,B)=>()=>(z&&(B=z(z=0)),B);var i=a(import.meta.url);var
|
|
3
|
-
`);X=L.pop()||"";for(let O of L){if(!O.startsWith("data: "))continue;try{let I=JSON.parse(O.slice(6));if(I.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(I.type==="new_task"||I.type==="new_message"||I.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 ${Q/1000}s...`),await this.sleep(Q),Q=Math.min(Q*1.5,60000)}}async processInbox(){try{let B=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let Q of B)await this.call("ack_inbox",{alias:this.alias,message_id:Q.id}),this.log(`← ${Q.from_session}: ${Q.content.slice(0,60)}`),this.emit("task",Q),this.emit("message",Q)}catch(z){this.log(`inbox error: ${z.message}`)}}sleep(z){return new Promise((B)=>setTimeout(B,z))}};e=D});import{readFileSync as V,writeFileSync as R,existsSync as E,mkdirSync as
|
|
4
|
-
`)}function
|
|
2
|
+
import{createRequire as a}from"node:module";var n=Object.defineProperty;var l=(z)=>z;function t(z,B){this[z]=l.bind(null,B)}var r=(z,B)=>{for(var Q in B)n(z,Q,{get:B[Q],enumerable:!0,configurable:!0,set:t.bind(B,Q)})};var o=(z,B)=>()=>(z&&(B=z(z=0)),B);var i=a(import.meta.url);var P={};r(P,{default:()=>e,CommHub:()=>D});import{EventEmitter as s}from"events";import{hostname as j}from"os";var D,e;var v=o(()=>{D=class D extends s{url;alias;token;agent;resumeId;heartbeatInterval;reconnectDelay;heartbeatTimer;sseAbort;running=!1;constructor(z){super();if(this.url=z.url.replace(/\/$/,""),this.alias=z.alias,this.token=z.token,this.agent=z.agent||"sdk",this.resumeId=`sdk-${z.alias}-${Date.now().toString(36)}`,this.heartbeatInterval=z.heartbeatInterval??180000,this.reconnectDelay=z.reconnectDelay??3000,z.autoConnect!==!1)this.connect()}log(z){console.log(`[${new Date().toTimeString().slice(0,8)}] [commhub:${this.alias}] ${z}`)}async call(z,B){let Q={"Content-Type":"application/json"};if(this.token)Q.Authorization=`Bearer ${this.token}`;let Y=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:Q,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:z,arguments:B}})})).json(),$=Y?.result?.content?.[0]?.text;return $?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((z)=>this.log(`heartbeat failed: ${z.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(z,B,Q="normal"){return this.call("send_task",{alias:z,task:B,priority:Q,from_session:this.alias})}async message(z,B){return this.call("send_message",{alias:z,message:B,from_session:this.alias})}async reply(z,B,Q="completed"){return this.call("reply",{task_id:z,text:B,status:Q})}async status(z,B){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:z,server:j(),hostname:j(),agent:this.agent,project_dir:process.cwd(),...B})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(z,B){return this.call("broadcast",{message:z,filter_server:B?.server,filter_status:B?.status})}async connectSSE(){let z=encodeURIComponent(this.alias),B=`${this.url}/events/${z}`,Q=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 Y=await fetch(B,{headers:W,signal:this.sseAbort.signal});if(!Y.ok||!Y.body){this.log(`SSE failed: ${Y.status}`),await this.sleep(Q),Q=Math.min(Q*1.5,60000);continue}Q=this.reconnectDelay;let $=Y.body.getReader(),U=new TextDecoder,X="";while(this.running){let{done:Z,value:T}=await $.read();if(Z)break;X+=U.decode(T,{stream:!0});let L=X.split(`
|
|
3
|
+
`);X=L.pop()||"";for(let O of L){if(!O.startsWith("data: "))continue;try{let I=JSON.parse(O.slice(6));if(I.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(I.type==="new_task"||I.type==="new_message"||I.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 ${Q/1000}s...`),await this.sleep(Q),Q=Math.min(Q*1.5,60000)}}async processInbox(){try{let B=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let Q of B)await this.call("ack_inbox",{alias:this.alias,message_id:Q.id}),this.log(`← ${Q.from_session}: ${Q.content.slice(0,60)}`),this.emit("task",Q),this.emit("message",Q)}catch(z){this.log(`inbox error: ${z.message}`)}}sleep(z){return new Promise((B)=>setTimeout(B,z))}};e=D});import{readFileSync as V,writeFileSync as R,existsSync as E,mkdirSync as A,readdirSync as y}from"fs";import{join as N}from"path";import{spawn as zz}from"child_process";import{createInterface as Yz}from"readline";var K=process.argv.slice(2),F=K[0],q=process.env.HOME||process.env.USERPROFILE||"~";function h(){return N(q,".anet","config.json")}function x(){return N(process.cwd(),".anet","profiles")}function G(){let z=h();if(E(z))try{return JSON.parse(V(z,"utf-8"))}catch{}return{}}function Bz(z){let B=N(q,".anet");A(B,{recursive:!0}),R(N(B,"config.json"),JSON.stringify(z,null,2)+`
|
|
4
|
+
`)}function H(z){let B=N(x(),`${z}.json`);if(E(B))try{return JSON.parse(V(B,"utf-8"))}catch{}return null}function u(z,B){let Q=x();A(Q,{recursive:!0}),R(N(Q,`${z}.json`),JSON.stringify(B,null,2)+`
|
|
5
5
|
`)}function g(){let z=x();if(!E(z))return[];return y(z).filter((B)=>B.endsWith(".json")).map((B)=>B.replace(/\.json$/,""))}function k(){let z={_channels:[],_envs:[]};for(let B=0;B<K.length;B++){if(K[B]==="--channel"&&K[B+1]){z._channels.push(K[++B]);continue}if(K[B]==="--env"&&K[B+1]){z._envs.push(K[++B]);continue}if(K[B].startsWith("--")&&K[B+1]&&!K[B+1].startsWith("--"))z[K[B].slice(2)]=K[++B]}return z}function b(){console.log(`
|
|
6
6
|
anet — AI Agent Network CLI
|
|
7
7
|
|
|
@@ -21,7 +21,7 @@ Quick start:
|
|
|
21
21
|
anet start 指挥室 # 新建
|
|
22
22
|
anet resume 指挥室 # 下次恢复
|
|
23
23
|
`)}async function Qz(){let z=k(),B=z.hub;if(!B)B=await _("CommHub URL (e.g. http://YOUR_IP:9200)"),f();if(!B)console.error("Error: hub URL required"),process.exit(1);B=B.replace(/\/+$/,"");try{let Y=await(await fetch(`${B}/health`)).json();console.log(`✅ CommHub v${Y.version} — ${Y.sessions} sessions, ${Y.sse_connections} SSE`)}catch(W){console.error(`❌ Cannot reach ${B}: ${W.message}`),process.exit(1)}let Q=G();if(Q.hub=B,z.token)Q.token=z.token;Bz(Q),console.log(`
|
|
24
|
-
Saved to ${h()}`),console.log("Next: anet init project")}async function Wz(){let B=G().hub;if(!B)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Q=N(process.cwd(),".anet");
|
|
24
|
+
Saved to ${h()}`),console.log("Next: anet init project")}async function Wz(){let B=G().hub;if(!B)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Q=N(process.cwd(),".anet");A(Q,{recursive:!0});let W=N(Q,"node-server.ts");if(!E(W)){let T=[N(new URL(".",import.meta.url).pathname,"..","..","src","node-server.ts"),N(new URL(".",import.meta.url).pathname,"..","src","node-server.ts"),N(process.argv[1],"..","..","src","node-server.ts")],L=!1;for(let O of T)if(E(O)){R(W,V(O,"utf-8")),console.log(" ✅ .anet/node-server.ts"),L=!0;break}if(!L)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 Y=N(Q,"package.json");if(!E(Y)){R(Y,JSON.stringify({private:!0,dependencies:{"@modelcontextprotocol/sdk":"^1.12.0"}},null,2)+`
|
|
25
25
|
`);try{let{execSync:T}=await import("child_process");T("bun install",{cwd:Q,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}let $=N(Q,".env");R($,`COMMHUB_URL=${B}
|
|
26
26
|
`),console.log(`CommHub URL: ${B}`);let U=N(process.cwd(),".mcp.json"),X={};if(E(U))try{X=JSON.parse(V(U,"utf-8"))}catch{}if(!X.mcpServers?.commhub)X.mcpServers=X.mcpServers||{},X.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/node-server.ts"]},R(U,JSON.stringify(X,null,2)+`
|
|
27
27
|
`),console.log(".mcp.json: commhub → .anet/node-server.ts");else console.log(".mcp.json: commhub already set");let Z=N(process.cwd(),"CLAUDE.md");if(!E(Z))R(Z,`# Agent Network (CommHub)
|
|
@@ -63,7 +63,7 @@ commhub_get_all_status()
|
|
|
63
63
|
- 回复指挥室用 commhub_send_task(不是 commhub_reply,reply 不推送)
|
|
64
64
|
- 不要猜 alias,用 get_all_status 查
|
|
65
65
|
`),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 Xz(){let z=K[2];if(!z)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let B=G(),Q=k(),W=Q.alias||z,Y=Q.hub||B.hub;if(!Y)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let $={};for(let L of Q._envs){let O=L.indexOf("=");if(O>0)$[L.slice(0,O)]=L.slice(O+1)}let U={anet_version:"0.0.11",...Q.name?{name:Q.name}:{},alias:W,hub:Y,channels:Q._channels.length>0?Q._channels:["server:commhub"],env:$,flags:{dangerouslySkipPermissions:!0,...Q["teammate-mode"]?{teammateMode:Q["teammate-mode"]}:{}},...Q.resume?{resume:Q.resume}:{},...Q["resume-alias"]?{resumeAlias:Q["resume-alias"]}:{}},X=N(q,".claude","channels","commhub"),Z=process.cwd().replace(/\//g,"-"),T=N(X,Z);if(
|
|
66
|
+
✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function Xz(){let z=K[2];if(!z)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let B=G(),Q=k(),W=Q.alias||z,Y=Q.hub||B.hub;if(!Y)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let $={};for(let L of Q._envs){let O=L.indexOf("=");if(O>0)$[L.slice(0,O)]=L.slice(O+1)}let U={anet_version:"0.0.11",...Q.name?{name:Q.name}:{},alias:W,hub:Y,channels:Q._channels.length>0?Q._channels:["server:commhub"],env:$,flags:{dangerouslySkipPermissions:!0,...Q["teammate-mode"]?{teammateMode:Q["teammate-mode"]}:{}},...Q.resume?{resume:Q.resume}:{},...Q["resume-alias"]?{resumeAlias:Q["resume-alias"]}:{}},X=N(q,".claude","channels","commhub"),Z=process.cwd().replace(/\//g,"-"),T=N(X,Z);if(A(T,{recursive:!0}),R(N(T,".env"),`COMMHUB_ALIAS=${W}
|
|
67
67
|
`),u(z,U),console.log(`
|
|
68
68
|
✅ Profile "${z}" saved`),console.log(` alias: ${W}`),console.log(` channels: ${U.channels.join(", ")}`),Object.keys($).length)console.log(` env: ${Object.keys($).join(", ")}`);console.log(`
|
|
69
69
|
Start: anet start ${z}`)}var J=null;function Zz(){if(!J)J=Yz({input:process.stdin,output:process.stdout});return J}function f(){if(J)J.close(),J=null}function _(z,B){let Q=B?` [${B}]`:"";return new Promise((W)=>{Zz().question(`${z}${Q}: `,(Y)=>{W(Y.trim()||B||"")})})}async function $z(z){let B=G();console.log(`
|
|
@@ -71,13 +71,16 @@ Profile "${z}" not found. Let's create it:
|
|
|
71
71
|
`);let Q=await _("Alias",z),Y=(await _("Channels (comma-separated)","server:commhub")).split(",").map((L)=>L.trim()).filter(Boolean),$=await _("Extra env (K=V, comma-separated, empty to skip)"),U=await _("Teammate mode (empty to skip)"),X={};if($)for(let L of $.split(",")){let O=L.trim().indexOf("=");if(O>0)X[L.trim().slice(0,O)]=L.trim().slice(O+1)}let Z=B.hub;if(!Z)console.error(`
|
|
72
72
|
Run 'anet init' first to configure hub URL`),process.exit(1);let T={anet_version:"0.0.20",alias:Q,hub:Z,channels:Y,env:X,flags:{dangerouslySkipPermissions:!0,...U?{teammateMode:U}:{}}};return u(z,T),f(),console.log(`
|
|
73
73
|
✅ Profile "${z}" saved
|
|
74
|
-
`),T}async function m(z,B){let Q=
|
|
75
|
-
`),zz("claude",Y,{env:W,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}async function S(){let z=K[1];if(!z){p("start");return}await m(z,"start")}async function Nz(){let z=K[1];if(!z){p("resume");return}
|
|
74
|
+
`),T}async function m(z,B){let Q=H(z);if(!Q)Q=await $z(z);let W={...process.env,COMMHUB_ALIAS:Q.alias};for(let[X,Z]of Object.entries(Q.env))W[X]=Z.replace(/^~/,q);let Y=[];if(Q.flags.dangerouslySkipPermissions)Y.push("--dangerously-skip-permissions");for(let X of Q.channels)if(X.startsWith("server:"))Y.push("--dangerously-load-development-channels",X);else Y.push("--channels",X);if(Q.flags.teammateMode)Y.push("--teammate-mode",Q.flags.teammateMode);if(B==="resume"){let X=Q.resumeAlias||Q.name||Q.alias;Y.push("--resume",X)}Y.push("-n",Q.name||Q.alias),console.log(`[anet] ${B==="start"?"Starting new":"Resuming"} "${z}" (${Q.alias})...
|
|
75
|
+
`),zz("claude",Y,{env:W,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}async function S(){let z=K[1];if(!z){p("start");return}await m(z,"start")}async function Nz(){let z=K[1];if(!z){p("resume");return}if(!H(z))console.log(`Profile "${z}" not found. Create one first:
|
|
76
|
+
|
|
77
|
+
anet start ${z}
|
|
78
|
+
`),process.exit(1);await m(z,"resume")}function p(z){let B=g();if(B.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
|
|
76
79
|
Profiles:
|
|
77
|
-
`);for(let Q of B){let W=
|
|
80
|
+
`);for(let Q of B){let W=H(Q);console.log(` ${Q}${W?.name?` (${W.name})`:""} → ${W?.alias} [${W?.channels.join(", ")}]`)}console.log(`
|
|
78
81
|
anet ${z} <id>
|
|
79
82
|
`)}async function Uz(){let z=g();if(z.length>0){console.log(`
|
|
80
83
|
Profiles:
|
|
81
|
-
`);for(let X of z){let Z=
|
|
84
|
+
`);for(let X of z){let Z=H(X);console.log(` ${X}${Z?.name?` (${Z.name})`:""} → ${Z?.alias} [${Z?.channels.join(", ")}]`)}console.log()}let B=process.cwd(),Q=N(q,".claude","sessions"),W=[];if(E(Q))for(let X of y(Q).filter((Z)=>Z.endsWith(".json")))try{let Z=JSON.parse(V(N(Q,X),"utf-8"));if(Z.cwd===B)W.push(Z)}catch{}if(W.length===0&&z.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
|
|
82
85
|
`);return}let Y=G(),$=[],U={};if(Y.hub)try{let[X,Z]=await Promise.all([fetch(`${Y.hub}/api/status`).then((T)=>T.json()),fetch(`${Y.hub}/health`).then((T)=>T.json())]);$=X.sessions||[],U=Z.sse_sessions||{}}catch{}if(W.length>0){console.log(`Sessions (${B}):
|
|
83
|
-
`),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let X of W){let Z=X.sessionId.slice(0,18),T=!1;try{process.kill(X.pid,0),T=!0}catch{}let L="(not in network)",O=B.replace(/\//g,"-"),I=N(q,".claude","channels","commhub",O,".env");if(E(I)){let w=V(I,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(w){let
|
|
86
|
+
`),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let X of W){let Z=X.sessionId.slice(0,18),T=!1;try{process.kill(X.pid,0),T=!0}catch{}let L="(not in network)",O=B.replace(/\//g,"-"),I=N(q,".claude","channels","commhub",O,".env");if(E(I)){let w=V(I,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(w){let M=w[1].trim(),C=$.find((d)=>d.alias===M),c=U[M]?"●":"○";L=C?`${M} ${C.status} ${c}`:`${M} (not registered)`}}console.log(` ${Z} ${(T?`${X.pid}`:`${X.pid}✕`).padEnd(7)} ${L}`)}console.log()}}async function Kz(){let z=G(),B=k(),Q=process.env.COMMHUB_URL||B.hub||z.hub||"http://127.0.0.1:9200",W=process.env.COMMHUB_ALIAS||B.alias;if(!W)console.error("Error: --alias required"),process.exit(1);let{CommHub:Y}=await Promise.resolve().then(() => (v(),P)),$=new Y({url:Q,alias:W});$.on("task",async(U)=>{console.log(`[${W}] ← ${U.from_session}: ${U.content.slice(0,100)}`),await $.send(U.from_session,`[${W}] 收到: ${U.content.slice(0,200)}`)}),$.on("connected",()=>console.log(`[${W}] Connected`)),$.on("disconnected",()=>console.log(`[${W}] Reconnecting...`)),process.on("SIGINT",()=>$.disconnect().then(()=>process.exit(0))),console.log(`[${W}] Listening on ${Q}`)}switch(F){case"init":if(K[1]==="project")Wz();else if(K[1]==="profile")Xz();else Qz();break;case"start":S();break;case"resume":Nz();break;case"ls":case"list":Uz();break;case"run":Kz();break;case"--help":case"-h":case void 0:b();break;default:if(H(F))K.unshift("start"),S();else console.error(`Unknown: ${F}`),b(),process.exit(1)}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleep2agi/agent-network",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
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",
|