agent-relay 2.1.4 → 2.1.5

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 (39) hide show
  1. package/dist/index.cjs +206 -12
  2. package/package.json +19 -19
  3. package/packages/api-types/package.json +1 -1
  4. package/packages/benchmark/package.json +4 -4
  5. package/packages/bridge/dist/spawner.d.ts.map +1 -1
  6. package/packages/bridge/dist/spawner.js +39 -5
  7. package/packages/bridge/dist/spawner.js.map +1 -1
  8. package/packages/bridge/package.json +8 -8
  9. package/packages/bridge/src/spawner.ts +40 -5
  10. package/packages/cli-tester/package.json +1 -1
  11. package/packages/config/package.json +2 -2
  12. package/packages/continuity/package.json +2 -2
  13. package/packages/daemon/package.json +12 -12
  14. package/packages/hooks/package.json +4 -4
  15. package/packages/mcp/package.json +3 -3
  16. package/packages/memory/package.json +2 -2
  17. package/packages/policy/package.json +2 -2
  18. package/packages/protocol/package.json +1 -1
  19. package/packages/resiliency/package.json +1 -1
  20. package/packages/sdk/package.json +2 -2
  21. package/packages/spawner/package.json +1 -1
  22. package/packages/state/package.json +1 -1
  23. package/packages/storage/package.json +2 -2
  24. package/packages/telemetry/package.json +1 -1
  25. package/packages/trajectory/package.json +2 -2
  26. package/packages/user-directory/package.json +2 -2
  27. package/packages/utils/package.json +2 -2
  28. package/packages/wrapper/dist/opencode-wrapper.d.ts +6 -2
  29. package/packages/wrapper/dist/opencode-wrapper.d.ts.map +1 -1
  30. package/packages/wrapper/dist/opencode-wrapper.js +34 -10
  31. package/packages/wrapper/dist/opencode-wrapper.js.map +1 -1
  32. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +22 -2
  33. package/packages/wrapper/dist/relay-pty-orchestrator.d.ts.map +1 -1
  34. package/packages/wrapper/dist/relay-pty-orchestrator.js +174 -4
  35. package/packages/wrapper/dist/relay-pty-orchestrator.js.map +1 -1
  36. package/packages/wrapper/package.json +6 -6
  37. package/packages/wrapper/src/opencode-wrapper.ts +37 -9
  38. package/packages/wrapper/src/relay-pty-orchestrator.ts +197 -4
  39. package/relay-snippets/agent-relay-snippet.md +17 -5
package/dist/index.cjs CHANGED
@@ -46309,6 +46309,54 @@ var __filename2 = (0, import_node_url2.fileURLToPath)(import_meta_url);
46309
46309
  var __dirname2 = (0, import_node_path11.dirname)(__filename2);
46310
46310
  var MAX_SOCKET_PATH_LENGTH = 107;
46311
46311
  var MAX_OUTPUT_BUFFER_SIZE = 10 * 1024 * 1024;
46312
+ var ACTIVITY_VERIFICATION = {
46313
+ /** Time to wait for activity patterns after injection (ms) */
46314
+ TIMEOUT_MS: 5e3,
46315
+ /** How often to check for activity patterns (ms) */
46316
+ POLL_INTERVAL_MS: 200,
46317
+ /** Maximum retries when no activity is detected */
46318
+ MAX_RETRIES: 3,
46319
+ /** Delay between retries (ms) */
46320
+ RETRY_DELAY_MS: 500,
46321
+ /**
46322
+ * Patterns indicating the task was received and displayed.
46323
+ * These are the primary verification patterns.
46324
+ */
46325
+ TASK_RECEIVED_PATTERNS: [
46326
+ /\[Pasted text #\d+/,
46327
+ // Claude Code shows "[Pasted text #1 +95 lines]"
46328
+ /› Relay message from/,
46329
+ // Codex shows "› Relay message from"
46330
+ /Relay message from \w+ \[[\w-]+\]/
46331
+ // Droid/Gemini shows "Relay message from Agent [id]:"
46332
+ ],
46333
+ /**
46334
+ * Patterns indicating the CLI is thinking/processing.
46335
+ * Secondary verification - proves the CLI is active.
46336
+ */
46337
+ THINKING_PATTERNS: [
46338
+ /\(.*esc to (?:interrupt|stop)\)/i,
46339
+ // All CLIs: "(esc to interrupt)" or "(Press ESC to stop)"
46340
+ /[✻✶✳✢·✽⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/,
46341
+ // Spinner characters (Claude + Droid)
46342
+ /Thinking\.\.\./,
46343
+ // Droid: "Thinking..."
46344
+ /Working/,
46345
+ // Codex: "Working"
46346
+ /Forming|Noodling|Manifesting/i
46347
+ // Claude Code thinking states
46348
+ ],
46349
+ /**
46350
+ * Patterns indicating tool execution started.
46351
+ * Tertiary verification - proves the CLI is working.
46352
+ */
46353
+ TOOL_EXECUTION_PATTERNS: [
46354
+ /⏺\s*(Bash|Read|Write|Edit|Glob|Grep|Task|WebFetch)/,
46355
+ // Claude Code tool markers
46356
+ /•\s*Running/
46357
+ // Codex: "• Running: command"
46358
+ ]
46359
+ };
46312
46360
  function hashWorkspaceId(workspaceId) {
46313
46361
  return (0, import_node_crypto9.createHash)("sha256").update(workspaceId).digest("hex").slice(0, 12);
46314
46362
  }
@@ -46331,6 +46379,7 @@ var RelayPtyOrchestrator = class extends BaseWrapper {
46331
46379
  outputBuffer = "";
46332
46380
  rawBuffer = "";
46333
46381
  lastParsedLength = 0;
46382
+ bufferTrimCount = 0;
46334
46383
  // Interactive mode (show output to terminal)
46335
46384
  isInteractive = false;
46336
46385
  // Injection state
@@ -46879,13 +46928,19 @@ Stderr: ${stderrBuffer.slice(0, 500)}` : "";
46879
46928
  this.rawBuffer += data;
46880
46929
  this.outputBuffer += data;
46881
46930
  this.hasReceivedOutput = true;
46931
+ let buffersTrimmed = false;
46882
46932
  if (this.rawBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
46883
46933
  const trimAmount = this.rawBuffer.length - MAX_OUTPUT_BUFFER_SIZE;
46884
46934
  this.rawBuffer = this.rawBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
46885
46935
  this.lastParsedLength = Math.max(0, this.lastParsedLength - trimAmount);
46936
+ buffersTrimmed = true;
46886
46937
  }
46887
46938
  if (this.outputBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
46888
46939
  this.outputBuffer = this.outputBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
46940
+ buffersTrimmed = true;
46941
+ }
46942
+ if (buffersTrimmed) {
46943
+ this.bufferTrimCount += 1;
46889
46944
  }
46890
46945
  this.feedIdleDetectorOutput(data);
46891
46946
  const indicator = this.formatUnreadIndicator();
@@ -48129,14 +48184,103 @@ Then output: \`->relay-file:spawn\`
48129
48184
  this.relayPtyProcess.stdin.write(buffer);
48130
48185
  }
48131
48186
  /**
48132
- * Inject a task using the socket-based injection system with verification.
48187
+ * Verify that the CLI shows activity after task injection.
48188
+ * Checks output for patterns indicating the task was received and processing started.
48189
+ *
48190
+ * This catches the race condition where PTY write succeeds but CLI wasn't ready
48191
+ * (the T-003 failure scenario where CLI showed bell characters instead of processing).
48192
+ *
48193
+ * @param outputBefore The output buffer content before injection
48194
+ * @returns Promise resolving to true if activity detected, false otherwise
48195
+ */
48196
+ async verifyActivityAfterInjection(outputBefore) {
48197
+ const startTime = Date.now();
48198
+ const { TIMEOUT_MS, POLL_INTERVAL_MS, TASK_RECEIVED_PATTERNS, THINKING_PATTERNS, TOOL_EXECUTION_PATTERNS } = ACTIVITY_VERIFICATION;
48199
+ const trimCountBefore = this.bufferTrimCount;
48200
+ while (Date.now() - startTime < TIMEOUT_MS) {
48201
+ if (this.bufferTrimCount !== trimCountBefore) {
48202
+ this.log(` Activity verified: output buffer trimmed during verification (large output)`);
48203
+ return true;
48204
+ }
48205
+ const currentOutput = this.outputBuffer;
48206
+ const newOutput = currentOutput.slice(outputBefore.length);
48207
+ if (newOutput.length > 0) {
48208
+ const belCount = (newOutput.match(/\x07/g) || []).length;
48209
+ if (belCount > 10) {
48210
+ this.logError(` Input rejected: CLI produced ${belCount} BEL characters`);
48211
+ return false;
48212
+ }
48213
+ for (const pattern of TASK_RECEIVED_PATTERNS) {
48214
+ if (pattern.test(newOutput)) {
48215
+ this.log(` Activity verified: task received pattern matched`);
48216
+ return true;
48217
+ }
48218
+ }
48219
+ for (const pattern of THINKING_PATTERNS) {
48220
+ if (pattern.test(newOutput)) {
48221
+ this.log(` Activity verified: thinking pattern matched`);
48222
+ return true;
48223
+ }
48224
+ }
48225
+ for (const pattern of TOOL_EXECUTION_PATTERNS) {
48226
+ if (pattern.test(newOutput)) {
48227
+ this.log(` Activity verified: tool execution pattern matched`);
48228
+ return true;
48229
+ }
48230
+ }
48231
+ const meaningfulOutput = newOutput.replace(/[\x00-\x1f]/g, "");
48232
+ if (meaningfulOutput.length > 100) {
48233
+ this.log(` Activity verified: significant output growth (${meaningfulOutput.length} meaningful chars)`);
48234
+ return true;
48235
+ }
48236
+ }
48237
+ await sleep(POLL_INTERVAL_MS);
48238
+ }
48239
+ this.log(` No activity detected within ${TIMEOUT_MS}ms`);
48240
+ return false;
48241
+ }
48242
+ /**
48243
+ * Inject a task using the socket-based injection system with activity verification.
48133
48244
  * This is the preferred method for spawned agent task delivery.
48134
48245
  *
48246
+ * After socket confirms delivery, verifies the CLI shows activity (task received,
48247
+ * thinking indicators, or tool execution). Retries if no activity is detected.
48248
+ *
48135
48249
  * @param task The task text to inject
48136
48250
  * @param from The sender name (default: "spawner")
48137
- * @returns Promise resolving to true if injection succeeded, false otherwise
48251
+ * @returns Promise resolving to true if task was delivered AND activity verified, false otherwise
48138
48252
  */
48139
48253
  async injectTask(task, from = "spawner") {
48254
+ const { MAX_RETRIES, RETRY_DELAY_MS } = ACTIVITY_VERIFICATION;
48255
+ const STABILIZATION_DELAY_MS = 1500;
48256
+ this.log(` Waiting ${STABILIZATION_DELAY_MS}ms for CLI stabilization before task injection`);
48257
+ await sleep(STABILIZATION_DELAY_MS);
48258
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
48259
+ if (attempt > 0) {
48260
+ this.log(` Retry ${attempt}/${MAX_RETRIES} - waiting ${RETRY_DELAY_MS}ms before retry`);
48261
+ await sleep(RETRY_DELAY_MS);
48262
+ }
48263
+ const outputBefore = this.outputBuffer;
48264
+ const delivered = await this.performTaskInjection(task, from);
48265
+ if (!delivered) {
48266
+ this.logError(` Task delivery failed on attempt ${attempt + 1}`);
48267
+ continue;
48268
+ }
48269
+ const activityVerified = await this.verifyActivityAfterInjection(outputBefore);
48270
+ if (activityVerified) {
48271
+ this.log(` Task delivered and activity verified successfully`);
48272
+ return true;
48273
+ }
48274
+ this.logError(` Task delivered but no activity detected (attempt ${attempt + 1})`);
48275
+ }
48276
+ this.logError(` Task injection failed after ${MAX_RETRIES + 1} attempts - no CLI activity detected`);
48277
+ return false;
48278
+ }
48279
+ /**
48280
+ * Perform a single task injection attempt (without retry logic).
48281
+ * @returns true if the injection was sent successfully, false otherwise
48282
+ */
48283
+ async performTaskInjection(task, from) {
48140
48284
  if (!this.socket || !this.socketConnected) {
48141
48285
  this.log(` Socket not connected for task injection, falling back to stdin write`);
48142
48286
  try {
@@ -48389,6 +48533,12 @@ var openCodeApi = new OpenCodeApi();
48389
48533
 
48390
48534
  // packages/wrapper/dist/opencode-wrapper.js
48391
48535
  var import_node_child_process4 = require("node:child_process");
48536
+ var TASK_INJECTION = {
48537
+ /** Maximum retries when injection fails */
48538
+ MAX_RETRIES: 3,
48539
+ /** Delay between retries (ms) */
48540
+ RETRY_DELAY_MS: 500
48541
+ };
48392
48542
  var OpenCodeWrapper = class extends BaseWrapper {
48393
48543
  config;
48394
48544
  // OpenCode API client
@@ -48644,19 +48794,32 @@ var OpenCodeWrapper = class extends BaseWrapper {
48644
48794
  }
48645
48795
  }
48646
48796
  /**
48647
- * Inject a task into the agent
48797
+ * Inject a task into the agent with retry logic.
48798
+ *
48799
+ * Retries on transient failures to match RelayPtyOrchestrator behavior.
48800
+ * This ensures consistent reliability across all wrapper types.
48801
+ *
48648
48802
  * @param task - The task description to inject
48649
48803
  * @param _from - The sender name (used for formatting)
48650
- * @returns true if injection succeeded
48804
+ * @returns true if injection succeeded, false otherwise
48651
48805
  */
48652
48806
  async injectTask(task, _from) {
48653
- try {
48654
- await this.performInjection(task);
48655
- return true;
48656
- } catch (error2) {
48657
- console.error("[OpenCodeWrapper] Task injection failed:", error2);
48658
- return false;
48807
+ const { MAX_RETRIES, RETRY_DELAY_MS } = TASK_INJECTION;
48808
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
48809
+ if (attempt > 0) {
48810
+ console.log(`[OpenCodeWrapper] Retry ${attempt}/${MAX_RETRIES} - waiting ${RETRY_DELAY_MS}ms before retry`);
48811
+ await sleep(RETRY_DELAY_MS);
48812
+ }
48813
+ try {
48814
+ await this.performInjection(task);
48815
+ console.log(`[OpenCodeWrapper] Task delivered successfully${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`);
48816
+ return true;
48817
+ } catch (error2) {
48818
+ console.error(`[OpenCodeWrapper] Task delivery failed (attempt ${attempt + 1}/${MAX_RETRIES + 1}):`, error2);
48819
+ }
48659
48820
  }
48821
+ console.error(`[OpenCodeWrapper] Task injection failed after ${MAX_RETRIES + 1} attempts`);
48822
+ return false;
48660
48823
  }
48661
48824
  /**
48662
48825
  * Get output lines (for compatibility with spawner)
@@ -65364,8 +65527,9 @@ ${relayInstructions}`;
65364
65527
  }
65365
65528
  if (task && task.trim()) {
65366
65529
  const ready = await openCodeWrapper.waitUntilReadyForMessages(2e4, 100);
65530
+ let taskSent = false;
65367
65531
  if (ready) {
65368
- const taskSent = await openCodeWrapper.injectTask(task, spawnerName || "spawner");
65532
+ taskSent = await openCodeWrapper.injectTask(task, spawnerName || "spawner");
65369
65533
  if (!taskSent) {
65370
65534
  log3.warn(`Failed to inject task for ${name} via OpenCodeWrapper`);
65371
65535
  } else if (debug) {
@@ -65374,6 +65538,25 @@ ${relayInstructions}`;
65374
65538
  } else {
65375
65539
  log3.warn(`OpenCodeWrapper ${name} not ready for task injection`);
65376
65540
  }
65541
+ if (!taskSent) {
65542
+ const tracedError = createTraceableError("Task injection failed", {
65543
+ agentName: name,
65544
+ cli,
65545
+ taskLength: task.length,
65546
+ ready
65547
+ });
65548
+ log3.error(`CRITICAL: ${tracedError.logMessage}`);
65549
+ await openCodeWrapper.stop();
65550
+ if (this.onClearSpawning) {
65551
+ this.onClearSpawning(name);
65552
+ }
65553
+ return {
65554
+ success: false,
65555
+ name,
65556
+ error: tracedError.userMessage,
65557
+ errorId: tracedError.errorId
65558
+ };
65559
+ }
65377
65560
  }
65378
65561
  const workerInfo2 = {
65379
65562
  name,
@@ -65514,7 +65697,7 @@ ${relayInstructions}`;
65514
65697
  log3.debug(`Task injected to ${name} (attempt ${attempt})`);
65515
65698
  break;
65516
65699
  } else {
65517
- throw new Error("Task injection returned false");
65700
+ throw new Error("Task injection returned false - delivery failed");
65518
65701
  }
65519
65702
  } catch (err) {
65520
65703
  log3.debug(`Attempt ${attempt}/${maxRetries}: Error injecting task for ${name}: ${err.message}`);
@@ -65531,6 +65714,17 @@ ${relayInstructions}`;
65531
65714
  taskLength: task.length
65532
65715
  });
65533
65716
  log3.error(`CRITICAL: ${tracedError.logMessage}`);
65717
+ await pty.stop();
65718
+ this.activeWorkers.delete(name);
65719
+ if (this.onClearSpawning) {
65720
+ this.onClearSpawning(name);
65721
+ }
65722
+ return {
65723
+ success: false,
65724
+ name,
65725
+ error: tracedError.userMessage,
65726
+ errorId: tracedError.errorId
65727
+ };
65534
65728
  }
65535
65729
  }
65536
65730
  const workerInfo = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -130,25 +130,25 @@
130
130
  },
131
131
  "homepage": "https://github.com/AgentWorkforce/relay#readme",
132
132
  "dependencies": {
133
- "@agent-relay/bridge": "2.1.4",
134
- "@agent-relay/config": "2.1.4",
135
- "@agent-relay/continuity": "2.1.4",
136
- "@agent-relay/daemon": "2.1.4",
137
- "@agent-relay/hooks": "2.1.4",
138
- "@agent-relay/mcp": "2.1.4",
139
- "@agent-relay/protocol": "2.1.4",
140
- "@agent-relay/resiliency": "2.1.4",
141
- "@agent-relay/sdk": "2.1.4",
142
- "@agent-relay/spawner": "2.1.4",
143
- "@agent-relay/state": "2.1.4",
144
- "@agent-relay/storage": "2.1.4",
145
- "@agent-relay/telemetry": "2.1.4",
146
- "@agent-relay/trajectory": "2.1.4",
147
- "@agent-relay/user-directory": "2.1.4",
148
- "@agent-relay/utils": "2.1.4",
149
- "@agent-relay/wrapper": "2.1.4",
133
+ "@agent-relay/bridge": "2.1.5",
134
+ "@agent-relay/config": "2.1.5",
135
+ "@agent-relay/continuity": "2.1.5",
136
+ "@agent-relay/daemon": "2.1.5",
137
+ "@agent-relay/hooks": "2.1.5",
138
+ "@agent-relay/mcp": "2.1.5",
139
+ "@agent-relay/protocol": "2.1.5",
140
+ "@agent-relay/resiliency": "2.1.5",
141
+ "@agent-relay/sdk": "2.1.5",
142
+ "@agent-relay/spawner": "2.1.5",
143
+ "@agent-relay/state": "2.1.5",
144
+ "@agent-relay/storage": "2.1.5",
145
+ "@agent-relay/telemetry": "2.1.5",
146
+ "@agent-relay/trajectory": "2.1.5",
147
+ "@agent-relay/user-directory": "2.1.5",
148
+ "@agent-relay/utils": "2.1.5",
149
+ "@agent-relay/wrapper": "2.1.5",
150
150
  "@modelcontextprotocol/sdk": "^1.0.0",
151
- "agent-trajectories": "^0.2.3",
151
+ "agent-trajectories": "^0.3.0",
152
152
  "chokidar": "^5.0.0",
153
153
  "commander": "^12.1.0",
154
154
  "compare-versions": "^6.1.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/api-types",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "Shared API types and Zod schemas for Agent Relay",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-relay/benchmark",
3
- "version": "2.1.4",
3
+ "version": "2.1.5",
4
4
  "description": "Performance benchmarking for agent swarms, sub-agents, and single agents using Harbor",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -54,9 +54,9 @@
54
54
  "directory": "packages/benchmark"
55
55
  },
56
56
  "dependencies": {
57
- "@agent-relay/sdk": "2.1.4",
58
- "@agent-relay/protocol": "2.1.4",
59
- "@agent-relay/spawner": "2.1.4",
57
+ "@agent-relay/sdk": "2.1.5",
58
+ "@agent-relay/protocol": "2.1.5",
59
+ "@agent-relay/spawner": "2.1.5",
60
60
  "commander": "^12.1.0",
61
61
  "yaml": "^2.3.4"
62
62
  },
@@ -1 +1 @@
1
- {"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../src/spawner.ts"],"names":[],"mappings":"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"}
@@ -962,8 +962,9 @@ export class AgentSpawner {
962
962
  // Send task to the newly spawned agent if provided
963
963
  if (task && task.trim()) {
964
964
  const ready = await openCodeWrapper.waitUntilReadyForMessages(20000, 100);
965
+ let taskSent = false;
965
966
  if (ready) {
966
- const taskSent = await openCodeWrapper.injectTask(task, spawnerName || 'spawner');
967
+ taskSent = await openCodeWrapper.injectTask(task, spawnerName || 'spawner');
967
968
  if (!taskSent) {
968
969
  log.warn(`Failed to inject task for ${name} via OpenCodeWrapper`);
969
970
  }
@@ -974,6 +975,27 @@ export class AgentSpawner {
974
975
  else {
975
976
  log.warn(`OpenCodeWrapper ${name} not ready for task injection`);
976
977
  }
978
+ // If task injection failed, kill the agent and return error
979
+ // An agent without its task is useless and will just sit idle
980
+ if (!taskSent) {
981
+ const tracedError = createTraceableError('Task injection failed', {
982
+ agentName: name,
983
+ cli,
984
+ taskLength: task.length,
985
+ ready,
986
+ });
987
+ log.error(`CRITICAL: ${tracedError.logMessage}`);
988
+ await openCodeWrapper.stop();
989
+ if (this.onClearSpawning) {
990
+ this.onClearSpawning(name);
991
+ }
992
+ return {
993
+ success: false,
994
+ name,
995
+ error: tracedError.userMessage,
996
+ errorId: tracedError.errorId,
997
+ };
998
+ }
977
999
  }
978
1000
  // Track the worker (cast to AgentWrapper for type compatibility)
979
1001
  const workerInfo = {
@@ -1133,7 +1155,7 @@ export class AgentSpawner {
1133
1155
  // Fallback for older wrapper types
1134
1156
  await pty.waitUntilCliReady(15000, 100);
1135
1157
  }
1136
- // Inject task via socket (with verification and retries)
1158
+ // Inject task via socket (relay-pty confirms write)
1137
1159
  const success = await pty.injectTask(task, spawnerName || 'spawner');
1138
1160
  if (success) {
1139
1161
  taskSent = true;
@@ -1142,7 +1164,8 @@ export class AgentSpawner {
1142
1164
  break;
1143
1165
  }
1144
1166
  else {
1145
- throw new Error('Task injection returned false');
1167
+ // Delivery failed - safe to retry
1168
+ throw new Error('Task injection returned false - delivery failed');
1146
1169
  }
1147
1170
  }
1148
1171
  catch (err) {
@@ -1162,8 +1185,19 @@ export class AgentSpawner {
1162
1185
  taskLength: task.length,
1163
1186
  });
1164
1187
  log.error(`CRITICAL: ${tracedError.logMessage}`);
1165
- // Note: We don't return an error here because the agent is running,
1166
- // but we track the errorId so support can investigate if user reports it
1188
+ // Kill the agent since it's useless without its task - it will just sit idle
1189
+ // Return an error so the caller knows the spawn effectively failed
1190
+ await pty.stop();
1191
+ this.activeWorkers.delete(name);
1192
+ if (this.onClearSpawning) {
1193
+ this.onClearSpawning(name);
1194
+ }
1195
+ return {
1196
+ success: false,
1197
+ name,
1198
+ error: tracedError.userMessage,
1199
+ errorId: tracedError.errorId,
1200
+ };
1167
1201
  }
1168
1202
  }
1169
1203
  // Track the worker