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.
Files changed (126) hide show
  1. package/CLAUDE.md +113 -0
  2. package/README.md +195 -1
  3. package/dist/federation/address.d.ts +24 -0
  4. package/dist/federation/address.d.ts.map +1 -0
  5. package/dist/federation/address.js +54 -0
  6. package/dist/federation/address.js.map +1 -0
  7. package/dist/federation/connection-manager.d.ts +118 -0
  8. package/dist/federation/connection-manager.d.ts.map +1 -0
  9. package/dist/federation/connection-manager.js +369 -0
  10. package/dist/federation/connection-manager.js.map +1 -0
  11. package/dist/federation/delivery-queue.d.ts +66 -0
  12. package/dist/federation/delivery-queue.d.ts.map +1 -0
  13. package/dist/federation/delivery-queue.js +199 -0
  14. package/dist/federation/delivery-queue.js.map +1 -0
  15. package/dist/federation/index.d.ts +7 -0
  16. package/dist/federation/index.d.ts.map +1 -0
  17. package/dist/federation/index.js +6 -0
  18. package/dist/federation/index.js.map +1 -0
  19. package/dist/federation/routing-engine.d.ts +74 -0
  20. package/dist/federation/routing-engine.d.ts.map +1 -0
  21. package/dist/federation/routing-engine.js +158 -0
  22. package/dist/federation/routing-engine.js.map +1 -0
  23. package/dist/federation/trust.d.ts +39 -0
  24. package/dist/federation/trust.d.ts.map +1 -0
  25. package/dist/federation/trust.js +64 -0
  26. package/dist/federation/trust.js.map +1 -0
  27. package/dist/index.d.ts +60 -2
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +217 -18
  30. package/dist/index.js.map +1 -1
  31. package/dist/ipc/ipc-server.d.ts +21 -0
  32. package/dist/ipc/ipc-server.d.ts.map +1 -0
  33. package/dist/ipc/ipc-server.js +173 -0
  34. package/dist/ipc/ipc-server.js.map +1 -0
  35. package/dist/jsonrpc/mail-server.d.ts +45 -0
  36. package/dist/jsonrpc/mail-server.d.ts.map +1 -0
  37. package/dist/jsonrpc/mail-server.js +284 -0
  38. package/dist/jsonrpc/mail-server.js.map +1 -0
  39. package/dist/map/map-client.d.ts +91 -0
  40. package/dist/map/map-client.d.ts.map +1 -0
  41. package/dist/map/map-client.js +202 -0
  42. package/dist/map/map-client.js.map +1 -0
  43. package/dist/mcp/mcp-server.d.ts +23 -0
  44. package/dist/mcp/mcp-server.d.ts.map +1 -0
  45. package/dist/mcp/mcp-server.js +226 -0
  46. package/dist/mcp/mcp-server.js.map +1 -0
  47. package/dist/push/notifier.d.ts +49 -0
  48. package/dist/push/notifier.d.ts.map +1 -0
  49. package/dist/push/notifier.js +150 -0
  50. package/dist/push/notifier.js.map +1 -0
  51. package/dist/registry/warm-registry.d.ts +63 -0
  52. package/dist/registry/warm-registry.d.ts.map +1 -0
  53. package/dist/registry/warm-registry.js +173 -0
  54. package/dist/registry/warm-registry.js.map +1 -0
  55. package/dist/router/message-router.d.ts +44 -0
  56. package/dist/router/message-router.d.ts.map +1 -0
  57. package/dist/router/message-router.js +137 -0
  58. package/dist/router/message-router.js.map +1 -0
  59. package/dist/storage/interface.d.ts +31 -0
  60. package/dist/storage/interface.d.ts.map +1 -0
  61. package/dist/storage/interface.js +2 -0
  62. package/dist/storage/interface.js.map +1 -0
  63. package/dist/storage/memory.d.ts +28 -0
  64. package/dist/storage/memory.d.ts.map +1 -0
  65. package/dist/storage/memory.js +118 -0
  66. package/dist/storage/memory.js.map +1 -0
  67. package/dist/storage/sqlite.d.ts +35 -0
  68. package/dist/storage/sqlite.d.ts.map +1 -0
  69. package/dist/storage/sqlite.js +445 -0
  70. package/dist/storage/sqlite.js.map +1 -0
  71. package/dist/traceability/traceability.d.ts +29 -0
  72. package/dist/traceability/traceability.d.ts.map +1 -0
  73. package/dist/traceability/traceability.js +150 -0
  74. package/dist/traceability/traceability.js.map +1 -0
  75. package/dist/types.d.ts +261 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +3 -0
  78. package/dist/types.js.map +1 -0
  79. package/docs/DESIGN.md +1156 -0
  80. package/docs/PLAN.md +545 -0
  81. package/hooks/inbox-hook.mjs +119 -0
  82. package/hooks/register-hook.mjs +69 -0
  83. package/package.json +33 -25
  84. package/rules/agent-inbox.md +78 -0
  85. package/src/federation/address.ts +61 -0
  86. package/src/federation/connection-manager.ts +458 -0
  87. package/src/federation/delivery-queue.ts +222 -0
  88. package/src/federation/index.ts +6 -0
  89. package/src/federation/routing-engine.ts +188 -0
  90. package/src/federation/trust.ts +71 -0
  91. package/src/index.ts +299 -0
  92. package/src/ipc/ipc-server.ts +207 -0
  93. package/src/jsonrpc/mail-server.ts +356 -0
  94. package/src/map/map-client.ts +260 -0
  95. package/src/mcp/mcp-server.ts +272 -0
  96. package/src/push/notifier.ts +192 -0
  97. package/src/registry/warm-registry.ts +210 -0
  98. package/src/router/message-router.ts +175 -0
  99. package/src/storage/interface.ts +48 -0
  100. package/src/storage/memory.ts +145 -0
  101. package/src/storage/sqlite.ts +645 -0
  102. package/src/traceability/traceability.ts +183 -0
  103. package/src/types.ts +297 -0
  104. package/test/federation/address.test.ts +101 -0
  105. package/test/federation/connection-manager.test.ts +546 -0
  106. package/test/federation/delivery-queue.test.ts +159 -0
  107. package/test/federation/integration.test.ts +823 -0
  108. package/test/federation/routing-engine.test.ts +117 -0
  109. package/test/federation/sdk-integration.test.ts +748 -0
  110. package/test/federation/trust.test.ts +89 -0
  111. package/test/ipc-jsonrpc.test.ts +113 -0
  112. package/test/ipc-server.test.ts +197 -0
  113. package/test/mail-server.test.ts +208 -0
  114. package/test/map-client.test.ts +408 -0
  115. package/test/message-router.test.ts +184 -0
  116. package/test/push-notifier.test.ts +139 -0
  117. package/test/registry/warm-registry.test.ts +171 -0
  118. package/test/sqlite-storage.test.ts +243 -0
  119. package/test/storage.test.ts +196 -0
  120. package/test/traceability.test.ts +123 -0
  121. package/tsconfig.json +20 -0
  122. package/tsup.config.ts +10 -0
  123. package/vitest.config.ts +8 -0
  124. package/dist/index.d.mts +0 -2
  125. package/dist/index.mjs +0 -1
  126. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,226 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ export class InboxMcpServer {
5
+ router;
6
+ storage;
7
+ defaultScope;
8
+ mcp;
9
+ registry = null;
10
+ constructor(router, storage, defaultScope = "default") {
11
+ this.router = router;
12
+ this.storage = storage;
13
+ this.defaultScope = defaultScope;
14
+ this.mcp = new McpServer({
15
+ name: "agent-inbox",
16
+ version: "0.1.0",
17
+ });
18
+ this.registerTools();
19
+ }
20
+ /**
21
+ * Attach a warm registry for federation-aware agent registration.
22
+ */
23
+ setRegistry(registry) {
24
+ this.registry = registry;
25
+ }
26
+ registerTools() {
27
+ this.mcp.tool("send_message", "Send a message to one or more agents. Supports replies (inReplyTo), threading (threadTag), and federated addressing (agent@system).", {
28
+ to: z
29
+ .union([z.string(), z.array(z.string())])
30
+ .describe("Recipient agent ID(s). Use 'agent@system' for federated addressing."),
31
+ body: z
32
+ .string()
33
+ .optional()
34
+ .describe("Plain text message body (shorthand for content)"),
35
+ content: z
36
+ .object({
37
+ type: z.string(),
38
+ })
39
+ .passthrough()
40
+ .optional()
41
+ .describe("Structured message content"),
42
+ from: z
43
+ .string()
44
+ .optional()
45
+ .describe("Sender agent ID (defaults to caller)"),
46
+ threadTag: z
47
+ .string()
48
+ .optional()
49
+ .describe("Thread tag for grouping related messages"),
50
+ inReplyTo: z
51
+ .string()
52
+ .optional()
53
+ .describe("Message ID this is a reply to"),
54
+ importance: z
55
+ .enum(["low", "normal", "high", "urgent"])
56
+ .optional()
57
+ .describe("Message importance level"),
58
+ subject: z.string().optional().describe("Message subject"),
59
+ }, async ({ to, body, content, from, threadTag, inReplyTo, importance, subject }) => {
60
+ const payload = content ?? body ?? "";
61
+ const senderId = from ?? "anonymous";
62
+ const message = await this.router.routeMessage({
63
+ from: senderId,
64
+ to,
65
+ payload,
66
+ threadTag,
67
+ inReplyTo,
68
+ importance,
69
+ subject,
70
+ });
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: JSON.stringify({ ok: true, messageId: message.id }),
76
+ },
77
+ ],
78
+ };
79
+ });
80
+ this.mcp.tool("check_inbox", "Check inbox for messages addressed to an agent. Auto-registers the agent if not already registered.", {
81
+ agentId: z.string().describe("Agent ID to check inbox for"),
82
+ unreadOnly: z
83
+ .boolean()
84
+ .optional()
85
+ .describe("Only return unread messages (default true)"),
86
+ limit: z
87
+ .number()
88
+ .optional()
89
+ .describe("Max messages to return"),
90
+ }, async ({ agentId, unreadOnly, limit }) => {
91
+ // Auto-register the agent if not already known
92
+ this.ensureAgent(agentId);
93
+ const messages = this.storage.getInbox(agentId, {
94
+ unreadOnly: unreadOnly ?? true,
95
+ limit,
96
+ });
97
+ // Auto-mark as read
98
+ for (const msg of messages) {
99
+ this.router.markRead(msg.id, agentId);
100
+ }
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: JSON.stringify({
106
+ count: messages.length,
107
+ messages: messages.map((m) => ({
108
+ id: m.id,
109
+ from: m.sender_id,
110
+ subject: m.subject,
111
+ content: m.content,
112
+ threadTag: m.thread_tag,
113
+ importance: m.importance,
114
+ createdAt: m.created_at,
115
+ inReplyTo: m.in_reply_to,
116
+ })),
117
+ }),
118
+ },
119
+ ],
120
+ };
121
+ });
122
+ this.mcp.tool("read_thread", "Read all messages in a thread (by thread_tag)", {
123
+ threadTag: z.string().describe("Thread tag to read"),
124
+ scope: z
125
+ .string()
126
+ .optional()
127
+ .describe("Scope (defaults to 'default')"),
128
+ }, async ({ threadTag, scope }) => {
129
+ const messages = this.storage.getThread({
130
+ threadTag,
131
+ scope: scope ?? this.defaultScope,
132
+ });
133
+ return {
134
+ content: [
135
+ {
136
+ type: "text",
137
+ text: JSON.stringify({
138
+ threadTag,
139
+ count: messages.length,
140
+ messages: messages.map((m) => ({
141
+ id: m.id,
142
+ from: m.sender_id,
143
+ content: m.content,
144
+ createdAt: m.created_at,
145
+ inReplyTo: m.in_reply_to,
146
+ })),
147
+ }),
148
+ },
149
+ ],
150
+ };
151
+ });
152
+ this.mcp.tool("list_agents", "List agents registered in the inbox (local and optionally federated)", {
153
+ scope: z
154
+ .string()
155
+ .optional()
156
+ .describe("Filter by scope"),
157
+ includeFederated: z
158
+ .boolean()
159
+ .optional()
160
+ .describe("Include agents known from federation routing table"),
161
+ }, async ({ scope, includeFederated }) => {
162
+ const agents = this.storage.listAgents(scope);
163
+ const localList = agents.map((a) => ({
164
+ agentId: a.agent_id,
165
+ name: a.display_name,
166
+ scope: a.scope,
167
+ status: a.status,
168
+ program: a.program,
169
+ lastActive: a.last_active_at,
170
+ location: "local",
171
+ }));
172
+ let federatedList = [];
173
+ if (includeFederated && this.router.getFederation()) {
174
+ const federation = this.router.getFederation();
175
+ const routingTable = federation.routing.getTable();
176
+ federatedList = routingTable.map((entry) => ({
177
+ agentId: entry.agentId,
178
+ peerId: entry.peerId,
179
+ status: entry.status,
180
+ location: "federated",
181
+ }));
182
+ }
183
+ return {
184
+ content: [
185
+ {
186
+ type: "text",
187
+ text: JSON.stringify({
188
+ count: localList.length + federatedList.length,
189
+ agents: [...localList, ...federatedList],
190
+ }),
191
+ },
192
+ ],
193
+ };
194
+ });
195
+ }
196
+ /** Auto-register an agent if not already known (lazy registration on first inbox check) */
197
+ ensureAgent(agentId) {
198
+ const existing = this.storage.listAgents().find((a) => a.agent_id === agentId);
199
+ if (existing)
200
+ return;
201
+ const now = new Date().toISOString();
202
+ const agent = {
203
+ agent_id: agentId,
204
+ scope: this.defaultScope,
205
+ status: "active",
206
+ metadata: {},
207
+ registered_at: now,
208
+ last_active_at: now,
209
+ };
210
+ if (this.registry) {
211
+ this.registry.register(agent);
212
+ }
213
+ else {
214
+ this.storage.putAgent(agent);
215
+ }
216
+ }
217
+ async start() {
218
+ const transport = new StdioServerTransport();
219
+ await this.mcp.connect(transport);
220
+ }
221
+ /** Expose for testing — returns the underlying McpServer */
222
+ get server() {
223
+ return this.mcp;
224
+ }
225
+ }
226
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/mcp/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,MAAM,OAAO,cAAc;IAKf;IACA;IACA;IANF,GAAG,CAAY;IACf,QAAQ,GAAwB,IAAI,CAAC;IAE7C,YACU,MAAqB,EACrB,OAAgB,EAChB,eAAuB,SAAS;QAFhC,WAAM,GAAN,MAAM,CAAe;QACrB,YAAO,GAAP,OAAO,CAAS;QAChB,iBAAY,GAAZ,YAAY,CAAoB;QAExC,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC;YACvB,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,QAAsB;QAChC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,cAAc,EACd,qIAAqI,EACrI;YACE,EAAE,EAAE,CAAC;iBACF,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;iBACxC,QAAQ,CACP,qEAAqE,CACtE;YACH,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,iDAAiD,CAAC;YAC9D,OAAO,EAAE,CAAC;iBACP,MAAM,CAAC;gBACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;aACjB,CAAC;iBACD,WAAW,EAAE;iBACb,QAAQ,EAAE;iBACV,QAAQ,CAAC,4BAA4B,CAAC;YACzC,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,sCAAsC,CAAC;YACnD,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,0CAA0C,CAAC;YACvD,SAAS,EAAE,CAAC;iBACT,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,+BAA+B,CAAC;YAC5C,UAAU,EAAE,CAAC;iBACV,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;iBACzC,QAAQ,EAAE;iBACV,QAAQ,CAAC,0BAA0B,CAAC;YACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;SAC3D,EACD,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,EAAE;YAC/E,MAAM,OAAO,GAAG,OAAO,IAAI,IAAI,IAAI,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,IAAI,WAAW,CAAC;YACrC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC7C,IAAI,EAAE,QAAQ;gBACd,EAAE;gBACF,OAAO;gBACP,SAAS;gBACT,SAAS;gBACT,UAAU;gBACV,OAAO;aACR,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,aAAa,EACb,qGAAqG,EACrG;YACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;YAC3D,UAAU,EAAE,CAAC;iBACV,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,4CAA4C,CAAC;YACzD,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,wBAAwB,CAAC;SACtC,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,EAAE;YACvC,+CAA+C;YAC/C,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE;gBAC9C,UAAU,EAAE,UAAU,IAAI,IAAI;gBAC9B,KAAK;aACN,CAAC,CAAC;YAEH,oBAAoB;YACpB,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;gBAC3B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACxC,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,QAAQ,CAAC,MAAM;4BACtB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCAC7B,EAAE,EAAE,CAAC,CAAC,EAAE;gCACR,IAAI,EAAE,CAAC,CAAC,SAAS;gCACjB,OAAO,EAAE,CAAC,CAAC,OAAO;gCAClB,OAAO,EAAE,CAAC,CAAC,OAAO;gCAClB,SAAS,EAAE,CAAC,CAAC,UAAU;gCACvB,UAAU,EAAE,CAAC,CAAC,UAAU;gCACxB,SAAS,EAAE,CAAC,CAAC,UAAU;gCACvB,SAAS,EAAE,CAAC,CAAC,WAAW;6BACzB,CAAC,CAAC;yBACJ,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,aAAa,EACb,+CAA+C,EAC/C;YACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;YACpD,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,+BAA+B,CAAC;SAC7C,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;gBACtC,SAAS;gBACT,KAAK,EAAE,KAAK,IAAI,IAAI,CAAC,YAAY;aAClC,CAAC,CAAC;YACH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,SAAS;4BACT,KAAK,EAAE,QAAQ,CAAC,MAAM;4BACtB,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCAC7B,EAAE,EAAE,CAAC,CAAC,EAAE;gCACR,IAAI,EAAE,CAAC,CAAC,SAAS;gCACjB,OAAO,EAAE,CAAC,CAAC,OAAO;gCAClB,SAAS,EAAE,CAAC,CAAC,UAAU;gCACvB,SAAS,EAAE,CAAC,CAAC,WAAW;6BACzB,CAAC,CAAC;yBACJ,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,aAAa,EACb,sEAAsE,EACtE;YACE,KAAK,EAAE,CAAC;iBACL,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,iBAAiB,CAAC;YAC9B,gBAAgB,EAAE,CAAC;iBAChB,OAAO,EAAE;iBACT,QAAQ,EAAE;iBACV,QAAQ,CAAC,oDAAoD,CAAC;SAClE,EACD,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnC,OAAO,EAAE,CAAC,CAAC,QAAQ;gBACnB,IAAI,EAAE,CAAC,CAAC,YAAY;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,UAAU,EAAE,CAAC,CAAC,cAAc;gBAC5B,QAAQ,EAAE,OAAgB;aAC3B,CAAC,CAAC,CAAC;YAEJ,IAAI,aAAa,GAKZ,EAAE,CAAC;YACR,IAAI,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC;gBACpD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAG,CAAC;gBAChD,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACnD,aAAa,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC3C,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,MAAM,EAAE,KAAK,CAAC,MAAM;oBACpB,QAAQ,EAAE,WAAoB;iBAC/B,CAAC,CAAC,CAAC;YACN,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM;4BAC9C,MAAM,EAAE,CAAC,GAAG,SAAS,EAAE,GAAG,aAAa,CAAC;yBACzC,CAAC;qBACH;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;IACJ,CAAC;IAED,2FAA2F;IACnF,WAAW,CAAC,OAAe;QACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,CAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAC9B,CAAC;QACF,IAAI,QAAQ;YAAE,OAAO;QAErB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,KAAK,GAAU;YACnB,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,IAAI,CAAC,YAAY;YACxB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,EAAE;YACZ,aAAa,EAAE,GAAG;YAClB,cAAc,EAAE,GAAG;SACpB,CAAC;QAEF,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,4DAA4D;IAC5D,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,49 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { Storage } from "../storage/interface.js";
3
+ /**
4
+ * Push notification system for Agent Inbox.
5
+ *
6
+ * Agents can't receive server-initiated messages via MCP stdio transport,
7
+ * so we use the same injection pattern as claude-code-swarm:
8
+ *
9
+ * 1. New messages arrive → written to per-agent inbox files (NDJSON)
10
+ * 2. Agent's hook (UserPromptSubmit) reads the inbox file and injects
11
+ * messages into the agent's context as formatted markdown
12
+ * 3. Agent sees new messages at the start of their next turn
13
+ *
14
+ * This class also supports webhook-style push for external consumers.
15
+ */
16
+ export interface NotifierConfig {
17
+ /** Directory for per-agent inbox files */
18
+ inboxDir: string;
19
+ /** Optional webhook URLs to POST new messages to */
20
+ webhooks?: string[];
21
+ }
22
+ export interface InboxFileEntry {
23
+ messageId: string;
24
+ from: string;
25
+ to: string;
26
+ subject?: string;
27
+ content: unknown;
28
+ threadTag?: string;
29
+ importance: string;
30
+ timestamp: string;
31
+ }
32
+ export declare class PushNotifier {
33
+ private config;
34
+ private storage;
35
+ private webhooks;
36
+ constructor(config: NotifierConfig, storage: Storage, events: EventEmitter);
37
+ private onMessage;
38
+ /** Write a message to an agent's inbox file (NDJSON) */
39
+ private writeAgentInbox;
40
+ /** Read and format an agent's pending inbox as markdown (for hook injection) */
41
+ readAndClearAgentInbox(agentId: string): string | null;
42
+ /** Get the path to an agent's inbox file */
43
+ agentInboxPath(agentId: string): string;
44
+ /** Fire webhook notification (best-effort) */
45
+ private fireWebhook;
46
+ }
47
+ /** Format inbox entries as markdown for agent context injection */
48
+ export declare function formatInboxMarkdown(entries: InboxFileEntry[]): string;
49
+ //# sourceMappingURL=notifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/push/notifier.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,YAAY;IAIrB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;IAJjB,OAAO,CAAC,QAAQ,CAAW;gBAGjB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,OAAO,EACxB,MAAM,EAAE,YAAY;IAWtB,OAAO,CAAC,SAAS;IAYjB,wDAAwD;IACxD,OAAO,CAAC,eAAe;IAmBvB,gFAAgF;IAChF,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAkCtD,4CAA4C;IAC5C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAMvC,8CAA8C;YAChC,WAAW;CAuB1B;AAED,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CA0BrE"}
@@ -0,0 +1,150 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ export class PushNotifier {
4
+ config;
5
+ storage;
6
+ webhooks;
7
+ constructor(config, storage, events) {
8
+ this.config = config;
9
+ this.storage = storage;
10
+ this.webhooks = config.webhooks ?? [];
11
+ // Subscribe to message.created events
12
+ events.on("message.created", (msg) => this.onMessage(msg));
13
+ // Ensure inbox directory exists
14
+ fs.mkdirSync(config.inboxDir, { recursive: true });
15
+ }
16
+ onMessage(message) {
17
+ // Write to each recipient's per-agent inbox file
18
+ for (const recipient of message.recipients) {
19
+ this.writeAgentInbox(recipient.agent_id, message);
20
+ }
21
+ // Fire webhooks (best-effort)
22
+ for (const url of this.webhooks) {
23
+ this.fireWebhook(url, message).catch(() => { });
24
+ }
25
+ }
26
+ /** Write a message to an agent's inbox file (NDJSON) */
27
+ writeAgentInbox(agentId, message) {
28
+ const filePath = this.agentInboxPath(agentId);
29
+ const entry = {
30
+ messageId: message.id,
31
+ from: message.sender_id,
32
+ to: agentId,
33
+ subject: message.subject,
34
+ content: message.content,
35
+ threadTag: message.thread_tag,
36
+ importance: message.importance,
37
+ timestamp: message.created_at,
38
+ };
39
+ try {
40
+ fs.appendFileSync(filePath, JSON.stringify(entry) + "\n");
41
+ }
42
+ catch {
43
+ // Best-effort write
44
+ }
45
+ }
46
+ /** Read and format an agent's pending inbox as markdown (for hook injection) */
47
+ readAndClearAgentInbox(agentId) {
48
+ const filePath = this.agentInboxPath(agentId);
49
+ let raw;
50
+ try {
51
+ raw = fs.readFileSync(filePath, "utf-8").trim();
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ if (!raw)
57
+ return null;
58
+ // Parse entries
59
+ const entries = [];
60
+ for (const line of raw.split("\n")) {
61
+ if (!line.trim())
62
+ continue;
63
+ try {
64
+ entries.push(JSON.parse(line));
65
+ }
66
+ catch {
67
+ // Skip malformed lines
68
+ }
69
+ }
70
+ if (entries.length === 0)
71
+ return null;
72
+ // Clear the file
73
+ try {
74
+ fs.writeFileSync(filePath, "");
75
+ }
76
+ catch {
77
+ // Best-effort clear
78
+ }
79
+ return formatInboxMarkdown(entries);
80
+ }
81
+ /** Get the path to an agent's inbox file */
82
+ agentInboxPath(agentId) {
83
+ // Sanitize agentId for use as filename
84
+ const safe = agentId.replace(/[^a-zA-Z0-9_-]/g, "_");
85
+ return path.join(this.config.inboxDir, `${safe}.inbox.jsonl`);
86
+ }
87
+ /** Fire webhook notification (best-effort) */
88
+ async fireWebhook(url, message) {
89
+ try {
90
+ await fetch(url, {
91
+ method: "POST",
92
+ headers: { "Content-Type": "application/json" },
93
+ body: JSON.stringify({
94
+ event: "message.created",
95
+ message: {
96
+ id: message.id,
97
+ from: message.sender_id,
98
+ recipients: message.recipients.map((r) => r.agent_id),
99
+ content: message.content,
100
+ threadTag: message.thread_tag,
101
+ importance: message.importance,
102
+ createdAt: message.created_at,
103
+ },
104
+ }),
105
+ signal: AbortSignal.timeout(5000),
106
+ });
107
+ }
108
+ catch {
109
+ // Best-effort
110
+ }
111
+ }
112
+ }
113
+ /** Format inbox entries as markdown for agent context injection */
114
+ export function formatInboxMarkdown(entries) {
115
+ const lines = [];
116
+ lines.push(`## [Inbox] ${entries.length} new message(s)\n`);
117
+ for (const entry of entries) {
118
+ const age = formatAge(entry.timestamp);
119
+ const priority = entry.importance !== "normal" ? ` [${entry.importance}]` : "";
120
+ const subject = entry.subject ? ` — ${entry.subject}` : "";
121
+ const thread = entry.threadTag ? ` (thread: ${entry.threadTag})` : "";
122
+ lines.push(`**From ${entry.from}** (${age} ago)${priority}${subject}${thread}`);
123
+ // Format content
124
+ const content = entry.content;
125
+ if (content && typeof content === "object" && content.type === "text") {
126
+ lines.push(`> ${content.text}`);
127
+ }
128
+ else if (typeof entry.content === "string") {
129
+ lines.push(`> ${entry.content}`);
130
+ }
131
+ else {
132
+ lines.push(`> \`${JSON.stringify(content)}\``);
133
+ }
134
+ lines.push("");
135
+ }
136
+ return lines.join("\n");
137
+ }
138
+ function formatAge(timestamp) {
139
+ const diff = Date.now() - new Date(timestamp).getTime();
140
+ if (diff < 1000)
141
+ return "<1s";
142
+ if (diff < 60_000)
143
+ return `${Math.floor(diff / 1000)}s`;
144
+ if (diff < 3600_000)
145
+ return `${Math.floor(diff / 60_000)}m`;
146
+ if (diff < 86400_000)
147
+ return `${Math.floor(diff / 3600_000)}h`;
148
+ return `${Math.floor(diff / 86400_000)}d`;
149
+ }
150
+ //# sourceMappingURL=notifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifier.js","sourceRoot":"","sources":["../../src/push/notifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAqClC,MAAM,OAAO,YAAY;IAIb;IACA;IAJF,QAAQ,CAAW;IAE3B,YACU,MAAsB,EACtB,OAAgB,EACxB,MAAoB;QAFZ,WAAM,GAAN,MAAM,CAAgB;QACtB,YAAO,GAAP,OAAO,CAAS;QAGxB,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;QAEtC,sCAAsC;QACtC,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,GAAY,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAEpE,gCAAgC;QAChC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,CAAC;IAEO,SAAS,CAAC,OAAgB;QAChC,iDAAiD;QACjD,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YAC3C,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACpD,CAAC;QAED,8BAA8B;QAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,wDAAwD;IAChD,eAAe,CAAC,OAAe,EAAE,OAAgB;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAmB;YAC5B,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,IAAI,EAAE,OAAO,CAAC,SAAS;YACvB,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,SAAS,EAAE,OAAO,CAAC,UAAU;YAC7B,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,SAAS,EAAE,OAAO,CAAC,UAAU;SAC9B,CAAC;QACF,IAAI,CAAC;YACH,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;QACtB,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,sBAAsB,CAAC,OAAe;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,GAAW,CAAC;QAChB,IAAI,CAAC;YACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,gBAAgB;QAChB,MAAM,OAAO,GAAqB,EAAE,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,SAAS;YAC3B,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC,CAAC;YACnD,CAAC;YAAC,MAAM,CAAC;gBACP,uBAAuB;YACzB,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtC,iBAAiB;QACjB,IAAI,CAAC;YACH,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,oBAAoB;QACtB,CAAC;QAED,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,4CAA4C;IAC5C,cAAc,CAAC,OAAe;QAC5B,uCAAuC;QACvC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,IAAI,cAAc,CAAC,CAAC;IAChE,CAAC;IAED,8CAA8C;IACtC,KAAK,CAAC,WAAW,CAAC,GAAW,EAAE,OAAgB;QACrD,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,GAAG,EAAE;gBACf,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,iBAAiB;oBACxB,OAAO,EAAE;wBACP,EAAE,EAAE,OAAO,CAAC,EAAE;wBACd,IAAI,EAAE,OAAO,CAAC,SAAS;wBACvB,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;wBACrD,OAAO,EAAE,OAAO,CAAC,OAAO;wBACxB,SAAS,EAAE,OAAO,CAAC,UAAU;wBAC7B,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,SAAS,EAAE,OAAO,CAAC,UAAU;qBAC9B;iBACF,CAAC;gBACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,cAAc;QAChB,CAAC;IACH,CAAC;CACF;AAED,mEAAmE;AACnE,MAAM,UAAU,mBAAmB,CAAC,OAAyB;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,cAAc,OAAO,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAE5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,MAAM,QAAQ,GACZ,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtE,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,IAAI,OAAO,GAAG,QAAQ,QAAQ,GAAG,OAAO,GAAG,MAAM,EAAE,CAAC,CAAC;QAEhF,iBAAiB;QACjB,MAAM,OAAO,GAAG,KAAK,CAAC,OAAkC,CAAC;QACzD,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACtE,KAAK,CAAC,IAAI,CAAC,KAAM,OAA4B,CAAC,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,SAAiB;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IACxD,IAAI,IAAI,GAAG,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,IAAI,GAAG,MAAM;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC;IACxD,IAAI,IAAI,GAAG,QAAQ;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;IAC5D,IAAI,IAAI,GAAG,SAAS;QAAE,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC;IAC/D,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { EventEmitter } from "node:events";
2
+ import type { Agent, AgentRegistryConfig, WarmAgentStatus } from "../types.js";
3
+ import type { Storage } from "../storage/interface.js";
4
+ /**
5
+ * Warm agent registry with active/away/expired lifecycle.
6
+ *
7
+ * Wraps the storage layer to add TTL-based status management.
8
+ * Agents transition: active → away (on disconnect) → expired (after grace period).
9
+ */
10
+ export declare class WarmRegistry {
11
+ private storage;
12
+ private events;
13
+ private entries;
14
+ private config;
15
+ constructor(storage: Storage, events: EventEmitter, config?: Partial<AgentRegistryConfig>);
16
+ /**
17
+ * Register an agent. First-wins — rejects if ID is taken by an active/away agent.
18
+ * Returns true if registered, false if ID conflict.
19
+ */
20
+ register(agent: Agent): boolean;
21
+ /**
22
+ * Mark an agent as disconnected. Starts grace period timer.
23
+ */
24
+ disconnect(agentId: string): boolean;
25
+ /**
26
+ * Reconnect a previously disconnected agent.
27
+ * Cancels grace period and restores active status.
28
+ */
29
+ reconnect(agentId: string): boolean;
30
+ /**
31
+ * Transition agent to expired. Not routable, but retained for audit.
32
+ */
33
+ expire(agentId: string): void;
34
+ /**
35
+ * Fully remove an agent from the registry.
36
+ */
37
+ remove(agentId: string): void;
38
+ /**
39
+ * Check if an agent is routable (active or away).
40
+ */
41
+ isRoutable(agentId: string): boolean;
42
+ /**
43
+ * Get the warm status of an agent.
44
+ */
45
+ getStatus(agentId: string): WarmAgentStatus | "unknown";
46
+ /**
47
+ * List all entries with their warm status.
48
+ */
49
+ listEntries(): Array<{
50
+ agentId: string;
51
+ warmStatus: WarmAgentStatus;
52
+ }>;
53
+ /**
54
+ * List all routable agent IDs.
55
+ */
56
+ listRoutable(): string[];
57
+ /**
58
+ * Clean up all timers. Call on shutdown.
59
+ */
60
+ destroy(): void;
61
+ private clearTimers;
62
+ }
63
+ //# sourceMappingURL=warm-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"warm-registry.d.ts","sourceRoot":"","sources":["../../src/registry/warm-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACV,KAAK,EACL,mBAAmB,EACnB,eAAe,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAgBvD;;;;;GAKG;AACH,qBAAa,YAAY;IAKrB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,MAAM;IALhB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,MAAM,CAAsB;gBAG1B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,YAAY,EAC5B,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC;IAKvC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO;IAsB/B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAuBpC;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAoBnC;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAqB7B;;OAEG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAU7B;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAMpC;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAKvD;;OAEG;IACH,WAAW,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,eAAe,CAAA;KAAE,CAAC;IAOtE;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE;IAMxB;;OAEG;IACH,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,WAAW;CAUpB"}