agent-relay 2.0.15 → 2.0.16

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 (92) hide show
  1. package/dist/dashboard/out/404.html +1 -1
  2. package/dist/dashboard/out/app/onboarding.html +1 -1
  3. package/dist/dashboard/out/app/onboarding.txt +1 -1
  4. package/dist/dashboard/out/app.html +1 -1
  5. package/dist/dashboard/out/app.txt +1 -1
  6. package/dist/dashboard/out/cloud/link.html +1 -1
  7. package/dist/dashboard/out/cloud/link.txt +1 -1
  8. package/dist/dashboard/out/connect-repos.html +1 -1
  9. package/dist/dashboard/out/connect-repos.txt +1 -1
  10. package/dist/dashboard/out/history.html +1 -1
  11. package/dist/dashboard/out/history.txt +1 -1
  12. package/dist/dashboard/out/index.html +1 -1
  13. package/dist/dashboard/out/index.txt +1 -1
  14. package/dist/dashboard/out/login.html +1 -1
  15. package/dist/dashboard/out/login.txt +1 -1
  16. package/dist/dashboard/out/metrics.html +1 -1
  17. package/dist/dashboard/out/metrics.txt +1 -1
  18. package/dist/dashboard/out/pricing.html +1 -1
  19. package/dist/dashboard/out/pricing.txt +1 -1
  20. package/dist/dashboard/out/providers/setup/claude.html +1 -1
  21. package/dist/dashboard/out/providers/setup/claude.txt +1 -1
  22. package/dist/dashboard/out/providers/setup/codex.html +1 -1
  23. package/dist/dashboard/out/providers/setup/codex.txt +1 -1
  24. package/dist/dashboard/out/providers/setup/cursor.html +1 -1
  25. package/dist/dashboard/out/providers/setup/cursor.txt +1 -1
  26. package/dist/dashboard/out/providers.html +1 -1
  27. package/dist/dashboard/out/providers.txt +1 -1
  28. package/dist/dashboard/out/signup.html +1 -1
  29. package/dist/dashboard/out/signup.txt +1 -1
  30. package/package.json +16 -16
  31. package/packages/api-types/package.json +1 -1
  32. package/packages/bridge/package.json +8 -8
  33. package/packages/cloud/package.json +6 -6
  34. package/packages/config/package.json +2 -2
  35. package/packages/continuity/package.json +1 -1
  36. package/packages/daemon/package.json +12 -12
  37. package/packages/dashboard/package.json +13 -13
  38. package/packages/dashboard/ui-dist/404.html +1 -1
  39. package/packages/dashboard/ui-dist/app/onboarding.html +1 -1
  40. package/packages/dashboard/ui-dist/app/onboarding.txt +1 -1
  41. package/packages/dashboard/ui-dist/app.html +1 -1
  42. package/packages/dashboard/ui-dist/app.txt +1 -1
  43. package/packages/dashboard/ui-dist/cloud/link.html +1 -1
  44. package/packages/dashboard/ui-dist/cloud/link.txt +1 -1
  45. package/packages/dashboard/ui-dist/connect-repos.html +1 -1
  46. package/packages/dashboard/ui-dist/connect-repos.txt +1 -1
  47. package/packages/dashboard/ui-dist/history.html +1 -1
  48. package/packages/dashboard/ui-dist/history.txt +1 -1
  49. package/packages/dashboard/ui-dist/index.html +1 -1
  50. package/packages/dashboard/ui-dist/index.txt +1 -1
  51. package/packages/dashboard/ui-dist/login.html +1 -1
  52. package/packages/dashboard/ui-dist/login.txt +1 -1
  53. package/packages/dashboard/ui-dist/metrics.html +1 -1
  54. package/packages/dashboard/ui-dist/metrics.txt +1 -1
  55. package/packages/dashboard/ui-dist/pricing.html +1 -1
  56. package/packages/dashboard/ui-dist/pricing.txt +1 -1
  57. package/packages/dashboard/ui-dist/providers/setup/claude.html +1 -1
  58. package/packages/dashboard/ui-dist/providers/setup/claude.txt +1 -1
  59. package/packages/dashboard/ui-dist/providers/setup/codex.html +1 -1
  60. package/packages/dashboard/ui-dist/providers/setup/codex.txt +1 -1
  61. package/packages/dashboard/ui-dist/providers/setup/cursor.html +1 -1
  62. package/packages/dashboard/ui-dist/providers/setup/cursor.txt +1 -1
  63. package/packages/dashboard/ui-dist/providers.html +1 -1
  64. package/packages/dashboard/ui-dist/providers.txt +1 -1
  65. package/packages/dashboard/ui-dist/signup.html +1 -1
  66. package/packages/dashboard/ui-dist/signup.txt +1 -1
  67. package/packages/dashboard-server/package.json +12 -12
  68. package/packages/hooks/package.json +4 -4
  69. package/packages/mcp/package.json +2 -2
  70. package/packages/memory/package.json +2 -2
  71. package/packages/policy/package.json +2 -2
  72. package/packages/protocol/package.json +1 -1
  73. package/packages/resiliency/package.json +1 -1
  74. package/packages/sdk/package.json +2 -2
  75. package/packages/spawner/package.json +1 -1
  76. package/packages/state/package.json +1 -1
  77. package/packages/storage/package.json +2 -2
  78. package/packages/telemetry/package.json +1 -1
  79. package/packages/trajectory/package.json +2 -2
  80. package/packages/user-directory/package.json +2 -2
  81. package/packages/utils/package.json +1 -1
  82. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +0 -10
  83. package/packages/wrapper/dist/relay-pty-orchestrator.js +20 -219
  84. package/packages/wrapper/package.json +6 -6
  85. /package/dist/dashboard/out/_next/static/{bq6ZiKOzerlXFO47thgmf → itBGQ1M8yMA_hC42DKCqv}/_buildManifest.js +0 -0
  86. /package/dist/dashboard/out/_next/static/{bq6ZiKOzerlXFO47thgmf → itBGQ1M8yMA_hC42DKCqv}/_ssgManifest.js +0 -0
  87. /package/packages/dashboard/ui-dist/_next/static/{QTQdtgzP39wQJMKOsufyD → ML6Zby1B5OtZvl0Pa1zSZ}/_buildManifest.js +0 -0
  88. /package/packages/dashboard/ui-dist/_next/static/{QTQdtgzP39wQJMKOsufyD → ML6Zby1B5OtZvl0Pa1zSZ}/_ssgManifest.js +0 -0
  89. /package/packages/dashboard/ui-dist/_next/static/{bq6ZiKOzerlXFO47thgmf → Ni5Di0TB0PDcrvEYBFRKd}/_buildManifest.js +0 -0
  90. /package/packages/dashboard/ui-dist/_next/static/{bq6ZiKOzerlXFO47thgmf → Ni5Di0TB0PDcrvEYBFRKd}/_ssgManifest.js +0 -0
  91. /package/packages/dashboard/ui-dist/_next/static/{cVzRYB5TNHLQXh3CNCQ5b → itBGQ1M8yMA_hC42DKCqv}/_buildManifest.js +0 -0
  92. /package/packages/dashboard/ui-dist/_next/static/{cVzRYB5TNHLQXh3CNCQ5b → itBGQ1M8yMA_hC42DKCqv}/_ssgManifest.js +0 -0
@@ -93,7 +93,6 @@ export declare class RelayPtyOrchestrator extends BaseWrapper {
93
93
  private lastParsedLength;
94
94
  private isInteractive;
95
95
  private pendingInjections;
96
- private pendingSendEnter;
97
96
  private backpressureActive;
98
97
  private readyForMessages;
99
98
  private throttle;
@@ -236,15 +235,6 @@ export declare class RelayPtyOrchestrator extends BaseWrapper {
236
235
  * If verification fails, retries up to MAX_RETRIES times.
237
236
  */
238
237
  private handleInjectResult;
239
- /**
240
- * Handle SendEnter result (stuck input recovery)
241
- * Called when relay-pty responds to a SendEnter request
242
- */
243
- private handleSendEnterResult;
244
- /**
245
- * Do a full retry with message content (used when SendEnter fails or for subsequent retries)
246
- */
247
- private doFullRetry;
248
238
  /**
249
239
  * Handle backpressure notification
250
240
  */
@@ -28,7 +28,7 @@ const __dirname = dirname(__filename);
28
28
  import { BaseWrapper } from './base-wrapper.js';
29
29
  import { parseSummaryWithDetails, parseSessionEndFromOutput } from './parser.js';
30
30
  import { findRelayPtyBinary as findRelayPtyBinaryUtil } from '@agent-relay/utils/relay-pty-path';
31
- import { stripAnsi, sleep, buildInjectionString, verifyInjection, INJECTION_CONSTANTS, AdaptiveThrottle, } from './shared.js';
31
+ import { stripAnsi, sleep, buildInjectionString, AdaptiveThrottle, } from './shared.js';
32
32
  import { getMemoryMonitor, formatBytes, getCgroupManager, } from '@agent-relay/resiliency';
33
33
  // ============================================================================
34
34
  // Types for relay-pty socket protocol
@@ -63,8 +63,6 @@ export class RelayPtyOrchestrator extends BaseWrapper {
63
63
  isInteractive = false;
64
64
  // Injection state
65
65
  pendingInjections = new Map();
66
- // Pending SendEnter requests (for stuck input recovery)
67
- pendingSendEnter = new Map();
68
66
  backpressureActive = false;
69
67
  readyForMessages = false;
70
68
  // Adaptive throttle for message queue - adjusts delay based on success/failure
@@ -1119,10 +1117,8 @@ export class RelayPtyOrchestrator extends BaseWrapper {
1119
1117
  this.log(` Shutdown acknowledged`);
1120
1118
  break;
1121
1119
  case 'send_enter_result':
1122
- // Handle SendEnter result (stuck input recovery)
1123
- this.handleSendEnterResult(response).catch((err) => {
1124
- this.logError(` Error handling send_enter result: ${err.message}`);
1125
- });
1120
+ // SendEnter is no longer used - trust Rust delivery confirmation
1121
+ this.log(` Received send_enter_result (deprecated)`);
1126
1122
  break;
1127
1123
  }
1128
1124
  }
@@ -1145,150 +1141,26 @@ export class RelayPtyOrchestrator extends BaseWrapper {
1145
1141
  }
1146
1142
  if (response.status === 'delivered') {
1147
1143
  // Rust says it sent the message + Enter key
1148
- // Now verify the message actually appeared in the terminal output
1149
- this.log(` Message ${pending.shortId} marked delivered by Rust, verifying in output...`);
1150
- // In interactive mode, we can't verify because stdout goes directly to terminal
1151
- // Trust Rust's "delivered" status in this case
1152
- if (this.isInteractive) {
1153
- this.log(` Interactive mode - trusting Rust delivery status`);
1154
- clearTimeout(pending.timeout);
1155
- this.pendingInjections.delete(response.id);
1156
- if (pending.retryCount === 0) {
1157
- this.injectionMetrics.successFirstTry++;
1158
- }
1159
- else {
1160
- this.injectionMetrics.successWithRetry++;
1161
- }
1162
- this.injectionMetrics.total++;
1163
- pending.resolve(true);
1164
- this.log(` Message ${pending.shortId} delivered (interactive mode) ✓`);
1165
- return;
1166
- }
1167
- // Skip verification if queue is backing up - trust Rust's delivery status
1168
- // relay-pty writes directly to PTY which is more reliable than tmux
1169
- const queueBackingUp = this.messageQueue.length >= 2;
1170
- if (queueBackingUp) {
1171
- this.log(` Queue backing up (${this.messageQueue.length} pending), skipping verification for ${pending.shortId}`);
1172
- clearTimeout(pending.timeout);
1173
- this.pendingInjections.delete(response.id);
1174
- if (pending.retryCount === 0) {
1175
- this.injectionMetrics.successFirstTry++;
1176
- }
1177
- else {
1178
- this.injectionMetrics.successWithRetry++;
1179
- }
1180
- this.injectionMetrics.total++;
1181
- pending.resolve(true);
1182
- return;
1183
- }
1184
- // Give a brief moment for output to be captured
1185
- await sleep(100);
1186
- // Verify the message pattern appears in captured output
1187
- const verified = await verifyInjection(pending.shortId, pending.from, async () => this.getCleanOutput());
1188
- if (verified) {
1189
- clearTimeout(pending.timeout);
1190
- this.pendingInjections.delete(response.id);
1191
- // Update metrics based on retry count (0 = first try)
1192
- if (pending.retryCount === 0) {
1193
- this.injectionMetrics.successFirstTry++;
1194
- }
1195
- else {
1196
- this.injectionMetrics.successWithRetry++;
1197
- this.log(` Message ${pending.shortId} succeeded on attempt ${pending.retryCount + 1}`);
1198
- }
1199
- this.injectionMetrics.total++;
1200
- pending.resolve(true);
1201
- this.log(` Message ${pending.shortId} verified in output ✓`);
1144
+ // Trust Rust's delivery confirmation - relay-pty writes directly to PTY which is very reliable.
1145
+ //
1146
+ // IMPORTANT: We don't verify by looking for the message in output because:
1147
+ // 1. TUI CLIs (Claude, Codex, Gemini) don't echo input like traditional terminals
1148
+ // 2. The injected text appears as INPUT to the PTY, not OUTPUT
1149
+ // 3. Output-based verification always fails for TUIs, causing unnecessary retries
1150
+ //
1151
+ // This is different from tmux-wrapper where we inject via tmux send-keys
1152
+ // and can observe the echoed input in the pane output.
1153
+ this.log(` Message ${pending.shortId} delivered by Rust ✓`);
1154
+ clearTimeout(pending.timeout);
1155
+ this.pendingInjections.delete(response.id);
1156
+ if (pending.retryCount === 0) {
1157
+ this.injectionMetrics.successFirstTry++;
1202
1158
  }
1203
1159
  else {
1204
- // Message was "delivered" but not found in output
1205
- // This is the bug case - Enter key may not have been processed
1206
- this.log(` Message ${pending.shortId} NOT found in output after delivery`);
1207
- // Check if we should retry
1208
- if (pending.retryCount < INJECTION_CONSTANTS.MAX_RETRIES - 1) {
1209
- clearTimeout(pending.timeout);
1210
- this.pendingInjections.delete(response.id);
1211
- // Wait before retry with backoff
1212
- await sleep(INJECTION_CONSTANTS.RETRY_BACKOFF_MS * (pending.retryCount + 1));
1213
- // IMPORTANT: Check again if message appeared (late verification / race condition fix)
1214
- // The previous injection may have succeeded but verification timed out
1215
- const lateVerified = await verifyInjection(pending.shortId, pending.from, async () => this.getCleanOutput());
1216
- if (lateVerified) {
1217
- this.log(` Message ${pending.shortId} found on late verification, skipping retry`);
1218
- if (pending.retryCount === 0) {
1219
- this.injectionMetrics.successFirstTry++;
1220
- }
1221
- else {
1222
- this.injectionMetrics.successWithRetry++;
1223
- }
1224
- this.injectionMetrics.total++;
1225
- pending.resolve(true);
1226
- return;
1227
- }
1228
- // On first retry attempt (retryCount === 0), try SendEnter first
1229
- // This handles the case where message content was written but Enter wasn't processed
1230
- if (pending.retryCount === 0) {
1231
- this.log(` Trying SendEnter first for ${pending.shortId} (stuck input recovery)`);
1232
- // Send just the Enter key
1233
- const sendEnterRequest = {
1234
- type: 'send_enter',
1235
- id: response.id,
1236
- };
1237
- // Track this SendEnter request for verification
1238
- const sendEnterTimeout = setTimeout(() => {
1239
- this.logError(` SendEnter timeout for ${pending.shortId}`);
1240
- this.pendingSendEnter.delete(response.id);
1241
- // Fall back to full retry after SendEnter timeout
1242
- this.doFullRetry(response.id, pending);
1243
- }, 5000); // 5 second timeout for SendEnter
1244
- this.pendingSendEnter.set(response.id, {
1245
- resolve: (verified) => {
1246
- if (verified) {
1247
- // SendEnter worked!
1248
- this.injectionMetrics.successWithRetry++;
1249
- this.injectionMetrics.total++;
1250
- pending.resolve(true);
1251
- }
1252
- else {
1253
- // SendEnter didn't work, do full retry
1254
- this.doFullRetry(response.id, pending);
1255
- }
1256
- },
1257
- timeout: sendEnterTimeout,
1258
- from: pending.from,
1259
- shortId: pending.shortId,
1260
- retryCount: pending.retryCount,
1261
- originalBody: pending.originalBody,
1262
- originalResolve: pending.resolve,
1263
- });
1264
- this.sendSocketRequest(sendEnterRequest).catch((err) => {
1265
- this.logError(` SendEnter request failed: ${err.message}`);
1266
- clearTimeout(sendEnterTimeout);
1267
- this.pendingSendEnter.delete(response.id);
1268
- // Fall back to full retry
1269
- this.doFullRetry(response.id, pending);
1270
- });
1271
- }
1272
- else {
1273
- // On subsequent retries (retryCount > 0), do full retry directly
1274
- this.doFullRetry(response.id, pending);
1275
- }
1276
- }
1277
- else {
1278
- // Max retries exceeded
1279
- this.logError(` Message ${pending.shortId} failed after ${INJECTION_CONSTANTS.MAX_RETRIES} attempts - NOT found in output`);
1280
- clearTimeout(pending.timeout);
1281
- this.pendingInjections.delete(response.id);
1282
- this.injectionMetrics.failed++;
1283
- this.injectionMetrics.total++;
1284
- pending.resolve(false);
1285
- this.emit('injection-failed', {
1286
- messageId: response.id,
1287
- from: pending.from,
1288
- error: 'Message delivered but not verified in output after max retries',
1289
- });
1290
- }
1160
+ this.injectionMetrics.successWithRetry++;
1291
1161
  }
1162
+ this.injectionMetrics.total++;
1163
+ pending.resolve(true);
1292
1164
  }
1293
1165
  else if (response.status === 'failed') {
1294
1166
  clearTimeout(pending.timeout);
@@ -1305,77 +1177,6 @@ export class RelayPtyOrchestrator extends BaseWrapper {
1305
1177
  }
1306
1178
  // queued/injecting are intermediate states - wait for final status
1307
1179
  }
1308
- /**
1309
- * Handle SendEnter result (stuck input recovery)
1310
- * Called when relay-pty responds to a SendEnter request
1311
- */
1312
- async handleSendEnterResult(response) {
1313
- this.log(` handleSendEnterResult: id=${response.id.substring(0, 8)} success=${response.success}`);
1314
- const pendingEnter = this.pendingSendEnter.get(response.id);
1315
- if (!pendingEnter) {
1316
- this.log(` No pending SendEnter found for ${response.id.substring(0, 8)}`);
1317
- return;
1318
- }
1319
- clearTimeout(pendingEnter.timeout);
1320
- this.pendingSendEnter.delete(response.id);
1321
- if (!response.success) {
1322
- this.log(` SendEnter failed for ${pendingEnter.shortId}, will try full retry`);
1323
- pendingEnter.resolve(false);
1324
- return;
1325
- }
1326
- // SendEnter succeeded - wait and verify
1327
- this.log(` SendEnter sent for ${pendingEnter.shortId}, waiting to verify...`);
1328
- await sleep(150); // Give time for Enter to be processed
1329
- // Verify the message appeared in output
1330
- const verified = await verifyInjection(pendingEnter.shortId, pendingEnter.from, async () => this.getCleanOutput());
1331
- if (verified) {
1332
- this.log(` Message ${pendingEnter.shortId} verified after SendEnter ✓`);
1333
- pendingEnter.resolve(true);
1334
- }
1335
- else {
1336
- this.log(` Message ${pendingEnter.shortId} still not verified after SendEnter, will try full retry`);
1337
- pendingEnter.resolve(false);
1338
- }
1339
- }
1340
- /**
1341
- * Do a full retry with message content (used when SendEnter fails or for subsequent retries)
1342
- */
1343
- doFullRetry(messageId, pending) {
1344
- this.log(` Doing full retry for ${pending.shortId} (attempt ${pending.retryCount + 2}/${INJECTION_CONSTANTS.MAX_RETRIES})`);
1345
- // Re-inject by sending another socket request
1346
- // Prepend [RETRY] to help agent notice this is a retry
1347
- const retryBody = pending.originalBody.startsWith('[RETRY]')
1348
- ? pending.originalBody
1349
- : `[RETRY] ${pending.originalBody}`;
1350
- const retryRequest = {
1351
- type: 'inject',
1352
- id: messageId,
1353
- from: pending.from,
1354
- body: retryBody,
1355
- priority: 1, // Higher priority for retries
1356
- };
1357
- // Create new pending entry with incremented retry count
1358
- const newTimeout = setTimeout(() => {
1359
- this.logError(` Retry timeout for ${pending.shortId}`);
1360
- this.pendingInjections.delete(messageId);
1361
- pending.resolve(false);
1362
- }, 30000);
1363
- this.pendingInjections.set(messageId, {
1364
- resolve: pending.resolve,
1365
- reject: pending.reject,
1366
- timeout: newTimeout,
1367
- from: pending.from,
1368
- shortId: pending.shortId,
1369
- retryCount: pending.retryCount + 1,
1370
- originalBody: retryBody,
1371
- });
1372
- this.sendSocketRequest(retryRequest).catch((err) => {
1373
- this.logError(` Full retry request failed: ${err.message}`);
1374
- clearTimeout(newTimeout);
1375
- this.pendingInjections.delete(messageId);
1376
- pending.resolve(false);
1377
- });
1378
- }
1379
1180
  /**
1380
1181
  * Handle backpressure notification
1381
1182
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/wrapper",
3
- "version": "2.0.15",
3
+ "version": "2.0.16",
4
4
  "description": "CLI agent wrappers for Agent Relay - tmux, pty integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,11 +30,11 @@
30
30
  "clean": "rm -rf dist"
31
31
  },
32
32
  "dependencies": {
33
- "@agent-relay/api-types": "2.0.15",
34
- "@agent-relay/protocol": "2.0.15",
35
- "@agent-relay/config": "2.0.15",
36
- "@agent-relay/continuity": "2.0.15",
37
- "@agent-relay/resiliency": "2.0.15"
33
+ "@agent-relay/api-types": "2.0.16",
34
+ "@agent-relay/protocol": "2.0.16",
35
+ "@agent-relay/config": "2.0.16",
36
+ "@agent-relay/continuity": "2.0.16",
37
+ "@agent-relay/resiliency": "2.0.16"
38
38
  },
39
39
  "devDependencies": {
40
40
  "typescript": "^5.9.3",