bus-agent 2.3.4 → 2.3.6
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/{.env.coco → .env.bus} +1 -1
- package/AGENTS.md +6 -6
- package/README.md +176 -230
- package/SKILL.md +35 -35
- package/backup.js +4 -4
- package/bridge.js +5 -5
- package/bus-aliases.sh +10 -0
- package/{coco-cli.js → bus-cli.js} +18 -18
- package/{coco-tool.js → bus-tool.js} +13 -13
- package/bus.js +26 -0
- package/claude-mcp.json +2 -2
- package/clients/{coco-client.ts → bus-client.ts} +6 -6
- package/clients/{coco_client.py → bus_client.py} +7 -7
- package/cursor-mcp.json +1 -1
- package/doctor.js +1 -1
- package/hermes-forwarder.js +1 -1
- package/hermes.example.json +2 -2
- package/index.js +1 -1
- package/lib/backup.js +9 -9
- package/lib/bus.js +1 -1
- package/lib/daemon.js +7 -7
- package/lib/doctor.js +4 -4
- package/lib/mcp.js +10 -10
- package/lib/memory.js +1 -1
- package/lib/orchestrator.js +1 -1
- package/lib/scheduler.js +2 -2
- package/lib/tunnel.js +12 -12
- package/mcporter.example.json +2 -2
- package/opencode-mcp.json +2 -2
- package/package.json +9 -9
- package/scripts/install.bat +1 -1
- package/scripts/install.ps1 +10 -10
- package/setup.js +32 -32
- package/tunnel.js +2 -2
- package/webhook-gateway.js +2 -2
- package/coco-aliases.sh +0 -10
- package/coco.js +0 -26
package/SKILL.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
# MCP
|
|
1
|
+
# MCP Bus — Universal Agent Communication Hub
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
MCP
|
|
5
|
+
MCP Bus is an **Agent Communication Hub** — an MCP server that lets **any MCP-compatible agent** talk to any other.
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
OpenClaw (Andul) ──┐
|
|
9
|
-
├──▶ MCP
|
|
9
|
+
├──▶ MCP Bus (Agent Bus) ◀──▶ Claude Desktop
|
|
10
10
|
Hermes Agent ──────┘ Cursor
|
|
11
11
|
│ Any MCP agent
|
|
12
12
|
├─ message_send(to, msg)
|
|
@@ -26,7 +26,7 @@ GitHub: https://github.com/ClewCode/bus-agent
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
# Stdio mode (via mcporter)
|
|
29
|
-
mcporter add
|
|
29
|
+
mcporter add bus-agent --stdio "node E:\_system\.openclaw\workspace\repos\mcp-coco\index.js"
|
|
30
30
|
|
|
31
31
|
# Daemon mode
|
|
32
32
|
node E:\_system\.openclaw\workspace\repos\mcp-coco\index.js --daemon
|
|
@@ -44,7 +44,7 @@ node E:\_system\.openclaw\workspace\repos\mcp-coco\index.js --health
|
|
|
44
44
|
| `ask_hermes(prompt, session_key?)` | Talk to Hermes Agent (multi-turn) |
|
|
45
45
|
| `hermes_send(target, message)` | Send via Hermes to chat platform |
|
|
46
46
|
| `hermes_channels(platform?)` | List Hermes channels |
|
|
47
|
-
| `
|
|
47
|
+
| `bus_health()` | Health check (CLI + gateway) |
|
|
48
48
|
|
|
49
49
|
### Agent Bus (new)
|
|
50
50
|
|
|
@@ -94,36 +94,36 @@ bus memory rebuild andul
|
|
|
94
94
|
|
|
95
95
|
```bash
|
|
96
96
|
# Agent A registers
|
|
97
|
-
mcporter call
|
|
97
|
+
mcporter call bus-agent.agent_register name="alice"
|
|
98
98
|
|
|
99
99
|
# Agent A sends to B
|
|
100
|
-
mcporter call
|
|
100
|
+
mcporter call bus-agent.message_send from="alice" to="bob" message="Hello!"
|
|
101
101
|
|
|
102
102
|
# Agent B fetches later
|
|
103
|
-
mcporter call
|
|
103
|
+
mcporter call bus-agent.message_fetch agent_name="bob"
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
### 2. Register → Wait (long-poll, real-time)
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
109
|
# Agent B waits for messages (blocks up to 30s)
|
|
110
|
-
mcporter call
|
|
110
|
+
mcporter call bus-agent.message_wait agent_name="bob" timeout_ms=60000
|
|
111
111
|
|
|
112
112
|
# Agent A sends → B gets the message immediately
|
|
113
|
-
mcporter call
|
|
113
|
+
mcporter call bus-agent.message_send from="alice" to="bob" message="Ping!"
|
|
114
114
|
```
|
|
115
115
|
|
|
116
116
|
### 3. Channel (multi-agent chat)
|
|
117
117
|
|
|
118
118
|
```bash
|
|
119
119
|
# Create
|
|
120
|
-
mcporter call
|
|
120
|
+
mcporter call bus-agent.channel_create channel_id="dev" topic="Dev chat"
|
|
121
121
|
|
|
122
122
|
# Join
|
|
123
|
-
mcporter call
|
|
123
|
+
mcporter call bus-agent.channel_join channel_id="dev" agent_name="alice"
|
|
124
124
|
|
|
125
125
|
# Chat (sent to all members)
|
|
126
|
-
mcporter call
|
|
126
|
+
mcporter call bus-agent.channel_send channel_id="dev" from="alice" message="Hey team!"
|
|
127
127
|
```
|
|
128
128
|
|
|
129
129
|
## Webhook Gateway (port 8080)
|
|
@@ -163,13 +163,13 @@ node hermes-forwarder.js
|
|
|
163
163
|
|
|
164
164
|
## Scheduled Tasks (Windows)
|
|
165
165
|
|
|
166
|
-
All
|
|
166
|
+
All Bus services can run as Windows Scheduled Tasks (auto-start on boot, auto-restart on crash):
|
|
167
167
|
|
|
168
168
|
| Task | Purpose | Port |
|
|
169
169
|
|------|---------|------|
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
170
|
+
| `MCP_Bus_Daemon` | Bus MCP server (agent bus) | stdio |
|
|
171
|
+
| `MCP_Bus_Webhook` | Webhook Gateway | :8080 |
|
|
172
|
+
| `MCP_Bus_HermesFwd` | Hermes Auto-Forwarder | — |
|
|
173
173
|
|
|
174
174
|
Install:
|
|
175
175
|
```powershell
|
|
@@ -182,27 +182,27 @@ CLI agents (OpenCode, Claude Code, shell scripts) can access the message bus **d
|
|
|
182
182
|
|
|
183
183
|
```bash
|
|
184
184
|
# Set your agent name (optional, defaults to $USER)
|
|
185
|
-
export
|
|
185
|
+
export BUS_AGENT=opencode
|
|
186
186
|
|
|
187
187
|
# List agents
|
|
188
|
-
node
|
|
188
|
+
node bus-cli.js agents
|
|
189
189
|
|
|
190
190
|
# Check inbox
|
|
191
|
-
node
|
|
191
|
+
node bus-cli.js inbox
|
|
192
192
|
|
|
193
193
|
# Send a message
|
|
194
|
-
node
|
|
194
|
+
node bus-cli.js send andul "Hello from OpenCode!"
|
|
195
195
|
|
|
196
196
|
# Reply to a specific message
|
|
197
|
-
node
|
|
197
|
+
node bus-cli.js reply <message-id> "Thanks!"
|
|
198
198
|
|
|
199
199
|
# Watch for new messages (poll every 2s)
|
|
200
|
-
node
|
|
200
|
+
node bus-cli.js watch
|
|
201
201
|
|
|
202
202
|
# Or use the shorter wrapper
|
|
203
|
-
node
|
|
204
|
-
node
|
|
205
|
-
node
|
|
203
|
+
node bus.js agents
|
|
204
|
+
node bus.js inbox
|
|
205
|
+
node bus.js send andul "Hey!"
|
|
206
206
|
```
|
|
207
207
|
|
|
208
208
|
## One-liner for OpenCode
|
|
@@ -210,8 +210,8 @@ node coco.js send andul "Hey!"
|
|
|
210
210
|
Set this in your shell profile:
|
|
211
211
|
```bash
|
|
212
212
|
# ~/.bashrc or ~/.zshrc or $PROFILE (PowerShell)
|
|
213
|
-
export
|
|
214
|
-
alias
|
|
213
|
+
export BUS_AGENT=opencode
|
|
214
|
+
alias bus='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus.js'
|
|
215
215
|
```
|
|
216
216
|
|
|
217
217
|
Then just:
|
|
@@ -233,12 +233,12 @@ When you run `bus send`, it auto-registers your agent on the bus. Other agents (
|
|
|
233
233
|
|
|
234
234
|
## Integration with Hermes
|
|
235
235
|
|
|
236
|
-
MCP
|
|
236
|
+
MCP Bus auto-registers itself as `bus-agent` (default). Hermes can connect via:
|
|
237
237
|
```bash
|
|
238
238
|
mcporter add hermes --stdio "hermes mcp serve --accept-hooks"
|
|
239
239
|
```
|
|
240
240
|
|
|
241
|
-
Then OpenClaw and Hermes can DM through
|
|
241
|
+
Then OpenClaw and Hermes can DM through Bus message bus — no need for direct subprocess calls.
|
|
242
242
|
|
|
243
243
|
## Troubleshooting
|
|
244
244
|
|
|
@@ -271,17 +271,17 @@ All data is JSON. Back up `.bus/` to preserve conversations.
|
|
|
271
271
|
|
|
272
272
|
### Bus Doctor
|
|
273
273
|
|
|
274
|
-
Diagnostics and health checks for the
|
|
274
|
+
Diagnostics and health checks for the Agent bus:
|
|
275
275
|
|
|
276
276
|
```bash
|
|
277
277
|
node doctor.js [--quick] [--fix] [--report] [--watch]
|
|
278
278
|
# or via CLI
|
|
279
|
-
node
|
|
279
|
+
node bus-cli.js doctor [--quick] [--fix]
|
|
280
280
|
```
|
|
281
281
|
|
|
282
282
|
Performs 18 checks: bus directory, permissions, agent registry (profiles, stale agents), orphaned agents, message integrity, channels, scheduler validity, auto-reply rules, workflows, disk usage, stale PIDs, event logs. With `--fix`, auto-creates missing directories, removes stale PID files, deletes corrupted messages.
|
|
283
283
|
|
|
284
|
-
###
|
|
284
|
+
### Bus Tunnel
|
|
285
285
|
|
|
286
286
|
Cross-machine bus proxy. Expose your local bus to remote agents:
|
|
287
287
|
|
|
@@ -291,7 +291,7 @@ node tunnel.js client --host <ip> --port 9090 --secret ***
|
|
|
291
291
|
node tunnel.js sync --remote http://<ip>:9090
|
|
292
292
|
node tunnel.js ssh --remote user@host
|
|
293
293
|
# or via CLI
|
|
294
|
-
node
|
|
294
|
+
node bus-cli.js tunnel server --port 9090 --secret ***
|
|
295
295
|
```
|
|
296
296
|
|
|
297
297
|
Server exposes HTTP endpoints: `/health`, `/bus/agents`, `/bus/send`, `/bus/register`. Client pushes local agents and recent messages at configurable interval. Sync mode merges agent registries bidirectionally.
|
|
@@ -308,7 +308,7 @@ node backup.js --diff <file> # Compare with current state
|
|
|
308
308
|
node backup.js --cleanup 30 # Remove old backups
|
|
309
309
|
node backup.js --watch 60 # Auto-backup every 60 min
|
|
310
310
|
# or via CLI
|
|
311
|
-
node
|
|
311
|
+
node bus-cli.js backup --list
|
|
312
312
|
```
|
|
313
313
|
|
|
314
314
|
Backups stored in `.backups/` directory. Each backup includes checksum verification. Diff shows added/removed/modified files.
|
package/backup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Bus Backup & Restore — Bus State Management CLI Wrapper
|
|
4
4
|
*
|
|
5
5
|
* Thin wrapper around lib/backup.js
|
|
6
6
|
* Usage: see --help
|
|
@@ -13,7 +13,7 @@ const args = process.argv.slice(2);
|
|
|
13
13
|
const cmd = args[0];
|
|
14
14
|
|
|
15
15
|
function help() {
|
|
16
|
-
console.log(`\n╔═══════════════════════════════════════════════╗\n║
|
|
16
|
+
console.log(`\n╔═══════════════════════════════════════════════╗\n║ Bus — Backup & Restore ║\n╚═══════════════════════════════════════════════╝\n`);
|
|
17
17
|
console.log('Usage:');
|
|
18
18
|
console.log(' node backup.js Create backup (timestamped name)');
|
|
19
19
|
console.log(' node backup.js --out <file> Create backup with custom path');
|
|
@@ -26,8 +26,8 @@ function help() {
|
|
|
26
26
|
console.log(' node backup.js --watch <minutes> Auto-backup every N minutes\n');
|
|
27
27
|
console.log('Examples:');
|
|
28
28
|
console.log(' node backup.js');
|
|
29
|
-
console.log(' node backup.js --restore .backups/
|
|
30
|
-
console.log(' node backup.js --diff .backups/
|
|
29
|
+
console.log(' node backup.js --restore .backups/bus-2026-06-24.coco');
|
|
30
|
+
console.log(' node backup.js --diff .backups/bus-2026-06-24.coco');
|
|
31
31
|
console.log(' node backup.js --cleanup 30');
|
|
32
32
|
console.log(' node backup.js --watch 60\n');
|
|
33
33
|
}
|
package/bridge.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Bus External Bridge — Connect external platforms to the Agent Bus
|
|
4
4
|
*
|
|
5
5
|
* Generic bridge pattern that can be adapted for:
|
|
6
6
|
* - Slack (Web API + Events API)
|
|
@@ -66,7 +66,7 @@ class GenericBridge {
|
|
|
66
66
|
registered_at: agents[this.agentName]?.registered_at || new Date().toISOString(),
|
|
67
67
|
};
|
|
68
68
|
fs.writeFileSync(agentsFile, JSON.stringify(agents, null, 2), 'utf-8');
|
|
69
|
-
console.log(` ✅ Registered as "${this.agentName}" on
|
|
69
|
+
console.log(` ✅ Registered as "${this.agentName}" on Agent Bus`);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// Map external channel → bus channel
|
|
@@ -222,7 +222,7 @@ const CHANNELS_DIR = path.join(BUS_DIR, 'channels');
|
|
|
222
222
|
function help() {
|
|
223
223
|
console.log(`
|
|
224
224
|
╔═══════════════════════════════════════════════╗
|
|
225
|
-
║ MCP
|
|
225
|
+
║ MCP Bus — External Platform Bridge ║
|
|
226
226
|
╚═══════════════════════════════════════════════╝
|
|
227
227
|
|
|
228
228
|
Usage:
|
|
@@ -281,11 +281,11 @@ async function main() {
|
|
|
281
281
|
|
|
282
282
|
console.log(`
|
|
283
283
|
╔══════════════════════════════════════════════╗
|
|
284
|
-
║ MCP
|
|
284
|
+
║ MCP Bus — ${type.padEnd(22)}║
|
|
285
285
|
╚══════════════════════════════════════════════╝
|
|
286
286
|
`);
|
|
287
287
|
|
|
288
|
-
bridge.registerAgent(`${type} bridge — connects ${type} to
|
|
288
|
+
bridge.registerAgent(`${type} bridge — connects ${type} to Agent Bus`);
|
|
289
289
|
startBridgeListener(bridge, port);
|
|
290
290
|
bridge.start();
|
|
291
291
|
|
package/bus-aliases.sh
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
# ── Bus Agent Aliases ──
|
|
3
|
+
alias bus-agents='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js agents'
|
|
4
|
+
alias bus-inbox='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js inbox'
|
|
5
|
+
alias bus-send='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js send'
|
|
6
|
+
alias bus-whoami='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js whoami'
|
|
7
|
+
alias bus-status='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js status'
|
|
8
|
+
alias bus-search='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js search'
|
|
9
|
+
alias bus-watch='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js watch'
|
|
10
|
+
alias bus-channel='node E:\_system\.openclaw\workspace\repos\mcp-coco\bus-cli.js channel'
|
|
@@ -78,7 +78,7 @@ function main() {
|
|
|
78
78
|
|
|
79
79
|
function cmdWhoami() {
|
|
80
80
|
const agents = loadAgents();
|
|
81
|
-
const name = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
81
|
+
const name = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
82
82
|
const seen = agents[name];
|
|
83
83
|
const profile = seen || {};
|
|
84
84
|
console.log(`\n👤 Your Agent Identity:`);
|
|
@@ -147,7 +147,7 @@ function cmdAgents(filterArgs) {
|
|
|
147
147
|
// ── Inbox (enhanced with --from filter) ──
|
|
148
148
|
|
|
149
149
|
function cmdInbox(agentName, extra) {
|
|
150
|
-
const agent = agentName || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
150
|
+
const agent = agentName || process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
151
151
|
const dir = path.join(MSGS_DIR, agent);
|
|
152
152
|
|
|
153
153
|
const opts = { from: null, unread: false };
|
|
@@ -204,7 +204,7 @@ function cmdSend(to, text) {
|
|
|
204
204
|
console.log('Usage: bus send <to> <message>');
|
|
205
205
|
process.exit(1);
|
|
206
206
|
}
|
|
207
|
-
const from = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
207
|
+
const from = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
208
208
|
const msg = {
|
|
209
209
|
id: `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
|
|
210
210
|
from,
|
|
@@ -223,7 +223,7 @@ function cmdReply(msgId, text) {
|
|
|
223
223
|
console.log('Usage: bus reply <msg-id> <message>');
|
|
224
224
|
process.exit(1);
|
|
225
225
|
}
|
|
226
|
-
const from = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
226
|
+
const from = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
227
227
|
|
|
228
228
|
let original = null;
|
|
229
229
|
if (fs.existsSync(MSGS_DIR)) {
|
|
@@ -266,7 +266,7 @@ function cmdProfile(subArgs) {
|
|
|
266
266
|
return cmdProfileEdit(subArgs.slice(1));
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
const agentName = subArgs[0] || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
269
|
+
const agentName = subArgs[0] || process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
270
270
|
const agents = loadAgents();
|
|
271
271
|
const profile = agents[agentName];
|
|
272
272
|
|
|
@@ -295,7 +295,7 @@ function cmdProfile(subArgs) {
|
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
function cmdProfileEdit(edits) {
|
|
298
|
-
const name = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
298
|
+
const name = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
299
299
|
const agents = loadAgents();
|
|
300
300
|
if (!agents[name]) {
|
|
301
301
|
console.log(`❌ Not registered. Register first with: send or whoami`);
|
|
@@ -375,7 +375,7 @@ function cmdStatus() {
|
|
|
375
375
|
const online = Object.entries(agents).filter(([, a]) => new Date(a.last_seen).getTime() > cutoff);
|
|
376
376
|
const offline = Object.entries(agents).filter(([, a]) => new Date(a.last_seen).getTime() <= cutoff);
|
|
377
377
|
|
|
378
|
-
const myName = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
378
|
+
const myName = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
379
379
|
const me = agents[myName];
|
|
380
380
|
const myOnline = me && new Date(me.last_seen).getTime() > cutoff;
|
|
381
381
|
|
|
@@ -433,7 +433,7 @@ function cmdSubscribe(channelId) {
|
|
|
433
433
|
const logDir = path.join(CHANNELS_DIR, channelId, 'log');
|
|
434
434
|
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
435
435
|
|
|
436
|
-
const myName = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
436
|
+
const myName = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
437
437
|
|
|
438
438
|
// Join if not already
|
|
439
439
|
const ch = JSON.parse(fs.readFileSync(chPath, 'utf-8'));
|
|
@@ -574,7 +574,7 @@ function cmdChannel(subArgs) {
|
|
|
574
574
|
const chId = subArgs[1];
|
|
575
575
|
const topic = subArgs.slice(2).join(' ') || '';
|
|
576
576
|
if (!chId) { console.log('Usage: bus channel create <name> [topic]'); return; }
|
|
577
|
-
const ch = { id: chId, topic, created_by: process.env.COCO_AGENT || 'cli', created_at: new Date().toISOString(), members: [] };
|
|
577
|
+
const ch = { id: chId, topic, created_by: process.env.BUS_AGENT || process.env.COCO_AGENT || 'cli', created_at: new Date().toISOString(), members: [] };
|
|
578
578
|
fs.writeFileSync(path.join(CHANNELS_DIR, `${chId}.json`), JSON.stringify(ch, null, 2), 'utf-8');
|
|
579
579
|
console.log(`✅ Channel "#${chId}" created`);
|
|
580
580
|
return;
|
|
@@ -582,7 +582,7 @@ function cmdChannel(subArgs) {
|
|
|
582
582
|
|
|
583
583
|
if (sub === 'join') {
|
|
584
584
|
const chId = subArgs[1];
|
|
585
|
-
const agentName = subArgs[2] || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
585
|
+
const agentName = subArgs[2] || process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
586
586
|
if (!chId) { console.log('Usage: bus channel join <name> [agent]'); return; }
|
|
587
587
|
const chPath = path.join(CHANNELS_DIR, `${chId}.json`);
|
|
588
588
|
if (!fs.existsSync(chPath)) { console.log(`❌ Channel "${chId}" not found`); return; }
|
|
@@ -600,7 +600,7 @@ function cmdChannel(subArgs) {
|
|
|
600
600
|
console.log('Usage: bus channel send <channel> <message>');
|
|
601
601
|
return;
|
|
602
602
|
}
|
|
603
|
-
const from = process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
603
|
+
const from = process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
604
604
|
const chPath = path.join(CHANNELS_DIR, `${channelId}.json`);
|
|
605
605
|
if (!fs.existsSync(chPath)) {
|
|
606
606
|
console.log(`❌ Channel "${channelId}" not found`);
|
|
@@ -655,7 +655,7 @@ function cmdChannel(subArgs) {
|
|
|
655
655
|
// ── Watch ──
|
|
656
656
|
|
|
657
657
|
function cmdWatch(agentName) {
|
|
658
|
-
const agent = agentName || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
658
|
+
const agent = agentName || process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'anonymous';
|
|
659
659
|
const dir = path.join(MSGS_DIR, agent);
|
|
660
660
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
661
661
|
|
|
@@ -708,10 +708,10 @@ function cmdTunnel(args) {
|
|
|
708
708
|
const mode = args[0];
|
|
709
709
|
if (!mode || mode === '--help') {
|
|
710
710
|
console.log('Usage: bus tunnel server|client|sync|ssh [options]');
|
|
711
|
-
console.log('
|
|
712
|
-
console.log('
|
|
713
|
-
console.log('
|
|
714
|
-
console.log('
|
|
711
|
+
console.log(' bus tunnel server --port 9090 --secret <token>');
|
|
712
|
+
console.log(' bus tunnel client --host <ip> --port 9090 --secret <token>');
|
|
713
|
+
console.log(' bus tunnel sync --remote http://<ip>:9090');
|
|
714
|
+
console.log(' bus tunnel ssh --remote user@host');
|
|
715
715
|
return;
|
|
716
716
|
}
|
|
717
717
|
const opts = { busDir: BUS_DIR };
|
|
@@ -910,7 +910,7 @@ Commands:
|
|
|
910
910
|
filters: --online, --status, --capability, --tag, --model, --search
|
|
911
911
|
|
|
912
912
|
whoami Show your agent identity
|
|
913
|
-
inbox [agent] [--from X] Check messages (default: \$
|
|
913
|
+
inbox [agent] [--from X] Check messages (default: \$BUS_AGENT)
|
|
914
914
|
send <to> <message> Send a message to another agent
|
|
915
915
|
reply <msg-id> <message> Reply to an incoming message
|
|
916
916
|
profile [agent] Show agent profile details
|
|
@@ -968,7 +968,7 @@ Commands:
|
|
|
968
968
|
memory rebuild <agent> Rebuild vector embeddings for all memories
|
|
969
969
|
|
|
970
970
|
Environment:
|
|
971
|
-
|
|
971
|
+
BUS_AGENT=opencode Set your agent name for inbox/send
|
|
972
972
|
|
|
973
973
|
Examples:
|
|
974
974
|
bus agents --online --capability code-review
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Bus Tool Wrapper — Direct bus calls from any tool/exec context
|
|
4
4
|
*
|
|
5
5
|
* Acts as a lightweight RPC bridge between tools (OpenClaw, CLI, etc.)
|
|
6
|
-
* and the
|
|
6
|
+
* and the Agent Bus. No MCP needed — direct file access.
|
|
7
7
|
*
|
|
8
8
|
* Usage:
|
|
9
|
-
* node
|
|
9
|
+
* node bus-tool.js <tool> [args...]
|
|
10
10
|
*
|
|
11
11
|
* Examples:
|
|
12
|
-
* node
|
|
13
|
-
* node
|
|
14
|
-
* node
|
|
15
|
-
* node
|
|
16
|
-
* node
|
|
17
|
-
* node
|
|
18
|
-
* node
|
|
12
|
+
* node bus-tool.js agent_list '{"online_only":true}'
|
|
13
|
+
* node bus-tool.js agent_get_profile '{"name":"bus-agent"}'
|
|
14
|
+
* node bus-tool.js message_send '{"from":"andul","to":"hermes","message":"Hello!"}'
|
|
15
|
+
* node bus-tool.js message_fetch '{"agent_name":"andul"}'
|
|
16
|
+
* node bus-tool.js agent_search '{"query":"code"}'
|
|
17
|
+
* node bus-tool.js agent_register '{"name":"andul","description":"Andul 🐺","capabilities":["chat","code","browsing"]}'
|
|
18
|
+
* node bus-tool.js bus_health '{}'
|
|
19
19
|
*/
|
|
20
20
|
const path = require('path');
|
|
21
21
|
const fs = require('fs');
|
|
@@ -39,8 +39,8 @@ async function main() {
|
|
|
39
39
|
let result;
|
|
40
40
|
|
|
41
41
|
switch (tool) {
|
|
42
|
-
//
|
|
43
|
-
case '
|
|
42
|
+
// Bus Health
|
|
43
|
+
case 'bus_health':
|
|
44
44
|
result = await bridge.healthCheck();
|
|
45
45
|
break;
|
|
46
46
|
|
|
@@ -159,7 +159,7 @@ async function main() {
|
|
|
159
159
|
|
|
160
160
|
function getToolList() {
|
|
161
161
|
return [
|
|
162
|
-
'
|
|
162
|
+
'bus_health',
|
|
163
163
|
'agent_register', 'agent_update_profile', 'agent_get_profile',
|
|
164
164
|
'agent_list', 'agent_search', 'agent_heartbeat', 'agent_set_status',
|
|
165
165
|
'message_send', 'message_broadcast', 'message_fetch', 'message_delete',
|
package/bus.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Bus — Convenience entry point for CLI agents
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node bus.js agents # List agents
|
|
7
|
+
* node bus.js inbox # Check your messages
|
|
8
|
+
* node bus.js send "message" # Send to last reply-to agent
|
|
9
|
+
* node bus.js send <to> msg # Send to specific agent
|
|
10
|
+
* node bus.js watch # Watch for new messages
|
|
11
|
+
*/
|
|
12
|
+
const { execSync } = require('child_process');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const CLI = path.join(__dirname, 'bus-cli.js');
|
|
16
|
+
const args = process.argv.slice(2).join(' ');
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
const result = execSync(`node "${CLI}" ${args}`, {
|
|
20
|
+
encoding: 'utf-8',
|
|
21
|
+
stdio: 'inherit',
|
|
22
|
+
env: { ...process.env },
|
|
23
|
+
});
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// errors already shown via stdio
|
|
26
|
+
}
|
package/claude-mcp.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Bus Agent Client — TypeScript/JS SDK for Agent Bus
|
|
3
3
|
*
|
|
4
|
-
* Direct file-based access to the
|
|
4
|
+
* Direct file-based access to the Agent Bus. No MCP needed.
|
|
5
5
|
* Works in Node.js. For browser, use the WebSocket/proxy approach.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* import {
|
|
8
|
+
* import { BusClient } from './bus-client.js';
|
|
9
9
|
*
|
|
10
|
-
* const bus = new
|
|
10
|
+
* const bus = new BusClient('/path/to/.bus', 'my-agent');
|
|
11
11
|
* await bus.register({ description: 'My agent' });
|
|
12
12
|
* await bus.send('hermes', 'Hello!');
|
|
13
13
|
* const msgs = await bus.fetchMessages();
|
|
@@ -42,7 +42,7 @@ interface BusMessage {
|
|
|
42
42
|
timestamp: string;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export class
|
|
45
|
+
export class BusClient {
|
|
46
46
|
private busDir: string;
|
|
47
47
|
private msgsDir: string;
|
|
48
48
|
private agentsFile: string;
|
|
@@ -54,7 +54,7 @@ export class CoCoClient {
|
|
|
54
54
|
this.msgsDir = path.join(busDir, 'messages');
|
|
55
55
|
this.agentsFile = path.join(busDir, 'agents.json');
|
|
56
56
|
this.channelsDir = path.join(busDir, 'channels');
|
|
57
|
-
this.agentName = agentName || process.env.COCO_AGENT || process.env.USER || 'ts-agent';
|
|
57
|
+
this.agentName = agentName || process.env.BUS_AGENT || process.env.COCO_AGENT || process.env.USER || 'ts-agent';
|
|
58
58
|
this._ensureDirs();
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Bus Bus Client — Python SDK for Agent Bus
|
|
3
3
|
|
|
4
|
-
Direct file-based access to the
|
|
4
|
+
Direct file-based access to the Bus Agent Bus. No MCP needed.
|
|
5
5
|
Any agent with filesystem access to the bus directory can use this.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
from
|
|
8
|
+
from bus_client import BusClient
|
|
9
9
|
|
|
10
|
-
bus =
|
|
10
|
+
bus = BusClient("/path/to/bus-agent/.bus", agent_name="my-agent")
|
|
11
11
|
bus.register(description="My Python agent", capabilities=["data-analysis", "api-calls"])
|
|
12
12
|
bus.send("hermes", "Hello from Python!")
|
|
13
13
|
msgs = bus.fetch_messages()
|
|
@@ -22,14 +22,14 @@ import time
|
|
|
22
22
|
import uuid
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class BusClient:
|
|
26
26
|
def __init__(self, bus_dir, agent_name=None):
|
|
27
27
|
self.bus_dir = bus_dir
|
|
28
28
|
self.msgs_dir = os.path.join(bus_dir, "messages")
|
|
29
29
|
self.agents_file = os.path.join(bus_dir, "agents.json")
|
|
30
30
|
self.channels_dir = os.path.join(bus_dir, "channels")
|
|
31
31
|
self.events_dir = os.path.join(bus_dir, "events")
|
|
32
|
-
self.agent_name = agent_name or os.environ.get("COCO_AGENT") or os.environ.get("USER", "python-agent")
|
|
32
|
+
self.agent_name = agent_name or os.environ.get("BUS_AGENT") or os.environ.get("COCO_AGENT") or os.environ.get("USER", "python-agent")
|
|
33
33
|
self._ensure_dirs()
|
|
34
34
|
|
|
35
35
|
def _ensure_dirs(self):
|
|
@@ -55,7 +55,7 @@ class CoCoClient:
|
|
|
55
55
|
# ── Registration ──
|
|
56
56
|
|
|
57
57
|
def register(self, description="", capabilities=None, model=None, tags=None, version="1.0.0", status="idle"):
|
|
58
|
-
"""Register yourself on the
|
|
58
|
+
"""Register yourself on the Bus Agent Bus."""
|
|
59
59
|
agents = self._load_agents()
|
|
60
60
|
existing = agents.get(self.agent_name, {})
|
|
61
61
|
agents[self.agent_name] = {
|
package/cursor-mcp.json
CHANGED
package/doctor.js
CHANGED
package/hermes-forwarder.js
CHANGED
|
@@ -135,7 +135,7 @@ async function poll() {
|
|
|
135
135
|
|
|
136
136
|
console.log(`
|
|
137
137
|
╔══════════════════════════════════════════╗
|
|
138
|
-
║ MCP
|
|
138
|
+
║ MCP Bus — Hermes Auto-Forwarder ║
|
|
139
139
|
║ ║
|
|
140
140
|
║ Any DM to "hermes" → ║
|
|
141
141
|
║ ask_hermes(prompt) → reply back ║
|
package/hermes.example.json
CHANGED
package/index.js
CHANGED
|
@@ -33,7 +33,7 @@ async function main() {
|
|
|
33
33
|
const bus = new AgentBus();
|
|
34
34
|
const scheduler = new Scheduler(bus);
|
|
35
35
|
scheduler.start();
|
|
36
|
-
console.log('
|
|
36
|
+
console.log('Bus Scheduler running. Press Ctrl+C to stop.');
|
|
37
37
|
// Keep alive
|
|
38
38
|
process.on('SIGINT', () => { scheduler.stop(); process.exit(0); });
|
|
39
39
|
process.on('SIGTERM', () => { scheduler.stop(); process.exit(0); });
|