@sleep2agi/agent-network 0.0.8 → 0.0.9

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
@@ -39,7 +39,12 @@ COMMHUB_ALIAS="指挥室" TELEGRAM_STATE_DIR=~/.claude/channels/telegram-vincent
39
39
  --teammate-mode in-process --resume 98039093-...
40
40
  ```
41
41
 
42
- Profile 把这些参数存到 JSON,以后只需:**`anet start commander`**
42
+ Profile 把这些参数存到 JSON,以后只需:
43
+
44
+ ```bash
45
+ anet start 指挥室 # 新建 session
46
+ anet resume 指挥室 # 恢复上次 session
47
+ ```
43
48
 
44
49
  同一目录可以有多个 profile(指挥室、通信龙、SDK马)。
45
50
 
@@ -58,14 +63,19 @@ anet init profile <id> [options] # → .anet/profiles/<id>.json
58
63
  配置文件位置:
59
64
 
60
65
  ```
61
- ~/.anet/config.json 全局(hub URL
62
- {workpath}/.mcp.json MCP server 配置(commhub stdio)
66
+ ~/.anet/config.json 全局(hub URL,一次性)
67
+ {workpath}/.anet/server.ts Channel 插件
68
+ {workpath}/.anet/package.json 依赖声明
69
+ {workpath}/.anet/.env COMMHUB_URL
63
70
  {workpath}/.anet/profiles/cmd.json 启动 profile
71
+ {workpath}/.mcp.json MCP 配置(commhub → .anet/server.ts)
64
72
  ```
65
73
 
74
+ 全部在项目目录内,不碰全局 `~/.claude/`。
75
+
66
76
  #### anet init
67
77
 
68
- 交互式输入 hub URL,测试连接,保存到 `~/.anet/config.json`。
78
+ hub URL(全局,一次性):
69
79
 
70
80
  ```bash
71
81
  anet init
@@ -77,11 +87,15 @@ anet init
77
87
 
78
88
  #### anet init project
79
89
 
80
- 下载 Channel 插件 + 安装依赖 + 写 `.mcp.json`(commhub stdio)+.env
90
+ 下载 Channel 插件到 `.anet/` + 安装依赖 + 写 `.mcp.json` +`.env`:
81
91
 
82
92
  ```bash
83
93
  cd ~/my-project
84
94
  anet init project
95
+ # ✅ .anet/server.ts
96
+ # ✅ Dependencies installed
97
+ # CommHub URL: http://YOUR_IP:9200
98
+ # .mcp.json: commhub → .anet/server.ts
85
99
  ```
86
100
 
87
101
  #### anet init profile
@@ -113,12 +127,13 @@ anet init profile commander --alias 指挥室 \
113
127
  anet init profile worker --alias 开发马 --channel server:commhub
114
128
  ```
115
129
 
116
- ### anet start
130
+ ### anet start / resume
117
131
 
118
132
  ```bash
119
- anet start commander # 启动指定 profile
133
+ anet start 指挥室 # 新建 session
134
+ anet resume 指挥室 # 恢复上次 session(按名字搜索)
120
135
  anet start # 列出所有 profile
121
- anet commander # 快捷方式(等于 anet start commander)
136
+ anet 指挥室 # 快捷方式(等于 anet start 指挥室)
122
137
  ```
123
138
 
124
139
  ### anet ls
@@ -191,7 +206,9 @@ const { CommHub } = require('@sleep2agi/agent-network');
191
206
 
192
207
  | 版本 | 变更 |
193
208
  |------|------|
194
- | 0.0.7 | init project 改写 .mcp.json(不写 ~/.claude.json),避免全局污染 |
209
+ | 0.0.9 | start/resume 分离,resume 按名字搜索恢复 session |
210
+ | 0.0.8 | init project 所有文件放 .anet/(不碰全局 ~/.claude/) |
211
+ | 0.0.7 | init project 改写 .mcp.json(不写 ~/.claude.json) |
195
212
  | 0.0.6 | 三级 init(全局/项目/profile),`anet ls` 简化为当前目录 |
196
213
  | 0.0.5 | `anet ls` 显示本地 sessions + CommHub 网络状态 |
197
214
  | 0.0.4 | CLI 瘦身 580KB→13KB,Node.js 兼容,profile 系统 |
package/dist/bin/cli.js CHANGED
@@ -1,37 +1,39 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as d}from"node:module";var f=Object.defineProperty;var g=(Q)=>Q;function m(Q,z){this[Q]=g.bind(null,z)}var c=(Q,z)=>{for(var V in z)f(Q,V,{get:z[V],enumerable:!0,configurable:!0,set:m.bind(z,V)})};var p=(Q,z)=>()=>(Q&&(z=Q(Q=0)),z);var l=d(import.meta.url);var C={};c(C,{default:()=>t,CommHub:()=>H});import{EventEmitter as n}from"events";import{hostname as D}from"os";var H,t;var P=p(()=>{H=class H extends n{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,z){let V={"Content-Type":"application/json"};if(this.token)V.Authorization=`Bearer ${this.token}`;let $=await(await fetch(`${this.url}/mcp`,{method:"POST",headers:V,body:JSON.stringify({jsonrpc:"2.0",id:Date.now(),method:"tools/call",params:{name:Q,arguments:z}})})).json(),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((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,z,V="normal"){return this.call("send_task",{alias:Q,task:z,priority:V,from_session:this.alias})}async message(Q,z){return this.call("send_message",{alias:Q,message:z,from_session:this.alias})}async reply(Q,z,V="completed"){return this.call("reply",{task_id:Q,text:z,status:V})}async status(Q,z){return this.call("report_status",{resume_id:this.resumeId,alias:this.alias,status:Q,server:D(),hostname:D(),agent:this.agent,project_dir:process.cwd(),...z})}async getAllStatus(){return this.call("get_all_status",{})}async broadcast(Q,z){return this.call("broadcast",{message:Q,filter_server:z?.server,filter_status:z?.status})}async connectSSE(){let Q=encodeURIComponent(this.alias),z=`${this.url}/events/${Q}`,V=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(z,{headers:X,signal:this.sseAbort.signal});if(!$.ok||!$.body){this.log(`SSE failed: ${$.status}`),await this.sleep(V),V=Math.min(V*1.5,60000);continue}V=this.reconnectDelay;let Y=$.body.getReader(),N=new TextDecoder,Z="";while(this.running){let{done:L,value:T}=await Y.read();if(L)break;Z+=N.decode(T,{stream:!0});let U=Z.split(`
3
- `);Z=U.pop()||"";for(let _ of U){if(!_.startsWith("data: "))continue;try{let B=JSON.parse(_.slice(6));if(B.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(B.type==="new_task"||B.type==="new_message"||B.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 ${V/1000}s...`),await this.sleep(V),V=Math.min(V*1.5,60000)}}async processInbox(){try{let z=(await this.call("get_inbox",{alias:this.alias,limit:10}))?.messages||[];for(let V of z)await this.call("ack_inbox",{alias:this.alias,message_id:V.id}),this.log(`← ${V.from_session}: ${V.content.slice(0,60)}`),this.emit("task",V),this.emit("message",V)}catch(Q){this.log(`inbox error: ${Q.message}`)}}sleep(Q){return new Promise((z)=>setTimeout(z,Q))}};t=H});import{readFileSync as E,writeFileSync as K,existsSync as q,mkdirSync as G,readdirSync as b}from"fs";import{join as R}from"path";import{spawn as r}from"child_process";var W=process.argv.slice(2),A=W[0],O=process.env.HOME||process.env.USERPROFILE||"~";function S(){return R(O,".anet","config.json")}function F(){return R(process.cwd(),".anet","profiles")}function I(){let Q=S();if(q(Q))try{return JSON.parse(E(Q,"utf-8"))}catch{}return{}}function o(Q){let z=R(O,".anet");G(z,{recursive:!0}),K(R(z,"config.json"),JSON.stringify(Q,null,2)+`
4
- `)}function J(Q){let z=R(F(),`${Q}.json`);if(q(z))try{return JSON.parse(E(z,"utf-8"))}catch{}return null}function a(Q,z){let V=F();G(V,{recursive:!0}),K(R(V,`${Q}.json`),JSON.stringify(z,null,2)+`
5
- `)}function y(){let Q=F();if(!q(Q))return[];return b(Q).filter((z)=>z.endsWith(".json")).map((z)=>z.replace(/\.json$/,""))}function k(){let Q={_channels:[],_envs:[]};for(let z=0;z<W.length;z++){if(W[z]==="--channel"&&W[z+1]){Q._channels.push(W[++z]);continue}if(W[z]==="--env"&&W[z+1]){Q._envs.push(W[++z]);continue}if(W[z].startsWith("--")&&W[z+1]&&!W[z+1].startsWith("--"))Q[W[z].slice(2)]=W[++z]}return Q}function j(){console.log(`
2
+ import{createRequire as n}from"node:module";var m=Object.defineProperty;var c=(z)=>z;function p(z,B){this[z]=c.bind(null,B)}var d=(z,B)=>{for(var Q in B)m(z,Q,{get:B[Q],enumerable:!0,configurable:!0,set:p.bind(B,Q)})};var l=(z,B)=>()=>(z&&(B=z(z=0)),B);var t=n(import.meta.url);var P={};d(P,{default:()=>o,CommHub:()=>H});import{EventEmitter as r}from"events";import{hostname as w}from"os";var H,o;var j=l(()=>{H=class H extends r{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 W=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(),Z=W?.result?.content?.[0]?.text;return Z?JSON.parse(Z):W}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:w(),hostname:w(),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 V={Accept:"text/event-stream"};if(this.token)V.Authorization=`Bearer ${this.token}`;let W=await fetch(B,{headers:V,signal:this.sseAbort.signal});if(!W.ok||!W.body){this.log(`SSE failed: ${W.status}`),await this.sleep(Q),Q=Math.min(Q*1.5,60000);continue}Q=this.reconnectDelay;let Z=W.body.getReader(),L=new TextDecoder,X="";while(this.running){let{done:Y,value:U}=await Z.read();if(Y)break;X+=L.decode(U,{stream:!0});let R=X.split(`
3
+ `);X=R.pop()||"";for(let T of R){if(!T.startsWith("data: "))continue;try{let q=JSON.parse(T.slice(6));if(q.type==="connected"){this.log("SSE connected"),this.emit("connected");continue}if(q.type==="new_task"||q.type==="new_message"||q.type==="broadcast")await this.processInbox()}catch{}}}}catch(V){if(V.name==="AbortError")break;this.emit("error",V),this.log(`SSE error: ${V.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))}};o=H});import{readFileSync as E,writeFileSync as K,existsSync as _,mkdirSync as J,readdirSync as b}from"fs";import{join as N}from"path";import{spawn as a}from"child_process";var $=process.argv.slice(2),A=$[0],O=process.env.HOME||process.env.USERPROFILE||"~";function S(){return N(O,".anet","config.json")}function F(){return N(process.cwd(),".anet","profiles")}function I(){let z=S();if(_(z))try{return JSON.parse(E(z,"utf-8"))}catch{}return{}}function i(z){let B=N(O,".anet");J(B,{recursive:!0}),K(N(B,"config.json"),JSON.stringify(z,null,2)+`
4
+ `)}function G(z){let B=N(F(),`${z}.json`);if(_(B))try{return JSON.parse(E(B,"utf-8"))}catch{}return null}function e(z,B){let Q=F();J(Q,{recursive:!0}),K(N(Q,`${z}.json`),JSON.stringify(B,null,2)+`
5
+ `)}function y(){let z=F();if(!_(z))return[];return b(z).filter((B)=>B.endsWith(".json")).map((B)=>B.replace(/\.json$/,""))}function k(){let z={_channels:[],_envs:[]};for(let B=0;B<$.length;B++){if($[B]==="--channel"&&$[B+1]){z._channels.push($[++B]);continue}if($[B]==="--env"&&$[B+1]){z._envs.push($[++B]);continue}if($[B].startsWith("--")&&$[B+1]&&!$[B+1].startsWith("--"))z[$[B].slice(2)]=$[++B]}return z}function C(){console.log(`
6
6
  anet — AI Agent Network CLI
7
7
 
8
8
  anet init Configure hub URL (global, once)
9
9
  anet init project Setup current project (channel plugin + config)
10
10
  anet init profile <id> Create a launch profile
11
- anet start <id> Start Claude Code with profile
12
- anet ls Show sessions + network status
11
+ anet start <id> New session with profile
12
+ anet resume <id> Resume last session with profile
13
+ anet ls Show profiles + sessions + network
13
14
  anet run Run standalone SSE agent
14
15
  anet --help This help
15
16
 
16
17
  Quick start:
17
18
  anet init
18
19
  anet init project
19
- anet init profile cmd --alias 指挥室 --channel server:commhub
20
- anet start cmd
21
- `)}async function i(){let Q=k(),z=Q.hub;if(!z)process.stdout.write("CommHub URL (e.g. http://YOUR_IP:9200): "),z=await new Promise((X)=>{let $="";process.stdin.setEncoding("utf-8"),process.stdin.once("data",(Y)=>{X(Y.toString().trim())})});if(!z)console.error("Error: hub URL required"),process.exit(1);try{let $=await(await fetch(`${z}/health`)).json();console.log(`✅ CommHub v${$.version} — ${$.sessions} sessions, ${$.sse_connections} SSE`)}catch(X){console.error(`❌ Cannot reach ${z}: ${X.message}`),process.exit(1)}let V=I();if(V.hub=z,Q.token)V.token=Q.token;o(V),console.log(`
22
- Saved to ${S()}`),console.log("Next: anet init project")}async function e(){let z=I().hub;if(!z)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let V=R(process.cwd(),".anet");G(V,{recursive:!0});let X=R(V,"server.ts");if(!q(X)){console.log("Downloading Channel plugin...");try{let L=await fetch("https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/server.ts");if(L.ok)K(X,await L.text()),console.log(" ✅ .anet/server.ts")}catch(L){console.log(` ❌ Failed: ${L.message}`),console.log(" Manual: curl -sL https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/server.ts -o .anet/server.ts")}}else console.log("Channel plugin: exists");let $=R(V,"package.json");if(!q($))try{let L=await fetch("https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/package.json");if(L.ok){K($,await L.text());try{let{execSync:T}=await import("child_process");T("bun install",{cwd:V,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}}catch{}let Y=R(V,".env");K(Y,`COMMHUB_URL=${z}
23
- `),console.log(`CommHub URL: ${z}`);let N=R(process.cwd(),".mcp.json"),Z={};if(q(N))try{Z=JSON.parse(E(N,"utf-8"))}catch{}if(!Z.mcpServers?.commhub)Z.mcpServers=Z.mcpServers||{},Z.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/server.ts"]},K(N,JSON.stringify(Z,null,2)+`
20
+ anet init profile 指挥室 --alias 指挥室 --channel server:commhub
21
+ anet start 指挥室 # 新建
22
+ anet resume 指挥室 # 下次恢复
23
+ `)}async function s(){let z=k(),B=z.hub;if(!B)process.stdout.write("CommHub URL (e.g. http://YOUR_IP:9200): "),B=await new Promise((V)=>{let W="";process.stdin.setEncoding("utf-8"),process.stdin.once("data",(Z)=>{V(Z.toString().trim())})});if(!B)console.error("Error: hub URL required"),process.exit(1);try{let W=await(await fetch(`${B}/health`)).json();console.log(`✅ CommHub v${W.version} — ${W.sessions} sessions, ${W.sse_connections} SSE`)}catch(V){console.error(`❌ Cannot reach ${B}: ${V.message}`),process.exit(1)}let Q=I();if(Q.hub=B,z.token)Q.token=z.token;i(Q),console.log(`
24
+ Saved to ${S()}`),console.log("Next: anet init project")}async function zz(){let B=I().hub;if(!B)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Q=N(process.cwd(),".anet");J(Q,{recursive:!0});let V=N(Q,"server.ts");if(!_(V)){console.log("Downloading Channel plugin...");try{let Y=await fetch("https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/server.ts");if(Y.ok)K(V,await Y.text()),console.log(" ✅ .anet/server.ts")}catch(Y){console.log(` ❌ Failed: ${Y.message}`),console.log(" Manual: curl -sL https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/server.ts -o .anet/server.ts")}}else console.log("Channel plugin: exists");let W=N(Q,"package.json");if(!_(W))try{let Y=await fetch("https://raw.githubusercontent.com/sleep2agi/agent-comm-hub/main/channel/package.json");if(Y.ok){K(W,await Y.text());try{let{execSync:U}=await import("child_process");U("bun install",{cwd:Q,stdio:"pipe"}),console.log(" ✅ Dependencies installed")}catch{console.log(" ⚠️ Run: cd .anet && bun install")}}}catch{}let Z=N(Q,".env");K(Z,`COMMHUB_URL=${B}
25
+ `),console.log(`CommHub URL: ${B}`);let L=N(process.cwd(),".mcp.json"),X={};if(_(L))try{X=JSON.parse(E(L,"utf-8"))}catch{}if(!X.mcpServers?.commhub)X.mcpServers=X.mcpServers||{},X.mcpServers.commhub={type:"stdio",command:"bun",args:[".anet/server.ts"]},K(L,JSON.stringify(X,null,2)+`
24
26
  `),console.log(".mcp.json: commhub → .anet/server.ts");else console.log(".mcp.json: commhub already set");console.log(`
25
- ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function s(){let Q=W[2];if(!Q)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let z=I(),V=k(),X=V.alias||Q,$=V.hub||z.hub;if(!$)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Y={};for(let U of V._envs){let _=U.indexOf("=");if(_>0)Y[U.slice(0,_)]=U.slice(_+1)}let N={...V.name?{name:V.name}:{},alias:X,hub:$,channels:V._channels.length>0?V._channels:["server:commhub"],env:Y,flags:{dangerouslySkipPermissions:!0,...V["teammate-mode"]?{teammateMode:V["teammate-mode"]}:{}},...V.resume?{resume:V.resume}:{}},Z=R(O,".claude","channels","commhub"),L=process.cwd().replace(/\//g,"-"),T=R(Z,L);if(G(T,{recursive:!0}),K(R(T,".env"),`COMMHUB_ALIAS=${X}
26
- `),a(Q,N),console.log(`
27
- ✅ Profile "${Q}" saved`),console.log(` alias: ${X}`),console.log(` channels: ${N.channels.join(", ")}`),Object.keys(Y).length)console.log(` env: ${Object.keys(Y).join(", ")}`);console.log(`
28
- Start: anet start ${Q}`)}function v(){let Q=W[1];if(!Q){let Y=y();if(Y.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
27
+ ✅ Project ready. Next: anet init profile <id> --alias <名字> --channel server:commhub`)}function Bz(){let z=$[2];if(!z)console.error("Usage: anet init profile <id> --alias <名字> [--channel ...] [--env ...]"),process.exit(1);let B=I(),Q=k(),V=Q.alias||z,W=Q.hub||B.hub;if(!W)console.error("Run 'anet init' first to configure hub URL"),process.exit(1);let Z={};for(let R of Q._envs){let T=R.indexOf("=");if(T>0)Z[R.slice(0,T)]=R.slice(T+1)}let L={...Q.name?{name:Q.name}:{},alias:V,hub:W,channels:Q._channels.length>0?Q._channels:["server:commhub"],env:Z,flags:{dangerouslySkipPermissions:!0,...Q["teammate-mode"]?{teammateMode:Q["teammate-mode"]}:{}},...Q.resume?{resume:Q.resume}:{}},X=N(O,".claude","channels","commhub"),Y=process.cwd().replace(/\//g,"-"),U=N(X,Y);if(J(U,{recursive:!0}),K(N(U,".env"),`COMMHUB_ALIAS=${V}
28
+ `),e(z,L),console.log(`
29
+ ✅ Profile "${z}" saved`),console.log(` alias: ${V}`),console.log(` channels: ${L.channels.join(", ")}`),Object.keys(Z).length)console.log(` env: ${Object.keys(Z).join(", ")}`);console.log(`
30
+ Start: anet start ${z}`)}function u(z,B){let Q=G(z);if(!Q)console.error(`Profile "${z}" not found. Run: anet ls`),process.exit(1);let V={...process.env,COMMHUB_ALIAS:Q.alias};for(let[X,Y]of Object.entries(Q.env))V[X]=Y.replace(/^~/,O);let W=[];if(Q.flags.dangerouslySkipPermissions)W.push("--dangerously-skip-permissions");for(let X of Q.channels)if(X.startsWith("server:"))W.push("--dangerously-load-development-channels",X);else W.push("--channels",X);if(Q.flags.teammateMode)W.push("--teammate-mode",Q.flags.teammateMode);if(B==="resume")W.push("--resume",Q.name||Q.alias);W.push("-n",Q.name||Q.alias),console.log(`[anet] ${B==="start"?"Starting new":"Resuming"} "${z}" (${Q.alias})...
31
+ `),a("claude",W,{env:V,stdio:"inherit",shell:!0}).on("exit",(X)=>process.exit(X||0))}function v(){let z=$[1];if(!z){h("start");return}u(z,"start")}function Qz(){let z=$[1];if(!z){h("resume");return}u(z,"resume")}function h(z){let B=y();if(B.length===0){console.log("No profiles. Run: anet init profile <id> --alias <名字>");return}console.log(`
29
32
  Profiles:
30
- `);for(let N of Y){let Z=J(N);console.log(` ${N}${Z?.name?` (${Z.name})`:""} → ${Z?.alias} [${Z?.channels.join(", ")}]`)}console.log(`
31
- anet start <id>
32
- `);return}let z=J(Q);if(!z)console.error(`Profile "${Q}" not found. Run: anet ls`),process.exit(1);let V={...process.env,COMMHUB_ALIAS:z.alias};for(let[Y,N]of Object.entries(z.env))V[Y]=N.replace(/^~/,O);let X=[];if(z.flags.dangerouslySkipPermissions)X.push("--dangerously-skip-permissions");for(let Y of z.channels)if(Y.startsWith("server:"))X.push("--dangerously-load-development-channels",Y);else X.push("--channels",Y);if(z.flags.teammateMode)X.push("--teammate-mode",z.flags.teammateMode);if(z.resume)X.push("--resume",z.resume);X.push("-n",z.name||z.alias),console.log(`[anet] Starting "${Q}" (${z.alias})...
33
- `),r("claude",X,{env:V,stdio:"inherit",shell:!0}).on("exit",(Y)=>process.exit(Y||0))}async function zz(){let Q=y();if(Q.length>0){console.log(`
33
+ `);for(let Q of B){let V=G(Q);console.log(` ${Q}${V?.name?` (${V.name})`:""} → ${V?.alias} [${V?.channels.join(", ")}]`)}console.log(`
34
+ anet ${z} <id>
35
+ `)}async function Vz(){let z=y();if(z.length>0){console.log(`
34
36
  Profiles:
35
- `);for(let Z of Q){let L=J(Z);console.log(` ${Z}${L?.name?` (${L.name})`:""} → ${L?.alias} [${L?.channels.join(", ")}]`)}console.log()}let z=process.cwd(),V=R(O,".claude","sessions"),X=[];if(q(V))for(let Z of b(V).filter((L)=>L.endsWith(".json")))try{let L=JSON.parse(E(R(V,Z),"utf-8"));if(L.cwd===z)X.push(L)}catch{}if(X.length===0&&Q.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
36
- `);return}let $=I(),Y=[],N={};if($.hub)try{let[Z,L]=await Promise.all([fetch(`${$.hub}/api/status`).then((T)=>T.json()),fetch(`${$.hub}/health`).then((T)=>T.json())]);Y=Z.sessions||[],N=L.sse_sessions||{}}catch{}if(X.length>0){console.log(`Sessions (${z}):
37
- `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let Z of X){let L=Z.sessionId.slice(0,18),T=!1;try{process.kill(Z.pid,0),T=!0}catch{}let U="(not in network)",_=z.replace(/\//g,"-"),B=R(O,".claude","channels","commhub",_,".env");if(q(B)){let w=E(B,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(w){let M=w[1].trim(),x=Y.find((h)=>h.alias===M),u=N[M]?"●":"○";U=x?`${M} ${x.status} ${u}`:`${M} (not registered)`}}console.log(` ${L} ${(T?`${Z.pid}`:`${Z.pid}✕`).padEnd(7)} ${U}`)}console.log()}}async function Qz(){let Q=I(),z=k(),V=process.env.COMMHUB_URL||z.hub||Q.hub||"http://127.0.0.1:9200",X=process.env.COMMHUB_ALIAS||z.alias;if(!X)console.error("Error: --alias required"),process.exit(1);let{CommHub:$}=await Promise.resolve().then(() => (P(),C)),Y=new $({url:V,alias:X});Y.on("task",async(N)=>{console.log(`[${X}] ← ${N.from_session}: ${N.content.slice(0,100)}`),await Y.send(N.from_session,`[${X}] 收到: ${N.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 ${V}`)}switch(A){case"init":if(W[1]==="project")e();else if(W[1]==="profile")s();else i();break;case"start":v();break;case"ls":case"list":zz();break;case"run":Qz();break;case"--help":case"-h":case void 0:j();break;default:if(J(A))W.unshift("start"),v();else console.error(`Unknown: ${A}`),j(),process.exit(1)}
37
+ `);for(let X of z){let Y=G(X);console.log(` ${X}${Y?.name?` (${Y.name})`:""} → ${Y?.alias} [${Y?.channels.join(", ")}]`)}console.log()}let B=process.cwd(),Q=N(O,".claude","sessions"),V=[];if(_(Q))for(let X of b(Q).filter((Y)=>Y.endsWith(".json")))try{let Y=JSON.parse(E(N(Q,X),"utf-8"));if(Y.cwd===B)V.push(Y)}catch{}if(V.length===0&&z.length===0){console.log("No sessions or profiles in this directory."),console.log(`Get started: anet init
38
+ `);return}let W=I(),Z=[],L={};if(W.hub)try{let[X,Y]=await Promise.all([fetch(`${W.hub}/api/status`).then((U)=>U.json()),fetch(`${W.hub}/health`).then((U)=>U.json())]);Z=X.sessions||[],L=Y.sse_sessions||{}}catch{}if(V.length>0){console.log(`Sessions (${B}):
39
+ `),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let X of V){let Y=X.sessionId.slice(0,18),U=!1;try{process.kill(X.pid,0),U=!0}catch{}let R="(not in network)",T=B.replace(/\//g,"-"),q=N(O,".claude","channels","commhub",T,".env");if(_(q)){let x=E(q,"utf-8").match(/COMMHUB_ALIAS=(.+)/);if(x){let M=x[1].trim(),D=Z.find((g)=>g.alias===M),f=L[M]?"●":"○";R=D?`${M} ${D.status} ${f}`:`${M} (not registered)`}}console.log(` ${Y} ${(U?`${X.pid}`:`${X.pid}✕`).padEnd(7)} ${R}`)}console.log()}}async function Wz(){let z=I(),B=k(),Q=process.env.COMMHUB_URL||B.hub||z.hub||"http://127.0.0.1:9200",V=process.env.COMMHUB_ALIAS||B.alias;if(!V)console.error("Error: --alias required"),process.exit(1);let{CommHub:W}=await Promise.resolve().then(() => (j(),P)),Z=new W({url:Q,alias:V});Z.on("task",async(L)=>{console.log(`[${V}] ← ${L.from_session}: ${L.content.slice(0,100)}`),await Z.send(L.from_session,`[${V}] 收到: ${L.content.slice(0,200)}`)}),Z.on("connected",()=>console.log(`[${V}] Connected`)),Z.on("disconnected",()=>console.log(`[${V}] Reconnecting...`)),process.on("SIGINT",()=>Z.disconnect().then(()=>process.exit(0))),console.log(`[${V}] Listening on ${Q}`)}switch(A){case"init":if($[1]==="project")zz();else if($[1]==="profile")Bz();else s();break;case"start":v();break;case"resume":Qz();break;case"ls":case"list":Vz();break;case"run":Wz();break;case"--help":case"-h":case void 0:C();break;default:if(G(A))$.unshift("start"),v();else console.error(`Unknown: ${A}`),C(),process.exit(1)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/agent-network",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
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",