agent-relay 0.1.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.
Files changed (143) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/LICENSE +22 -0
  3. package/PROTOCOL.md +319 -0
  4. package/README.md +791 -0
  5. package/dist/cli/index.d.ts +7 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +1591 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/daemon/connection.d.ts +60 -0
  10. package/dist/daemon/connection.d.ts.map +1 -0
  11. package/dist/daemon/connection.js +245 -0
  12. package/dist/daemon/connection.js.map +1 -0
  13. package/dist/daemon/index.d.ts +4 -0
  14. package/dist/daemon/index.d.ts.map +1 -0
  15. package/dist/daemon/index.js +4 -0
  16. package/dist/daemon/index.js.map +1 -0
  17. package/dist/daemon/router.d.ts +72 -0
  18. package/dist/daemon/router.d.ts.map +1 -0
  19. package/dist/daemon/router.js +183 -0
  20. package/dist/daemon/router.js.map +1 -0
  21. package/dist/daemon/server.d.ts +52 -0
  22. package/dist/daemon/server.d.ts.map +1 -0
  23. package/dist/daemon/server.js +186 -0
  24. package/dist/daemon/server.js.map +1 -0
  25. package/dist/dashboard/public/index.html +690 -0
  26. package/dist/dashboard/server.d.ts +2 -0
  27. package/dist/dashboard/server.d.ts.map +1 -0
  28. package/dist/dashboard/server.js +220 -0
  29. package/dist/dashboard/server.js.map +1 -0
  30. package/dist/games/index.d.ts +2 -0
  31. package/dist/games/index.d.ts.map +1 -0
  32. package/dist/games/index.js +2 -0
  33. package/dist/games/index.js.map +1 -0
  34. package/dist/games/tictactoe.d.ts +24 -0
  35. package/dist/games/tictactoe.d.ts.map +1 -0
  36. package/dist/games/tictactoe.js +160 -0
  37. package/dist/games/tictactoe.js.map +1 -0
  38. package/dist/hooks/inbox-check/hook.d.ts +28 -0
  39. package/dist/hooks/inbox-check/hook.d.ts.map +1 -0
  40. package/dist/hooks/inbox-check/hook.js +97 -0
  41. package/dist/hooks/inbox-check/hook.js.map +1 -0
  42. package/dist/hooks/inbox-check/index.d.ts +8 -0
  43. package/dist/hooks/inbox-check/index.d.ts.map +1 -0
  44. package/dist/hooks/inbox-check/index.js +8 -0
  45. package/dist/hooks/inbox-check/index.js.map +1 -0
  46. package/dist/hooks/inbox-check/types.d.ts +31 -0
  47. package/dist/hooks/inbox-check/types.d.ts.map +1 -0
  48. package/dist/hooks/inbox-check/types.js +5 -0
  49. package/dist/hooks/inbox-check/types.js.map +1 -0
  50. package/dist/hooks/inbox-check/utils.d.ts +44 -0
  51. package/dist/hooks/inbox-check/utils.d.ts.map +1 -0
  52. package/dist/hooks/inbox-check/utils.js +107 -0
  53. package/dist/hooks/inbox-check/utils.js.map +1 -0
  54. package/dist/index.d.ts +10 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +10 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/protocol/framing.d.ts +32 -0
  59. package/dist/protocol/framing.d.ts.map +1 -0
  60. package/dist/protocol/framing.js +71 -0
  61. package/dist/protocol/framing.js.map +1 -0
  62. package/dist/protocol/index.d.ts +3 -0
  63. package/dist/protocol/index.d.ts.map +1 -0
  64. package/dist/protocol/index.js +3 -0
  65. package/dist/protocol/index.js.map +1 -0
  66. package/dist/protocol/types.d.ts +104 -0
  67. package/dist/protocol/types.d.ts.map +1 -0
  68. package/dist/protocol/types.js +6 -0
  69. package/dist/protocol/types.js.map +1 -0
  70. package/dist/state/agent-state.d.ts +40 -0
  71. package/dist/state/agent-state.d.ts.map +1 -0
  72. package/dist/state/agent-state.js +120 -0
  73. package/dist/state/agent-state.js.map +1 -0
  74. package/dist/storage/adapter.d.ts +29 -0
  75. package/dist/storage/adapter.d.ts.map +1 -0
  76. package/dist/storage/adapter.js +2 -0
  77. package/dist/storage/adapter.js.map +1 -0
  78. package/dist/storage/sqlite-adapter.d.ts +15 -0
  79. package/dist/storage/sqlite-adapter.d.ts.map +1 -0
  80. package/dist/storage/sqlite-adapter.js +116 -0
  81. package/dist/storage/sqlite-adapter.js.map +1 -0
  82. package/dist/supervisor/inbox.d.ts +38 -0
  83. package/dist/supervisor/inbox.d.ts.map +1 -0
  84. package/dist/supervisor/inbox.js +162 -0
  85. package/dist/supervisor/inbox.js.map +1 -0
  86. package/dist/supervisor/index.d.ts +10 -0
  87. package/dist/supervisor/index.d.ts.map +1 -0
  88. package/dist/supervisor/index.js +10 -0
  89. package/dist/supervisor/index.js.map +1 -0
  90. package/dist/supervisor/spawner.d.ts +54 -0
  91. package/dist/supervisor/spawner.d.ts.map +1 -0
  92. package/dist/supervisor/spawner.js +282 -0
  93. package/dist/supervisor/spawner.js.map +1 -0
  94. package/dist/supervisor/state.d.ts +132 -0
  95. package/dist/supervisor/state.d.ts.map +1 -0
  96. package/dist/supervisor/state.js +465 -0
  97. package/dist/supervisor/state.js.map +1 -0
  98. package/dist/supervisor/supervisor.d.ts +67 -0
  99. package/dist/supervisor/supervisor.d.ts.map +1 -0
  100. package/dist/supervisor/supervisor.js +263 -0
  101. package/dist/supervisor/supervisor.js.map +1 -0
  102. package/dist/supervisor/types.d.ts +139 -0
  103. package/dist/supervisor/types.d.ts.map +1 -0
  104. package/dist/supervisor/types.js +12 -0
  105. package/dist/supervisor/types.js.map +1 -0
  106. package/dist/utils/index.d.ts +2 -0
  107. package/dist/utils/index.d.ts.map +1 -0
  108. package/dist/utils/index.js +2 -0
  109. package/dist/utils/index.js.map +1 -0
  110. package/dist/utils/name-generator.d.ts +17 -0
  111. package/dist/utils/name-generator.d.ts.map +1 -0
  112. package/dist/utils/name-generator.js +52 -0
  113. package/dist/utils/name-generator.js.map +1 -0
  114. package/dist/webhook/spawner.d.ts +79 -0
  115. package/dist/webhook/spawner.d.ts.map +1 -0
  116. package/dist/webhook/spawner.js +288 -0
  117. package/dist/webhook/spawner.js.map +1 -0
  118. package/dist/wrapper/client.d.ts +72 -0
  119. package/dist/wrapper/client.d.ts.map +1 -0
  120. package/dist/wrapper/client.js +306 -0
  121. package/dist/wrapper/client.js.map +1 -0
  122. package/dist/wrapper/inbox.d.ts +37 -0
  123. package/dist/wrapper/inbox.d.ts.map +1 -0
  124. package/dist/wrapper/inbox.js +73 -0
  125. package/dist/wrapper/inbox.js.map +1 -0
  126. package/dist/wrapper/index.d.ts +4 -0
  127. package/dist/wrapper/index.d.ts.map +1 -0
  128. package/dist/wrapper/index.js +7 -0
  129. package/dist/wrapper/index.js.map +1 -0
  130. package/dist/wrapper/parser.d.ts +94 -0
  131. package/dist/wrapper/parser.d.ts.map +1 -0
  132. package/dist/wrapper/parser.js +360 -0
  133. package/dist/wrapper/parser.js.map +1 -0
  134. package/dist/wrapper/pty-wrapper.d.ts +125 -0
  135. package/dist/wrapper/pty-wrapper.d.ts.map +1 -0
  136. package/dist/wrapper/pty-wrapper.js +494 -0
  137. package/dist/wrapper/pty-wrapper.js.map +1 -0
  138. package/dist/wrapper/tmux-wrapper.d.ts +131 -0
  139. package/dist/wrapper/tmux-wrapper.d.ts.map +1 -0
  140. package/dist/wrapper/tmux-wrapper.js +427 -0
  141. package/dist/wrapper/tmux-wrapper.js.map +1 -0
  142. package/install.sh +69 -0
  143. package/package.json +82 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ Initial public release.
6
+
7
+ - Local daemon + client protocol for low-latency agent messaging (Unix domain sockets).
8
+ - `agent-relay wrap` for intercepting `@relay:AgentName ...` and `[[RELAY]]...[[/RELAY]]` messages.
9
+ - Inbox utilities (`inbox-write`, `inbox-poll`, etc.) for file-based coordination in shared workspaces.
10
+ - Built-in demos/games (e.g., tic-tac-toe) to validate turn-based coordination.
11
+
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Khaliq Gant
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/PROTOCOL.md ADDED
@@ -0,0 +1,319 @@
1
+ # Agent Relay Protocol Specification
2
+
3
+ Version 1.0
4
+
5
+ ## Goals
6
+
7
+ - Low-latency local IPC (<5ms)
8
+ - Strict framing with backpressure
9
+ - At-least-once delivery (optional exactly-once within session)
10
+ - Reconnect + state resync
11
+ - Simple to implement in Rust/Go/TypeScript
12
+
13
+ ## Non-Goals
14
+
15
+ - Cross-host networking
16
+ - Encryption (local-only)
17
+ - Unbounded buffering
18
+
19
+ ---
20
+
21
+ ## 1. Transport
22
+
23
+ **Preferred:** Unix Domain Socket (stream)
24
+ - Path: `/tmp/agent-relay.sock` (configurable)
25
+
26
+ **Windows fallback:** Named Pipe
27
+ - Path: `\\.\pipe\agent-relay`
28
+
29
+ **Connection model:** Each wrapper opens 1 duplex stream to daemon.
30
+
31
+ ---
32
+
33
+ ## 2. Framing
34
+
35
+ Stream is a sequence of frames.
36
+
37
+ ### Frame Header
38
+ - 4-byte big-endian unsigned length `N` (bytes)
39
+ - Followed by `N` bytes UTF-8 JSON
40
+
41
+ ### Limits
42
+ - `N` MUST be <= `max_frame_bytes` (default: 1 MiB)
43
+ - If exceeded, daemon closes connection with error
44
+ - JSON payload MUST be an object
45
+
46
+ ### Example (pseudo)
47
+ ```
48
+ 0000003A {"v":1,"type":"HELLO","agent":"claude-1",...}
49
+ ```
50
+ Where `0x3A` (58) is the byte length of the JSON payload.
51
+
52
+ ---
53
+
54
+ ## 3. Envelope
55
+
56
+ All messages are `Envelope` objects:
57
+
58
+ ```typescript
59
+ interface Envelope {
60
+ v: 1; // Protocol version
61
+ type: MessageType; // See below
62
+ id: string; // Unique per-sender (UUIDv4)
63
+ ts: number; // Milliseconds since epoch
64
+ from?: string; // Agent name (set by daemon)
65
+ to?: string | '*'; // Target or broadcast
66
+ topic?: string; // Optional topic/channel
67
+ payload: object; // Type-specific payload
68
+ }
69
+ ```
70
+
71
+ ### Message Types
72
+
73
+ | Type | Direction | Purpose |
74
+ |------|-----------|---------|
75
+ | `HELLO` | Client→Server | Initiate handshake |
76
+ | `WELCOME` | Server→Client | Confirm session |
77
+ | `SEND` | Client→Server | Send message |
78
+ | `DELIVER` | Server→Client | Deliver message |
79
+ | `ACK` | Both | Acknowledge receipt |
80
+ | `NACK` | Both | Negative acknowledgment |
81
+ | `PING` | Server→Client | Heartbeat |
82
+ | `PONG` | Client→Server | Heartbeat response |
83
+ | `ERROR` | Server→Client | Error notification |
84
+ | `BUSY` | Server→Client | Backpressure signal |
85
+ | `RESUME` | Client→Server | Resume session |
86
+ | `SYNC` | Server→Client | State sync info |
87
+ | `BYE` | Both | Graceful disconnect |
88
+ | `SUBSCRIBE` | Client→Server | Subscribe to topic |
89
+ | `UNSUBSCRIBE` | Client→Server | Unsubscribe from topic |
90
+
91
+ ---
92
+
93
+ ## 4. Handshake
94
+
95
+ ### New Session
96
+
97
+ **Client → Server: HELLO**
98
+ ```json
99
+ {
100
+ "v": 1,
101
+ "type": "HELLO",
102
+ "id": "uuid",
103
+ "ts": 1734440000000,
104
+ "payload": {
105
+ "agent": "claude-1",
106
+ "capabilities": {
107
+ "ack": true,
108
+ "resume": true,
109
+ "max_inflight": 256,
110
+ "supports_topics": true
111
+ },
112
+ "session": {
113
+ "resume_token": "optional-previous-token"
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ **Server → Client: WELCOME**
120
+ ```json
121
+ {
122
+ "v": 1,
123
+ "type": "WELCOME",
124
+ "id": "uuid",
125
+ "ts": 1734440000001,
126
+ "payload": {
127
+ "session_id": "s-abc123",
128
+ "resume_token": "new-token-for-reconnect",
129
+ "server": {
130
+ "max_frame_bytes": 1048576,
131
+ "heartbeat_ms": 5000
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 5. Sending and Delivery
140
+
141
+ ### Client → Server: SEND
142
+ ```json
143
+ {
144
+ "v": 1,
145
+ "type": "SEND",
146
+ "id": "m-001",
147
+ "ts": 1734440000100,
148
+ "to": "codex-1",
149
+ "topic": "chat",
150
+ "payload": {
151
+ "kind": "message",
152
+ "body": "Your turn",
153
+ "data": {}
154
+ },
155
+ "payload_meta": {
156
+ "requires_ack": true,
157
+ "ttl_ms": 60000
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Server → Recipient: DELIVER
163
+ ```json
164
+ {
165
+ "v": 1,
166
+ "type": "DELIVER",
167
+ "id": "d-001",
168
+ "ts": 1734440000102,
169
+ "from": "claude-1",
170
+ "to": "codex-1",
171
+ "topic": "chat",
172
+ "payload": {
173
+ "kind": "message",
174
+ "body": "Your turn",
175
+ "data": {}
176
+ },
177
+ "delivery": {
178
+ "seq": 42,
179
+ "session_id": "s-abc123"
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### Recipient → Server: ACK
185
+ ```json
186
+ {
187
+ "v": 1,
188
+ "type": "ACK",
189
+ "id": "uuid",
190
+ "ts": 1734440000103,
191
+ "payload": {
192
+ "ack_id": "d-001",
193
+ "seq": 42
194
+ }
195
+ }
196
+ ```
197
+
198
+ ### Ordering Guarantee
199
+
200
+ Per `(topic, from → to)` stream, daemon guarantees in-order DELIVER by `delivery.seq`.
201
+
202
+ No global ordering across topics.
203
+
204
+ ---
205
+
206
+ ## 6. Backpressure
207
+
208
+ Backpressure signaling is reserved for future versions. The current daemon is best-effort and does not implement bounded outbound queues or `BUSY` responses.
209
+
210
+ ### Server → Client: BUSY
211
+ ```json
212
+ {
213
+ "v": 1,
214
+ "type": "BUSY",
215
+ "id": "uuid",
216
+ "ts": 1734440000300,
217
+ "payload": {
218
+ "retry_after_ms": 50,
219
+ "queue_depth": 1000
220
+ }
221
+ }
222
+ ```
223
+
224
+ Client should back off (exponential with jitter).
225
+
226
+ ---
227
+
228
+ ## 7. Heartbeats
229
+
230
+ - Daemon sends PING every `heartbeat_ms` if idle
231
+ - Wrapper replies PONG with same nonce
232
+ - Missing PONG for `2 * heartbeat_ms` → connection dead
233
+
234
+ ---
235
+
236
+ ## 8. Reconnect / Resume
237
+
238
+ ### Client → Server: RESUME
239
+ ```json
240
+ {
241
+ "v": 1,
242
+ "type": "RESUME",
243
+ "id": "uuid",
244
+ "ts": 1734440001000,
245
+ "payload": {
246
+ "session_id": "s-abc123",
247
+ "agent": "claude-1",
248
+ "streams": {
249
+ "chat": { "last_seq": 45 }
250
+ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### Server → Client: SYNC
256
+ ```json
257
+ {
258
+ "v": 1,
259
+ "type": "SYNC",
260
+ "id": "uuid",
261
+ "ts": 1734440001001,
262
+ "payload": {
263
+ "session_id": "s-abc123",
264
+ "streams": [
265
+ { "topic": "chat", "peer": "codex-1", "last_seq": 45, "server_last_seq": 49 }
266
+ ]
267
+ }
268
+ }
269
+ ```
270
+
271
+ Server then replays DELIVER messages from `last_seq + 1` to `server_last_seq`.
272
+
273
+ ### Stale Resume
274
+
275
+ If resume gap exceeds retention, server sends NACK with code "STALE".
276
+ Client should send fresh HELLO.
277
+
278
+ ---
279
+
280
+ ## 9. PTY Pattern Extractor
281
+
282
+ ### Block Format (preferred)
283
+
284
+ ```
285
+ [[RELAY]]
286
+ {"to": "*", "type": "message", "body": "Hello everyone"}
287
+ [[/RELAY]]
288
+ ```
289
+
290
+ ### Inline Format (single line only)
291
+
292
+ ```
293
+ @relay:codex-1 Your turn to play
294
+ @thinking:* Considering the Queen...
295
+ ```
296
+
297
+ ### Rules
298
+
299
+ 1. Block: Only parse when `[[RELAY]]` at start of line
300
+ 2. Inline: Only at start of line, not in code fences
301
+ 3. Escape: `\@relay:` outputs literal `@relay:`
302
+
303
+ ---
304
+
305
+ ## 10. Connection Lifecycle
306
+
307
+ ```
308
+ DISCONNECTED → CONNECTING → HANDSHAKING → READY
309
+ ↑ ↓
310
+ BACKOFF ←─────── ERROR
311
+ ```
312
+
313
+ ### Backoff Strategy
314
+
315
+ - Initial: 100ms
316
+ - Multiplier: 2x
317
+ - Max: 30s
318
+ - Jitter: ±15%
319
+ - Max attempts: 10