agent-inbox 0.0.1 → 0.1.2
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/CLAUDE.md +113 -0
- package/README.md +195 -1
- package/dist/federation/address.d.ts +24 -0
- package/dist/federation/address.d.ts.map +1 -0
- package/dist/federation/address.js +54 -0
- package/dist/federation/address.js.map +1 -0
- package/dist/federation/connection-manager.d.ts +118 -0
- package/dist/federation/connection-manager.d.ts.map +1 -0
- package/dist/federation/connection-manager.js +369 -0
- package/dist/federation/connection-manager.js.map +1 -0
- package/dist/federation/delivery-queue.d.ts +66 -0
- package/dist/federation/delivery-queue.d.ts.map +1 -0
- package/dist/federation/delivery-queue.js +199 -0
- package/dist/federation/delivery-queue.js.map +1 -0
- package/dist/federation/index.d.ts +7 -0
- package/dist/federation/index.d.ts.map +1 -0
- package/dist/federation/index.js +6 -0
- package/dist/federation/index.js.map +1 -0
- package/dist/federation/routing-engine.d.ts +74 -0
- package/dist/federation/routing-engine.d.ts.map +1 -0
- package/dist/federation/routing-engine.js +158 -0
- package/dist/federation/routing-engine.js.map +1 -0
- package/dist/federation/trust.d.ts +39 -0
- package/dist/federation/trust.d.ts.map +1 -0
- package/dist/federation/trust.js +64 -0
- package/dist/federation/trust.js.map +1 -0
- package/dist/index.d.ts +60 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +217 -18
- package/dist/index.js.map +1 -1
- package/dist/ipc/ipc-server.d.ts +21 -0
- package/dist/ipc/ipc-server.d.ts.map +1 -0
- package/dist/ipc/ipc-server.js +173 -0
- package/dist/ipc/ipc-server.js.map +1 -0
- package/dist/jsonrpc/mail-server.d.ts +45 -0
- package/dist/jsonrpc/mail-server.d.ts.map +1 -0
- package/dist/jsonrpc/mail-server.js +284 -0
- package/dist/jsonrpc/mail-server.js.map +1 -0
- package/dist/map/map-client.d.ts +91 -0
- package/dist/map/map-client.d.ts.map +1 -0
- package/dist/map/map-client.js +202 -0
- package/dist/map/map-client.js.map +1 -0
- package/dist/mcp/mcp-server.d.ts +23 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -0
- package/dist/mcp/mcp-server.js +226 -0
- package/dist/mcp/mcp-server.js.map +1 -0
- package/dist/push/notifier.d.ts +49 -0
- package/dist/push/notifier.d.ts.map +1 -0
- package/dist/push/notifier.js +150 -0
- package/dist/push/notifier.js.map +1 -0
- package/dist/registry/warm-registry.d.ts +63 -0
- package/dist/registry/warm-registry.d.ts.map +1 -0
- package/dist/registry/warm-registry.js +173 -0
- package/dist/registry/warm-registry.js.map +1 -0
- package/dist/router/message-router.d.ts +44 -0
- package/dist/router/message-router.d.ts.map +1 -0
- package/dist/router/message-router.js +137 -0
- package/dist/router/message-router.js.map +1 -0
- package/dist/storage/interface.d.ts +31 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +2 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/memory.d.ts +28 -0
- package/dist/storage/memory.d.ts.map +1 -0
- package/dist/storage/memory.js +118 -0
- package/dist/storage/memory.js.map +1 -0
- package/dist/storage/sqlite.d.ts +35 -0
- package/dist/storage/sqlite.d.ts.map +1 -0
- package/dist/storage/sqlite.js +445 -0
- package/dist/storage/sqlite.js.map +1 -0
- package/dist/traceability/traceability.d.ts +29 -0
- package/dist/traceability/traceability.d.ts.map +1 -0
- package/dist/traceability/traceability.js +150 -0
- package/dist/traceability/traceability.js.map +1 -0
- package/dist/types.d.ts +261 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/docs/DESIGN.md +1156 -0
- package/docs/PLAN.md +545 -0
- package/hooks/inbox-hook.mjs +119 -0
- package/hooks/register-hook.mjs +69 -0
- package/package.json +33 -25
- package/rules/agent-inbox.md +78 -0
- package/src/federation/address.ts +61 -0
- package/src/federation/connection-manager.ts +458 -0
- package/src/federation/delivery-queue.ts +222 -0
- package/src/federation/index.ts +6 -0
- package/src/federation/routing-engine.ts +188 -0
- package/src/federation/trust.ts +71 -0
- package/src/index.ts +299 -0
- package/src/ipc/ipc-server.ts +207 -0
- package/src/jsonrpc/mail-server.ts +356 -0
- package/src/map/map-client.ts +260 -0
- package/src/mcp/mcp-server.ts +272 -0
- package/src/push/notifier.ts +192 -0
- package/src/registry/warm-registry.ts +210 -0
- package/src/router/message-router.ts +175 -0
- package/src/storage/interface.ts +48 -0
- package/src/storage/memory.ts +145 -0
- package/src/storage/sqlite.ts +645 -0
- package/src/traceability/traceability.ts +183 -0
- package/src/types.ts +297 -0
- package/test/federation/address.test.ts +101 -0
- package/test/federation/connection-manager.test.ts +546 -0
- package/test/federation/delivery-queue.test.ts +159 -0
- package/test/federation/integration.test.ts +823 -0
- package/test/federation/routing-engine.test.ts +117 -0
- package/test/federation/sdk-integration.test.ts +748 -0
- package/test/federation/trust.test.ts +89 -0
- package/test/ipc-jsonrpc.test.ts +113 -0
- package/test/ipc-server.test.ts +197 -0
- package/test/mail-server.test.ts +208 -0
- package/test/map-client.test.ts +408 -0
- package/test/message-router.test.ts +184 -0
- package/test/push-notifier.test.ts +139 -0
- package/test/registry/warm-registry.test.ts +171 -0
- package/test/sqlite-storage.test.ts +243 -0
- package/test/storage.test.ts +196 -0
- package/test/traceability.test.ts +123 -0
- package/tsconfig.json +20 -0
- package/tsup.config.ts +10 -0
- package/vitest.config.ts +8 -0
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* SessionStart hook — auto-registers the agent with Agent Inbox
|
|
5
|
+
* so it can receive messages immediately.
|
|
6
|
+
*
|
|
7
|
+
* Connects to the Agent Inbox IPC socket and sends a register_agent
|
|
8
|
+
* request. If the socket isn't running, silently continues.
|
|
9
|
+
*
|
|
10
|
+
* Setup (in .claude/settings.json or ~/.claude/settings.json):
|
|
11
|
+
*
|
|
12
|
+
* {
|
|
13
|
+
* "hooks": {
|
|
14
|
+
* "SessionStart": [{
|
|
15
|
+
* "hooks": [{
|
|
16
|
+
* "type": "command",
|
|
17
|
+
* "command": "node /path/to/agent-inbox/hooks/register-hook.mjs"
|
|
18
|
+
* }]
|
|
19
|
+
* }]
|
|
20
|
+
* }
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* Environment:
|
|
24
|
+
* INBOX_AGENT_ID — Agent ID to register (required)
|
|
25
|
+
* INBOX_AGENT_NAME — Display name (optional, defaults to agent ID)
|
|
26
|
+
* INBOX_SOCKET — IPC socket path
|
|
27
|
+
* (default: ~/.cache/agent-inbox/inbox.sock)
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import * as net from "node:net";
|
|
31
|
+
import * as path from "node:path";
|
|
32
|
+
import * as os from "node:os";
|
|
33
|
+
|
|
34
|
+
const agentId = process.env.INBOX_AGENT_ID;
|
|
35
|
+
if (!agentId) {
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const agentName = process.env.INBOX_AGENT_NAME || agentId;
|
|
40
|
+
const socketPath =
|
|
41
|
+
process.env.INBOX_SOCKET ||
|
|
42
|
+
path.join(os.homedir(), ".cache", "agent-inbox", "inbox.sock");
|
|
43
|
+
|
|
44
|
+
const request = JSON.stringify({
|
|
45
|
+
action: "register_agent",
|
|
46
|
+
agentId,
|
|
47
|
+
name: agentName,
|
|
48
|
+
program: "claude-code",
|
|
49
|
+
}) + "\n";
|
|
50
|
+
|
|
51
|
+
const client = net.createConnection(socketPath, () => {
|
|
52
|
+
client.write(request);
|
|
53
|
+
// Read one response then close
|
|
54
|
+
client.once("data", () => {
|
|
55
|
+
client.end();
|
|
56
|
+
process.exit(0);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Best-effort — if socket doesn't exist, just continue
|
|
61
|
+
client.on("error", () => {
|
|
62
|
+
process.exit(0);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Timeout after 2 seconds
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
client.destroy();
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}, 2000);
|
package/package.json
CHANGED
|
@@ -1,30 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-inbox",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Agent
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Agent Inbox — message routing, traceability, and MCP tools for multi-agent systems",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
|
-
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"import": {
|
|
11
|
-
"types": "./dist/index.d.mts",
|
|
12
|
-
"default": "./dist/index.mjs"
|
|
13
|
-
},
|
|
14
|
-
"require": {
|
|
15
|
-
"types": "./dist/index.d.ts",
|
|
16
|
-
"default": "./dist/index.js"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"files": [
|
|
21
|
-
"dist"
|
|
22
|
-
],
|
|
23
8
|
"scripts": {
|
|
24
|
-
"build": "
|
|
25
|
-
"dev": "
|
|
26
|
-
"test": "
|
|
27
|
-
"
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"dev": "tsc --watch",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"test:watch": "vitest",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"publish:npm": "npm publish --access public",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"version:patch": "npm version patch && git push && git push --tags",
|
|
17
|
+
"version:minor": "npm version minor && git push && git push --tags",
|
|
18
|
+
"version:major": "npm version major && git push && git push --tags"
|
|
28
19
|
},
|
|
29
20
|
"repository": {
|
|
30
21
|
"type": "git",
|
|
@@ -37,9 +28,26 @@
|
|
|
37
28
|
"url": "https://github.com/alexngai/agent-inbox/issues"
|
|
38
29
|
},
|
|
39
30
|
"homepage": "https://github.com/alexngai/agent-inbox#readme",
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
36
|
+
"better-sqlite3": "^12.6.2",
|
|
37
|
+
"ulid": "^2.3.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@multi-agent-protocol/sdk": "*"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"@multi-agent-protocol/sdk": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
40
47
|
"devDependencies": {
|
|
41
|
-
"@types/
|
|
42
|
-
"
|
|
43
|
-
"typescript": "^5.
|
|
48
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
49
|
+
"@types/node": "^22.0.0",
|
|
50
|
+
"typescript": "^5.7.0",
|
|
51
|
+
"vitest": "^3.0.0"
|
|
44
52
|
}
|
|
45
53
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Agent Inbox — Messaging Rules
|
|
2
|
+
|
|
3
|
+
You have access to a message inbox for communicating with other agents.
|
|
4
|
+
Messages may be injected into your context automatically, or you can check manually.
|
|
5
|
+
|
|
6
|
+
## Tools
|
|
7
|
+
|
|
8
|
+
You have 4 messaging tools: `send_message`, `check_inbox`, `read_thread`, `list_agents`.
|
|
9
|
+
|
|
10
|
+
## Sending messages
|
|
11
|
+
|
|
12
|
+
Use `send_message` to send a message or reply:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
send_message({ to: "alice", body: "Task complete, results in /tmp/output.json" })
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
To reply to a specific message, include `inReplyTo`:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
send_message({ to: "alice", body: "Acknowledged, proceeding.", inReplyTo: "msg-id-here" })
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Parameters:**
|
|
25
|
+
- `to` (required) — Recipient agent ID, or array of IDs. Use `"agent@system"` for federated agents.
|
|
26
|
+
- `body` — Plain text message (shorthand for content)
|
|
27
|
+
- `from` — Your agent ID (set automatically if registered)
|
|
28
|
+
- `subject` — Short subject line
|
|
29
|
+
- `threadTag` — Group related messages under a tag (e.g. `"deploy-v2"`)
|
|
30
|
+
- `inReplyTo` — Message ID you're replying to
|
|
31
|
+
- `importance` — `"low"`, `"normal"` (default), `"high"`, or `"urgent"`
|
|
32
|
+
|
|
33
|
+
## Checking your inbox
|
|
34
|
+
|
|
35
|
+
Use `check_inbox` to pull messages addressed to you:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
check_inbox({ agentId: "your-agent-id" })
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If inbox messages are injected automatically (via hook), they appear as a block like:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
## [Inbox] 2 new message(s)
|
|
45
|
+
|
|
46
|
+
**From alice** (5m ago) [high] — Deploy status
|
|
47
|
+
> Cluster is healthy, ready for rollout
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Threads
|
|
51
|
+
|
|
52
|
+
Use `threadTag` to group related messages. Read an entire thread with:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
read_thread({ threadTag: "deploy-v2" })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Addressing
|
|
59
|
+
|
|
60
|
+
- `"bob"` — local agent on this system
|
|
61
|
+
- `"bob@system-2"` — agent on a federated remote system
|
|
62
|
+
- `"@system-2"` — broadcast to all agents on a remote system
|
|
63
|
+
|
|
64
|
+
## Discovering other agents
|
|
65
|
+
|
|
66
|
+
Use `list_agents` to see who's available:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
list_agents({})
|
|
70
|
+
list_agents({ includeFederated: true })
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Conventions
|
|
74
|
+
|
|
75
|
+
- Reply to messages promptly so senders know you received them
|
|
76
|
+
- Use `importance: "high"` or `"urgent"` sparingly — only for time-sensitive coordination
|
|
77
|
+
- Use threads (`threadTag`) for multi-step workflows so context stays grouped
|
|
78
|
+
- Keep messages concise — other agents have limited context windows too
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { FederatedAddress } from "../types.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Parse a federated address string into its components.
|
|
5
|
+
*
|
|
6
|
+
* Formats:
|
|
7
|
+
* "agent-id" → { agent: "agent-id" } (local)
|
|
8
|
+
* "agent-id@system-id" → { agent: "agent-id", system: "system-id" } (federated)
|
|
9
|
+
* "@system-id" → { system: "system-id" } (broadcast to system)
|
|
10
|
+
* "agent-id@system/scope" → { agent: "agent-id", system: "system", scope: "scope" }
|
|
11
|
+
*/
|
|
12
|
+
export function parseAddress(address: string): FederatedAddress {
|
|
13
|
+
const atIdx = address.indexOf("@");
|
|
14
|
+
if (atIdx === -1) {
|
|
15
|
+
// No @ — local address
|
|
16
|
+
return { agent: address };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const agent = atIdx > 0 ? address.slice(0, atIdx) : undefined;
|
|
20
|
+
const rest = address.slice(atIdx + 1);
|
|
21
|
+
|
|
22
|
+
// Check for scope separator (/)
|
|
23
|
+
const slashIdx = rest.indexOf("/");
|
|
24
|
+
if (slashIdx === -1) {
|
|
25
|
+
return { agent, system: rest };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
agent,
|
|
30
|
+
system: rest.slice(0, slashIdx),
|
|
31
|
+
scope: rest.slice(slashIdx + 1),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Serialize a FederatedAddress back to string form.
|
|
37
|
+
*/
|
|
38
|
+
export function formatAddress(addr: FederatedAddress): string {
|
|
39
|
+
let result = addr.agent ?? "";
|
|
40
|
+
if (addr.system) {
|
|
41
|
+
result += `@${addr.system}`;
|
|
42
|
+
if (addr.scope) {
|
|
43
|
+
result += `/${addr.scope}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check if an address targets a remote system.
|
|
51
|
+
*/
|
|
52
|
+
export function isRemoteAddress(addr: FederatedAddress): boolean {
|
|
53
|
+
return addr.system !== undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Check if an address is a broadcast (no specific agent).
|
|
58
|
+
*/
|
|
59
|
+
export function isBroadcastAddress(addr: FederatedAddress): boolean {
|
|
60
|
+
return addr.system !== undefined && addr.agent === undefined;
|
|
61
|
+
}
|