@agent-relay/wrapper 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 (115) hide show
  1. package/dist/__fixtures__/claude-outputs.d.ts +49 -0
  2. package/dist/__fixtures__/claude-outputs.d.ts.map +1 -0
  3. package/dist/__fixtures__/claude-outputs.js +443 -0
  4. package/dist/__fixtures__/claude-outputs.js.map +1 -0
  5. package/dist/__fixtures__/codex-outputs.d.ts +9 -0
  6. package/dist/__fixtures__/codex-outputs.d.ts.map +1 -0
  7. package/dist/__fixtures__/codex-outputs.js +94 -0
  8. package/dist/__fixtures__/codex-outputs.js.map +1 -0
  9. package/dist/__fixtures__/gemini-outputs.d.ts +19 -0
  10. package/dist/__fixtures__/gemini-outputs.d.ts.map +1 -0
  11. package/dist/__fixtures__/gemini-outputs.js +144 -0
  12. package/dist/__fixtures__/gemini-outputs.js.map +1 -0
  13. package/dist/__fixtures__/index.d.ts +68 -0
  14. package/dist/__fixtures__/index.d.ts.map +1 -0
  15. package/dist/__fixtures__/index.js +44 -0
  16. package/dist/__fixtures__/index.js.map +1 -0
  17. package/dist/auth-detection.d.ts +49 -0
  18. package/dist/auth-detection.d.ts.map +1 -0
  19. package/dist/auth-detection.js +199 -0
  20. package/dist/auth-detection.js.map +1 -0
  21. package/dist/base-wrapper.d.ts +225 -0
  22. package/dist/base-wrapper.d.ts.map +1 -0
  23. package/dist/base-wrapper.js +572 -0
  24. package/dist/base-wrapper.js.map +1 -0
  25. package/dist/client.d.ts +254 -0
  26. package/dist/client.d.ts.map +1 -0
  27. package/dist/client.js +801 -0
  28. package/dist/client.js.map +1 -0
  29. package/dist/id-generator.d.ts +35 -0
  30. package/dist/id-generator.d.ts.map +1 -0
  31. package/dist/id-generator.js +60 -0
  32. package/dist/id-generator.js.map +1 -0
  33. package/dist/idle-detector.d.ts +110 -0
  34. package/dist/idle-detector.d.ts.map +1 -0
  35. package/dist/idle-detector.js +304 -0
  36. package/dist/idle-detector.js.map +1 -0
  37. package/dist/inbox.d.ts +37 -0
  38. package/dist/inbox.d.ts.map +1 -0
  39. package/dist/inbox.js +73 -0
  40. package/dist/inbox.js.map +1 -0
  41. package/dist/index.d.ts +37 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +47 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/parser.d.ts +236 -0
  46. package/dist/parser.d.ts.map +1 -0
  47. package/dist/parser.js +1238 -0
  48. package/dist/parser.js.map +1 -0
  49. package/dist/prompt-composer.d.ts +67 -0
  50. package/dist/prompt-composer.d.ts.map +1 -0
  51. package/dist/prompt-composer.js +168 -0
  52. package/dist/prompt-composer.js.map +1 -0
  53. package/dist/relay-pty-orchestrator.d.ts +407 -0
  54. package/dist/relay-pty-orchestrator.d.ts.map +1 -0
  55. package/dist/relay-pty-orchestrator.js +1885 -0
  56. package/dist/relay-pty-orchestrator.js.map +1 -0
  57. package/dist/shared.d.ts +201 -0
  58. package/dist/shared.d.ts.map +1 -0
  59. package/dist/shared.js +341 -0
  60. package/dist/shared.js.map +1 -0
  61. package/dist/stuck-detector.d.ts +161 -0
  62. package/dist/stuck-detector.d.ts.map +1 -0
  63. package/dist/stuck-detector.js +402 -0
  64. package/dist/stuck-detector.js.map +1 -0
  65. package/dist/tmux-resolver.d.ts +55 -0
  66. package/dist/tmux-resolver.d.ts.map +1 -0
  67. package/dist/tmux-resolver.js +175 -0
  68. package/dist/tmux-resolver.js.map +1 -0
  69. package/dist/tmux-wrapper.d.ts +345 -0
  70. package/dist/tmux-wrapper.d.ts.map +1 -0
  71. package/dist/tmux-wrapper.js +1747 -0
  72. package/dist/tmux-wrapper.js.map +1 -0
  73. package/dist/trajectory-integration.d.ts +292 -0
  74. package/dist/trajectory-integration.d.ts.map +1 -0
  75. package/dist/trajectory-integration.js +979 -0
  76. package/dist/trajectory-integration.js.map +1 -0
  77. package/dist/wrapper-types.d.ts +41 -0
  78. package/dist/wrapper-types.d.ts.map +1 -0
  79. package/dist/wrapper-types.js +7 -0
  80. package/dist/wrapper-types.js.map +1 -0
  81. package/package.json +63 -0
  82. package/src/__fixtures__/claude-outputs.ts +471 -0
  83. package/src/__fixtures__/codex-outputs.ts +99 -0
  84. package/src/__fixtures__/gemini-outputs.ts +151 -0
  85. package/src/__fixtures__/index.ts +47 -0
  86. package/src/auth-detection.ts +244 -0
  87. package/src/base-wrapper.test.ts +540 -0
  88. package/src/base-wrapper.ts +741 -0
  89. package/src/client.test.ts +262 -0
  90. package/src/client.ts +984 -0
  91. package/src/id-generator.test.ts +71 -0
  92. package/src/id-generator.ts +69 -0
  93. package/src/idle-detector.test.ts +390 -0
  94. package/src/idle-detector.ts +370 -0
  95. package/src/inbox.test.ts +233 -0
  96. package/src/inbox.ts +89 -0
  97. package/src/index.ts +170 -0
  98. package/src/parser.regression.test.ts +251 -0
  99. package/src/parser.test.ts +1359 -0
  100. package/src/parser.ts +1477 -0
  101. package/src/prompt-composer.test.ts +219 -0
  102. package/src/prompt-composer.ts +231 -0
  103. package/src/relay-pty-orchestrator.test.ts +1027 -0
  104. package/src/relay-pty-orchestrator.ts +2270 -0
  105. package/src/shared.test.ts +221 -0
  106. package/src/shared.ts +454 -0
  107. package/src/stuck-detector.test.ts +303 -0
  108. package/src/stuck-detector.ts +511 -0
  109. package/src/tmux-resolver.test.ts +104 -0
  110. package/src/tmux-resolver.ts +207 -0
  111. package/src/tmux-wrapper.test.ts +316 -0
  112. package/src/tmux-wrapper.ts +2010 -0
  113. package/src/trajectory-detection.test.ts +151 -0
  114. package/src/trajectory-integration.ts +1261 -0
  115. package/src/wrapper-types.ts +45 -0
@@ -0,0 +1,402 @@
1
+ /**
2
+ * StuckDetector - Detect when an agent is stuck
3
+ *
4
+ * Implements agent-relay-501: Stuck detection heuristics
5
+ *
6
+ * Detects five stuck conditions:
7
+ * 1. Extended idle (no output for 10+ minutes)
8
+ * 2. Error loop (same error message repeated 3+ times)
9
+ * 3. Output loop (same output pattern repeated 3+ times)
10
+ * 4. Tool loop (same file operated on 10+ times in 5 minutes)
11
+ * 5. Output flood (abnormally high output rate suggesting infinite loop)
12
+ *
13
+ * NOTE: Message intent detection (agent says "I'll send" but doesn't) was removed
14
+ * because pattern-based NLP detection is unreliable. A protocol-level approach
15
+ * (detecting stale outbox files) should be implemented in relay-pty instead.
16
+ *
17
+ * Emits 'stuck' event when detected, with reason and details.
18
+ */
19
+ import { EventEmitter } from 'node:events';
20
+ const DEFAULT_CONFIG = {
21
+ extendedIdleMs: 10 * 60 * 1000, // 10 minutes
22
+ loopThreshold: 3,
23
+ checkIntervalMs: 30 * 1000, // 30 seconds
24
+ minLoopLength: 20, // Minimum chars to consider a meaningful loop
25
+ errorPatterns: [
26
+ /error:/i,
27
+ /failed:/i,
28
+ /exception:/i,
29
+ /timeout/i,
30
+ /connection refused/i,
31
+ /permission denied/i,
32
+ /command not found/i,
33
+ /no such file/i,
34
+ ],
35
+ toolLoopThreshold: 10, // Same file operated on 10+ times = likely stuck
36
+ toolLoopWindowMs: 5 * 60 * 1000, // 5 minute window for tool loop detection
37
+ outputFloodLinesPerMinute: 5000, // 5000+ lines/min is abnormal
38
+ outputFloodMinDurationMs: 2 * 60 * 1000, // Wait 2 minutes before flood detection
39
+ };
40
+ /** Patterns to extract tool invocations from Claude Code output */
41
+ const TOOL_PATTERNS = [
42
+ // Claude Code tool patterns: ⏺ Write(path), ⏺ Read(path), etc.
43
+ /[⏺●]\s*(Read|Write|Edit|Glob|Grep|Bash)\(([^)]+)\)/g,
44
+ // Alternative patterns without symbols
45
+ /\b(Read|Write|Edit)\s*\(\s*([^)]+)\s*\)/g,
46
+ ];
47
+ export class StuckDetector extends EventEmitter {
48
+ config;
49
+ lastOutputTime = Date.now();
50
+ recentOutputs = [];
51
+ checkInterval = null;
52
+ isStuck = false;
53
+ stuckReason = null;
54
+ // Tool loop detection
55
+ toolInvocations = [];
56
+ // Output flood detection
57
+ outputLineCount = 0;
58
+ outputStartTime = Date.now();
59
+ constructor(config = {}) {
60
+ super();
61
+ this.config = { ...DEFAULT_CONFIG, ...config };
62
+ }
63
+ /**
64
+ * Start monitoring for stuck conditions.
65
+ * Call this after the agent process starts.
66
+ */
67
+ start() {
68
+ this.stop(); // Clear any existing interval
69
+ this.isStuck = false;
70
+ this.stuckReason = null;
71
+ this.lastOutputTime = Date.now();
72
+ this.recentOutputs = [];
73
+ this.toolInvocations = [];
74
+ this.outputLineCount = 0;
75
+ this.outputStartTime = Date.now();
76
+ this.checkInterval = setInterval(() => {
77
+ this.checkStuck();
78
+ }, this.config.checkIntervalMs);
79
+ }
80
+ /**
81
+ * Stop monitoring.
82
+ */
83
+ stop() {
84
+ if (this.checkInterval) {
85
+ clearInterval(this.checkInterval);
86
+ this.checkInterval = null;
87
+ }
88
+ }
89
+ /**
90
+ * Feed output to the detector.
91
+ * Call this for every output chunk from the agent.
92
+ */
93
+ onOutput(chunk) {
94
+ this.lastOutputTime = Date.now();
95
+ // Track output volume (count newlines)
96
+ const lineCount = (chunk.match(/\n/g) || []).length;
97
+ this.outputLineCount += lineCount;
98
+ // Extract and track tool invocations
99
+ this.extractToolInvocations(chunk);
100
+ // Normalize and store recent output
101
+ const normalized = this.normalizeOutput(chunk);
102
+ if (normalized.length >= this.config.minLoopLength) {
103
+ this.recentOutputs.push(normalized);
104
+ // Keep only recent outputs (5x threshold for pattern detection)
105
+ const maxOutputs = this.config.loopThreshold * 5;
106
+ if (this.recentOutputs.length > maxOutputs) {
107
+ this.recentOutputs = this.recentOutputs.slice(-maxOutputs);
108
+ }
109
+ }
110
+ // If we were stuck, check if we're unstuck now
111
+ if (this.isStuck) {
112
+ this.isStuck = false;
113
+ this.stuckReason = null;
114
+ this.emit('unstuck', { timestamp: Date.now() });
115
+ }
116
+ }
117
+ /**
118
+ * Extract tool invocations from output and track them.
119
+ */
120
+ extractToolInvocations(chunk) {
121
+ const now = Date.now();
122
+ // Strip ANSI codes for cleaner matching
123
+ // eslint-disable-next-line no-control-regex
124
+ const clean = chunk.replace(/\x1B(?:\[[0-9;?]*[A-Za-z]|\].*?(?:\x07|\x1B\\)|[@-Z\\-_])/g, '');
125
+ // Track what we've already matched in this chunk to prevent duplicates
126
+ const matchedInChunk = new Set();
127
+ for (const pattern of TOOL_PATTERNS) {
128
+ // Reset lastIndex for global regex
129
+ pattern.lastIndex = 0;
130
+ let match;
131
+ while ((match = pattern.exec(clean)) !== null) {
132
+ const tool = match[1];
133
+ const target = match[2].trim();
134
+ // Normalize file paths (remove ~ prefix, trailing whitespace)
135
+ const normalizedTarget = target
136
+ .replace(/^~\//, '')
137
+ .replace(/\s+$/, '');
138
+ // Deduplicate within this chunk (multiple patterns may match same invocation)
139
+ const key = `${tool}:${normalizedTarget}`;
140
+ if (matchedInChunk.has(key))
141
+ continue;
142
+ matchedInChunk.add(key);
143
+ this.toolInvocations.push({
144
+ tool,
145
+ target: normalizedTarget,
146
+ timestamp: now,
147
+ });
148
+ }
149
+ }
150
+ // Prune old invocations outside the window
151
+ const windowStart = now - this.config.toolLoopWindowMs;
152
+ this.toolInvocations = this.toolInvocations.filter(inv => inv.timestamp >= windowStart);
153
+ }
154
+ /**
155
+ * Normalize output for comparison (strip ANSI, trim, lowercase).
156
+ */
157
+ normalizeOutput(output) {
158
+ // Strip ANSI escape codes
159
+ // eslint-disable-next-line no-control-regex
160
+ let normalized = output.replace(/\x1B(?:\[[0-9;?]*[A-Za-z]|\].*?(?:\x07|\x1B\\)|[@-Z\\-_])/g, '');
161
+ // Normalize whitespace
162
+ normalized = normalized.replace(/\s+/g, ' ').trim().toLowerCase();
163
+ return normalized;
164
+ }
165
+ /**
166
+ * Check for stuck conditions.
167
+ */
168
+ checkStuck() {
169
+ // Don't re-emit if already stuck
170
+ if (this.isStuck)
171
+ return;
172
+ // Check 1: Extended idle
173
+ const idleDuration = Date.now() - this.lastOutputTime;
174
+ if (idleDuration >= this.config.extendedIdleMs) {
175
+ this.emitStuck({
176
+ reason: 'extended_idle',
177
+ details: `No output for ${Math.round(idleDuration / 60000)} minutes`,
178
+ timestamp: Date.now(),
179
+ idleDurationMs: idleDuration,
180
+ });
181
+ return;
182
+ }
183
+ // Check 2: Error loop
184
+ const errorLoop = this.detectErrorLoop();
185
+ if (errorLoop) {
186
+ this.emitStuck({
187
+ reason: 'error_loop',
188
+ details: `Same error repeated ${errorLoop.count} times`,
189
+ timestamp: Date.now(),
190
+ repeatedContent: errorLoop.error,
191
+ repetitions: errorLoop.count,
192
+ });
193
+ return;
194
+ }
195
+ // Check 3: Output loop
196
+ const outputLoop = this.detectOutputLoop();
197
+ if (outputLoop) {
198
+ this.emitStuck({
199
+ reason: 'output_loop',
200
+ details: `Same output repeated ${outputLoop.count} times`,
201
+ timestamp: Date.now(),
202
+ repeatedContent: outputLoop.output.substring(0, 100),
203
+ repetitions: outputLoop.count,
204
+ });
205
+ return;
206
+ }
207
+ // Check 4: Tool loop (same file operated on repeatedly)
208
+ const toolLoop = this.detectToolLoop();
209
+ if (toolLoop) {
210
+ this.emitStuck({
211
+ reason: 'tool_loop',
212
+ details: `${toolLoop.tool} called on "${toolLoop.target}" ${toolLoop.count} times in ${Math.round(this.config.toolLoopWindowMs / 60000)} minutes`,
213
+ timestamp: Date.now(),
214
+ targetFile: toolLoop.target,
215
+ toolName: toolLoop.tool,
216
+ repetitions: toolLoop.count,
217
+ });
218
+ return;
219
+ }
220
+ // Check 5: Output flood (abnormally high output rate)
221
+ const flood = this.detectOutputFlood();
222
+ if (flood) {
223
+ this.emitStuck({
224
+ reason: 'output_flood',
225
+ details: `Abnormally high output: ${flood.linesPerMinute.toFixed(0)} lines/min over ${Math.round(flood.durationMs / 60000)} minutes`,
226
+ timestamp: Date.now(),
227
+ linesPerMinute: flood.linesPerMinute,
228
+ });
229
+ return;
230
+ }
231
+ }
232
+ /**
233
+ * Detect repeated error messages.
234
+ */
235
+ detectErrorLoop() {
236
+ const errorOutputs = [];
237
+ for (const output of this.recentOutputs) {
238
+ for (const pattern of this.config.errorPatterns) {
239
+ if (pattern.test(output)) {
240
+ errorOutputs.push(output);
241
+ break;
242
+ }
243
+ }
244
+ }
245
+ if (errorOutputs.length < this.config.loopThreshold) {
246
+ return null;
247
+ }
248
+ // Check if the same error appears repeatedly
249
+ const errorCounts = new Map();
250
+ for (const error of errorOutputs) {
251
+ const count = (errorCounts.get(error) || 0) + 1;
252
+ errorCounts.set(error, count);
253
+ if (count >= this.config.loopThreshold) {
254
+ return { error, count };
255
+ }
256
+ }
257
+ return null;
258
+ }
259
+ /**
260
+ * Detect repeated output patterns (not necessarily errors).
261
+ */
262
+ detectOutputLoop() {
263
+ if (this.recentOutputs.length < this.config.loopThreshold) {
264
+ return null;
265
+ }
266
+ // Check for identical consecutive outputs
267
+ const outputCounts = new Map();
268
+ for (const output of this.recentOutputs) {
269
+ const count = (outputCounts.get(output) || 0) + 1;
270
+ outputCounts.set(output, count);
271
+ if (count >= this.config.loopThreshold) {
272
+ return { output, count };
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+ /**
278
+ * Detect when the same file is being operated on repeatedly.
279
+ * This catches cases like an agent repeatedly reading/writing the same file
280
+ * in a loop, even if the output content differs each time.
281
+ */
282
+ detectToolLoop() {
283
+ if (this.toolInvocations.length < this.config.toolLoopThreshold) {
284
+ return null;
285
+ }
286
+ // Count operations per file (combining all tool types)
287
+ const fileCounts = new Map();
288
+ for (const inv of this.toolInvocations) {
289
+ const existing = fileCounts.get(inv.target);
290
+ if (existing) {
291
+ existing.count++;
292
+ existing.tools.add(inv.tool);
293
+ }
294
+ else {
295
+ fileCounts.set(inv.target, { count: 1, tools: new Set([inv.tool]) });
296
+ }
297
+ }
298
+ // Find files that exceed the threshold
299
+ for (const [target, data] of Array.from(fileCounts.entries())) {
300
+ if (data.count >= this.config.toolLoopThreshold) {
301
+ // Report the most common tool used on this file
302
+ const toolCounts = new Map();
303
+ for (const inv of this.toolInvocations) {
304
+ if (inv.target === target) {
305
+ toolCounts.set(inv.tool, (toolCounts.get(inv.tool) || 0) + 1);
306
+ }
307
+ }
308
+ let maxTool = 'Unknown';
309
+ let maxCount = 0;
310
+ for (const [tool, toolCount] of Array.from(toolCounts.entries())) {
311
+ if (toolCount > maxCount) {
312
+ maxTool = tool;
313
+ maxCount = toolCount;
314
+ }
315
+ }
316
+ return { tool: maxTool, target, count: data.count };
317
+ }
318
+ }
319
+ return null;
320
+ }
321
+ /**
322
+ * Detect abnormally high output rates that suggest an infinite loop.
323
+ * Only triggers after minimum duration to avoid false positives during
324
+ * normal high-output operations (like builds or tests).
325
+ */
326
+ detectOutputFlood() {
327
+ const durationMs = Date.now() - this.outputStartTime;
328
+ // Don't check until minimum duration has passed
329
+ if (durationMs < this.config.outputFloodMinDurationMs) {
330
+ return null;
331
+ }
332
+ const durationMinutes = durationMs / 60000;
333
+ const linesPerMinute = this.outputLineCount / durationMinutes;
334
+ if (linesPerMinute >= this.config.outputFloodLinesPerMinute) {
335
+ return { linesPerMinute, durationMs };
336
+ }
337
+ return null;
338
+ }
339
+ /**
340
+ * Emit stuck event.
341
+ */
342
+ emitStuck(event) {
343
+ this.isStuck = true;
344
+ this.stuckReason = event.reason;
345
+ this.emit('stuck', event);
346
+ }
347
+ /**
348
+ * Check if currently detected as stuck.
349
+ */
350
+ getIsStuck() {
351
+ return this.isStuck;
352
+ }
353
+ /**
354
+ * Get the reason for being stuck (if stuck).
355
+ */
356
+ getStuckReason() {
357
+ return this.stuckReason;
358
+ }
359
+ /**
360
+ * Get time since last output in milliseconds.
361
+ */
362
+ getIdleDuration() {
363
+ return Date.now() - this.lastOutputTime;
364
+ }
365
+ /**
366
+ * Reset state.
367
+ */
368
+ reset() {
369
+ this.isStuck = false;
370
+ this.stuckReason = null;
371
+ this.lastOutputTime = Date.now();
372
+ this.recentOutputs = [];
373
+ this.toolInvocations = [];
374
+ this.outputLineCount = 0;
375
+ this.outputStartTime = Date.now();
376
+ }
377
+ /**
378
+ * Get current output statistics (useful for debugging).
379
+ */
380
+ getOutputStats() {
381
+ const durationMs = Date.now() - this.outputStartTime;
382
+ const durationMinutes = Math.max(durationMs / 60000, 0.001); // Avoid division by zero
383
+ return {
384
+ lineCount: this.outputLineCount,
385
+ durationMs,
386
+ linesPerMinute: this.outputLineCount / durationMinutes,
387
+ };
388
+ }
389
+ /**
390
+ * Get recent tool invocations (useful for debugging).
391
+ */
392
+ getToolInvocations() {
393
+ return [...this.toolInvocations];
394
+ }
395
+ }
396
+ /**
397
+ * Create a stuck detector with default configuration.
398
+ */
399
+ export function createStuckDetector(config = {}) {
400
+ return new StuckDetector(config);
401
+ }
402
+ //# sourceMappingURL=stuck-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stuck-detector.js","sourceRoot":"","sources":["../src/stuck-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Tmux Binary Resolver
3
+ *
4
+ * Locates tmux binary with fallback to bundled version.
5
+ * Priority:
6
+ * 1. System tmux (in PATH)
7
+ * 2. Bundled tmux within the agent-relay package (bin/tmux)
8
+ */
9
+ /** Path where bundled tmux binary is installed (within the package) */
10
+ export declare function getBundledTmuxDir(): string;
11
+ export declare function getBundledTmuxPath(): string;
12
+ export declare const BUNDLED_TMUX_DIR: string;
13
+ export declare const BUNDLED_TMUX_PATH: string;
14
+ /** Minimum supported tmux version */
15
+ export declare const MIN_TMUX_VERSION = "3.0";
16
+ export interface TmuxInfo {
17
+ /** Full path to tmux binary */
18
+ path: string;
19
+ /** Version string (e.g., "3.6a") */
20
+ version: string;
21
+ /** Whether this is the bundled version */
22
+ isBundled: boolean;
23
+ }
24
+ /**
25
+ * Resolve tmux binary path with fallback to bundled version.
26
+ * Returns null if tmux is not available.
27
+ */
28
+ export declare function resolveTmux(): TmuxInfo | null;
29
+ /**
30
+ * Get the tmux command to use. Throws if tmux is not available.
31
+ */
32
+ export declare function getTmuxPath(): string;
33
+ /**
34
+ * Check if tmux is available (either system or bundled)
35
+ */
36
+ export declare function isTmuxAvailable(): boolean;
37
+ /**
38
+ * Get platform identifier for downloading binaries
39
+ */
40
+ export declare function getPlatformIdentifier(): string | null;
41
+ /**
42
+ * Error thrown when tmux is not available
43
+ */
44
+ export declare class TmuxNotFoundError extends Error {
45
+ constructor();
46
+ }
47
+ /**
48
+ * Check if installed tmux version meets minimum requirements
49
+ */
50
+ export declare function checkTmuxVersion(): {
51
+ ok: boolean;
52
+ version: string | null;
53
+ minimum: string;
54
+ };
55
+ //# sourceMappingURL=tmux-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-resolver.d.ts","sourceRoot":"","sources":["../src/tmux-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAoBH,uEAAuE;AACvE,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAGD,eAAO,MAAM,gBAAgB,QAAsB,CAAC;AACpD,eAAO,MAAM,iBAAiB,QAAuB,CAAC;AAEtD,qCAAqC;AACrC,eAAO,MAAM,gBAAgB,QAAQ,CAAC;AAEtC,MAAM,WAAW,QAAQ;IACvB,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,SAAS,EAAE,OAAO,CAAC;CACpB;AAkCD;;;GAGG;AACH,wBAAgB,WAAW,IAAI,QAAQ,GAAG,IAAI,CA4B7C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAMpC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAYrD;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;;CAoB3C;AAaD;;GAEG;AACH,wBAAgB,gBAAgB,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAc3F"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Tmux Binary Resolver
3
+ *
4
+ * Locates tmux binary with fallback to bundled version.
5
+ * Priority:
6
+ * 1. System tmux (in PATH)
7
+ * 2. Bundled tmux within the agent-relay package (bin/tmux)
8
+ */
9
+ import { execSync } from 'node:child_process';
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ import os from 'node:os';
13
+ import { fileURLToPath } from 'node:url';
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+ /**
17
+ * Get the package root directory (where agent-relay is installed)
18
+ * This works whether we're in dist/utils/ or src/utils/
19
+ */
20
+ function getPackageRoot() {
21
+ // Navigate up from dist/utils or src/utils to package root
22
+ return path.resolve(__dirname, '..', '..');
23
+ }
24
+ /** Path where bundled tmux binary is installed (within the package) */
25
+ export function getBundledTmuxDir() {
26
+ return path.join(getPackageRoot(), 'bin');
27
+ }
28
+ export function getBundledTmuxPath() {
29
+ return path.join(getBundledTmuxDir(), 'tmux');
30
+ }
31
+ // Legacy exports for backwards compatibility
32
+ export const BUNDLED_TMUX_DIR = getBundledTmuxDir();
33
+ export const BUNDLED_TMUX_PATH = getBundledTmuxPath();
34
+ /** Minimum supported tmux version */
35
+ export const MIN_TMUX_VERSION = '3.0';
36
+ /**
37
+ * Check if tmux exists at a given path and get its version
38
+ */
39
+ function getTmuxVersion(tmuxPath) {
40
+ try {
41
+ const output = execSync(`"${tmuxPath}" -V`, {
42
+ encoding: 'utf-8',
43
+ stdio: ['pipe', 'pipe', 'pipe'],
44
+ });
45
+ // Output format: "tmux 3.6a" or similar
46
+ const match = output.trim().match(/tmux\s+(\d+\.\d+\w?)/i);
47
+ return match ? match[1] : null;
48
+ }
49
+ catch {
50
+ return null;
51
+ }
52
+ }
53
+ /**
54
+ * Find tmux in system PATH
55
+ */
56
+ function findSystemTmux() {
57
+ try {
58
+ const output = execSync('which tmux', {
59
+ encoding: 'utf-8',
60
+ stdio: ['pipe', 'pipe', 'pipe'],
61
+ });
62
+ return output.trim() || null;
63
+ }
64
+ catch {
65
+ return null;
66
+ }
67
+ }
68
+ /**
69
+ * Resolve tmux binary path with fallback to bundled version.
70
+ * Returns null if tmux is not available.
71
+ */
72
+ export function resolveTmux() {
73
+ // 1. Check system tmux first
74
+ const systemPath = findSystemTmux();
75
+ if (systemPath) {
76
+ const version = getTmuxVersion(systemPath);
77
+ if (version) {
78
+ return {
79
+ path: systemPath,
80
+ version,
81
+ isBundled: false,
82
+ };
83
+ }
84
+ }
85
+ // 2. Check bundled tmux (within the package)
86
+ const bundledPath = getBundledTmuxPath();
87
+ if (fs.existsSync(bundledPath)) {
88
+ const version = getTmuxVersion(bundledPath);
89
+ if (version) {
90
+ return {
91
+ path: bundledPath,
92
+ version,
93
+ isBundled: true,
94
+ };
95
+ }
96
+ }
97
+ return null;
98
+ }
99
+ /**
100
+ * Get the tmux command to use. Throws if tmux is not available.
101
+ */
102
+ export function getTmuxPath() {
103
+ const info = resolveTmux();
104
+ if (!info) {
105
+ throw new TmuxNotFoundError();
106
+ }
107
+ return info.path;
108
+ }
109
+ /**
110
+ * Check if tmux is available (either system or bundled)
111
+ */
112
+ export function isTmuxAvailable() {
113
+ return resolveTmux() !== null;
114
+ }
115
+ /**
116
+ * Get platform identifier for downloading binaries
117
+ */
118
+ export function getPlatformIdentifier() {
119
+ const platform = os.platform();
120
+ const arch = os.arch();
121
+ if (platform === 'darwin') {
122
+ return arch === 'arm64' ? 'macos-arm64' : 'macos-x86_64';
123
+ }
124
+ else if (platform === 'linux') {
125
+ return arch === 'arm64' ? 'linux-arm64' : 'linux-x86_64';
126
+ }
127
+ // Unsupported platform
128
+ return null;
129
+ }
130
+ /**
131
+ * Error thrown when tmux is not available
132
+ */
133
+ export class TmuxNotFoundError extends Error {
134
+ constructor() {
135
+ const platformInstructions = (() => {
136
+ switch (os.platform()) {
137
+ case 'darwin':
138
+ return ' macOS: brew install tmux';
139
+ case 'linux':
140
+ return ' Ubuntu/Debian: sudo apt install tmux\n Fedora: sudo dnf install tmux\n Arch: sudo pacman -S tmux';
141
+ case 'win32':
142
+ return ' Windows: tmux requires WSL (Windows Subsystem for Linux)\n Install WSL, then: sudo apt install tmux';
143
+ default:
144
+ return ' See: https://github.com/tmux/tmux/wiki/Installing';
145
+ }
146
+ })();
147
+ super(`tmux is required but not found.\n\nInstall tmux:\n${platformInstructions}\n\nThen reinstall agent-relay: npm install agent-relay`);
148
+ this.name = 'TmuxNotFoundError';
149
+ }
150
+ }
151
+ /**
152
+ * Parse version string to compare versions
153
+ */
154
+ function parseVersion(version) {
155
+ const match = version.match(/(\d+)\.(\d+)/);
156
+ if (!match) {
157
+ return { major: 0, minor: 0 };
158
+ }
159
+ return { major: parseInt(match[1], 10), minor: parseInt(match[2], 10) };
160
+ }
161
+ /**
162
+ * Check if installed tmux version meets minimum requirements
163
+ */
164
+ export function checkTmuxVersion() {
165
+ const info = resolveTmux();
166
+ if (!info) {
167
+ return { ok: false, version: null, minimum: MIN_TMUX_VERSION };
168
+ }
169
+ const installed = parseVersion(info.version);
170
+ const required = parseVersion(MIN_TMUX_VERSION);
171
+ const ok = installed.major > required.major ||
172
+ (installed.major === required.major && installed.minor >= required.minor);
173
+ return { ok, version: info.version, minimum: MIN_TMUX_VERSION };
174
+ }
175
+ //# sourceMappingURL=tmux-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tmux-resolver.js","sourceRoot":"","sources":["../src/tmux-resolver.ts"],"names":[],"mappings":"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"}