agent-relay 0.1.0 → 1.0.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 (86) hide show
  1. package/README.md +56 -730
  2. package/dist/cli/index.d.ts +6 -1
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +109 -1521
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/daemon/server.d.ts +8 -1
  7. package/dist/daemon/server.d.ts.map +1 -1
  8. package/dist/daemon/server.js +23 -7
  9. package/dist/daemon/server.js.map +1 -1
  10. package/dist/index.d.ts +0 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +0 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/storage/adapter.d.ts +43 -0
  15. package/dist/storage/adapter.d.ts.map +1 -1
  16. package/dist/storage/adapter.js +105 -1
  17. package/dist/storage/adapter.js.map +1 -1
  18. package/dist/storage/sqlite-adapter.d.ts +1 -0
  19. package/dist/storage/sqlite-adapter.d.ts.map +1 -1
  20. package/dist/storage/sqlite-adapter.js +26 -0
  21. package/dist/storage/sqlite-adapter.js.map +1 -1
  22. package/dist/utils/project-namespace.d.ts +46 -0
  23. package/dist/utils/project-namespace.d.ts.map +1 -0
  24. package/dist/utils/project-namespace.js +111 -0
  25. package/dist/utils/project-namespace.js.map +1 -0
  26. package/dist/wrapper/client.d.ts +1 -1
  27. package/dist/wrapper/client.d.ts.map +1 -1
  28. package/dist/wrapper/client.js +1 -1
  29. package/dist/wrapper/client.js.map +1 -1
  30. package/dist/wrapper/index.d.ts +0 -1
  31. package/dist/wrapper/index.d.ts.map +1 -1
  32. package/dist/wrapper/index.js +2 -3
  33. package/dist/wrapper/index.js.map +1 -1
  34. package/dist/wrapper/tmux-wrapper.d.ts +5 -0
  35. package/dist/wrapper/tmux-wrapper.d.ts.map +1 -1
  36. package/dist/wrapper/tmux-wrapper.js +94 -19
  37. package/dist/wrapper/tmux-wrapper.js.map +1 -1
  38. package/docs/AGENTS.md +386 -0
  39. package/docs/CLI-SIMPLIFICATION-COMPLETE.md +48 -0
  40. package/docs/CONTRIBUTING.md +151 -0
  41. package/docs/TMUX_IMPLEMENTATION_NOTES.md +364 -0
  42. package/docs/removable-code-analysis.md +24 -0
  43. package/install.sh +10 -2
  44. package/package.json +3 -4
  45. package/dist/games/index.d.ts +0 -2
  46. package/dist/games/index.d.ts.map +0 -1
  47. package/dist/games/index.js +0 -2
  48. package/dist/games/index.js.map +0 -1
  49. package/dist/games/tictactoe.d.ts +0 -24
  50. package/dist/games/tictactoe.d.ts.map +0 -1
  51. package/dist/games/tictactoe.js +0 -160
  52. package/dist/games/tictactoe.js.map +0 -1
  53. package/dist/supervisor/inbox.d.ts +0 -38
  54. package/dist/supervisor/inbox.d.ts.map +0 -1
  55. package/dist/supervisor/inbox.js +0 -162
  56. package/dist/supervisor/inbox.js.map +0 -1
  57. package/dist/supervisor/index.d.ts +0 -10
  58. package/dist/supervisor/index.d.ts.map +0 -1
  59. package/dist/supervisor/index.js +0 -10
  60. package/dist/supervisor/index.js.map +0 -1
  61. package/dist/supervisor/spawner.d.ts +0 -54
  62. package/dist/supervisor/spawner.d.ts.map +0 -1
  63. package/dist/supervisor/spawner.js +0 -282
  64. package/dist/supervisor/spawner.js.map +0 -1
  65. package/dist/supervisor/state.d.ts +0 -132
  66. package/dist/supervisor/state.d.ts.map +0 -1
  67. package/dist/supervisor/state.js +0 -465
  68. package/dist/supervisor/state.js.map +0 -1
  69. package/dist/supervisor/supervisor.d.ts +0 -67
  70. package/dist/supervisor/supervisor.d.ts.map +0 -1
  71. package/dist/supervisor/supervisor.js +0 -263
  72. package/dist/supervisor/supervisor.js.map +0 -1
  73. package/dist/supervisor/types.d.ts +0 -139
  74. package/dist/supervisor/types.d.ts.map +0 -1
  75. package/dist/supervisor/types.js +0 -12
  76. package/dist/supervisor/types.js.map +0 -1
  77. package/dist/webhook/spawner.d.ts +0 -79
  78. package/dist/webhook/spawner.d.ts.map +0 -1
  79. package/dist/webhook/spawner.js +0 -288
  80. package/dist/webhook/spawner.js.map +0 -1
  81. package/dist/wrapper/pty-wrapper.d.ts +0 -125
  82. package/dist/wrapper/pty-wrapper.d.ts.map +0 -1
  83. package/dist/wrapper/pty-wrapper.js +0 -494
  84. package/dist/wrapper/pty-wrapper.js.map +0 -1
  85. /package/{CHANGELOG.md → docs/CHANGELOG.md} +0 -0
  86. /package/{PROTOCOL.md → docs/PROTOCOL.md} +0 -0
@@ -0,0 +1,364 @@
1
+ # tmux Implementation Notes
2
+
3
+ ## Previous Failure Analysis
4
+
5
+ ### What Failed: "Game never even started"
6
+
7
+ The previous tmux implementation had these issues:
8
+
9
+ 1. **Nested PTY Attachment**: Created tmux session, then attached via node-pty
10
+ ```typescript
11
+ // Created tmux session
12
+ execSync(`tmux new-session -d -s ${session} '${command}'`);
13
+ // Then attached via PTY
14
+ this.ptyProcess = pty.spawn('tmux', ['attach-session', '-t', session]);
15
+ ```
16
+ This creates: Agent CLI → tmux → tmux attach → node-pty
17
+ Double terminal layer causes escape sequence issues.
18
+
19
+ 2. **Command Quoting Problem**: Single quotes break complex commands
20
+ ```bash
21
+ tmux new-session -d -s session 'claude -p "You're playing..."'
22
+ # The apostrophe in "You're" breaks the quoting
23
+ ```
24
+
25
+ 3. **Environment Variables Not Passed**: ENV vars set on attach, not on session
26
+ - The agent process inside tmux doesn't see AGENT_RELAY_NAME
27
+
28
+ 4. **No Session Ready Wait**: Attached immediately after creating session
29
+ - Session might not be ready, causing race conditions
30
+
31
+ ## New Architecture: No Attachment
32
+
33
+ ```
34
+ ┌──────────────────────────────────┐
35
+ │ tmux session "relay-AgentX" │
36
+ │ (detached, running in background)│
37
+ │ ┌────────────────────────────┐ │
38
+ │ │ agent CLI process │ │
39
+ │ │ (claude, codex, etc) │ │
40
+ │ └────────────────────────────┘ │
41
+ └──────────────────────────────────┘
42
+ ↑ ↓
43
+ send-keys capture-pane
44
+ (inject input) (read output)
45
+ │ │
46
+ ┌──────────────────────────────────┐
47
+ │ TmuxWrapper (this process) │
48
+ │ - Polls capture-pane @ 100ms │
49
+ │ - Detects new output (diff) │
50
+ │ - Parses @relay: commands │
51
+ │ - Writes to stdout for user │
52
+ │ - Injects messages via send-keys│
53
+ │ - Forwards user stdin to tmux │
54
+ └──────────────────────────────────┘
55
+ ```
56
+
57
+ ## Key Differences from Previous Implementation
58
+
59
+ 1. **No PTY attachment** - Eliminates double-terminal problem
60
+ 2. **capture-pane polling** - Direct access to terminal content
61
+ 3. **Proper command escaping** - Use shell escaping, not simple quotes
62
+ 4. **Environment via tmux** - Set ENV in tmux session directly
63
+ 5. **Session ready wait** - Wait for session to be active before proceeding
64
+
65
+ ## Implementation Details
66
+
67
+ ### Starting a Session
68
+
69
+ ```bash
70
+ # Set environment variables IN the tmux session
71
+ tmux new-session -d -s relay-AgentX \
72
+ -x 120 -y 40 \
73
+ "export AGENT_RELAY_NAME=AgentX; exec claude"
74
+ ```
75
+
76
+ ### Capturing Output
77
+
78
+ ```bash
79
+ # Capture entire scrollback (not just visible pane)
80
+ tmux capture-pane -t relay-AgentX -p -S -
81
+ ```
82
+
83
+ ### Sending Input
84
+
85
+ ```bash
86
+ # Use -l for literal string (no escaping needed)
87
+ tmux send-keys -t relay-AgentX -l "Your message here"
88
+ tmux send-keys -t relay-AgentX Enter
89
+ ```
90
+
91
+ ### Handling User Input
92
+
93
+ Forward process stdin to tmux session:
94
+ ```typescript
95
+ process.stdin.on('data', (data) => {
96
+ execSync(`tmux send-keys -t ${session} -l "${escape(data)}"`);
97
+ });
98
+ ```
99
+
100
+ ## Edge Cases to Handle
101
+
102
+ 1. **Fast output**: capture-pane might miss fast scrolling
103
+ - Solution: Use -S - to get full scrollback, diff against last capture
104
+
105
+ 2. **Binary/escape sequences**: Output might contain control characters
106
+ - Solution: Strip ANSI codes before parsing @relay:
107
+
108
+ 3. **Session death**: tmux session might exit
109
+ - Solution: Monitor with `tmux has-session -t session`
110
+
111
+ 4. **Multiple messages**: Several @relay: in one capture
112
+ - Solution: Track last processed line/position
113
+
114
+ 5. **Stdin race conditions**: User types while we inject
115
+ - Solution: Queue injections, use mutex/lock
116
+
117
+ ## Testing Plan
118
+
119
+ 1. **Basic session start**: Does claude actually launch in tmux?
120
+ 2. **Output capture**: Can we see claude's output?
121
+ 3. **Input injection**: Can we send text and get response?
122
+ 4. **@relay detection**: Does parser find @relay: commands?
123
+ 5. **Full game**: Two agents playing tic-tac-toe
124
+
125
+ ## Rollback Plan
126
+
127
+ If this doesn't work, fall back to:
128
+ 1. File-based inbox (already implemented)
129
+ 2. Hook-based polling (Claude only)
130
+ 3. Spawn-per-message (loses context)
131
+
132
+ ---
133
+
134
+ ## Implementation Complete - Testing Instructions
135
+
136
+ ### Build Status: SUCCESS
137
+
138
+ The new TmuxWrapper has been implemented at:
139
+ - `src/wrapper/tmux-wrapper.ts`
140
+
141
+ CLI updated to support `--tmux2` flag.
142
+
143
+ ### Quick Test: Basic Session Start
144
+
145
+ ```bash
146
+ # Test 1: Does bash work in tmux?
147
+ node dist/cli/index.js wrap --tmux2 -n TestAgent -- bash
148
+
149
+ # You should see:
150
+ # - "Mode: tmux2 (new simplified tmux wrapper)"
151
+ # - Bash prompt in your terminal
152
+ # - Type commands, they should work
153
+ # - Ctrl+C to exit
154
+ ```
155
+
156
+ ### Test 2: Simple Echo Command
157
+
158
+ ```bash
159
+ # Start with echo (should immediately show output and exit)
160
+ node dist/cli/index.js wrap --tmux2 -n TestAgent -- echo "Hello World"
161
+ ```
162
+
163
+ ### Test 3: Claude CLI (No Relay)
164
+
165
+ ```bash
166
+ # Test Claude starts correctly
167
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude
168
+
169
+ # Expected: Claude CLI starts, you can interact with it
170
+ ```
171
+
172
+ ### Test 4: With Relay Daemon
173
+
174
+ ```bash
175
+ # Terminal 1: Start daemon
176
+ node dist/cli/index.js start -f
177
+
178
+ # Terminal 2: Start PlayerX
179
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude
180
+
181
+ # Terminal 3: Start PlayerO
182
+ node dist/cli/index.js wrap --tmux2 -n PlayerO -- claude
183
+
184
+ # Terminal 4: Send a test message
185
+ node dist/cli/index.js send -f Coordinator -t PlayerX -m "Hello from Coordinator"
186
+
187
+ # Expected: PlayerX terminal should show the message and inject it
188
+ ```
189
+
190
+ ### Test 5: Tic-Tac-Toe
191
+
192
+ ```bash
193
+ # Terminal 1: Daemon
194
+ node dist/cli/index.js start -f
195
+
196
+ # Terminal 2: PlayerX
197
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude -p "You are PlayerX playing tic-tac-toe. Use @relay:PlayerO to send moves. Start with your first move."
198
+
199
+ # Terminal 3: PlayerO
200
+ node dist/cli/index.js wrap --tmux2 -n PlayerO -- claude -p "You are PlayerO playing tic-tac-toe. Use @relay:PlayerX to send moves. Wait for PlayerX to start."
201
+ ```
202
+
203
+ ### Debugging
204
+
205
+ ```bash
206
+ # Check if tmux session exists
207
+ tmux list-sessions
208
+
209
+ # Attach to session manually to see what's happening
210
+ tmux attach -t relay-PlayerX-<pid>
211
+
212
+ # Kill stuck sessions
213
+ tmux kill-server
214
+ ```
215
+
216
+ ### Key Differences from Old tmux Implementation
217
+
218
+ 1. **No PTY attachment** - We don't `tmux attach` via node-pty
219
+ 2. **capture-pane polling** - Read output by polling, not events
220
+ 3. **send-keys -l** - Use literal mode for text injection
221
+ 4. **Environment via tmux setenv** - Set ENV vars in tmux session directly
222
+ 5. **Simpler architecture** - Less layers = fewer failure points
223
+
224
+ ---
225
+
226
+ ## Test Results - December 19, 2025
227
+
228
+ ### Basic Test: PASSED
229
+
230
+ Message injection into bash session works:
231
+
232
+ ```
233
+ [daemon] Agent registered: TestAgent
234
+ [router] Coordinator -> TestAgent: Hello TestAgent!...
235
+ [router] Delivered to TestAgent: success
236
+ [tmux:TestAgent] ← Coordinator: Hello TestAgent!...
237
+ [tmux:TestAgent] Injecting message from Coordinator
238
+ [tmux:TestAgent] Message injected successfully
239
+ bash-3.2$ Relay message from Coordinator: Hello TestAgent!
240
+ ```
241
+
242
+ The message was successfully typed into the bash terminal via tmux send-keys.
243
+
244
+ ### What Works
245
+
246
+ 1. **Session creation** - tmux session starts correctly
247
+ 2. **Output capture** - capture-pane polling detects new output
248
+ 3. **Relay connection** - Agent connects to daemon
249
+ 4. **Message routing** - Messages route between agents
250
+ 5. **Message injection** - Text is typed into the terminal via send-keys
251
+
252
+ ### Next Steps
253
+
254
+ 1. Test with Claude CLI (replace bash with claude)
255
+ 2. Test full tic-tac-toe game between two agents
256
+ 3. Verify @relay: command parsing works in both directions
257
+ 4. Check if multi-round injection remains stable (previous implementations failed after 2-3 rounds)
258
+
259
+ ### Critical Question
260
+
261
+ Does this implementation avoid the "fails after a few rounds" problem? The key difference:
262
+
263
+ - **Old approach**: PTY stdin write (`ptyProcess.write()`) - corrupts over time
264
+ - **New approach**: tmux send-keys (`tmux send-keys -l "..."`) - should be more stable
265
+
266
+ ---
267
+
268
+ ## December 19, 2025 - Attach-Based Implementation: SUCCESS
269
+
270
+ ### Problem with First tmux Attempt
271
+
272
+ The first tmux wrapper tried to:
273
+ 1. Poll `capture-pane` for output
274
+ 2. Write output to stdout
275
+ 3. This caused display corruption after message injection
276
+
277
+ ### Solution: Direct Attach
278
+
279
+ New architecture:
280
+ 1. Start agent in detached tmux session
281
+ 2. **Attach user directly** via `spawn('tmux', ['attach'], { stdio: 'inherit' })`
282
+ 3. Background polling is **completely silent** (no stdout writes)
283
+ 4. Injection via `send-keys` works on attached session
284
+ 5. Logs only to stderr
285
+
286
+ ### Test Result: PASSED
287
+
288
+ Message injection works without display corruption:
289
+ ```bash
290
+ # Terminal 1: Daemon
291
+ node dist/cli/index.js start -f
292
+
293
+ # Terminal 2: Agent
294
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude
295
+
296
+ # Terminal 3: Send message
297
+ node dist/cli/index.js send -f Test -t PlayerX -m "Hello!"
298
+ # → Message injected successfully, display intact
299
+ ```
300
+
301
+ ### Next: Multi-Round Tic-Tac-Toe Test
302
+
303
+ The critical test is whether injection remains stable over multiple rounds:
304
+ ```bash
305
+ # Terminal 1: Daemon
306
+ node dist/cli/index.js start -f
307
+
308
+ # Terminal 2: PlayerX
309
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude -p "Play tic-tac-toe. Use @relay:PlayerO to send moves."
310
+
311
+ # Terminal 3: PlayerO
312
+ node dist/cli/index.js wrap --tmux2 -n PlayerO -- claude -p "Play tic-tac-toe. Use @relay:PlayerX to send moves."
313
+ ```
314
+
315
+ If this works for a full game (5-9 moves), we've solved the problem.
316
+
317
+ ---
318
+
319
+ ## December 19, 2025 - Command Quoting Fix
320
+
321
+ ### Problem
322
+
323
+ Running with `-p` flag failed:
324
+ ```bash
325
+ node dist/cli/index.js wrap --tmux2 -n PlayerX -- claude -p "You are PlayerX..."
326
+ # Result: Claude terminal didn't open
327
+ ```
328
+
329
+ ### Root Cause
330
+
331
+ The CLI was joining all command parts into a single string at line 229:
332
+ ```typescript
333
+ const command = commandParts.join(' ');
334
+ ```
335
+
336
+ And passing only this joined string to TmuxWrapper. But by the time args reach Node.js,
337
+ the shell has already stripped the outer quotes, so `commandParts` = `['claude', '-p', 'You are PlayerX...']`.
338
+
339
+ When joined back together without re-quoting: `claude -p You are PlayerX...` - the prompt is split.
340
+
341
+ ### Fix
342
+
343
+ 1. **CLI (index.ts)**: Split command and args separately:
344
+ ```typescript
345
+ const [mainCommand, ...commandArgs] = commandParts;
346
+ // Pass to TmuxWrapper as:
347
+ // command: mainCommand ('claude')
348
+ // args: commandArgs (['-p', 'You are PlayerX...'])
349
+ ```
350
+
351
+ 2. **TmuxWrapper**: `buildCommand()` re-quotes args containing spaces:
352
+ ```typescript
353
+ private buildCommand(): string {
354
+ const quotedArgs = this.config.args.map(arg => {
355
+ if (arg.includes(' ') || arg.includes('"') || arg.includes("'")) {
356
+ return `"${arg.replace(/"/g, '\\"')}"`;
357
+ }
358
+ return arg;
359
+ });
360
+ return `${this.config.command} ${quotedArgs.join(' ')}`;
361
+ }
362
+ ```
363
+
364
+ Result: `claude -p "You are PlayerX..."` is correctly sent to tmux.
@@ -0,0 +1,24 @@
1
+ # Removable Code Analysis
2
+
3
+ Requested: identify code/assets likely safe to remove (unused, legacy, or duplicates).
4
+
5
+ ## Candidates
6
+ 1) `run-dashboard.js`
7
+ - Purpose: helper to start dashboard from built `dist/dashboard/server.js`.
8
+ - Evidence: Dashboard now exposed via CLI subcommand `dashboard` in `src/cli/index.ts`. No `rg` references to `run-dashboard.js`. Redundant helper.
9
+
10
+ 2) `scripts/games/*` and `scripts/tictactoe-setup.sh`
11
+ - Purpose: old demo/game scripts (hearts/tictactoe).
12
+ - Evidence: Not referenced by CLI commands or docs (checked with `rg`). Pure examples; removable if demos not needed.
13
+
14
+ 3) `src/hooks/check-inbox.sh`
15
+ - Purpose: legacy hook example for Claude stop-event inbox check.
16
+ - Evidence: Replaced by compiled hook in `dist/hooks/inbox-check/*` and TypeScript sources in `src/hooks/inbox-check/*`. No other references via `rg`, so redundant.
17
+
18
+ 4) `coverage/` directory
19
+ - Purpose: test coverage artifacts.
20
+ - Evidence: Generated output; not source. Safe to delete/regenerate.
21
+
22
+ 5) `TOMORROW.md`
23
+ - Purpose: session notes / planning doc.
24
+ - Evidence: Not used by runtime or tests; optional to keep for historical notes only.
package/install.sh CHANGED
@@ -42,8 +42,16 @@ install_source() {
42
42
  curl -fsSL "https://github.com/$REPO/archive/main.tar.gz" | tar -xz -C "$INSTALL_DIR" --strip-components=1
43
43
  fi
44
44
 
45
- cd "$INSTALL_DIR" && npm ci && npm run build
46
- ln -sf "$INSTALL_DIR/dist/cli/index.js" "$BIN_DIR/agent-relay"
45
+ cd "$INSTALL_DIR" && npm ci && npm rebuild better-sqlite3 && npm run build
46
+
47
+ # Remove any existing symlink or file (old installs used symlinks which cause issues)
48
+ rm -f "$BIN_DIR/agent-relay"
49
+
50
+ # Create wrapper script that runs from install dir (for node_modules resolution)
51
+ cat > "$BIN_DIR/agent-relay" << WRAPPER
52
+ #!/usr/bin/env bash
53
+ cd "$INSTALL_DIR" && exec node dist/cli/index.js "\$@"
54
+ WRAPPER
47
55
  chmod +x "$BIN_DIR/agent-relay"
48
56
 
49
57
  [[ ":$PATH:" != *":$BIN_DIR:"* ]] && warn "Add to PATH: export PATH=\"\$PATH:$BIN_DIR\""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,9 +12,8 @@
12
12
  "dist/",
13
13
  "install.sh",
14
14
  "README.md",
15
- "PROTOCOL.md",
16
- "CHANGELOG.md",
17
- "LICENSE"
15
+ "LICENSE",
16
+ "docs/"
18
17
  ],
19
18
  "publishConfig": {
20
19
  "access": "public"
@@ -1,2 +0,0 @@
1
- export * from './tictactoe.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/games/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './tictactoe.js';
2
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/games/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Tic-Tac-Toe Setup Helpers
3
- *
4
- * This is a lightweight “game module” focused on generating instructions and
5
- * directory setup for manual or scripted agent runs.
6
- *
7
- * It intentionally does NOT spawn agent processes (that stays in CLI tooling),
8
- * and it uses the inbox CLI commands (`inbox-poll`, `inbox-write`) so it works
9
- * with any agent runtime.
10
- */
11
- export interface TicTacToeSetupOptions {
12
- dataDir: string;
13
- playerX?: string;
14
- playerO?: string;
15
- }
16
- export interface TicTacToeSetupResult {
17
- dataDir: string;
18
- playerX: string;
19
- playerO: string;
20
- instructionsXPath: string;
21
- instructionsOPath: string;
22
- }
23
- export declare function setupTicTacToe(options: TicTacToeSetupOptions): TicTacToeSetupResult;
24
- //# sourceMappingURL=tictactoe.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tictactoe.d.ts","sourceRoot":"","sources":["../../src/games/tictactoe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAwID,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CAmBnF"}
@@ -1,160 +0,0 @@
1
- /**
2
- * Tic-Tac-Toe Setup Helpers
3
- *
4
- * This is a lightweight “game module” focused on generating instructions and
5
- * directory setup for manual or scripted agent runs.
6
- *
7
- * It intentionally does NOT spawn agent processes (that stays in CLI tooling),
8
- * and it uses the inbox CLI commands (`inbox-poll`, `inbox-write`) so it works
9
- * with any agent runtime.
10
- */
11
- import fs from 'node:fs';
12
- import path from 'node:path';
13
- function instructionsForPlayerX(dataDir, playerX, playerO) {
14
- return `# Tic-Tac-Toe Autonomous Game Protocol
15
-
16
- You are **${playerX}** (X). You play FIRST. Your opponent is **${playerO}** (O).
17
-
18
- ## Board Positions
19
- \`\`\`
20
- 1 | 2 | 3
21
- -----------
22
- 4 | 5 | 6
23
- -----------
24
- 7 | 8 | 9
25
- \`\`\`
26
-
27
- ## Commands Available
28
- You have these \`agent-relay\` commands to communicate:
29
-
30
- **Wait for opponent's message (blocking):**
31
- \`\`\`bash
32
- agent-relay inbox-poll -n ${playerX} -d ${dataDir} --clear
33
- \`\`\`
34
-
35
- **Send a move to opponent:**
36
- \`\`\`bash
37
- agent-relay inbox-write -t ${playerO} -f ${playerX} -m "MOVE: X at position N" -d ${dataDir}
38
- \`\`\`
39
-
40
- ## PROTOCOL (follow EXACTLY)
41
-
42
- ### Since you're X, you go FIRST:
43
- 1. Make your first move to position 5 (center)
44
- 2. Send it to opponent:
45
- \`\`\`bash
46
- agent-relay inbox-write -t ${playerO} -f ${playerX} -m "MOVE: X at position 5" -d ${dataDir}
47
- \`\`\`
48
-
49
- ### Then enter the game loop:
50
- 1. **WAIT** for opponent's response (this will block until they respond):
51
- \`\`\`bash
52
- agent-relay inbox-poll -n ${playerX} -d ${dataDir} --clear
53
- \`\`\`
54
-
55
- 2. **UPDATE** your mental board state with opponent's move
56
-
57
- 3. **CHECK** for win/draw. If game over, send result and announce:
58
- \`\`\`bash
59
- agent-relay inbox-write -t ${playerO} -f ${playerX} -m "GAME OVER: X wins!" -d ${dataDir}
60
- \`\`\`
61
-
62
- 4. **MAKE** your next move and send it:
63
- \`\`\`bash
64
- agent-relay inbox-write -t ${playerO} -f ${playerX} -m "MOVE: X at position N" -d ${dataDir}
65
- \`\`\`
66
-
67
- 5. **REPEAT** from step 1 until game over
68
-
69
- ## Rules
70
- - Valid moves: positions 1-9 that are empty
71
- - Win: 3 in a row (horizontal, vertical, or diagonal)
72
- - Draw: all 9 positions filled with no winner
73
-
74
- ## CRITICAL
75
- - NEVER stop mid-game
76
- - ALWAYS use the inbox-poll command to wait (it blocks until opponent responds)
77
- - Keep track of the board state
78
- - Announce result when game ends
79
-
80
- ## START NOW
81
- Make your FIRST MOVE to position 5, then wait for opponent's response.
82
- `;
83
- }
84
- function instructionsForPlayerO(dataDir, playerX, playerO) {
85
- return `# Tic-Tac-Toe Autonomous Game Protocol
86
-
87
- You are **${playerO}** (O). ${playerX} plays first, so you WAIT for their move.
88
-
89
- ## Board Positions
90
- \`\`\`
91
- 1 | 2 | 3
92
- -----------
93
- 4 | 5 | 6
94
- -----------
95
- 7 | 8 | 9
96
- \`\`\`
97
-
98
- ## Commands Available
99
- You have these \`agent-relay\` commands to communicate:
100
-
101
- **Wait for opponent's message (blocking):**
102
- \`\`\`bash
103
- agent-relay inbox-poll -n ${playerO} -d ${dataDir} --clear
104
- \`\`\`
105
-
106
- **Send a move to opponent:**
107
- \`\`\`bash
108
- agent-relay inbox-write -t ${playerX} -f ${playerO} -m "MOVE: O at position N" -d ${dataDir}
109
- \`\`\`
110
-
111
- ## PROTOCOL (follow EXACTLY)
112
-
113
- ### Since you're O, you go SECOND. Start by waiting:
114
- 1. **WAIT** for opponent's first move (this will block until they move):
115
- \`\`\`bash
116
- agent-relay inbox-poll -n ${playerO} -d ${dataDir} --clear
117
- \`\`\`
118
-
119
- 2. **UPDATE** your mental board state with opponent's move
120
-
121
- 3. **CHECK** for win/draw. If game over, announce result.
122
-
123
- 4. **MAKE** your response move and send it:
124
- \`\`\`bash
125
- agent-relay inbox-write -t ${playerX} -f ${playerO} -m "MOVE: O at position N" -d ${dataDir}
126
- \`\`\`
127
-
128
- 5. **WAIT** for opponent's next move (back to step 1)
129
-
130
- ## Rules
131
- - Valid moves: positions 1-9 that are empty
132
- - Win: 3 in a row (horizontal, vertical, or diagonal)
133
- - Draw: all 9 positions filled with no winner
134
-
135
- ## CRITICAL
136
- - NEVER stop mid-game
137
- - ALWAYS use the inbox-poll command to wait (it blocks until opponent responds)
138
- - Keep track of the board state
139
- - Announce result when game ends
140
-
141
- ## START NOW
142
- Run the inbox-poll command to WAIT for ${playerX}'s first move.
143
- `;
144
- }
145
- export function setupTicTacToe(options) {
146
- const dataDir = options.dataDir;
147
- const playerX = options.playerX ?? 'PlayerX';
148
- const playerO = options.playerO ?? 'PlayerO';
149
- fs.mkdirSync(path.join(dataDir, playerX), { recursive: true });
150
- fs.mkdirSync(path.join(dataDir, playerO), { recursive: true });
151
- // Clear inboxes
152
- fs.writeFileSync(path.join(dataDir, playerX, 'inbox.md'), '', 'utf-8');
153
- fs.writeFileSync(path.join(dataDir, playerO, 'inbox.md'), '', 'utf-8');
154
- const instructionsXPath = path.join(dataDir, playerX, 'GAME_INSTRUCTIONS.md');
155
- const instructionsOPath = path.join(dataDir, playerO, 'GAME_INSTRUCTIONS.md');
156
- fs.writeFileSync(instructionsXPath, instructionsForPlayerX(dataDir, playerX, playerO), 'utf-8');
157
- fs.writeFileSync(instructionsOPath, instructionsForPlayerO(dataDir, playerX, playerO), 'utf-8');
158
- return { dataDir, playerX, playerO, instructionsXPath, instructionsOPath };
159
- }
160
- //# sourceMappingURL=tictactoe.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tictactoe.js","sourceRoot":"","sources":["../../src/games/tictactoe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAgB7B,SAAS,sBAAsB,CAAC,OAAe,EAAE,OAAe,EAAE,OAAe;IAC/E,OAAO;;YAEG,OAAO,8CAA8C,OAAO;;;;;;;;;;;;;;;;4BAgB5C,OAAO,OAAO,OAAO;;;;;6BAKpB,OAAO,OAAO,OAAO,kCAAkC,OAAO;;;;;;;;;gCAS3D,OAAO,OAAO,OAAO,kCAAkC,OAAO;;;;;;+BAM/D,OAAO,OAAO,OAAO;;;;;;;gCAOpB,OAAO,OAAO,OAAO,+BAA+B,OAAO;;;;;gCAK3D,OAAO,OAAO,OAAO,kCAAkC,OAAO;;;;;;;;;;;;;;;;;;CAkB7F,CAAC;AACF,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAe,EAAE,OAAe,EAAE,OAAe;IAC/E,OAAO;;YAEG,OAAO,WAAW,OAAO;;;;;;;;;;;;;;;;4BAgBT,OAAO,OAAO,OAAO;;;;;6BAKpB,OAAO,OAAO,OAAO,kCAAkC,OAAO;;;;;;;;+BAQ5D,OAAO,OAAO,OAAO;;;;;;;;;gCASpB,OAAO,OAAO,OAAO,kCAAkC,OAAO;;;;;;;;;;;;;;;;;yCAiBrD,OAAO;CAC/C,CAAC;AACF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAA8B;IAC3D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC;IAE7C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE/D,gBAAgB;IAChB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IACvE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAEvE,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC;IAC9E,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,sBAAsB,CAAC,CAAC;IAE9E,EAAE,CAAC,aAAa,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAChG,EAAE,CAAC,aAAa,CAAC,iBAAiB,EAAE,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;IAEhG,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;AAC7E,CAAC"}
@@ -1,38 +0,0 @@
1
- /**
2
- * Supervisor Inbox Utilities
3
- *
4
- * Provides an atomic "claim" for an agent inbox file to avoid losing messages
5
- * that arrive while the supervisor is processing.
6
- */
7
- export interface InboxMessage {
8
- from: string;
9
- timestamp: string;
10
- body: string;
11
- }
12
- export interface ClaimedInbox {
13
- inboxPath: string;
14
- processingPath: string;
15
- content: string;
16
- }
17
- /**
18
- * Parse inbox markdown into structured messages.
19
- *
20
- * Expected format (repeated blocks):
21
- * ## Message from <sender> | <timestamp>
22
- * <body>
23
- */
24
- export declare function parseInboxMarkdown(content: string): InboxMessage[];
25
- /**
26
- * Atomically claim an inbox by renaming it to a processing file.
27
- * New incoming messages will be written to a new inbox.md.
28
- */
29
- export declare function claimInbox(inboxPath: string): ClaimedInbox | null;
30
- /**
31
- * Finalize a claimed inbox.
32
- *
33
- * - On success: delete processing file.
34
- * - On failure: re-queue the claimed content back into inbox.md without
35
- * overwriting any messages that arrived while processing.
36
- */
37
- export declare function finalizeClaim(claim: ClaimedInbox, success: boolean): void;
38
- //# sourceMappingURL=inbox.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../../src/supervisor/inbox.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAeD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CA4DlE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAyBjE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CA6CzE"}