agenthub-multiagent-mcp 1.9.0 → 1.10.0

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.
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentHub Daemon — Persistent bridge for autonomous Claude Code agents
4
+ *
5
+ * Maintains a WebSocket connection to AgentHub and spawns Claude Code
6
+ * sessions to handle incoming messages. This solves the "idle agent"
7
+ * problem where no hooks fire because there's no user interaction.
8
+ *
9
+ * Usage:
10
+ * agenthub-daemon --agent-id <id> --project-dir <path>
11
+ * agenthub-daemon --agent-id krishi-dev --project-dir /home/user/project
12
+ *
13
+ * Environment:
14
+ * AGENTHUB_URL - AgentHub server URL (default: https://agenthub.contetial.com)
15
+ * AGENTHUB_API_KEY - API key for authentication (required)
16
+ *
17
+ * The daemon:
18
+ * 1. Connects to AgentHub via WebSocket
19
+ * 2. Listens for incoming messages and tasks
20
+ * 3. Spawns `claude` CLI to process each message
21
+ * 4. Sends the response back to AgentHub
22
+ * 5. Reconnects automatically on disconnection
23
+ */
24
+ export {};
25
+ //# sourceMappingURL=daemon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
package/dist/daemon.js ADDED
@@ -0,0 +1,267 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentHub Daemon — Persistent bridge for autonomous Claude Code agents
4
+ *
5
+ * Maintains a WebSocket connection to AgentHub and spawns Claude Code
6
+ * sessions to handle incoming messages. This solves the "idle agent"
7
+ * problem where no hooks fire because there's no user interaction.
8
+ *
9
+ * Usage:
10
+ * agenthub-daemon --agent-id <id> --project-dir <path>
11
+ * agenthub-daemon --agent-id krishi-dev --project-dir /home/user/project
12
+ *
13
+ * Environment:
14
+ * AGENTHUB_URL - AgentHub server URL (default: https://agenthub.contetial.com)
15
+ * AGENTHUB_API_KEY - API key for authentication (required)
16
+ *
17
+ * The daemon:
18
+ * 1. Connects to AgentHub via WebSocket
19
+ * 2. Listens for incoming messages and tasks
20
+ * 3. Spawns `claude` CLI to process each message
21
+ * 4. Sends the response back to AgentHub
22
+ * 5. Reconnects automatically on disconnection
23
+ */
24
+ import WebSocket from "ws";
25
+ import { spawn } from "child_process";
26
+ // Parse CLI arguments
27
+ const args = process.argv.slice(2);
28
+ function getArg(name) {
29
+ const idx = args.indexOf(`--${name}`);
30
+ return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
31
+ }
32
+ const AGENT_ID = getArg("agent-id") || process.env.AGENTHUB_AGENT_ID || "";
33
+ const PROJECT_DIR = getArg("project-dir") || process.cwd();
34
+ const API_KEY = process.env.AGENTHUB_API_KEY || "";
35
+ const API_URL = process.env.AGENTHUB_URL || "https://agenthub.contetial.com";
36
+ const WS_URL = API_URL.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
37
+ const MAX_CONCURRENT = parseInt(getArg("max-concurrent") || "1", 10);
38
+ const CLAUDE_CMD = getArg("claude-cmd") || "claude";
39
+ if (!AGENT_ID) {
40
+ console.error("Error: --agent-id or AGENTHUB_AGENT_ID required");
41
+ process.exit(1);
42
+ }
43
+ if (!API_KEY) {
44
+ console.error("Error: AGENTHUB_API_KEY environment variable required");
45
+ process.exit(1);
46
+ }
47
+ // State
48
+ let ws = null;
49
+ let reconnectAttempts = 0;
50
+ let activeProcesses = 0;
51
+ let isShuttingDown = false;
52
+ function log(msg, ...extra) {
53
+ const ts = new Date().toISOString();
54
+ console.log(`[${ts}] [agenthub-daemon] ${msg}`, ...extra);
55
+ }
56
+ function logError(msg, ...extra) {
57
+ const ts = new Date().toISOString();
58
+ console.error(`[${ts}] [agenthub-daemon] ${msg}`, ...extra);
59
+ }
60
+ /**
61
+ * Connect to AgentHub WebSocket
62
+ */
63
+ function connect() {
64
+ if (isShuttingDown)
65
+ return;
66
+ const url = `${WS_URL}/ws/agents/${AGENT_ID}?api_key=${API_KEY}`;
67
+ log(`Connecting to AgentHub as "${AGENT_ID}"...`);
68
+ ws = new WebSocket(url);
69
+ ws.on("open", () => {
70
+ log("WebSocket connected");
71
+ reconnectAttempts = 0;
72
+ });
73
+ ws.on("message", (data) => {
74
+ try {
75
+ const msg = JSON.parse(data.toString());
76
+ handleWSMessage(msg);
77
+ }
78
+ catch (err) {
79
+ logError("Failed to parse WebSocket message:", err);
80
+ }
81
+ });
82
+ ws.on("close", (code, reason) => {
83
+ log(`WebSocket closed (code: ${code}, reason: ${reason.toString()})`);
84
+ ws = null;
85
+ scheduleReconnect();
86
+ });
87
+ ws.on("error", (err) => {
88
+ logError("WebSocket error:", err.message);
89
+ });
90
+ }
91
+ /**
92
+ * Schedule reconnection with exponential backoff
93
+ */
94
+ function scheduleReconnect() {
95
+ if (isShuttingDown)
96
+ return;
97
+ reconnectAttempts++;
98
+ const delay = Math.min(1000 * Math.pow(2, reconnectAttempts - 1), 30000);
99
+ log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempts})...`);
100
+ setTimeout(() => {
101
+ if (!isShuttingDown)
102
+ connect();
103
+ }, delay);
104
+ }
105
+ /**
106
+ * Handle incoming WebSocket messages
107
+ */
108
+ function handleWSMessage(msg) {
109
+ // Respond to pings
110
+ if (msg.type === "ping") {
111
+ ws?.send(JSON.stringify({ type: "pong", timestamp: new Date().toISOString() }));
112
+ return;
113
+ }
114
+ // Handle incoming message
115
+ if (msg.type === "message" && msg.message) {
116
+ const m = msg.message;
117
+ log(`Message from ${m.from_agent}: ${m.subject}`);
118
+ // Acknowledge receipt
119
+ ws?.send(JSON.stringify({ type: "ack", message_id: m.id, timestamp: new Date().toISOString() }));
120
+ // Process with Claude
121
+ processWithClaude(`You received a message on AgentHub.\n\nFrom: ${m.from_agent}\nSubject: ${m.subject}\nType: ${m.type}\nPriority: ${m.priority}\n\nBody:\n${m.body}\n\nPlease review and respond using the reply tool with message_id="${m.id}".`, m.id);
122
+ return;
123
+ }
124
+ // Handle incoming task
125
+ if (msg.type === "task" && msg.task) {
126
+ const t = msg.task;
127
+ log(`Task from ${t.assigned_by}: ${t.task}`);
128
+ processWithClaude(`You have been assigned a new task on AgentHub.\n\nTask: ${t.task}\nAssigned by: ${t.assigned_by}\nPriority: ${t.priority}\nTask ID: ${t.id}\n\nPlease accept this task using accept_task with task_id="${t.id}", then start working on it.`, undefined);
129
+ return;
130
+ }
131
+ }
132
+ /**
133
+ * Spawn Claude Code CLI to process a message
134
+ */
135
+ function processWithClaude(prompt, messageId) {
136
+ if (activeProcesses >= MAX_CONCURRENT) {
137
+ log(`Skipping — already processing ${activeProcesses} message(s) (max: ${MAX_CONCURRENT})`);
138
+ // Still mark as read if possible
139
+ if (messageId)
140
+ markRead(messageId);
141
+ return;
142
+ }
143
+ activeProcesses++;
144
+ log(`Spawning Claude Code (active: ${activeProcesses}/${MAX_CONCURRENT})...`);
145
+ const child = spawn(CLAUDE_CMD, [
146
+ "--print",
147
+ "--dangerously-skip-permissions",
148
+ "--message", prompt,
149
+ ], {
150
+ cwd: PROJECT_DIR,
151
+ env: {
152
+ ...process.env,
153
+ AGENTHUB_AGENT_ID: AGENT_ID,
154
+ },
155
+ stdio: ["pipe", "pipe", "pipe"],
156
+ timeout: 300_000, // 5 minute timeout
157
+ });
158
+ let stdout = "";
159
+ let stderr = "";
160
+ child.stdout?.on("data", (data) => {
161
+ stdout += data.toString();
162
+ });
163
+ child.stderr?.on("data", (data) => {
164
+ stderr += data.toString();
165
+ });
166
+ child.on("close", (code) => {
167
+ activeProcesses--;
168
+ if (code === 0) {
169
+ log(`Claude completed successfully (output: ${stdout.length} chars)`);
170
+ // If this was a message, send a reply with Claude's response
171
+ if (messageId && stdout.trim()) {
172
+ sendReply(messageId, stdout.trim());
173
+ }
174
+ }
175
+ else {
176
+ logError(`Claude exited with code ${code}`);
177
+ if (stderr)
178
+ logError(`stderr: ${stderr.slice(0, 500)}`);
179
+ }
180
+ });
181
+ child.on("error", (err) => {
182
+ activeProcesses--;
183
+ logError(`Failed to spawn Claude:`, err.message);
184
+ });
185
+ }
186
+ /**
187
+ * Send a reply back to AgentHub
188
+ */
189
+ async function sendReply(messageId, body) {
190
+ try {
191
+ const response = await fetch(`${API_URL}/api/messages`, {
192
+ method: "POST",
193
+ headers: {
194
+ "Content-Type": "application/json",
195
+ "X-API-Key": API_KEY,
196
+ },
197
+ body: JSON.stringify({
198
+ from_agent: AGENT_ID,
199
+ to_agent: "", // Will be resolved from reply_to
200
+ type: "response",
201
+ subject: "Re: (auto-response)",
202
+ body: body.slice(0, 5000), // Limit response length
203
+ reply_to: messageId,
204
+ }),
205
+ });
206
+ if (response.ok) {
207
+ log(`Reply sent for message ${messageId}`);
208
+ }
209
+ else {
210
+ logError(`Reply failed: HTTP ${response.status}`);
211
+ }
212
+ }
213
+ catch (err) {
214
+ logError(`Reply failed:`, err);
215
+ }
216
+ }
217
+ /**
218
+ * Mark a message as read
219
+ */
220
+ async function markRead(messageId) {
221
+ try {
222
+ await fetch(`${API_URL}/api/messages/${messageId}/read`, {
223
+ method: "POST",
224
+ headers: {
225
+ "Content-Type": "application/json",
226
+ "X-API-Key": API_KEY,
227
+ },
228
+ body: JSON.stringify({ agent_id: AGENT_ID }),
229
+ });
230
+ }
231
+ catch {
232
+ // Non-fatal
233
+ }
234
+ }
235
+ /**
236
+ * Graceful shutdown
237
+ */
238
+ function shutdown() {
239
+ log("Shutting down...");
240
+ isShuttingDown = true;
241
+ ws?.close();
242
+ // Wait for active processes to finish
243
+ if (activeProcesses > 0) {
244
+ log(`Waiting for ${activeProcesses} active process(es)...`);
245
+ const check = setInterval(() => {
246
+ if (activeProcesses === 0) {
247
+ clearInterval(check);
248
+ process.exit(0);
249
+ }
250
+ }, 1000);
251
+ // Force exit after 30 seconds
252
+ setTimeout(() => process.exit(1), 30000);
253
+ }
254
+ else {
255
+ process.exit(0);
256
+ }
257
+ }
258
+ process.on("SIGINT", shutdown);
259
+ process.on("SIGTERM", shutdown);
260
+ // Start
261
+ log(`AgentHub Daemon starting`);
262
+ log(` Agent: ${AGENT_ID}`);
263
+ log(` Project: ${PROJECT_DIR}`);
264
+ log(` Server: ${API_URL}`);
265
+ log(` Max concurrent: ${MAX_CONCURRENT}`);
266
+ connect();
267
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAqGD;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAOrE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAmC/D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;CACvB;AAqGD;;GAEG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,IAAI,CAYrE;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAmC/D;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAExC"}
package/dist/state.js CHANGED
@@ -99,6 +99,10 @@ export function saveState(workingDir, state) {
99
99
  const json = JSON.stringify(state);
100
100
  const encrypted = encrypt(json);
101
101
  fs.writeFileSync(statePath, encrypted, { mode: 0o600 });
102
+ // Write plaintext hook file with agent_id for PostToolUse hooks
103
+ // Hooks run in user's shell and can't decrypt the state file
104
+ const hookPath = path.join(path.dirname(statePath), "hook-agent-id");
105
+ fs.writeFileSync(hookPath, state.agent_id, { mode: 0o600 });
102
106
  }
103
107
  /**
104
108
  * Load agent state from encrypted file
package/dist/state.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,eAAe,GAAG,EAAE,CAAC;AAC3B,MAAM,UAAU,GAAG,EAAE,CAAC,CAAC,WAAW;AAClC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAejC;;GAEG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACxC,MAAM,UAAU,GAAG,GAAG,QAAQ,GAAG,QAAQ,UAAU,CAAC;IAEpD,OAAO,MAAM,CAAC,UAAU,CACtB,UAAU,EACV,IAAI,EACJ,iBAAiB,EACjB,UAAU,EACV,QAAQ,CACT,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAEzC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;QAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;QAC3B,MAAM,CAAC,KAAK,EAAE;KACf,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAEpC,2CAA2C;IAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/D,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,OAAe;IAC9B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAEhD,IAAI,QAAQ,CAAC,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,SAAS,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAClC,WAAW,GAAG,SAAS,EACvB,CAAC,eAAe,CACjB,CAAC;IAEF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE5B,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACjE,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAE7B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;QAC9B,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC;QAC3B,QAAQ,CAAC,KAAK,EAAE;KACjB,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,UAAkB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,UAAkB;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CAAC,UAAkB;IAC5C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,UAAkB;IACxC,MAAM,GAAG,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,UAAkB,EAAE,KAAiB;IAC7D,cAAc,CAAC,UAAU,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAExD,gEAAgE;IAChE,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,UAAkB;IAC1C,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAElD,6CAA6C;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3D,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACnB,sCAAsC;YACtC,gEAAgE;YAChE,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;gBACtD,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,2BAA2B;gBACtD,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,uBAAuB;gBACnD,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxD,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;YACvE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACrD,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC;IACxC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,yEAAyE;QACzE,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB;IAC5C,MAAM,SAAS,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAE3C,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,UAAkB;IAC5C,OAAO,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "agenthub-multiagent-mcp",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "MCP server for AgentHub multi-agent communication",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "agenthub-multiagent-mcp": "./dist/index.js",
9
- "agenthub-hook": "./dist/planHookCli.js"
9
+ "agenthub-hook": "./dist/planHookCli.js",
10
+ "agenthub-daemon": "./dist/daemon.js"
10
11
  },
11
12
  "scripts": {
12
13
  "build": "tsc",
package/src/daemon.ts ADDED
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * AgentHub Daemon — Persistent bridge for autonomous Claude Code agents
4
+ *
5
+ * Maintains a WebSocket connection to AgentHub and spawns Claude Code
6
+ * sessions to handle incoming messages. This solves the "idle agent"
7
+ * problem where no hooks fire because there's no user interaction.
8
+ *
9
+ * Usage:
10
+ * agenthub-daemon --agent-id <id> --project-dir <path>
11
+ * agenthub-daemon --agent-id krishi-dev --project-dir /home/user/project
12
+ *
13
+ * Environment:
14
+ * AGENTHUB_URL - AgentHub server URL (default: https://agenthub.contetial.com)
15
+ * AGENTHUB_API_KEY - API key for authentication (required)
16
+ *
17
+ * The daemon:
18
+ * 1. Connects to AgentHub via WebSocket
19
+ * 2. Listens for incoming messages and tasks
20
+ * 3. Spawns `claude` CLI to process each message
21
+ * 4. Sends the response back to AgentHub
22
+ * 5. Reconnects automatically on disconnection
23
+ */
24
+
25
+ import WebSocket from "ws";
26
+ import { spawn } from "child_process";
27
+
28
+ // Parse CLI arguments
29
+ const args = process.argv.slice(2);
30
+ function getArg(name: string): string | undefined {
31
+ const idx = args.indexOf(`--${name}`);
32
+ return idx !== -1 && idx + 1 < args.length ? args[idx + 1] : undefined;
33
+ }
34
+
35
+ const AGENT_ID = getArg("agent-id") || process.env.AGENTHUB_AGENT_ID || "";
36
+ const PROJECT_DIR = getArg("project-dir") || process.cwd();
37
+ const API_KEY = process.env.AGENTHUB_API_KEY || "";
38
+ const API_URL = process.env.AGENTHUB_URL || "https://agenthub.contetial.com";
39
+ const WS_URL = API_URL.replace(/^https:/, "wss:").replace(/^http:/, "ws:");
40
+ const MAX_CONCURRENT = parseInt(getArg("max-concurrent") || "1", 10);
41
+ const CLAUDE_CMD = getArg("claude-cmd") || "claude";
42
+
43
+ if (!AGENT_ID) {
44
+ console.error("Error: --agent-id or AGENTHUB_AGENT_ID required");
45
+ process.exit(1);
46
+ }
47
+ if (!API_KEY) {
48
+ console.error("Error: AGENTHUB_API_KEY environment variable required");
49
+ process.exit(1);
50
+ }
51
+
52
+ // State
53
+ let ws: WebSocket | null = null;
54
+ let reconnectAttempts = 0;
55
+ let activeProcesses = 0;
56
+ let isShuttingDown = false;
57
+
58
+ function log(msg: string, ...extra: unknown[]): void {
59
+ const ts = new Date().toISOString();
60
+ console.log(`[${ts}] [agenthub-daemon] ${msg}`, ...extra);
61
+ }
62
+
63
+ function logError(msg: string, ...extra: unknown[]): void {
64
+ const ts = new Date().toISOString();
65
+ console.error(`[${ts}] [agenthub-daemon] ${msg}`, ...extra);
66
+ }
67
+
68
+ /**
69
+ * Connect to AgentHub WebSocket
70
+ */
71
+ function connect(): void {
72
+ if (isShuttingDown) return;
73
+
74
+ const url = `${WS_URL}/ws/agents/${AGENT_ID}?api_key=${API_KEY}`;
75
+ log(`Connecting to AgentHub as "${AGENT_ID}"...`);
76
+
77
+ ws = new WebSocket(url);
78
+
79
+ ws.on("open", () => {
80
+ log("WebSocket connected");
81
+ reconnectAttempts = 0;
82
+ });
83
+
84
+ ws.on("message", (data: WebSocket.Data) => {
85
+ try {
86
+ const msg = JSON.parse(data.toString());
87
+ handleWSMessage(msg);
88
+ } catch (err) {
89
+ logError("Failed to parse WebSocket message:", err);
90
+ }
91
+ });
92
+
93
+ ws.on("close", (code: number, reason: Buffer) => {
94
+ log(`WebSocket closed (code: ${code}, reason: ${reason.toString()})`);
95
+ ws = null;
96
+ scheduleReconnect();
97
+ });
98
+
99
+ ws.on("error", (err: Error) => {
100
+ logError("WebSocket error:", err.message);
101
+ });
102
+ }
103
+
104
+ /**
105
+ * Schedule reconnection with exponential backoff
106
+ */
107
+ function scheduleReconnect(): void {
108
+ if (isShuttingDown) return;
109
+
110
+ reconnectAttempts++;
111
+ const delay = Math.min(1000 * Math.pow(2, reconnectAttempts - 1), 30000);
112
+ log(`Reconnecting in ${delay}ms (attempt ${reconnectAttempts})...`);
113
+
114
+ setTimeout(() => {
115
+ if (!isShuttingDown) connect();
116
+ }, delay);
117
+ }
118
+
119
+ /**
120
+ * Handle incoming WebSocket messages
121
+ */
122
+ function handleWSMessage(msg: {
123
+ type: string;
124
+ message?: {
125
+ id: string;
126
+ from_agent: string;
127
+ subject: string;
128
+ body: string;
129
+ type: string;
130
+ priority: string;
131
+ };
132
+ task?: {
133
+ id: string;
134
+ task: string;
135
+ assigned_by: string;
136
+ priority: string;
137
+ };
138
+ }): void {
139
+ // Respond to pings
140
+ if (msg.type === "ping") {
141
+ ws?.send(JSON.stringify({ type: "pong", timestamp: new Date().toISOString() }));
142
+ return;
143
+ }
144
+
145
+ // Handle incoming message
146
+ if (msg.type === "message" && msg.message) {
147
+ const m = msg.message;
148
+ log(`Message from ${m.from_agent}: ${m.subject}`);
149
+
150
+ // Acknowledge receipt
151
+ ws?.send(JSON.stringify({ type: "ack", message_id: m.id, timestamp: new Date().toISOString() }));
152
+
153
+ // Process with Claude
154
+ processWithClaude(
155
+ `You received a message on AgentHub.\n\nFrom: ${m.from_agent}\nSubject: ${m.subject}\nType: ${m.type}\nPriority: ${m.priority}\n\nBody:\n${m.body}\n\nPlease review and respond using the reply tool with message_id="${m.id}".`,
156
+ m.id
157
+ );
158
+ return;
159
+ }
160
+
161
+ // Handle incoming task
162
+ if (msg.type === "task" && msg.task) {
163
+ const t = msg.task;
164
+ log(`Task from ${t.assigned_by}: ${t.task}`);
165
+
166
+ processWithClaude(
167
+ `You have been assigned a new task on AgentHub.\n\nTask: ${t.task}\nAssigned by: ${t.assigned_by}\nPriority: ${t.priority}\nTask ID: ${t.id}\n\nPlease accept this task using accept_task with task_id="${t.id}", then start working on it.`,
168
+ undefined
169
+ );
170
+ return;
171
+ }
172
+ }
173
+
174
+ /**
175
+ * Spawn Claude Code CLI to process a message
176
+ */
177
+ function processWithClaude(prompt: string, messageId: string | undefined): void {
178
+ if (activeProcesses >= MAX_CONCURRENT) {
179
+ log(`Skipping — already processing ${activeProcesses} message(s) (max: ${MAX_CONCURRENT})`);
180
+ // Still mark as read if possible
181
+ if (messageId) markRead(messageId);
182
+ return;
183
+ }
184
+
185
+ activeProcesses++;
186
+ log(`Spawning Claude Code (active: ${activeProcesses}/${MAX_CONCURRENT})...`);
187
+
188
+ const child = spawn(CLAUDE_CMD, [
189
+ "--print",
190
+ "--dangerously-skip-permissions",
191
+ "--message", prompt,
192
+ ], {
193
+ cwd: PROJECT_DIR,
194
+ env: {
195
+ ...process.env,
196
+ AGENTHUB_AGENT_ID: AGENT_ID,
197
+ },
198
+ stdio: ["pipe", "pipe", "pipe"],
199
+ timeout: 300_000, // 5 minute timeout
200
+ });
201
+
202
+ let stdout = "";
203
+ let stderr = "";
204
+
205
+ child.stdout?.on("data", (data: Buffer) => {
206
+ stdout += data.toString();
207
+ });
208
+
209
+ child.stderr?.on("data", (data: Buffer) => {
210
+ stderr += data.toString();
211
+ });
212
+
213
+ child.on("close", (code: number | null) => {
214
+ activeProcesses--;
215
+
216
+ if (code === 0) {
217
+ log(`Claude completed successfully (output: ${stdout.length} chars)`);
218
+
219
+ // If this was a message, send a reply with Claude's response
220
+ if (messageId && stdout.trim()) {
221
+ sendReply(messageId, stdout.trim());
222
+ }
223
+ } else {
224
+ logError(`Claude exited with code ${code}`);
225
+ if (stderr) logError(`stderr: ${stderr.slice(0, 500)}`);
226
+ }
227
+ });
228
+
229
+ child.on("error", (err: Error) => {
230
+ activeProcesses--;
231
+ logError(`Failed to spawn Claude:`, err.message);
232
+ });
233
+ }
234
+
235
+ /**
236
+ * Send a reply back to AgentHub
237
+ */
238
+ async function sendReply(messageId: string, body: string): Promise<void> {
239
+ try {
240
+ const response = await fetch(`${API_URL}/api/messages`, {
241
+ method: "POST",
242
+ headers: {
243
+ "Content-Type": "application/json",
244
+ "X-API-Key": API_KEY,
245
+ },
246
+ body: JSON.stringify({
247
+ from_agent: AGENT_ID,
248
+ to_agent: "", // Will be resolved from reply_to
249
+ type: "response",
250
+ subject: "Re: (auto-response)",
251
+ body: body.slice(0, 5000), // Limit response length
252
+ reply_to: messageId,
253
+ }),
254
+ });
255
+
256
+ if (response.ok) {
257
+ log(`Reply sent for message ${messageId}`);
258
+ } else {
259
+ logError(`Reply failed: HTTP ${response.status}`);
260
+ }
261
+ } catch (err) {
262
+ logError(`Reply failed:`, err);
263
+ }
264
+ }
265
+
266
+ /**
267
+ * Mark a message as read
268
+ */
269
+ async function markRead(messageId: string): Promise<void> {
270
+ try {
271
+ await fetch(`${API_URL}/api/messages/${messageId}/read`, {
272
+ method: "POST",
273
+ headers: {
274
+ "Content-Type": "application/json",
275
+ "X-API-Key": API_KEY,
276
+ },
277
+ body: JSON.stringify({ agent_id: AGENT_ID }),
278
+ });
279
+ } catch {
280
+ // Non-fatal
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Graceful shutdown
286
+ */
287
+ function shutdown(): void {
288
+ log("Shutting down...");
289
+ isShuttingDown = true;
290
+ ws?.close();
291
+ // Wait for active processes to finish
292
+ if (activeProcesses > 0) {
293
+ log(`Waiting for ${activeProcesses} active process(es)...`);
294
+ const check = setInterval(() => {
295
+ if (activeProcesses === 0) {
296
+ clearInterval(check);
297
+ process.exit(0);
298
+ }
299
+ }, 1000);
300
+ // Force exit after 30 seconds
301
+ setTimeout(() => process.exit(1), 30000);
302
+ } else {
303
+ process.exit(0);
304
+ }
305
+ }
306
+
307
+ process.on("SIGINT", shutdown);
308
+ process.on("SIGTERM", shutdown);
309
+
310
+ // Start
311
+ log(`AgentHub Daemon starting`);
312
+ log(` Agent: ${AGENT_ID}`);
313
+ log(` Project: ${PROJECT_DIR}`);
314
+ log(` Server: ${API_URL}`);
315
+ log(` Max concurrent: ${MAX_CONCURRENT}`);
316
+ connect();
package/src/state.ts CHANGED
@@ -141,6 +141,11 @@ export function saveState(workingDir: string, state: AgentState): void {
141
141
  const encrypted = encrypt(json);
142
142
 
143
143
  fs.writeFileSync(statePath, encrypted, { mode: 0o600 });
144
+
145
+ // Write plaintext hook file with agent_id for PostToolUse hooks
146
+ // Hooks run in user's shell and can't decrypt the state file
147
+ const hookPath = path.join(path.dirname(statePath), "hook-agent-id");
148
+ fs.writeFileSync(hookPath, state.agent_id, { mode: 0o600 });
144
149
  }
145
150
 
146
151
  /**