@caseyharalson/orrery 0.13.0 → 0.13.1
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.
|
@@ -251,14 +251,28 @@ function createDefaultResult(stepId, exitCode, stderr) {
|
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
/**
|
|
254
|
-
* Check if
|
|
254
|
+
* Check if agent stdout contains valid structured output (indicating a
|
|
255
|
+
* legitimate task-level result rather than an infrastructure failure).
|
|
256
|
+
* @param {string} stdout - Raw stdout from agent
|
|
257
|
+
* @returns {boolean}
|
|
258
|
+
*/
|
|
259
|
+
function hasValidAgentOutput(stdout) {
|
|
260
|
+
if (!stdout) return false;
|
|
261
|
+
const results = parseAgentResults(stdout);
|
|
262
|
+
return results.length > 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Check if an error condition should trigger failover to another agent.
|
|
267
|
+
* Failover triggers on any non-zero exit unless the agent produced valid
|
|
268
|
+
* structured output (indicating a legitimate task-level failure, not an
|
|
269
|
+
* infrastructure issue).
|
|
255
270
|
* @param {Object} result - Process result with exitCode, stdout, stderr
|
|
256
271
|
* @param {Error} spawnError - Error from spawn (if any)
|
|
257
272
|
* @param {boolean} timedOut - Whether the process timed out
|
|
258
|
-
* @param {Object} errorPatterns - Regex patterns for error detection
|
|
259
273
|
* @returns {{shouldFailover: boolean, reason: string}}
|
|
260
274
|
*/
|
|
261
|
-
function shouldTriggerFailover(result, spawnError, timedOut
|
|
275
|
+
function shouldTriggerFailover(result, spawnError, timedOut) {
|
|
262
276
|
// 1. Spawn failures (command not found, ENOENT)
|
|
263
277
|
if (spawnError) {
|
|
264
278
|
if (spawnError.code === "ENOENT") {
|
|
@@ -272,23 +286,12 @@ function shouldTriggerFailover(result, spawnError, timedOut, errorPatterns) {
|
|
|
272
286
|
return { shouldFailover: true, reason: "timeout" };
|
|
273
287
|
}
|
|
274
288
|
|
|
275
|
-
// 3. Non-zero exit
|
|
289
|
+
// 3. Non-zero exit — failover unless agent produced valid structured output
|
|
276
290
|
if (result && result.exitCode !== 0) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
// Check API error patterns
|
|
280
|
-
for (const pattern of errorPatterns.apiError || []) {
|
|
281
|
-
if (pattern.test(stderr)) {
|
|
282
|
-
return { shouldFailover: true, reason: "api_error" };
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Check token limit patterns
|
|
287
|
-
for (const pattern of errorPatterns.tokenLimit || []) {
|
|
288
|
-
if (pattern.test(stderr)) {
|
|
289
|
-
return { shouldFailover: true, reason: "token_limit" };
|
|
290
|
-
}
|
|
291
|
+
if (hasValidAgentOutput(result.stdout)) {
|
|
292
|
+
return { shouldFailover: false, reason: null };
|
|
291
293
|
}
|
|
294
|
+
return { shouldFailover: true, reason: "agent_error" };
|
|
292
295
|
}
|
|
293
296
|
|
|
294
297
|
return { shouldFailover: false, reason: null };
|
|
@@ -513,8 +516,7 @@ function invokeAgentWithFailover(
|
|
|
513
516
|
const { shouldFailover, reason } = shouldTriggerFailover(
|
|
514
517
|
result,
|
|
515
518
|
null,
|
|
516
|
-
result.timedOut
|
|
517
|
-
failoverConfig.errorPatterns || {}
|
|
519
|
+
result.timedOut
|
|
518
520
|
);
|
|
519
521
|
|
|
520
522
|
if (shouldFailover && i < availableAgents.length - 1) {
|
|
@@ -535,8 +537,7 @@ function invokeAgentWithFailover(
|
|
|
535
537
|
const { shouldFailover, reason } = shouldTriggerFailover(
|
|
536
538
|
null,
|
|
537
539
|
spawnError,
|
|
538
|
-
false
|
|
539
|
-
failoverConfig.errorPatterns || {}
|
|
540
|
+
false
|
|
540
541
|
);
|
|
541
542
|
|
|
542
543
|
if (shouldFailover && i < availableAgents.length - 1) {
|
|
@@ -595,6 +596,7 @@ module.exports = {
|
|
|
595
596
|
invokeAgentWithFailover,
|
|
596
597
|
parseAgentResults,
|
|
597
598
|
createDefaultResult,
|
|
599
|
+
shouldTriggerFailover,
|
|
598
600
|
waitForAll,
|
|
599
601
|
waitForAny
|
|
600
602
|
};
|
|
@@ -146,30 +146,7 @@ module.exports = {
|
|
|
146
146
|
|
|
147
147
|
// Timeout in milliseconds before trying next agent (15 minutes)
|
|
148
148
|
// Can be overridden via ORRERY_AGENT_TIMEOUT environment variable
|
|
149
|
-
timeoutMs: 900000
|
|
150
|
-
|
|
151
|
-
// Patterns to detect failover-triggering errors from stderr
|
|
152
|
-
errorPatterns: {
|
|
153
|
-
// API/connection errors
|
|
154
|
-
apiError: [
|
|
155
|
-
/API error/i,
|
|
156
|
-
/connection refused/i,
|
|
157
|
-
/ECONNRESET/i,
|
|
158
|
-
/ETIMEDOUT/i,
|
|
159
|
-
/network error/i,
|
|
160
|
-
/rate limit/i,
|
|
161
|
-
/429/,
|
|
162
|
-
/502/,
|
|
163
|
-
/503/
|
|
164
|
-
],
|
|
165
|
-
// Token/context limit errors
|
|
166
|
-
tokenLimit: [
|
|
167
|
-
/token limit/i,
|
|
168
|
-
/context.*(limit|length|exceeded)/i,
|
|
169
|
-
/maximum.*tokens/i,
|
|
170
|
-
/too long/i
|
|
171
|
-
]
|
|
172
|
-
}
|
|
149
|
+
timeoutMs: 900000
|
|
173
150
|
},
|
|
174
151
|
|
|
175
152
|
// Concurrency control
|