@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 +26 -9
- package/dist/bin/cli.js +24 -22
- package/package.json +1 -1
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
|
|
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}/.
|
|
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
|
-
|
|
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
|
|
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
|
|
133
|
+
anet start 指挥室 # 新建 session
|
|
134
|
+
anet resume 指挥室 # 恢复上次 session(按名字搜索)
|
|
120
135
|
anet start # 列出所有 profile
|
|
121
|
-
anet
|
|
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.
|
|
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
|
|
3
|
-
`);
|
|
4
|
-
`)}function
|
|
5
|
-
`)}function y(){let
|
|
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>
|
|
12
|
-
anet
|
|
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
|
|
20
|
-
anet start
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`),console.log(
|
|
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
|
|
26
|
-
`),
|
|
27
|
-
✅ Profile "${
|
|
28
|
-
Start: anet start ${
|
|
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
|
|
31
|
-
anet
|
|
32
|
-
`)
|
|
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
|
|
36
|
-
`);return}let
|
|
37
|
-
`),console.log(" SESSION PID NETWORK"),console.log(" ──────────────────── ─────── ─────────────────────");for(let
|
|
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.
|
|
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",
|