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
@@ -0,0 +1,125 @@
1
+ /**
2
+ * PTY Wrapper
3
+ * Wraps an agent CLI command in a pseudo-terminal and intercepts
4
+ * relay commands from output while injecting incoming messages.
5
+ */
6
+ export interface WrapperConfig {
7
+ name: string;
8
+ command: string;
9
+ args?: string[];
10
+ socketPath?: string;
11
+ cols?: number;
12
+ rows?: number;
13
+ cwd?: string;
14
+ env?: Record<string, string>;
15
+ /** Raw mode - bypass all parsing for terminal-heavy CLIs */
16
+ raw?: boolean;
17
+ /** Use tmux for message injection (more reliable) */
18
+ useTmux?: boolean;
19
+ /** Use osascript for OS-level keyboard simulation (macOS only) */
20
+ useOsascript?: boolean;
21
+ /** Use file-based inbox instead of stdin injection */
22
+ useInbox?: boolean;
23
+ /** Custom inbox directory */
24
+ inboxDir?: string;
25
+ }
26
+ export declare class PtyWrapper {
27
+ private config;
28
+ private ptyProcess?;
29
+ private client;
30
+ private parser;
31
+ private inbox?;
32
+ private running;
33
+ private lastOutputTime;
34
+ private messageQueue;
35
+ private processingMessage;
36
+ private recentlySentMessages;
37
+ private tmuxSessionName?;
38
+ private pendingRelayMessages;
39
+ private outputBuffer;
40
+ private lastOutputFlush;
41
+ constructor(config: WrapperConfig);
42
+ /**
43
+ * Start the wrapped agent process.
44
+ */
45
+ start(): Promise<void>;
46
+ /**
47
+ * Start with tmux for message injection.
48
+ */
49
+ private startWithTmux;
50
+ /**
51
+ * Start directly without tmux.
52
+ */
53
+ private startDirect;
54
+ /**
55
+ * Set up PTY event handlers.
56
+ */
57
+ private setupPtyHandlers;
58
+ /**
59
+ * Stop the wrapped process.
60
+ */
61
+ stop(): void;
62
+ /**
63
+ * Handle output from the PTY process.
64
+ */
65
+ private handlePtyOutput;
66
+ /**
67
+ * Schedule message injection after output settles.
68
+ * We inject messages when there's been a pause in output (tool finished).
69
+ */
70
+ private scheduleMessageInjection;
71
+ /**
72
+ * Inject pending relay messages into the output stream.
73
+ * Claude will see these as part of the terminal output.
74
+ * Then send a minimal trigger to stdin to prompt processing.
75
+ */
76
+ private injectPendingMessages;
77
+ /**
78
+ * Send a parsed relay command to the daemon.
79
+ * Includes deduplication to prevent sending the same message multiple times.
80
+ */
81
+ private sendRelayCommand;
82
+ /**
83
+ * Handle incoming message from relay.
84
+ *
85
+ * Strategy:
86
+ * - Always show notification in terminal (real-time visual cue)
87
+ * - If inbox mode: also write to inbox file (for hook polling)
88
+ * - No stdin injection (unreliable after a few rounds)
89
+ */
90
+ private handleIncomingMessage;
91
+ /**
92
+ * Process the next message in the queue when Claude is idle.
93
+ */
94
+ private processNextMessage;
95
+ /**
96
+ * Inject message using osascript (macOS keyboard simulation).
97
+ * This sends keystrokes at the OS level to the frontmost application.
98
+ */
99
+ private injectViaOsascript;
100
+ /**
101
+ * Inject message using tmux send-keys.
102
+ */
103
+ private injectViaTmux;
104
+ /**
105
+ * Inject message using direct PTY write.
106
+ */
107
+ private injectViaPty;
108
+ /**
109
+ * Wait until Claude has been idle (no output) for a period.
110
+ */
111
+ private waitForIdle;
112
+ /**
113
+ * Simulate human typing by sending characters one at a time.
114
+ */
115
+ private simulateTyping;
116
+ /**
117
+ * Check if wrapper is running.
118
+ */
119
+ get isRunning(): boolean;
120
+ /**
121
+ * Get agent name.
122
+ */
123
+ get name(): string;
124
+ }
125
+ //# sourceMappingURL=pty-wrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-wrapper.d.ts","sourceRoot":"","sources":["../../src/wrapper/pty-wrapper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,4DAA4D;IAC5D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAW;IAC9B,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,KAAK,CAAC,CAAe;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,YAAY,CAAqD;IACzE,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,oBAAoB,CAAkC;IAC9D,OAAO,CAAC,eAAe,CAAC,CAAS;IACjC,OAAO,CAAC,oBAAoB,CAA6C;IACzE,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,eAAe,CAAK;gBAEhB,MAAM,EAAE,aAAa;IAiCjC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC5B;;OAEG;YACW,aAAa;IAwC3B;;OAEG;YACW,WAAW;IAkBzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA4CxB;;OAEG;IACH,IAAI,IAAI,IAAI;IAYZ;;OAEG;IACH,OAAO,CAAC,eAAe;IA0BvB;;;OAGG;IACH,OAAO,CAAC,wBAAwB;IAahC;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAkC7B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAyBxB;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA2C1B;;;OAGG;YACW,kBAAkB;IA6BhC;;OAEG;YACW,aAAa;IA2B3B;;OAEG;YACW,YAAY;IAqB1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAkCnB;;OAEG;YACW,cAAc;IAQ5B;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
@@ -0,0 +1,494 @@
1
+ /**
2
+ * PTY Wrapper
3
+ * Wraps an agent CLI command in a pseudo-terminal and intercepts
4
+ * relay commands from output while injecting incoming messages.
5
+ */
6
+ import * as pty from 'node-pty';
7
+ import { execSync } from 'node:child_process';
8
+ import { RelayClient } from './client.js';
9
+ import { OutputParser } from './parser.js';
10
+ import { InboxManager } from './inbox.js';
11
+ export class PtyWrapper {
12
+ config;
13
+ ptyProcess;
14
+ client;
15
+ parser;
16
+ inbox;
17
+ running = false;
18
+ lastOutputTime = 0;
19
+ messageQueue = [];
20
+ processingMessage = false;
21
+ recentlySentMessages = new Map(); // hash -> timestamp
22
+ tmuxSessionName;
23
+ pendingRelayMessages = [];
24
+ outputBuffer = '';
25
+ lastOutputFlush = 0;
26
+ constructor(config) {
27
+ this.config = {
28
+ // Use actual terminal size, fallback to defaults
29
+ cols: process.stdout.columns || 120,
30
+ rows: process.stdout.rows || 40,
31
+ ...config,
32
+ };
33
+ this.client = new RelayClient({
34
+ agentName: config.name,
35
+ socketPath: config.socketPath,
36
+ });
37
+ this.parser = new OutputParser();
38
+ // Initialize inbox if using file-based messaging
39
+ if (config.useInbox) {
40
+ this.inbox = new InboxManager({
41
+ agentName: config.name,
42
+ inboxDir: config.inboxDir,
43
+ });
44
+ }
45
+ // Handle incoming messages
46
+ this.client.onMessage = (from, payload) => {
47
+ this.handleIncomingMessage(from, payload);
48
+ };
49
+ this.client.onStateChange = (state) => {
50
+ process.stderr.write(`[wrapper:${this.config.name}] Relay state: ${state}\n`);
51
+ };
52
+ }
53
+ /**
54
+ * Start the wrapped agent process.
55
+ */
56
+ async start() {
57
+ if (this.running)
58
+ return;
59
+ // Initialize inbox if using file-based messaging
60
+ if (this.inbox) {
61
+ this.inbox.init();
62
+ const inboxPath = this.inbox.getInboxPath();
63
+ process.stderr.write(`[wrapper:${this.config.name}] Inbox mode enabled\n`);
64
+ process.stderr.write(`[wrapper:${this.config.name}] Inbox path: ${inboxPath}\n`);
65
+ process.stderr.write(`[wrapper:${this.config.name}] Tell agent: "After each response, read ${inboxPath} for messages"\n`);
66
+ }
67
+ // Connect to relay daemon
68
+ try {
69
+ await this.client.connect();
70
+ }
71
+ catch (err) {
72
+ process.stderr.write(`[wrapper:${this.config.name}] Failed to connect to relay: ${err}\n`);
73
+ // Continue without relay - agent can still run standalone
74
+ }
75
+ // Parse command
76
+ const [cmd, ...defaultArgs] = this.config.command.split(' ');
77
+ const args = this.config.args ?? defaultArgs;
78
+ if (this.config.useTmux) {
79
+ await this.startWithTmux(cmd, args);
80
+ }
81
+ else {
82
+ await this.startDirect(cmd, args);
83
+ }
84
+ process.stderr.write(`[wrapper:${this.config.name}] Started: ${this.config.command}${this.config.useTmux ? ' (tmux mode)' : ''}${this.config.useInbox ? ' (inbox mode)' : ''}\n`);
85
+ }
86
+ /**
87
+ * Start with tmux for message injection.
88
+ */
89
+ async startWithTmux(cmd, args) {
90
+ // Create a unique tmux session name
91
+ this.tmuxSessionName = `relay-${this.config.name}-${Date.now()}`;
92
+ const fullCommand = [cmd, ...args].join(' ');
93
+ // Kill any existing session with this name
94
+ try {
95
+ execSync(`tmux kill-session -t ${this.tmuxSessionName} 2>/dev/null`, { encoding: 'utf-8' });
96
+ }
97
+ catch {
98
+ // Session doesn't exist, that's fine
99
+ }
100
+ // Create tmux session running the command
101
+ const tmuxCmd = `tmux new-session -d -s ${this.tmuxSessionName} -x ${this.config.cols} -y ${this.config.rows} '${fullCommand}'`;
102
+ execSync(tmuxCmd, {
103
+ cwd: this.config.cwd ?? process.cwd(),
104
+ env: {
105
+ ...process.env,
106
+ ...this.config.env,
107
+ AGENT_RELAY_NAME: this.config.name,
108
+ TERM: 'xterm-256color',
109
+ },
110
+ });
111
+ // Attach to tmux session via PTY (so we can capture output)
112
+ this.ptyProcess = pty.spawn('tmux', ['attach-session', '-t', this.tmuxSessionName], {
113
+ name: 'xterm-256color',
114
+ cols: this.config.cols,
115
+ rows: this.config.rows,
116
+ cwd: this.config.cwd ?? process.cwd(),
117
+ env: {
118
+ ...process.env,
119
+ TERM: 'xterm-256color',
120
+ },
121
+ });
122
+ this.running = true;
123
+ this.setupPtyHandlers();
124
+ }
125
+ /**
126
+ * Start directly without tmux.
127
+ */
128
+ async startDirect(cmd, args) {
129
+ this.ptyProcess = pty.spawn(cmd, args, {
130
+ name: 'xterm-256color',
131
+ cols: this.config.cols,
132
+ rows: this.config.rows,
133
+ cwd: this.config.cwd ?? process.cwd(),
134
+ env: {
135
+ ...process.env,
136
+ ...this.config.env,
137
+ AGENT_RELAY_NAME: this.config.name,
138
+ TERM: 'xterm-256color',
139
+ },
140
+ });
141
+ this.running = true;
142
+ this.setupPtyHandlers();
143
+ }
144
+ /**
145
+ * Set up PTY event handlers.
146
+ */
147
+ setupPtyHandlers() {
148
+ if (!this.ptyProcess)
149
+ return;
150
+ // Handle PTY output
151
+ this.ptyProcess.onData((data) => {
152
+ this.handlePtyOutput(data);
153
+ });
154
+ // Handle PTY exit
155
+ this.ptyProcess.onExit(({ exitCode, signal }) => {
156
+ process.stderr.write(`[wrapper:${this.config.name}] Process exited (code: ${exitCode}, signal: ${signal})\n`);
157
+ this.running = false;
158
+ this.client.destroy();
159
+ // Clean up tmux session if using tmux
160
+ if (this.tmuxSessionName) {
161
+ try {
162
+ execSync(`tmux kill-session -t ${this.tmuxSessionName} 2>/dev/null`);
163
+ }
164
+ catch {
165
+ // Ignore
166
+ }
167
+ }
168
+ // Exit the wrapper process with the same code as the wrapped process
169
+ process.exit(exitCode);
170
+ });
171
+ // Forward stdin to PTY
172
+ process.stdin.setRawMode?.(true);
173
+ process.stdin.resume();
174
+ process.stdin.on('data', (data) => {
175
+ if (this.ptyProcess) {
176
+ this.ptyProcess.write(data.toString());
177
+ }
178
+ });
179
+ // Handle terminal resize
180
+ process.stdout.on('resize', () => {
181
+ if (this.ptyProcess) {
182
+ this.ptyProcess.resize(process.stdout.columns, process.stdout.rows);
183
+ }
184
+ });
185
+ }
186
+ /**
187
+ * Stop the wrapped process.
188
+ */
189
+ stop() {
190
+ if (!this.running)
191
+ return;
192
+ if (this.ptyProcess) {
193
+ this.ptyProcess.kill();
194
+ this.ptyProcess = undefined;
195
+ }
196
+ this.client.destroy();
197
+ this.running = false;
198
+ }
199
+ /**
200
+ * Handle output from the PTY process.
201
+ */
202
+ handlePtyOutput(data) {
203
+ // Track output timing for idle detection
204
+ this.lastOutputTime = Date.now();
205
+ // Raw mode: pass through everything without parsing
206
+ if (this.config.raw) {
207
+ process.stdout.write(data);
208
+ return;
209
+ }
210
+ // Parse for relay commands
211
+ const { commands, output } = this.parser.parse(data);
212
+ // Send any extracted commands to relay
213
+ for (const cmd of commands) {
214
+ this.sendRelayCommand(cmd);
215
+ }
216
+ // Output to terminal (with relay commands filtered)
217
+ process.stdout.write(output);
218
+ // Buffer output and check for injection opportunity
219
+ this.outputBuffer += data;
220
+ this.scheduleMessageInjection();
221
+ }
222
+ /**
223
+ * Schedule message injection after output settles.
224
+ * We inject messages when there's been a pause in output (tool finished).
225
+ */
226
+ scheduleMessageInjection() {
227
+ // Clear any existing timer
228
+ if (this.lastOutputFlush) {
229
+ clearTimeout(this.lastOutputFlush);
230
+ }
231
+ // Schedule injection after 500ms of quiet (output stopped)
232
+ this.lastOutputFlush = Date.now();
233
+ setTimeout(() => {
234
+ this.injectPendingMessages();
235
+ }, 500);
236
+ }
237
+ /**
238
+ * Inject pending relay messages into the output stream.
239
+ * Claude will see these as part of the terminal output.
240
+ * Then send a minimal trigger to stdin to prompt processing.
241
+ */
242
+ injectPendingMessages() {
243
+ if (this.pendingRelayMessages.length === 0)
244
+ return;
245
+ if (!this.running || !this.ptyProcess)
246
+ return;
247
+ // Check if output has actually settled (no new output in 500ms)
248
+ const timeSinceOutput = Date.now() - this.lastOutputTime;
249
+ if (timeSinceOutput < 400) {
250
+ // Output still active, reschedule
251
+ this.scheduleMessageInjection();
252
+ return;
253
+ }
254
+ // Inject all pending messages to stdout (visible context)
255
+ const messages = this.pendingRelayMessages.splice(0);
256
+ for (const msg of messages) {
257
+ const notification = `\n\n📨 [RELAY MESSAGE FROM ${msg.from}]: ${msg.body}\n`;
258
+ process.stdout.write(notification);
259
+ process.stderr.write(`[relay] Injected message from ${msg.from} into output\n`);
260
+ }
261
+ // Clear output buffer
262
+ this.outputBuffer = '';
263
+ // Now send a minimal trigger to stdin to prompt Claude to process
264
+ // Using a short trigger instead of the full message for reliability
265
+ setTimeout(() => {
266
+ if (this.ptyProcess && this.running) {
267
+ process.stderr.write(`[relay] Sending minimal trigger to stdin\n`);
268
+ this.ptyProcess.write('respond to the relay message above\r');
269
+ }
270
+ }, 300);
271
+ }
272
+ /**
273
+ * Send a parsed relay command to the daemon.
274
+ * Includes deduplication to prevent sending the same message multiple times.
275
+ */
276
+ sendRelayCommand(cmd) {
277
+ // Create a hash of the message for deduplication
278
+ const msgHash = `${cmd.to}:${cmd.body}`;
279
+ const now = Date.now();
280
+ const lastSent = this.recentlySentMessages.get(msgHash);
281
+ // Skip if same message was sent in the last 5 seconds
282
+ if (lastSent && now - lastSent < 5000) {
283
+ process.stderr.write(`[relay] Skipping duplicate message to ${cmd.to}\n`);
284
+ return;
285
+ }
286
+ const success = this.client.sendMessage(cmd.to, cmd.body, cmd.kind, cmd.data);
287
+ if (success) {
288
+ this.recentlySentMessages.set(msgHash, now);
289
+ // Clean up old entries
290
+ for (const [hash, ts] of this.recentlySentMessages) {
291
+ if (now - ts > 10000)
292
+ this.recentlySentMessages.delete(hash);
293
+ }
294
+ process.stderr.write(`[relay → ${cmd.to}] ${cmd.body.substring(0, 50)}${cmd.body.length > 50 ? '...' : ''}\n`);
295
+ }
296
+ else {
297
+ process.stderr.write(`[relay] Failed to send to ${cmd.to}\n`);
298
+ }
299
+ }
300
+ /**
301
+ * Handle incoming message from relay.
302
+ *
303
+ * Strategy:
304
+ * - Always show notification in terminal (real-time visual cue)
305
+ * - If inbox mode: also write to inbox file (for hook polling)
306
+ * - No stdin injection (unreliable after a few rounds)
307
+ */
308
+ handleIncomingMessage(from, payload) {
309
+ // Log to stderr
310
+ process.stderr.write(`\n[relay ← ${from}] ${payload.body}\n`);
311
+ if (!this.running || !this.ptyProcess)
312
+ return;
313
+ // Sanitize the message for display
314
+ const sanitizedBody = payload.body.replace(/[\r\n]+/g, ' ').trim();
315
+ // Always show notification in terminal (real-time visual cue)
316
+ const notification = `\n\n📨 [RELAY MESSAGE FROM ${from}]: ${sanitizedBody}\n`;
317
+ process.stdout.write(notification);
318
+ // If inbox mode, also write to file for hook polling
319
+ if (this.inbox) {
320
+ this.inbox.addMessage(from, payload.body);
321
+ process.stderr.write(`[relay] Message written to inbox file (hook will poll)\n`);
322
+ }
323
+ }
324
+ /**
325
+ * Process the next message in the queue when Claude is idle.
326
+ */
327
+ processNextMessage() {
328
+ if (this.messageQueue.length === 0) {
329
+ this.processingMessage = false;
330
+ process.stderr.write(`[inject] Queue empty, done processing\n`);
331
+ return;
332
+ }
333
+ this.processingMessage = true;
334
+ const msg = this.messageQueue.shift();
335
+ process.stderr.write(`[inject] Processing message from ${msg.from}, waiting for idle...\n`);
336
+ // Wait for Claude to be idle (no output for 2 seconds)
337
+ this.waitForIdle().then(() => {
338
+ if (!this.running) {
339
+ this.processingMessage = false;
340
+ return;
341
+ }
342
+ process.stderr.write(`[inject] Claude is idle, injecting message\n`);
343
+ // Sanitize message: replace newlines with spaces, trim
344
+ const sanitizedBody = msg.payload.body.replace(/[\r\n]+/g, ' ').trim();
345
+ const injection = `Relay message from ${msg.from}: ${sanitizedBody}`;
346
+ if (this.config.useOsascript) {
347
+ // Use OS-level keyboard simulation (macOS)
348
+ this.injectViaOsascript(injection).then(() => {
349
+ setTimeout(() => this.processNextMessage(), 1000);
350
+ });
351
+ }
352
+ else if (this.config.useTmux && this.tmuxSessionName) {
353
+ // Use tmux send-keys for injection
354
+ this.injectViaTmux(injection).then(() => {
355
+ setTimeout(() => this.processNextMessage(), 1000);
356
+ });
357
+ }
358
+ else {
359
+ // Use direct PTY injection
360
+ this.injectViaPty(injection).then(() => {
361
+ setTimeout(() => this.processNextMessage(), 1000);
362
+ });
363
+ }
364
+ });
365
+ }
366
+ /**
367
+ * Inject message using osascript (macOS keyboard simulation).
368
+ * This sends keystrokes at the OS level to the frontmost application.
369
+ */
370
+ async injectViaOsascript(message) {
371
+ try {
372
+ // Escape special characters for AppleScript
373
+ const escaped = message
374
+ .replace(/\\/g, '\\\\')
375
+ .replace(/"/g, '\\"')
376
+ .replace(/'/g, "'");
377
+ // First, send Escape to exit any special modes
378
+ execSync(`osascript -e 'tell application "System Events" to key code 53'`); // ESC
379
+ await new Promise(r => setTimeout(r, 100));
380
+ // Clear line with Cmd+A then delete (select all in input, delete)
381
+ execSync(`osascript -e 'tell application "System Events" to keystroke "u" using control down'`); // Ctrl+U
382
+ await new Promise(r => setTimeout(r, 50));
383
+ // Type the message
384
+ process.stderr.write(`[inject] Sending via osascript: ${message.substring(0, 50)}...\n`);
385
+ execSync(`osascript -e 'tell application "System Events" to keystroke "${escaped}"'`);
386
+ await new Promise(r => setTimeout(r, 100));
387
+ // Send Enter
388
+ process.stderr.write(`[inject] Sending Enter via osascript\n`);
389
+ execSync(`osascript -e 'tell application "System Events" to key code 36'`); // Enter
390
+ }
391
+ catch (err) {
392
+ process.stderr.write(`[inject] osascript error: ${err}\n`);
393
+ }
394
+ }
395
+ /**
396
+ * Inject message using tmux send-keys.
397
+ */
398
+ async injectViaTmux(message) {
399
+ if (!this.tmuxSessionName)
400
+ return;
401
+ try {
402
+ // Escape special characters for tmux
403
+ const escaped = message.replace(/'/g, "'\\''");
404
+ // Send ESC to exit any special modes
405
+ execSync(`tmux send-keys -t ${this.tmuxSessionName} Escape`);
406
+ await new Promise(r => setTimeout(r, 50));
407
+ // Clear line
408
+ execSync(`tmux send-keys -t ${this.tmuxSessionName} C-u`);
409
+ await new Promise(r => setTimeout(r, 50));
410
+ // Send the message
411
+ execSync(`tmux send-keys -t ${this.tmuxSessionName} '${escaped}'`);
412
+ await new Promise(r => setTimeout(r, 100));
413
+ // Send Enter
414
+ process.stderr.write(`[inject] Sending Enter via tmux\n`);
415
+ execSync(`tmux send-keys -t ${this.tmuxSessionName} Enter`);
416
+ }
417
+ catch (err) {
418
+ process.stderr.write(`[inject] tmux send-keys error: ${err}\n`);
419
+ }
420
+ }
421
+ /**
422
+ * Inject message using direct PTY write.
423
+ */
424
+ async injectViaPty(message) {
425
+ if (!this.ptyProcess || !this.running)
426
+ return;
427
+ // Exit any special modes (INSERT, etc) first
428
+ this.ptyProcess.write('\x1b'); // ESC
429
+ this.ptyProcess.write('\x1b'); // Double ESC to be sure
430
+ this.ptyProcess.write('\x15'); // Ctrl+U to clear line
431
+ await new Promise(r => setTimeout(r, 100));
432
+ // Type character by character
433
+ await this.simulateTyping(message);
434
+ await new Promise(r => setTimeout(r, 200));
435
+ if (this.ptyProcess && this.running) {
436
+ process.stderr.write(`[inject] Typing done, sending Enter\n`);
437
+ this.ptyProcess.write('\r'); // Submit
438
+ }
439
+ }
440
+ /**
441
+ * Wait until Claude has been idle (no output) for a period.
442
+ */
443
+ waitForIdle(idleMs = 2000, maxWaitMs = 30000) {
444
+ return new Promise((resolve) => {
445
+ const startTime = Date.now();
446
+ const checkIdle = () => {
447
+ if (!this.running) {
448
+ resolve();
449
+ return;
450
+ }
451
+ const timeSinceOutput = Date.now() - this.lastOutputTime;
452
+ const totalWait = Date.now() - startTime;
453
+ // If idle for long enough, or max wait exceeded, proceed
454
+ if (timeSinceOutput >= idleMs) {
455
+ process.stderr.write(`[inject] Idle detected (${timeSinceOutput}ms since output)\n`);
456
+ resolve();
457
+ return;
458
+ }
459
+ if (totalWait >= maxWaitMs) {
460
+ process.stderr.write(`[inject] Max wait exceeded (${totalWait}ms), forcing inject\n`);
461
+ resolve();
462
+ return;
463
+ }
464
+ // Check again in 100ms
465
+ setTimeout(checkIdle, 100);
466
+ };
467
+ checkIdle();
468
+ });
469
+ }
470
+ /**
471
+ * Simulate human typing by sending characters one at a time.
472
+ */
473
+ async simulateTyping(text) {
474
+ for (const char of text) {
475
+ if (!this.ptyProcess || !this.running)
476
+ return;
477
+ this.ptyProcess.write(char);
478
+ await new Promise(resolve => setTimeout(resolve, 5)); // 5ms per character
479
+ }
480
+ }
481
+ /**
482
+ * Check if wrapper is running.
483
+ */
484
+ get isRunning() {
485
+ return this.running;
486
+ }
487
+ /**
488
+ * Get agent name.
489
+ */
490
+ get name() {
491
+ return this.config.name;
492
+ }
493
+ }
494
+ //# sourceMappingURL=pty-wrapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-wrapper.js","sourceRoot":"","sources":["../../src/wrapper/pty-wrapper.ts"],"names":[],"mappings":"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"}