@agentforge/core 0.18.6 → 0.18.8

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.
package/dist/index.cjs CHANGED
@@ -1245,6 +1245,47 @@ function snapshotExecutionMetrics(metrics) {
1245
1245
  };
1246
1246
  }
1247
1247
 
1248
+ // src/tools/execution-resilience.ts
1249
+ function normalizeThrownValue(error) {
1250
+ return error instanceof Error ? error : new Error(String(error));
1251
+ }
1252
+ async function executeWithRetries(execute, maxAttempts, retryDelay, shouldRetry) {
1253
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1254
+ try {
1255
+ return await execute();
1256
+ } catch (thrownValue) {
1257
+ const error = normalizeThrownValue(thrownValue);
1258
+ if (attempt === maxAttempts || !shouldRetry(error)) {
1259
+ throw error;
1260
+ }
1261
+ await new Promise((resolve) => setTimeout(resolve, retryDelay(attempt, error)));
1262
+ }
1263
+ }
1264
+ throw new Error("Retry execution requires at least one attempt");
1265
+ }
1266
+ async function executeWithTimeout(execute, timeoutMs, timeoutError, startOrder = "timeout-first") {
1267
+ let timeoutId;
1268
+ const startTimeout = () => new Promise((_, reject) => {
1269
+ timeoutId = setTimeout(() => reject(timeoutError()), timeoutMs);
1270
+ });
1271
+ try {
1272
+ let executionPromise;
1273
+ let timeoutPromise;
1274
+ if (startOrder === "execution-first") {
1275
+ executionPromise = execute();
1276
+ timeoutPromise = startTimeout();
1277
+ } else {
1278
+ timeoutPromise = startTimeout();
1279
+ executionPromise = execute();
1280
+ }
1281
+ return await Promise.race([executionPromise, timeoutPromise]);
1282
+ } finally {
1283
+ if (timeoutId !== void 0) {
1284
+ clearTimeout(timeoutId);
1285
+ }
1286
+ }
1287
+ }
1288
+
1248
1289
  // src/tools/executor-retry.ts
1249
1290
  function calculateBackoff(attempt, policy) {
1250
1291
  const initialDelay = policy.initialDelay || 1e3;
@@ -1264,10 +1305,7 @@ function calculateBackoff(attempt, policy) {
1264
1305
  return Math.min(delay, maxDelay);
1265
1306
  }
1266
1307
  function toError(error) {
1267
- if (error instanceof Error) {
1268
- return error;
1269
- }
1270
- return new Error(String(error));
1308
+ return normalizeThrownValue(error);
1271
1309
  }
1272
1310
  function resolveExecutionMethod(tool, logger6) {
1273
1311
  const executeFn = tool.invoke || tool.execute;
@@ -1293,28 +1331,20 @@ async function executeWithRetry(tool, input, policy, logger6) {
1293
1331
  `Invalid retry policy: maxAttempts must be an integer >= 1 (received ${String(policy.maxAttempts)})`
1294
1332
  );
1295
1333
  }
1296
- let lastError;
1297
- for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
1298
- try {
1299
- return await executeFn.call(tool, input);
1300
- } catch (error) {
1301
- const currentError = toError(error);
1302
- lastError = currentError;
1303
- if (policy.retryableErrors && policy.retryableErrors.length > 0) {
1304
- const isRetryable = policy.retryableErrors.some(
1305
- (message) => currentError.message.includes(message)
1306
- );
1307
- if (!isRetryable) {
1308
- throw currentError;
1309
- }
1310
- }
1311
- if (attempt < policy.maxAttempts) {
1312
- const delay = calculateBackoff(attempt, policy);
1313
- await new Promise((resolve) => setTimeout(resolve, delay));
1314
- }
1315
- }
1316
- }
1317
- throw lastError ?? new Error("Tool execution failed after retries");
1334
+ return executeWithRetries(
1335
+ () => executeFn.call(tool, input),
1336
+ policy.maxAttempts,
1337
+ (attempt) => calculateBackoff(attempt, policy),
1338
+ (error) => !policy.retryableErrors?.length || policy.retryableErrors.some((message) => error.message.includes(message))
1339
+ );
1340
+ }
1341
+ async function executeWithTimeout2(execute, timeout2) {
1342
+ return executeWithTimeout(
1343
+ execute,
1344
+ timeout2,
1345
+ () => new Error("Tool execution timeout"),
1346
+ "execution-first"
1347
+ );
1318
1348
  }
1319
1349
 
1320
1350
  // src/tools/executor-types.ts
@@ -1342,15 +1372,12 @@ function createToolExecutor(config = {}) {
1342
1372
  const metrics = createExecutionMetrics();
1343
1373
  async function executeSingle(tool, input, priority) {
1344
1374
  const startTime = Date.now();
1345
- let timeoutId;
1346
1375
  try {
1347
1376
  onExecutionStart?.(tool, input);
1348
- const result = await Promise.race([
1349
- executeWithRetry(tool, input, retryPolicy, logger2),
1350
- new Promise((_, reject) => {
1351
- timeoutId = setTimeout(() => reject(new Error("Tool execution timeout")), timeout2);
1352
- })
1353
- ]);
1377
+ const result = await executeWithTimeout2(
1378
+ () => executeWithRetry(tool, input, retryPolicy, logger2),
1379
+ timeout2
1380
+ );
1354
1381
  const duration = Date.now() - startTime;
1355
1382
  recordExecutionResult(metrics, priority, duration, true);
1356
1383
  onExecutionComplete?.(tool, input, result, duration);
@@ -1361,10 +1388,6 @@ function createToolExecutor(config = {}) {
1361
1388
  recordExecutionResult(metrics, priority, duration, false);
1362
1389
  onExecutionError?.(tool, input, normalizedError, duration);
1363
1390
  throw normalizedError;
1364
- } finally {
1365
- if (timeoutId) {
1366
- clearTimeout(timeoutId);
1367
- }
1368
1391
  }
1369
1392
  }
1370
1393
  function processQueue() {
@@ -1739,9 +1762,6 @@ function isConditionalStep(step) {
1739
1762
  function calculateRetryDelay(attempt, delay, backoff) {
1740
1763
  return backoff === "exponential" ? delay * Math.pow(2, attempt - 1) : delay * attempt;
1741
1764
  }
1742
- function toError2(error) {
1743
- return error instanceof Error ? error : new Error(String(error));
1744
- }
1745
1765
  function sequential(tools) {
1746
1766
  return {
1747
1767
  name: `sequential(${tools.map((t) => t.name).join(" -> ")})`,
@@ -1806,42 +1826,23 @@ function retry(tool, options = {}) {
1806
1826
  return {
1807
1827
  name: `retry(${tool.name})`,
1808
1828
  description: `${tool.description} (with retry)`,
1809
- invoke: async (input) => {
1810
- let lastError = new Error(`Tool ${tool.name} failed without an explicit error`);
1811
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1812
- try {
1813
- return await tool.invoke(input);
1814
- } catch (error) {
1815
- lastError = toError2(error);
1816
- if (attempt < maxAttempts) {
1817
- const waitTime = calculateRetryDelay(attempt, delay, backoff);
1818
- await new Promise((resolve) => setTimeout(resolve, waitTime));
1819
- }
1820
- }
1821
- }
1822
- throw lastError;
1823
- }
1829
+ invoke: async (input) => executeWithRetries(
1830
+ () => tool.invoke(input),
1831
+ maxAttempts,
1832
+ (attempt) => calculateRetryDelay(attempt, delay, backoff),
1833
+ () => true
1834
+ )
1824
1835
  };
1825
1836
  }
1826
1837
  function timeout(tool, ms) {
1827
1838
  return {
1828
1839
  name: `timeout(${tool.name})`,
1829
1840
  description: `${tool.description} (with ${ms}ms timeout)`,
1830
- invoke: async (input) => {
1831
- let timer;
1832
- const timeoutPromise = new Promise((_, reject) => {
1833
- timer = setTimeout(() => {
1834
- reject(new Error(`Tool ${tool.name} timed out after ${ms}ms`));
1835
- }, ms);
1836
- });
1837
- try {
1838
- return await Promise.race([tool.invoke(input), timeoutPromise]);
1839
- } finally {
1840
- if (timer !== void 0) {
1841
- clearTimeout(timer);
1842
- }
1843
- }
1844
- }
1841
+ invoke: async (input) => executeWithTimeout(
1842
+ () => tool.invoke(input),
1843
+ ms,
1844
+ () => new Error(`Tool ${tool.name} timed out after ${ms}ms`)
1845
+ )
1845
1846
  };
1846
1847
  }
1847
1848
  function cache(tool, ttl) {
@@ -4448,7 +4449,7 @@ function toErrorPayload(error) {
4448
4449
  }
4449
4450
  return { error: String(error) };
4450
4451
  }
4451
- function toError3(error) {
4452
+ function toError2(error) {
4452
4453
  if (error instanceof Error) {
4453
4454
  return error;
4454
4455
  }
@@ -4483,7 +4484,7 @@ var ConnectionPool = class {
4483
4484
  const interval = healthCheck.interval || 3e4;
4484
4485
  this.runtime.healthCheckTimer = setInterval(() => {
4485
4486
  performHealthChecks(this.runtime).catch((error) => {
4486
- const normalizedError = toError3(error);
4487
+ const normalizedError = toError2(error);
4487
4488
  logger4.error("Health check failed", toErrorPayload(normalizedError));
4488
4489
  options.onHealthCheckFail?.(normalizedError);
4489
4490
  });
package/dist/index.js CHANGED
@@ -1069,6 +1069,47 @@ function snapshotExecutionMetrics(metrics) {
1069
1069
  };
1070
1070
  }
1071
1071
 
1072
+ // src/tools/execution-resilience.ts
1073
+ function normalizeThrownValue(error) {
1074
+ return error instanceof Error ? error : new Error(String(error));
1075
+ }
1076
+ async function executeWithRetries(execute, maxAttempts, retryDelay, shouldRetry) {
1077
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1078
+ try {
1079
+ return await execute();
1080
+ } catch (thrownValue) {
1081
+ const error = normalizeThrownValue(thrownValue);
1082
+ if (attempt === maxAttempts || !shouldRetry(error)) {
1083
+ throw error;
1084
+ }
1085
+ await new Promise((resolve) => setTimeout(resolve, retryDelay(attempt, error)));
1086
+ }
1087
+ }
1088
+ throw new Error("Retry execution requires at least one attempt");
1089
+ }
1090
+ async function executeWithTimeout(execute, timeoutMs, timeoutError, startOrder = "timeout-first") {
1091
+ let timeoutId;
1092
+ const startTimeout = () => new Promise((_, reject) => {
1093
+ timeoutId = setTimeout(() => reject(timeoutError()), timeoutMs);
1094
+ });
1095
+ try {
1096
+ let executionPromise;
1097
+ let timeoutPromise;
1098
+ if (startOrder === "execution-first") {
1099
+ executionPromise = execute();
1100
+ timeoutPromise = startTimeout();
1101
+ } else {
1102
+ timeoutPromise = startTimeout();
1103
+ executionPromise = execute();
1104
+ }
1105
+ return await Promise.race([executionPromise, timeoutPromise]);
1106
+ } finally {
1107
+ if (timeoutId !== void 0) {
1108
+ clearTimeout(timeoutId);
1109
+ }
1110
+ }
1111
+ }
1112
+
1072
1113
  // src/tools/executor-retry.ts
1073
1114
  function calculateBackoff(attempt, policy) {
1074
1115
  const initialDelay = policy.initialDelay || 1e3;
@@ -1088,10 +1129,7 @@ function calculateBackoff(attempt, policy) {
1088
1129
  return Math.min(delay, maxDelay);
1089
1130
  }
1090
1131
  function toError(error) {
1091
- if (error instanceof Error) {
1092
- return error;
1093
- }
1094
- return new Error(String(error));
1132
+ return normalizeThrownValue(error);
1095
1133
  }
1096
1134
  function resolveExecutionMethod(tool, logger6) {
1097
1135
  const executeFn = tool.invoke || tool.execute;
@@ -1117,28 +1155,20 @@ async function executeWithRetry(tool, input, policy, logger6) {
1117
1155
  `Invalid retry policy: maxAttempts must be an integer >= 1 (received ${String(policy.maxAttempts)})`
1118
1156
  );
1119
1157
  }
1120
- let lastError;
1121
- for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
1122
- try {
1123
- return await executeFn.call(tool, input);
1124
- } catch (error) {
1125
- const currentError = toError(error);
1126
- lastError = currentError;
1127
- if (policy.retryableErrors && policy.retryableErrors.length > 0) {
1128
- const isRetryable = policy.retryableErrors.some(
1129
- (message) => currentError.message.includes(message)
1130
- );
1131
- if (!isRetryable) {
1132
- throw currentError;
1133
- }
1134
- }
1135
- if (attempt < policy.maxAttempts) {
1136
- const delay = calculateBackoff(attempt, policy);
1137
- await new Promise((resolve) => setTimeout(resolve, delay));
1138
- }
1139
- }
1140
- }
1141
- throw lastError ?? new Error("Tool execution failed after retries");
1158
+ return executeWithRetries(
1159
+ () => executeFn.call(tool, input),
1160
+ policy.maxAttempts,
1161
+ (attempt) => calculateBackoff(attempt, policy),
1162
+ (error) => !policy.retryableErrors?.length || policy.retryableErrors.some((message) => error.message.includes(message))
1163
+ );
1164
+ }
1165
+ async function executeWithTimeout2(execute, timeout2) {
1166
+ return executeWithTimeout(
1167
+ execute,
1168
+ timeout2,
1169
+ () => new Error("Tool execution timeout"),
1170
+ "execution-first"
1171
+ );
1142
1172
  }
1143
1173
 
1144
1174
  // src/tools/executor-types.ts
@@ -1166,15 +1196,12 @@ function createToolExecutor(config = {}) {
1166
1196
  const metrics = createExecutionMetrics();
1167
1197
  async function executeSingle(tool, input, priority) {
1168
1198
  const startTime = Date.now();
1169
- let timeoutId;
1170
1199
  try {
1171
1200
  onExecutionStart?.(tool, input);
1172
- const result = await Promise.race([
1173
- executeWithRetry(tool, input, retryPolicy, logger2),
1174
- new Promise((_, reject) => {
1175
- timeoutId = setTimeout(() => reject(new Error("Tool execution timeout")), timeout2);
1176
- })
1177
- ]);
1201
+ const result = await executeWithTimeout2(
1202
+ () => executeWithRetry(tool, input, retryPolicy, logger2),
1203
+ timeout2
1204
+ );
1178
1205
  const duration = Date.now() - startTime;
1179
1206
  recordExecutionResult(metrics, priority, duration, true);
1180
1207
  onExecutionComplete?.(tool, input, result, duration);
@@ -1185,10 +1212,6 @@ function createToolExecutor(config = {}) {
1185
1212
  recordExecutionResult(metrics, priority, duration, false);
1186
1213
  onExecutionError?.(tool, input, normalizedError, duration);
1187
1214
  throw normalizedError;
1188
- } finally {
1189
- if (timeoutId) {
1190
- clearTimeout(timeoutId);
1191
- }
1192
1215
  }
1193
1216
  }
1194
1217
  function processQueue() {
@@ -1563,9 +1586,6 @@ function isConditionalStep(step) {
1563
1586
  function calculateRetryDelay(attempt, delay, backoff) {
1564
1587
  return backoff === "exponential" ? delay * Math.pow(2, attempt - 1) : delay * attempt;
1565
1588
  }
1566
- function toError2(error) {
1567
- return error instanceof Error ? error : new Error(String(error));
1568
- }
1569
1589
  function sequential(tools) {
1570
1590
  return {
1571
1591
  name: `sequential(${tools.map((t) => t.name).join(" -> ")})`,
@@ -1630,42 +1650,23 @@ function retry(tool, options = {}) {
1630
1650
  return {
1631
1651
  name: `retry(${tool.name})`,
1632
1652
  description: `${tool.description} (with retry)`,
1633
- invoke: async (input) => {
1634
- let lastError = new Error(`Tool ${tool.name} failed without an explicit error`);
1635
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1636
- try {
1637
- return await tool.invoke(input);
1638
- } catch (error) {
1639
- lastError = toError2(error);
1640
- if (attempt < maxAttempts) {
1641
- const waitTime = calculateRetryDelay(attempt, delay, backoff);
1642
- await new Promise((resolve) => setTimeout(resolve, waitTime));
1643
- }
1644
- }
1645
- }
1646
- throw lastError;
1647
- }
1653
+ invoke: async (input) => executeWithRetries(
1654
+ () => tool.invoke(input),
1655
+ maxAttempts,
1656
+ (attempt) => calculateRetryDelay(attempt, delay, backoff),
1657
+ () => true
1658
+ )
1648
1659
  };
1649
1660
  }
1650
1661
  function timeout(tool, ms) {
1651
1662
  return {
1652
1663
  name: `timeout(${tool.name})`,
1653
1664
  description: `${tool.description} (with ${ms}ms timeout)`,
1654
- invoke: async (input) => {
1655
- let timer;
1656
- const timeoutPromise = new Promise((_, reject) => {
1657
- timer = setTimeout(() => {
1658
- reject(new Error(`Tool ${tool.name} timed out after ${ms}ms`));
1659
- }, ms);
1660
- });
1661
- try {
1662
- return await Promise.race([tool.invoke(input), timeoutPromise]);
1663
- } finally {
1664
- if (timer !== void 0) {
1665
- clearTimeout(timer);
1666
- }
1667
- }
1668
- }
1665
+ invoke: async (input) => executeWithTimeout(
1666
+ () => tool.invoke(input),
1667
+ ms,
1668
+ () => new Error(`Tool ${tool.name} timed out after ${ms}ms`)
1669
+ )
1669
1670
  };
1670
1671
  }
1671
1672
  function cache(tool, ttl) {
@@ -4272,7 +4273,7 @@ function toErrorPayload(error) {
4272
4273
  }
4273
4274
  return { error: String(error) };
4274
4275
  }
4275
- function toError3(error) {
4276
+ function toError2(error) {
4276
4277
  if (error instanceof Error) {
4277
4278
  return error;
4278
4279
  }
@@ -4307,7 +4308,7 @@ var ConnectionPool = class {
4307
4308
  const interval = healthCheck.interval || 3e4;
4308
4309
  this.runtime.healthCheckTimer = setInterval(() => {
4309
4310
  performHealthChecks(this.runtime).catch((error) => {
4310
- const normalizedError = toError3(error);
4311
+ const normalizedError = toError2(error);
4311
4312
  logger4.error("Health check failed", toErrorPayload(normalizedError));
4312
4313
  options.onHealthCheckFail?.(normalizedError);
4313
4314
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentforge/core",
3
- "version": "0.18.6",
3
+ "version": "0.18.8",
4
4
  "description": "Production-ready TypeScript agent framework built on LangGraph with orchestration, middleware, and typed abstractions.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",